From: Michael D. Lowis Date: Fri, 9 Sep 2022 20:44:21 +0000 (-0400) Subject: finished initial cut of task system X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=36e7b466f589dc1a2111b5245020016db6421ba4;p=proto%2Fcerise-os.git finished initial cut of task system --- diff --git a/tasks.c b/Kernel.c similarity index 83% rename from tasks.c rename to Kernel.c index 0ebe9f8..4e4ac38 100644 --- a/tasks.c +++ b/Kernel.c @@ -7,16 +7,17 @@ /* TODO: -* Recycle dead tasks -* implement message passing * implement task-local heap +* implement message passing */ +#define COND_WAIT_TIMEOUT_MS 100u + typedef struct Task_T { - long* stack_top; // top of tasks's stack - long* stack_base; // allocated memory for stack - struct Task_T* next; // pointer to next task + volatile long* stack_top; // top of tasks's stack + long* stack_base; // allocated memory for stack + struct Task_T* next; // pointer to next task } Task_T; typedef struct { @@ -64,7 +65,7 @@ static void WaitForCondition(pthread_cond_t* cond, pthread_mutex_t* mutex, int m static void WaitForTaskFree(Task_T* prev, Task_T* next) { - if (prev != next) + if (next && prev != next) { while (!next->stack_top) { @@ -173,7 +174,7 @@ __asm__( " ret\n" ); -static void Yield(void) +void Kernel_Yield(void) { AcquireLock(); printf("CPU %d is yielding\n", CpuID); @@ -189,7 +190,7 @@ static void Yield(void) SwapTask(prev, Running[CpuID].task); } -void ExitTask(void) +void Kernel_Exit(void) { puts("exiting"); AcquireLock(); @@ -207,13 +208,26 @@ void ExitTask(void) static Task_T* CreateTask(void (*task_fn)(void*), void* arg, int stacksize) { - if (stacksize == 0) { stacksize = 32768; } - Task_T* task = calloc(1, sizeof(Task_T)); - task->stack_base = calloc(stacksize/sizeof(long), sizeof(long)); + AcquireLock(); + Task_T* task = Dequeue(&DeadQueue); + WaitForTaskFree(NULL, task); + ReleaseLock(); + if (!task) + { + task = calloc(1, sizeof(Task_T)); + } + + /* allocate stack */ + if (stacksize == 0) + { + stacksize = 32768; + } + task->stack_base = realloc(task->stack_base, stacksize); + task->stack_top = &task->stack_base[stacksize/sizeof(long)-1]; // top of stack - *(--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) + *(--task->stack_top) = (long)Kernel_Exit; // 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->stack_top) = 0xdeadbeef; // initial values for saved registers @@ -222,7 +236,7 @@ static Task_T* CreateTask(void (*task_fn)(void*), void* arg, int stacksize) return task; } -void SpawnTask(void (*task_fn)(void*), void* arg, int stacksize) +void Kernel_Spawn(void (*task_fn)(void*), void* arg, int stacksize) { Task_T* task = CreateTask(task_fn, arg, stacksize); /* put task in the ready queue */ @@ -236,10 +250,10 @@ static void CpuIdle(void* arg) printf("CPU %d is started\n", CpuID); while(1) { - Yield(); + Kernel_Yield(); printf("CPU %d is idle\n", CpuID); AcquireLock(); - WaitForCondition(&ScheduleCond, &ScheduleLock, 10); + WaitForCondition(&ScheduleCond, &ScheduleLock, COND_WAIT_TIMEOUT_MS); ReleaseLock(); } } @@ -254,7 +268,7 @@ static void* CpuMain(void* arg) return NULL; /* unreachable */ } -void Init(void) +void Kernel(void) { pthread_mutex_init(&ScheduleLock, 0); pthread_cond_init(&ScheduleCond, NULL); @@ -266,12 +280,12 @@ void Init(void) } } -void WaitForExit(void) +void Kernel_Run(void) { while(1) { AcquireLock(); - WaitForCondition(&ScheduleCond, &ScheduleLock, 10); + WaitForCondition(&ScheduleCond, &ScheduleLock, COND_WAIT_TIMEOUT_MS); if (!ReadyQueue.head) { bool done = true; @@ -297,7 +311,7 @@ void task1(void* arg) for (int i = 0; i < 5; i++) { printf("%d Hello from task 1\n", CpuID); - Yield(); + Kernel_Yield(); } } @@ -306,7 +320,7 @@ void task2(void* arg) for (int i = 0; i < 5; i++) { printf("%d Hello from task 2\n", CpuID); - Yield(); + Kernel_Yield(); } } @@ -315,13 +329,13 @@ int main(int argc, char** argv) (void)argc; (void)argv; - Init(); + Kernel(); - SpawnTask(task1, 0, 0); - SpawnTask(task2, 0, 0); + Kernel_Spawn(task1, 0, 0); + Kernel_Spawn(task2, 0, 0); /* wait for all jobs to be done */ - WaitForExit(); + Kernel_Run(); puts("done"); return 0; diff --git a/Kernel.h b/Kernel.h new file mode 100644 index 0000000..07b694f --- /dev/null +++ b/Kernel.h @@ -0,0 +1,5 @@ +void Kernel_Yield(void); +void Kernel_Exit(void); +void Kernel_Spawn(void (*task_fn)(void*), void* arg, int stacksize); +void Kernel_Run(void); +