]> code.bitgloo.com Git - clyne/stmos.git/commitdiff
fork, getpid
authorClyne Sullivan <tullivan99@gmail.com>
Sun, 21 Oct 2018 17:10:34 +0000 (13:10 -0400)
committerClyne Sullivan <tullivan99@gmail.com>
Sun, 21 Oct 2018 17:10:34 +0000 (13:10 -0400)
src/kernel/clock.c
src/kernel/svc.c
src/kernel/task.c
src/kernel/task.h
src/user/user.c

index 5bfc93ad7c026ded88acd1c158b7d61390f8d1f3..5b80203a4e530166f3feaf58221ec5ad223af31a 100644 (file)
@@ -31,12 +31,10 @@ extern task_t *current;
 
 void clock_svc(uint32_t *args)
 {
-       if (args[0] == 0) {
-               current->sleep = ticks + args[1];
-               SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
-       } else if (args[0] == 1) {
+       if (args[0] == 0)
+               task_sleep(args[1]);
+       else if (args[0] == 1)
                udelay(args[1]);
-       }
 }
 
 void clock_init(void)
index edf2b68f9f1f92d1a97ba35ad54a62c211f90f58..4aa156ebc2e9976eeb8d17a74aa06a32b15a87c4 100644 (file)
@@ -1,7 +1,6 @@
 /**
  * @file svc.c
  * An unused handler for SVC calls
- * TODO: use SVC calls, possibly allowing for switch to unprivileged mode?
  *
  * Copyright (C) 2018 Clyne Sullivan
  *
@@ -28,9 +27,17 @@ extern void gpio_svc(uint32_t *);
 extern void clock_svc(uint32_t *);
 extern void task_svc(uint32_t *);
 
-void svc_handler(uint32_t *args)
-{
-       /*uint32_t*/int svc_number = ((char *)args[6])[-2];
+void SVC_Handler(void) {
+       uint32_t *args;
+
+       asm("\
+               tst lr, #4; \
+               ite eq; \
+               mrseq %0, msp; \
+               mrsne %0, psp; \
+       " : "=r" (args));
+
+       int svc_number = ((char *)args[6])[-2];
 
        switch (svc_number) {
        case -1:
@@ -44,24 +51,16 @@ void svc_handler(uint32_t *args)
                clock_svc(args);
                break;
        case 3:
+               asm("\
+                       mrs r0, psp; \
+                       stmdb r0!, {r4-r11, r14}; \
+                       mov %0, r0; \
+               " : "=r" (args[0]));
                task_svc(args);
-               asm("mov r0, %0" :: "r" (args[0]));
+               asm("mov r0, %0" :: "r" (args[0])); // TODO doesn't work, r0 overwritten on exc. return
                break;
        default:
                break;
        }
 }
 
-void SVC_Handler(void) {
-       uint32_t *args;
-
-       asm("\
-               tst lr, #4; \
-               ite eq; \
-               mrseq %0, msp; \
-               mrsne %0, psp; \
-       " : "=r" (args));
-
-       svc_handler(args);
-}
-
index 96051a932d4bda3b288d9e0396028eadea91c606..4f61e1d7d22543e5b1e3e669ac2c98070b6669d9 100644 (file)
 #include "task.h"
 #include <arch/stm/stm32l476xx.h>
 
-task_t *current, *prev;
+static task_t *task_current;
+static task_t *task_queue;
 static uint8_t task_disable = 0;
+static uint32_t task_next_pid = 0;
 
 int task_fork(uint32_t sp);
 void task_svc(uint32_t *args)
@@ -41,21 +43,41 @@ void task_hold(uint8_t hold)
                task_disable--;
 }
 
+void task_sleep(uint32_t ms)
+{
+       task_current->sleep = millis() + ms;
+       SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
+}
+
+uint32_t task_getpid(void)
+{
+       return task_current->pid;
+}
+
 void _exit(int code)
 {
        (void)code;
 
-       while (prev == 0);
+       if (task_queue == task_current) {
+               task_queue = task_queue->next;
+       } else {
+               task_t *prev = task_queue;
+               while (prev->next != 0 && prev->next != task_current)
+                       prev = prev->next;
 
-       prev->next = current->next;
+               if (prev->next != 0)
+                       prev->next = task_current->next;
+       }
 
        // Free this thread's stack, and task data.
        // Since we're single core, no one else can claim this memory until
        // a task switch, after which we're done with this memory anyway.
-       free(current->stack);
-       free(current);
+       free(task_current->stack);
+       free(task_current);
 
        SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
+       // TODO if child proc. set return code in parent task handle?
+       // or something like that
 }
 
 
@@ -87,6 +109,9 @@ task_t *task_create(void (*code)(void), uint16_t stackSize)
 {
        task_t *t = (task_t *)malloc(sizeof(task_t));
        t->next = 0;
+       t->sleep = 0;
+       t->pid = task_next_pid++;
+
        t->stack = (uint32_t *)malloc(stackSize);
        void *sp = (uint8_t *)t->stack + stackSize - 68; // excep. stack + regs
        t->sp = sp;
@@ -107,20 +132,18 @@ task_t *task_create(void (*code)(void), uint16_t stackSize)
        t->sp[14] = (uint32_t)code;
        t->sp[15] = (uint32_t)task_crt0;
        t->sp[16] = 0x01000000;
-       t->sleep = 0;
        return t;
 }
 
 void task_init(void (*init)(void), uint16_t stackSize)
 {
-       current = (task_t *)malloc(sizeof(task_t));
-       current->stack = 0; // free() is called on this
-
-       task_t *init_task = task_create(init, stackSize);
+       task_current = (task_t *)malloc(sizeof(task_t));
+       task_current->next = 0;
+       task_current->stack = 0; // free() is called on this
+       task_current->sp = 0;
+       task_current->sleep = 1000;
 
-       prev = init_task;
-       current->next = init_task;
-       init_task->next = init_task;
+       task_queue = task_create(init, stackSize);
 
        task_disable = 0;
 
@@ -143,8 +166,8 @@ void task_start(void (*task)(void), uint16_t stackSize)
 {
        task_hold(1);
        task_t *t = task_create(task, stackSize);
-       t->next = current->next;
-       current->next = t;
+       t->next = task_queue;
+       task_queue = t;
        task_hold(0);
 }
 
@@ -156,32 +179,37 @@ int task_fork_ret(void)
 // Return 0 for child, non-zero for parent
 int task_fork(uint32_t sp)
 {
-       task_hold(1);
+       asm("cpsid i");
 
-       // 1. Get a PC for the child
-       void (*pc)(void) = (void (*)(void))((uint32_t)task_fork_ret);
-
-       // 2. Prepare child task
-       alloc_t *stackInfo = (alloc_t *)(((uint8_t *)current->stack)
+       //// 1. Prepare child task
+       // Get parent task's stack info
+       alloc_t *stackInfo = (alloc_t *)(((uint8_t *)task_current->stack)
                - sizeof(alloc_t));
-       task_t *childTask = task_create(pc, stackInfo->size - 8);
-       for (uint32_t i = 0; i < (stackInfo->size - 8); i++)
-               childTask->stack[i] = current->stack[i];
 
-       //uint32_t *sp;
-       //asm("mov %0, sp" : "=r" (sp));
+       // Create child task data
+       task_t *childTask = (task_t *)malloc(sizeof(task_t));
+       childTask->stack = (uint32_t *)malloc(stackInfo->size - sizeof(alloc_t));
+       childTask->sleep = 0;
+       childTask->pid = task_next_pid++;
+
+       // Copy parent's stack
+       for (uint32_t i = 0; i < (stackInfo->size - sizeof(alloc_t)); i++)
+               childTask->stack[i] = task_current->stack[i];
+
        childTask->sp = (uint32_t *)((uint32_t)childTask->stack + (sp
-               - (uint32_t)current->stack));
+               - (uint32_t)task_current->stack));
+       childTask->sp[15] = (uint32_t)task_fork_ret;
+       //childTask->sp[16] = 0x01000000;
 
-       // 3. Insert child into task chain
-       childTask->next = current->next;
-       current->next = childTask;
+       //// 2. Insert child into task chain
+       childTask->next = task_queue;
+       task_queue = childTask;
 
-       // 4. Re-enable scheduler, make change happen
-       task_hold(0);
+       //// 3. Re-enable scheduler, make change happen
+       asm("cpsie i");
 
        SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
-       return 1;
+       return childTask->pid;
 }
 
 __attribute__ ((naked))
@@ -198,15 +226,21 @@ void PendSV_Handler(void)
                isb; \
                stmdb r0!, {r4-r11, r14}; \
                mov %0, r0; \
-       " : "=r" (current->sp));
+       " : "=r" (task_current->sp));
 
        // Load next task
-       prev = current;
        uint32_t ticks = millis();
        do {
-               current = current->next;
-       } while (current->sleep > ticks);
-       current->sleep = 0;
+               task_current = task_current->next;
+               if (task_current == 0)
+                       task_current = task_queue;
+       } while (task_current->sleep > ticks);
+       task_current->sleep = 0;
+
+       /*task_current = task_current->next;
+       if (task_current == 0)
+               task_current = task_queue;*/
+
 
        // Load stack pointer, return
        asm("\
@@ -214,6 +248,6 @@ void PendSV_Handler(void)
                ldmia r0!, {r4-r11, r14}; \
                msr psp, r0; \
                bx lr; \
-       " :: "r" (current->sp));
+       " :: "r" (task_current->sp));
 }
 
index 472e909e5d89992f8ca559842b7b143aef7468c2..0e2e07a989ab62498f6afbf3ac8703d3776ecbf3 100644 (file)
 /**
  * A structure to contain task data.
  */
-typedef struct {
-       void *next;      /**< pointer to the next task_t instance */
-       uint32_t *stack; /**< pointer to the task's stack */
-       uint32_t *sp;    /**< pointer to the task's last sp register value */
-       uint32_t sleep;  /**< number of milliseconds task is sleeping for */
+typedef struct task_t {
+       struct task_t *next; /**< pointer to the next task_t instance */
+       uint32_t *sp;        /**< pointer to the task's last sp register value */
+       uint32_t *stack;     /**< pointer to the task's stack */
+       uint32_t sleep;      /**< number of milliseconds task is sleeping for */
+       uint32_t pid;
 } task_t;
 
 /**
@@ -61,4 +62,8 @@ void task_hold(uint8_t hold);
  */
 void _exit(int code);
 
+void task_sleep(uint32_t ms);
+
+uint32_t task_getpid(void);
+
 #endif // TASK_H_
index 7a55678fc9202a4b493e5a02a3152e2d7bb8b220..87f4b49b594cc09277c5e2cf80512417d4880075 100644 (file)
@@ -17,7 +17,6 @@ int fork(void)
 {
        int result;
        asm("\
-               mov r0, sp; \
                svc 3; \
                mov %0, r0; \
        " : "=r" (result));
@@ -31,14 +30,14 @@ void user_main(void)
        if (fork() == 0) {
                while (1) {
                        gpio(GPIO_OUT, 5, 1);
-                       user_delay(1000);
+                       user_delay(2000);
                }
        } else {
                while (1) {
+                       user_delay(1000);
                        gpio(GPIO_OUT, 5, 0);
-                       user_delay(500);
+                       user_delay(1000);
                }
-       
        }
 }