/********************************************************************** * Filename: pcm.c * Pseudo cooperative multitasker using arrays of function pointers * * Copyright (c) 1995 Jeffrey M. Stefan * * **********************************************************************/ #include #include #include #include #include /*********************************************************************/ /* Delay value for demonstration only: this is used to slow down the */ /* tasks for the display. Adjust this value to see the state */ /* transitions within the tasks. */ /*********************************************************************/ #define DELAY_VAL 10 /*********************************************************************/ /* Use this define to define the maximum tasks in your application. */ /* Make sure that the number of tasks you run are at least equal to */ /* the number defined here, otherwise unpredictable (bad) things */ /* will happen. */ /*********************************************************************/ #define MAX_TASKS 3 /*********************************************************************/ /* The following defines are used for task return identifiers. The */ /* individual tasks may return someting to the main loop. Using */ /* these defines identify the task. */ /*********************************************************************/ #define TASK1_RET 1 #define TASK2_RET 2 #define TASK3_RET 3 /*******************************************************************/ /* Function (task) prototypes. These functions should return ints */ /* in order to inform main that it has finished processing. For */ /* example, nTask1 should return TASK1_RET, which is defined as 1. */ /*******************************************************************/ int nTask1(void); int nTask2(void); int nTask3(void); /******************************************************************/ /* main : main() acts like a task dispatcher or task scheduler. */ /******************************************************************/ main() { int nRetVal = 0; /* Return value from called function (task) */ int nCtr = 0; /* Function a(task) array index counter */ int (*fp)(); /* Function (task) pointer */ int *afp[] ={ /* array of function (task) pointers */ nTask1, nTask2, nTask3, NULL }; clrscr(); /************************************************************/ /* Dispatch Tasks using infinite for loop. */ /************************************************************/ for(;;) { fp = afp[nCtr]; /* Get the task address */ nRetVal = (*fp)(); /* execute task and get return value */ nCtr++; /* Increment task counter */ if(nCtr==MAX_TASKS) /* If last task was run, start over */ { nCtr=0; } /**************************************************************/ /* The following switch statement processes the return values */ /* from the task that just returned. The task may fill a data */ /* structure, signal event, or act on some other data. This */ /* area will be application specific. */ /**************************************************************/ switch(nRetVal) { case TASK1_RET: /*******************************************/ /* Process the data that Task 1 worked on. */ /*******************************************/ break; case TASK2_RET: /*******************************************/ /* Process the data that Task 2 worked on. */ /*******************************************/ break; case TASK3_RET: /*******************************************/ /* Process the data that Task 3 worked on. */ /*******************************************/ break; default: break; } /* switch */ if(kbhit()) { break; /* exit out of infinite loop */ } } /* main loop */ } /*********************************************************************/ /* nTask1 : First task in system. */ /* */ /*********************************************************************/ int nTask1() { static int nState = 0; /*******************************************************************/ /* The static nState variable remembers where the task left off. */ /* When the task is called again by the dispatcher in main loop, */ /* the switch statement will place the program counter at the last */ /* known state. This is effectively a cooperative context switch. */ /*******************************************************************/ switch(nState) { case 0 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 1; printf("Task1 State 0\r"); delay(DELAY_VAL); return(TASK1_RET); break; case 1 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 2; printf("Task1 State 1\r"); delay(DELAY_VAL); return(TASK1_RET); break; case 2 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 3; printf("Task1 State 2\r"); delay(DELAY_VAL); return(TASK1_RET); break; case 3 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ printf("Task1 State 3\r"); delay(DELAY_VAL); nState = 4; return(TASK1_RET); break; case 4 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ printf("Task1 State 4\r"); delay(DELAY_VAL); nState = 0; return(TASK1_RET); break; default : break; } /* switch */ return(TASK1_RET); } /*********************************************************************/ /* nTask2 : Second task in system. */ /* */ /*********************************************************************/ int nTask2() { static int nState = 0; switch(nState) { case 0 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 1; printf(" Task2 State 0\r"); delay(DELAY_VAL); return(TASK2_RET); break; case 1 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 2; printf(" Task2 State 1\r"); delay(DELAY_VAL); return(TASK2_RET); break; case 2 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 3; printf(" Task2 State 2\r"); delay(DELAY_VAL); return(TASK2_RET); break; case 3 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 4; printf(" Task2 State 3\r"); delay(DELAY_VAL); return(TASK2_RET); break; case 4 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 0; printf(" Task2 State 4\r"); delay(DELAY_VAL); return(TASK2_RET); break; default : break; } /* switch */ return TASK2_RET; } /********************************************************************/ /* nTask3 : Third task in system. */ /* */ /********************************************************************/ int nTask3() { static int nState = 0; switch(nState) { case 0 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 1; printf(" Task3 State 0\r"); delay(DELAY_VAL); return(TASK3_RET); break; case 1 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 2; printf(" Task3 State 1\r"); delay(DELAY_VAL); return(TASK3_RET); break; case 2 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 3; printf(" Task3 State 2\r"); delay(DELAY_VAL); return(TASK3_RET); break; case 3 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 4; printf(" Task3 State 3\r"); delay(DELAY_VAL); return(TASK3_RET); break; case 4 : /****************************************************/ /* Change nState to whatever new state is required. */ /****************************************************/ nState = 0; printf(" Task3 State 4\r"); delay(DELAY_VAL); return(TASK3_RET); break; default : break; } // switch return TASK3_RET; }