From bb1a5fc74769301c0a792cb83d3fa0bda8a780cb Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Mon, 2 Mar 2015 23:30:16 +0100 Subject: Add prototypes for process management... --- src/kernel/include/process.h | 31 +++++++++++++++++++++++++++---- src/kernel/include/thread.h | 5 +++-- src/kernel/user/process.c | 39 ++++++++++++++++++++++++++++++++++----- src/kernel/user/syscall.c | 5 ----- 4 files changed, 64 insertions(+), 16 deletions(-) (limited to 'src/kernel') diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 6e287e1..82f1b4d 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -18,8 +18,10 @@ #include +#include // common header defining process statuses + #define USERSTACK_ADDR 0xB8000000 -#define USERSTACK_SIZE 0x00020000 // 32 KB +#define USERSTACK_SIZE 0x00020000 // 32 KB - it is allocated on demand so no worries typedef struct process process_t; @@ -46,21 +48,40 @@ typedef struct process { hashtbl_t *files; int next_fd; - thread_t *thread; + thread_t *threads; uint64_t last_ran; int pid; struct process *parent; + struct process *next_child; + struct process *children; } process_t; typedef void* proc_entry_t; +// ---- Process creation, deletion, waiting, etc. +// Simple semantics : when a process exits, all its ressources are freed immediately +// except for the process_t that remains attached to the parent process until it does +// a wait() and acknowleges the process' ending +// When a process exits, all the children are orphaned and nobody can wait on them anymore, +// which is a bad thing : a user process must always wait for all its children ! + process_t *current_process(); process_t *new_process(process_t *parent); -// void delete_process(process_t *p); // TODO define semantics for freeing stuff bool start_process(process_t *p, proc_entry_t entry); // maps a region for user stack +void process_exit(process_t *p, int status, int exit_code); // exit current process + +bool process_new_thread(process_t *p, proc_entry_t entry, void* sp); +void process_thread_exited(thread_t *t); // called by threading code when a thread exits + +process_t *process_find_child(process_t *p, int pid); +void process_get_status(process_t *p, proc_status_t *st); +void process_wait(process_t *p, proc_status_t *st, bool block); // waits for exit and frees process_t structure +void process_wait_any_child(process_t *p, bool block); + +// ---- Process FS namespace & FD set bool proc_add_fs(process_t *p, fs_t *fs, const char* name); fs_t *proc_find_fs(process_t *p, const char* name); @@ -69,12 +90,14 @@ int proc_add_fd(process_t *p, fs_handle_t *f); // on error returns 0, nonzero o fs_handle_t *proc_read_fd(process_t *p, int fd); void proc_close_fd(process_t *p, int fd); +// ---- Process virtual memory space + bool mmap(process_t *proc, void* addr, size_t size, int mode); // create empty zone bool mmap_file(process_t *proc, fs_handle_t *h, size_t offset, void* addr, size_t size, int mode); bool mchmap(process_t *proc, void* addr, int mode); bool munmap(process_t *proc, void* addr); -// for syscalls : check that process is authorized to do that +// for syscalls : check that process is authorized to read/write given addresses // (if not, process exits with a segfault) void probe_for_read(const void* addr, size_t len); void probe_for_write(const void* addr, size_t len); diff --git a/src/kernel/include/thread.h b/src/kernel/include/thread.h index 127b0d7..163045d 100644 --- a/src/kernel/include/thread.h +++ b/src/kernel/include/thread.h @@ -30,9 +30,10 @@ typedef struct thread { region_info_t *stack_region; process_t *proc; - isr_handler_t user_ex_handler; // page fault in kernel memory accessed by user code (violation) + isr_handler_t user_ex_handler; // exception in user code struct thread *next_in_queue; + struct thread *next_in_proc; } thread_t; typedef void (*entry_t)(void*); @@ -48,7 +49,7 @@ void exit(); void usleep(int usecs); bool resume_thread(thread_t *thread); -void kill_thread(thread_t *thread); +void kill_thread(thread_t *thread); // cannot be called for current thread // Kernel critical sections #define CL_EXCL 3 // No interruptions accepted, context switching not allowed diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c index 3f8da08..649c801 100644 --- a/src/kernel/user/process.c +++ b/src/kernel/user/process.c @@ -17,6 +17,11 @@ process_t *current_process() { return 0; } +typedef struct { + proc_entry_t entry; + void *sp; +} setup_data_t; + // ============================== // // CREATING AND RUNNING PROCESSES // // ============================== // @@ -39,7 +44,7 @@ process_t *new_process(process_t *parent) { proc->last_ran = 0; proc->regions = 0; - proc->thread = 0; + proc->threads = 0; proc->pid = (next_pid++); proc->parent = parent; proc->next_fd = 1; @@ -54,13 +59,17 @@ error: return 0; } -static void run_user_code(void* entry) { +static void run_user_code(void* param) { + setup_data_t *d = (setup_data_t*)param; + process_t *proc = current_thread->proc; ASSERT(proc != 0); switch_pagedir(proc->pd); - void* esp = (void*)USERSTACK_ADDR + USERSTACK_SIZE; + void* esp = d->sp; + proc_entry_t entry = d->entry; + free(d); asm volatile(" \ cli; \ @@ -86,14 +95,34 @@ bool start_process(process_t *p, void* entry) { bool stack_ok = mmap(p, (void*)USERSTACK_ADDR, USERSTACK_SIZE, MM_READ | MM_WRITE); if (!stack_ok) return false; - thread_t *th = new_thread(run_user_code, entry); - if (th == 0) { + bool ok = process_new_thread(p, entry, (void*)USERSTACK_ADDR + USERSTACK_SIZE); + if (!ok) { munmap(p, (void*)USERSTACK_ADDR); return false; } + return true; +} + +bool process_new_thread(process_t *p, proc_entry_t entry, void* sp) { + setup_data_t *d = (setup_data_t*)malloc(sizeof(setup_data_t)); + d->entry = entry; + d->sp = sp; + + thread_t *th = new_thread(run_user_code, d); + if (th == 0) { + return false; + } + th->proc = p; th->user_ex_handler = proc_user_exception; + + { int st = enter_critical(CL_NOINT); // it's a bit complicated to use mutexes on process_t (TODO: think) + + th->next_in_proc = p->threads; + p->threads = th; + + exit_critical(st); } resume_thread(th); diff --git a/src/kernel/user/syscall.c b/src/kernel/user/syscall.c index 3041c6d..009903c 100644 --- a/src/kernel/user/syscall.c +++ b/src/kernel/user/syscall.c @@ -319,10 +319,6 @@ static uint32_t proc_wait_sc(sc_args_t args) { return -1; //TODO } -static uint32_t proc_wait_any_sc(sc_args_t args) { - return -1; //TODO -} - // ====================== // // SYSCALLS SETUP ROUTINE // // ====================== // @@ -365,7 +361,6 @@ void setup_syscall_table() { sc_handlers[SC_PROC_STATUS] = proc_status_sc; sc_handlers[SC_PROC_KILL] = proc_kill_sc; sc_handlers[SC_PROC_WAIT] = proc_wait_sc; - sc_handlers[SC_PROC_WAIT_ANY] = proc_wait_any_sc; } void syscall_handler(registers_t *regs) { -- cgit v1.2.3