aboutsummaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorAlex Auvolat <alex.auvolat@ens.fr>2015-03-02 23:30:16 +0100
committerAlex Auvolat <alex.auvolat@ens.fr>2015-03-03 00:07:27 +0100
commitbb1a5fc74769301c0a792cb83d3fa0bda8a780cb (patch)
tree14b406cc83798524e12d24ab211c4580d1c52f1f /src/kernel
parent0d47724c5f6201fdc7679327ad4a132c708b8042 (diff)
downloadkogata-bb1a5fc74769301c0a792cb83d3fa0bda8a780cb.tar.gz
kogata-bb1a5fc74769301c0a792cb83d3fa0bda8a780cb.zip
Add prototypes for process management...
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/include/process.h31
-rw-r--r--src/kernel/include/thread.h5
-rw-r--r--src/kernel/user/process.c39
-rw-r--r--src/kernel/user/syscall.c5
4 files changed, 64 insertions, 16 deletions
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 <mmap.h>
+#include <proc.h> // 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) {