diff --git a/headers/process.h b/headers/process.h index 7ece0d8..b2dc0b9 100644 --- a/headers/process.h +++ b/headers/process.h @@ -1,25 +1,32 @@ #pragma once +#include "list.h" #include "signal.h" +#include "thread.h" #include extern struct pcb *current_pcb; enum owner { OWNER_KERNEL, OWNER_USER }; +typedef uint16_t pid_t; +typedef uint8_t uid_t; struct pcb { void *cr3; uint32_t *heap; - uint16_t pid; - uint8_t uid; + pid_t pid; + uid_t uid; + tid_t tid; struct signal_data signals; struct pcb *next; struct pcb *prev; - struct tcb *thread_list; + struct pcb *daddy; + struct list *children; + struct list *thread_list; }; void switch_process(struct pcb *next_pcb); -struct pcb *create_process(uint8_t uid); +struct pcb *create_process(uid_t uid); // int8_t create_kernel_process(void); void remove_process(struct pcb *pcb); diff --git a/headers/thread.h b/headers/thread.h index 8e6672f..6f12a6e 100644 --- a/headers/thread.h +++ b/headers/thread.h @@ -1,10 +1,11 @@ #pragma once -#include "process.h" - #include -#define STACK_SIZE PAGE_SIZE * 4 +#define STACK_SIZE PAGE_SIZE * 4 +#define CURRENT_TCB ((struct tcb *)current_tcb->content) + +typedef uint16_t tid_t; typedef enum { NEW, @@ -16,10 +17,9 @@ typedef enum { struct tcb { uint32_t *esp; uint32_t *esp0; - uint16_t tid; + tid_t tid; state_t state; struct pcb *process; - struct tcb *next; }; struct tcb *create_thread(struct pcb *process, void (*entry)(void)); diff --git a/libbozo/headers/list.h b/libbozo/headers/list.h index b69e9bc..0372151 100644 --- a/libbozo/headers/list.h +++ b/libbozo/headers/list.h @@ -4,3 +4,6 @@ struct list { void *content; struct list *next; }; + +struct list *lst_last(struct list *head); +void lst_add_back(struct list **head, struct list *e); diff --git a/libbozo/src/list/lst_add_back.c b/libbozo/src/list/lst_add_back.c new file mode 100644 index 0000000..d855cc4 --- /dev/null +++ b/libbozo/src/list/lst_add_back.c @@ -0,0 +1,10 @@ +#include "list.h" + +void lst_add_back(struct list **head, struct list *e) +{ + struct list *last = lst_last(*head); + if (!last) + *head = e; + else + last->next = e; +} diff --git a/libbozo/src/list/lst_last.c b/libbozo/src/list/lst_last.c new file mode 100644 index 0000000..7eccb97 --- /dev/null +++ b/libbozo/src/list/lst_last.c @@ -0,0 +1,12 @@ +#include "list.h" +#include + +struct list *lst_last(struct list *head) +{ + if (!head) + return NULL; + struct list *it = head; + while (it->next) + it = it->next; + return it; +} diff --git a/src/multitasking/fork.c b/src/multitasking/fork.c new file mode 100644 index 0000000..6a11c5b --- /dev/null +++ b/src/multitasking/fork.c @@ -0,0 +1,40 @@ +#include "alloc.h" +#include "memory.h" +#include "process.h" +#include "string.h" +#include "thread.h" + +static struct tcb *thread_clone(struct tcb *thread) +{ + struct tcb *new_tcb = vmalloc(sizeof(struct tcb)); + if (!new_tcb) + return NULL; + new_tcb->tid = thread->tid; + new_tcb->esp0 = alloc_pages(STACK_SIZE, NULL); + if (!new_tcb->esp0) { + delete_thread(new_tcb); + return NULL; + } + memcpy(new_tcb->esp0, thread->esp0, STACK_SIZE); + return new_tcb; +} + +pid_t fork(void) +{ + struct pcb *new_pcb = create_process(current_pcb->uid); + if (!new_pcb) + return -1; + struct list *new_node = vmalloc(sizeof(struct list)); + if (!new_node) { + remove_process(new_pcb); + return -1; + } + new_pcb->daddy = current_pcb; + lst_add_back(&new_pcb->children, new_node); + current_pd = new_pcb->cr3; + // loop on threads clone + thread_clone(current_pcb->thread_list->content); + current_pd = current_pcb->cr3; + + return new_pcb->pid; +} diff --git a/src/multitasking/process.c b/src/multitasking/process.c index 3d4606c..eac4a0c 100644 --- a/src/multitasking/process.c +++ b/src/multitasking/process.c @@ -6,14 +6,15 @@ #include "string.h" -struct pcb *create_process(uint8_t uid) +struct pcb *create_process(uid_t uid) { - static uint32_t pid = 1; + static pid_t pid = 1; struct pcb *new_pcb = vmalloc(sizeof(struct pcb)); if (!new_pcb) return NULL; new_pcb->uid = uid; new_pcb->pid = pid++; + new_pcb->tid = 1; new_pcb->heap = alloc_pages(4096, &new_pcb->cr3); if (!new_pcb->heap) { @@ -22,6 +23,8 @@ struct pcb *create_process(uint8_t uid) } memcpy(new_pcb->heap, current_pd, 4096); + new_pcb->daddy = NULL; + new_pcb->children = NULL; new_pcb->next = new_pcb; new_pcb->prev = new_pcb; @@ -40,7 +43,7 @@ struct pcb *create_process(uint8_t uid) return new_pcb; } -void remove_pcb(struct pcb *pcb) +void remove_process(struct pcb *pcb) { struct pcb *left = pcb->prev; struct pcb *right = pcb->next; diff --git a/src/multitasking/scheduler.c b/src/multitasking/scheduler.c index 05b3d04..86be257 100644 --- a/src/multitasking/scheduler.c +++ b/src/multitasking/scheduler.c @@ -9,18 +9,18 @@ #include struct pcb *current_pcb; -struct tcb *current_tcb; +struct list *current_tcb; -static struct tcb *get_thread_to_switch(void) +static struct list *get_thread_to_switch(void) { struct pcb *it_p; - struct tcb *it_t; + struct list *it_t; it_p = current_pcb; it_t = current_tcb == NULL ? NULL : current_tcb->next; while (it_p) { while (it_t != NULL) { - if (it_t != NULL && it_t->state != WAITING) + if (it_t != NULL && CURRENT_TCB->state != WAITING) return it_t; it_t = it_t->next; } @@ -32,13 +32,14 @@ static struct tcb *get_thread_to_switch(void) void scheduler(uint32_t *esp) { - struct tcb *thread_to_switch = get_thread_to_switch(); - if (!thread_to_switch) + struct list *list_node = get_thread_to_switch(); + if (!list_node) kpanic("No existing threads \n"); + struct tcb *thread_to_switch = (struct tcb *)list_node->content; if (current_tcb) - current_tcb->esp = esp; + CURRENT_TCB->esp = esp; if (thread_to_switch->process != current_pcb) switch_process(thread_to_switch->process); - current_tcb = thread_to_switch; + current_tcb = list_node; switch_thread(thread_to_switch->esp); } diff --git a/src/multitasking/thread.c b/src/multitasking/thread.c index f764c31..1f8d4e7 100644 --- a/src/multitasking/thread.c +++ b/src/multitasking/thread.c @@ -2,17 +2,18 @@ #include "alloc.h" #include "assert.h" #include "interrupts.h" +#include "list.h" #include "memory.h" +#include "process.h" #include "string.h" #include "thread.h" struct tcb *create_thread(struct pcb *process, void (*entry)(void)) { - static uint32_t tid = 1; struct tcb *new_tcb = vmalloc(sizeof(struct tcb)); if (!new_tcb) return NULL; - new_tcb->tid = tid++; + new_tcb->tid = process->tid++; new_tcb->esp0 = alloc_pages(STACK_SIZE, NULL); if (!new_tcb->esp0) { @@ -40,18 +41,26 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void)) *(--stack) = 0; // ESI *(--stack) = 0; // EDI *(--stack) = 0x10; // kernel DS + new_tcb->esp = stack; new_tcb->process = process; - new_tcb->next = NULL; new_tcb->state = NEW; + struct list *new_node = vmalloc(sizeof(struct list)); + if (!new_node) { + free_pages(new_tcb->esp0, STACK_SIZE); + vfree(new_tcb); + return NULL; + } + new_node->content = new_tcb; + new_node->next = NULL; if (process->thread_list == NULL) { - process->thread_list = new_tcb; + process->thread_list = new_node; } else { - struct tcb *it = process->thread_list; + struct list *it = process->thread_list; while (it->next) it = it->next; - it->next = new_tcb; + it->next = new_node; } return new_tcb; @@ -60,10 +69,12 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void)) void delete_thread(struct tcb *thread) { vfree(thread->esp0); - struct tcb *it = thread->process->thread_list; + struct list *it = thread->process->thread_list; assert(it); - while (it->next != thread) + while (it->next && it->next->content != thread) it = it->next; + struct list *to_free = it; it->next = it->next->next; + vfree(to_free); vfree(thread); }