static pthread_mutex_t ScheduleLock;
static pthread_cond_t ScheduleCond;
static __thread int CpuID = 0;
-static long int TaskCount = 0;
static TaskQueue_T ReadyQueue = {0};
static TaskQueue_T DeadQueue = {0};
static CpuState_T* Running = NULL;
SwapTask(prev, Running[CpuID].task);
}
-void FinalizeTask(void)
+void ExitTask(void)
{
puts("exiting");
AcquireLock();
- TaskCount--;
- Running[CpuID].task = NULL; // TODO: Enqueue to dead queue
+ Enqueue(&DeadQueue, Running[CpuID].task);
+ Running[CpuID].task = NULL;
Running[CpuID].task = Select();
printf("starting task %p\n", Running[CpuID].task);
ReleaseLock();
Task_T* task = calloc(1, sizeof(Task_T));
task->stack_base = calloc(stacksize/sizeof(long), sizeof(long));
task->stack_top = &task->stack_base[stacksize/sizeof(long)-1]; // top of stack
- *(--task->stack_top) = (long)FinalizeTask; // coroutine cleanup
+ *(--task->stack_top) = (long)ExitTask; // coroutine cleanup
*(--task->stack_top) = (long)task_fn; // user's function to run (rop style!)
*(--task->stack_top) = (long)arg; // user's function argument (rdi)
for (int saved = 0; saved < 6; saved++)
Task_T* task = CreateTask(task_fn, arg, stacksize);
/* put task in the ready queue */
AcquireLock();
- TaskCount++;
Enter(task);
ReleaseLock();
}
Yield();
printf("CPU %d is idle\n", CpuID);
AcquireLock();
- WaitForCondition(&ScheduleCond, &ScheduleLock, 1);
+ WaitForCondition(&ScheduleCond, &ScheduleLock, 10);
ReleaseLock();
}
}
return NULL; /* unreachable */
}
+void Init(void)
+{
+ pthread_mutex_init(&ScheduleLock, 0);
+ pthread_cond_init(&ScheduleCond, NULL);
+ CpuCount = sysconf(_SC_NPROCESSORS_ONLN);
+ Running = calloc(CpuCount, sizeof(CpuState_T));
+ for (long int i = 0; i < CpuCount; i++)
+ {
+ pthread_create(&Running[i].thread, NULL, CpuMain, (void*)i);
+ }
+}
+
+void WaitForExit(void)
+{
+ while(1)
+ {
+ AcquireLock();
+ WaitForCondition(&ScheduleCond, &ScheduleLock, 10);
+ if (!ReadyQueue.head)
+ {
+ bool done = true;
+ for (long int i = 0; i < CpuCount; i++)
+ {
+ done = done && (Running[i].task == Running[i].idle);
+ }
+ if (done)
+ {
+ break;
+ }
+ }
+ ReleaseLock();
+ }
+}
+
/***************************************
Main Routine
***************************************/
(void)argc;
(void)argv;
- pthread_mutex_init(&ScheduleLock, 0);
- pthread_cond_init(&ScheduleCond, NULL);
- CpuCount = sysconf(_SC_NPROCESSORS_ONLN);
-// CpuCount = 1;
- Running = calloc(CpuCount, sizeof(CpuState_T));
- for (long int i = 0; i < CpuCount; i++)
- {
- pthread_create(&Running[i].thread, NULL, CpuMain, (void*)i);
- }
+ Init();
SpawnTask(task1, 0, 0);
SpawnTask(task2, 0, 0);
/* wait for all jobs to be done */
- while(1)
- {
- AcquireLock();
- WaitForCondition(&ScheduleCond, &ScheduleLock, 10);
-// printf("%ld %d %p\n", TaskCount, CpuCount, ReadyQueue.head);
- if (TaskCount == 0)
- {
- break;
- }
-// else
- {
- printf("count: %ld\n", TaskCount);
- printf("head: %p\n", ReadyQueue.head);
- printf("tasks:\n");
- for (long int i = 0; i < CpuCount; i++)
- {
- if (Running[i].task == Running[i].idle)
- {
- printf(" %02ld idle\n", i);
- }
- else
- {
- printf(" %02ld %p\n", i, Running[i].task);
- }
- }
-
- }
- ReleaseLock();
- }
+ WaitForExit();
puts("done");
+
return 0;
}
\ No newline at end of file