]> git.mdlowis.com Git - proto/cerise-os.git/commitdiff
finished initial cut of task system
authorMichael D. Lowis <mike.lowis@gentex.com>
Fri, 9 Sep 2022 20:44:21 +0000 (16:44 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Fri, 9 Sep 2022 20:44:21 +0000 (16:44 -0400)
Kernel.c [moved from tasks.c with 83% similarity]
Kernel.h [new file with mode: 0644]

similarity index 83%
rename from tasks.c
rename to Kernel.c
index 0ebe9f82988ff3ebfc68d98136ca9652ac2ec8bc..4e4ac38c9dc4234dc2aeccd780de691e3f0b43be 100644 (file)
--- 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 (file)
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);
+