/**** * Example 2: CoData pointers for scheduling selection ****/ #define NUMTASKS 4 typedef struct task { CoData cd; int id; int cycles; int next; } task; main(void) { /* CoData structures for tasks */ task t[NUMTASKS]; /* First "on" task and "off" task */ int firston, firstoff; /* Next task to execute, and the one to execute after that */ int nexttask, pending; /* CoData pointer for scheduling */ CoData* pcd; int i; /* Initialize tasks */ for (i = 0; i < NUMTASKS; ++i) { t[i].id = i+1; t[i].cycles = 0; t[i].next = i+1; CoBegin(&t[i].cd); } t[0].next = -1; t[NUMTASKS-1].next = -1; firston = 0; firstoff = 1; nexttask = 0; while(1) { /* Keyboard handler */ costate { while(1) { waitfor(kbhit()); switch(getchar()) { /* Stop one of the currently running tasks */ case '-': /* Make sure there is an enabled task */ if (firston == -1) { printf("All tasks stopped.\n"); break; } /* Is this the only one enabled task? */ i = firston; firston = t[i].next; /* Add task to front of disabled stack */ t[i].next = firstoff; firstoff = i; /* * Was that task scheduled to go next? If so, * reset the 'next task' id. */ if (nexttask == i) nexttask = firston; break; case '+': /* Make sure there is a disabled task */ if (firstoff == -1) { printf("All tasks running.\n"); break; } /* Is this the only one disabled task? */ i = firstoff; firstoff = t[i].next; /* Add task to front of enabled stack */ t[i].next = firston; firston = i; break; } } } /* Task selection code */ if (nexttask == -1 && firston == -1) /* Nothing enabled, nothing to run */ continue; else if (nexttask == -1) nexttask = firston; pending = t[nexttask].next; pcd = &t[nexttask].cd; ++t[nexttask].cycles; /* Task execution */ costate pcd { while (1) { switch (t[nexttask].id) { // Task 1 and 4's code; just print its name each time case 1: case 4: printf("Task #%d\n", t[nexttask].id); break; // Task 2's code; four parts, yield between each case 2: printf("Task #2, part 1\n"); yield; printf("Task #2, part 2\n"); yield; printf("Task #2, part 3\n"); yield; printf("Task #2, part 4\n"); break; // Task 3's code; run once for every 10 cycles of task 1 // then run task #1 again immediately (usually #2 would run // next and then #1...). case 3: waitfor(t[0].cycles % 10 == 0); printf("Task #3\n"); pending = 0; /* Named yield to thread #1 */ break; } yield; } } /* Select the next task to run */ nexttask = pending; } }