aboutsummaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/core/paging.c5
-rw-r--r--src/kernel/core/sys.c3
-rw-r--r--src/kernel/core/thread.c26
-rw-r--r--src/kernel/include/vfs.h3
-rw-r--r--src/kernel/user/ipc.c7
-rw-r--r--src/kernel/user/process.c66
-rw-r--r--src/kernel/user/syscall.c2
-rw-r--r--src/kernel/user/vfs.c34
8 files changed, 104 insertions, 42 deletions
diff --git a/src/kernel/core/paging.c b/src/kernel/core/paging.c
index f7ebf9c..6233443 100644
--- a/src/kernel/core/paging.c
+++ b/src/kernel/core/paging.c
@@ -58,9 +58,10 @@ void page_fault_handler(registers_t *regs) {
current_thread->user_ex_handler(regs);
} else {
if (pd->user_pfh == 0) {
- dbg_printf("Error: usermode page fault on PD with no user PFH.\n");
+ dbg_printf("Error: usermode page fault (0x%p) on PD with no user PFH.\n", vaddr);
dbg_printf("PD: 0x%p, kernel PD: 0x%p\n", get_current_pagedir(), get_kernel_pagedir());
- PANIC("Un-handlable usermode PF.\n");
+ dbg_dump_registers(regs);
+ PANIC("Un-handlable usermode PF.");
}
ASSERT(pd->user_pfh != 0);
pd->user_pfh(pd->user_pfh_data, regs, vaddr);
diff --git a/src/kernel/core/sys.c b/src/kernel/core/sys.c
index 290fdfa..333cb58 100644
--- a/src/kernel/core/sys.c
+++ b/src/kernel/core/sys.c
@@ -71,7 +71,7 @@ void load_kernel_symbol_map(char* text, size_t len) {
void kernel_stacktrace(uint32_t ebp, uint32_t eip) {
int i = 0;
- while (ebp >= K_HIGHHALF_ADDR && eip >= K_HIGHHALF_ADDR) {
+ while (ebp >= K_HIGHHALF_ADDR) {
char* sym = 0;
if (kernel_symbol_map != 0) sym = btree_lower(kernel_symbol_map, (void*)eip);
@@ -84,6 +84,7 @@ void kernel_stacktrace(uint32_t ebp, uint32_t eip) {
dbg_printf("| ...");
break;
}
+ if (eip == 0) break;
}
}
diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c
index 53b3e70..c4d4f93 100644
--- a/src/kernel/core/thread.c
+++ b/src/kernel/core/thread.c
@@ -120,7 +120,7 @@ void run_scheduler() {
// At this point, interrupts are disabled
// This function is expected NEVER TO RETURN
- /*thread_t *prev_thread = current_thread;*/
+ thread_t *prev_thread = current_thread;
if (current_thread != 0 && current_thread->state == T_STATE_RUNNING) {
current_thread->last_ran = get_kernel_time();
@@ -129,7 +129,7 @@ void run_scheduler() {
}
current_thread = dequeue_thread();
- /*if (current_thread != prev_thread) dbg_printf("[0x%p]\n", current_thread);*/
+ if (current_thread != prev_thread) dbg_printf("[0x%p]\n", current_thread);
if (current_thread != 0) {
thread_t *ptr = current_thread;
@@ -345,19 +345,19 @@ void usleep(int usecs) {
if (ok) wait_on(current_thread);
}
-void exit() {
- void exit_cleanup_task(void* v) {
- thread_t *t = (thread_t*)v;
-
- if (t->proc == 0) {
- // stand alone thread, can be deleted safely
- delete_thread(t);
- } else {
- // call specific routine from process code
- process_thread_exited(t);
- }
+void exit_cleanup_task(void* v) {
+ thread_t *t = (thread_t*)v;
+
+ if (t->proc == 0) {
+ // stand alone thread, can be deleted safely
+ delete_thread(t);
+ } else {
+ // call specific routine from process code
+ process_thread_exited(t);
}
+}
+void exit() {
int st = enter_critical(CL_NOSWITCH);
// the critical section here does not guarantee that worker_push will return immediately
// (it may switch before adding the delete_thread task), but once the task is added
diff --git a/src/kernel/include/vfs.h b/src/kernel/include/vfs.h
index 226f962..8f09d7f 100644
--- a/src/kernel/include/vfs.h
+++ b/src/kernel/include/vfs.h
@@ -55,6 +55,7 @@ typedef struct fs_handle {
struct fs_node *node;
int refs;
+ mutex_t lock;
int mode;
@@ -125,6 +126,8 @@ typedef struct {
typedef struct fs {
// Filled by VFS's make_fs()
int refs;
+ mutex_t lock;
+
struct fs *from_fs;
int ok_modes;
// Filled by FS's specific make() - all zero in the case of a subfs
diff --git a/src/kernel/user/ipc.c b/src/kernel/user/ipc.c
index 7f34fdf..308a9c1 100644
--- a/src/kernel/user/ipc.c
+++ b/src/kernel/user/ipc.c
@@ -83,6 +83,10 @@ fs_handle_pair_t make_channel(bool blocking) {
ret.b->node = nb;
ret.a->refs = ret.b->refs = 1;
ret.a->mode = ret.b->mode = FM_READ | FM_WRITE | (blocking ? FM_BLOCKING : 0);
+ ret.a->lock = ret.b->lock = MUTEX_UNLOCKED;
+
+ dbg_printf("hREF1c0x%p\n", ret.a);
+ dbg_printf("hREF1c0x%p\n", ret.b);
return ret;
@@ -274,8 +278,11 @@ fs_handle_t* make_shm(size_t size) {
h->fs = 0;
h->node = n;
h->refs = 1;
+ h->lock = MUTEX_UNLOCKED;
h->mode = FM_READ | FM_WRITE | FM_MMAP;
+ dbg_printf("hREF1s0x%p\n", h);
+
return h;
error:
diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c
index 2a4d98f..f56998e 100644
--- a/src/kernel/user/process.c
+++ b/src/kernel/user/process.c
@@ -9,6 +9,8 @@
static int next_pid = 1;
+void munmap_inner(process_t *proc, user_region_t *r);
+
void proc_user_exception(registers_t *regs);
void proc_usermem_pf(void* proc, registers_t *regs, void* addr);
@@ -154,20 +156,21 @@ bool start_process(process_t *p, void* entry) {
return true;
}
-void current_process_exit(int status, int exit_code) {
- void process_exit_v(void* args) {
- exit_data_t *d = (exit_data_t*)args;
- process_exit(d->proc, d->status, d->exit_code);
- free(d);
- }
+void current_process_exit_task(void* args) {
+ exit_data_t *d = (exit_data_t*)args;
+ process_exit(d->proc, d->status, d->exit_code);
+ free(d);
+}
- exit_data_t *d = (exit_data_t*)malloc(sizeof(exit_data_t));
+void current_process_exit(int status, int exit_code) {
+ exit_data_t *d;
+ while ((d = (exit_data_t*)malloc(sizeof(exit_data_t))) == 0) yield();
d->proc = current_process();;
d->status = status;
d->exit_code = exit_code;
- while (!worker_push(process_exit_v, d)) yield();
+ while (!worker_push(current_process_exit_task, d)) yield();
exit();
}
@@ -207,8 +210,9 @@ void process_exit(process_t *p, int status, int exit_code) {
process_t *ch = p->children;
p->children = ch->next_child;
- if (ch->status == PS_RUNNING || ch->status == PS_LOADING)
+ if (ch->status == PS_RUNNING || ch->status == PS_LOADING) {
process_exit(ch, PS_KILLED, 0);
+ }
free(ch);
}
@@ -222,7 +226,7 @@ void process_exit(process_t *p, int status, int exit_code) {
// unmap memory
while (p->regions != 0) {
- munmap(p, p->regions->addr);
+ munmap_inner(p, p->regions);
}
ASSERT(btree_count(p->regions_idx) == 0);
delete_btree(p->regions_idx);
@@ -441,6 +445,7 @@ bool proc_add_fs(process_t *p, fs_t *fs, const char* name) {
mutex_lock(&p->lock);
+ if (p->filesystems == 0) goto end;
if (hashtbl_find(p->filesystems, n) != 0) goto end;
add_ok = hashtbl_add(p->filesystems, n, fs);
@@ -458,7 +463,7 @@ end:
fs_t *proc_find_fs(process_t *p, const char* name) {
mutex_lock(&p->lock);
- fs_t *ret = (fs_t*)hashtbl_find(p->filesystems, name);
+ fs_t *ret = (p->filesystems != 0 ? (fs_t*)hashtbl_find(p->filesystems, name) : 0);
mutex_unlock(&p->lock);
return ret;
@@ -477,11 +482,10 @@ void proc_rm_fs(process_t *p, const char* name) {
}
int proc_add_fd(process_t *p, fs_handle_t *f) {
- int fd = p->next_fd++;
-
mutex_lock(&p->lock);
- bool add_ok = hashtbl_add(p->files, (void*)fd, f);
+ int fd = p->next_fd++;
+ bool add_ok = (p->files != 0 ? hashtbl_add(p->files, (void*)fd, f) : false);
mutex_unlock(&p->lock);
@@ -497,6 +501,7 @@ bool proc_add_fd_as(process_t *p, fs_handle_t *f, int fd) {
mutex_lock(&p->lock);
+ if (p->files == 0) goto end;
if (hashtbl_find(p->files, (void*)fd) != 0) goto end;
if (fd >= p->next_fd) p->next_fd = fd + 1;
@@ -511,7 +516,7 @@ end:
fs_handle_t *proc_read_fd(process_t *p, int fd) {
mutex_lock(&p->lock);
- fs_handle_t *ret = (fs_handle_t*)hashtbl_find(p->files, (void*)fd);
+ fs_handle_t *ret = (p->files != 0 ? (fs_handle_t*)hashtbl_find(p->files, (void*)fd) : 0);
mutex_unlock(&p->lock);
return ret;
@@ -520,7 +525,7 @@ fs_handle_t *proc_read_fd(process_t *p, int fd) {
void proc_close_fd(process_t *p, int fd) {
mutex_lock(&p->lock);
- fs_handle_t *x = (fs_handle_t*)hashtbl_find(p->files, (void*)fd);
+ fs_handle_t *x = (p->files != 0 ? (fs_handle_t*)hashtbl_find(p->files, (void*)fd) : 0);
if (x != 0) {
unref_file(x);
hashtbl_remove(p->files, (void*)fd);
@@ -536,7 +541,7 @@ void proc_close_fd(process_t *p, int fd) {
user_region_t *find_user_region(process_t *proc, const void* addr) {
mutex_lock(&proc->lock);
- user_region_t *r = (user_region_t*)btree_lower(proc->regions_idx, addr);
+ user_region_t *r = (proc->regions_idx != 0 ? (user_region_t*)btree_lower(proc->regions_idx, addr) : 0);
if (r != 0) {
ASSERT(addr >= r->addr);
@@ -561,6 +566,8 @@ bool mmap(process_t *proc, void* addr, size_t size, int mode) {
mutex_lock(&proc->lock);
+ if (proc->regions_idx == 0) goto error;
+
r->proc = proc;
r->addr = addr;
r->size = size;
@@ -592,6 +599,7 @@ error:
}
bool mmap_file(process_t *proc, fs_handle_t *h, size_t offset, void* addr, size_t size, int mode) {
+ dbg_printf("Mmap file 0x%p\n", h);
if (find_user_region(proc, addr) != 0) return false;
if ((uint32_t)addr & (~PAGE_MASK)) return false;
@@ -611,6 +619,8 @@ bool mmap_file(process_t *proc, fs_handle_t *h, size_t offset, void* addr, size_
mutex_lock(&proc->lock);
+ if (proc->regions_idx == 0) goto error;
+
r->addr = addr;
r->size = size;
@@ -673,12 +683,9 @@ bool mchmap(process_t *proc, void* addr, int mode) {
return true;
}
-bool munmap(process_t *proc, void* addr) {
- user_region_t *r = find_user_region(proc, addr);
- if (r == 0) return false;
-
- mutex_lock(&proc->lock);
-
+void munmap_inner(process_t *proc, user_region_t *r) {
+ // assume theprocess lock is locked
+ // will always succeed
if (proc->regions == r) {
proc->regions = r->next_in_proc;
} else {
@@ -707,14 +714,23 @@ bool munmap(process_t *proc, void* addr) {
}
switch_pagedir(save_pd);
- mutex_unlock(&proc->lock);
-
pager_rm_map(r->pager, r);
if (r->file != 0) unref_file(r->file);
if (r->own_pager) delete_pager(r->pager);
free(r);
+}
+
+bool munmap(process_t *proc, void* addr) {
+ user_region_t *r = find_user_region(proc, addr);
+ if (r == 0) return false;
+
+ mutex_lock(&proc->lock);
+
+ munmap_inner(proc, r);
+
+ mutex_unlock(&proc->lock);
return true;
}
diff --git a/src/kernel/user/syscall.c b/src/kernel/user/syscall.c
index 350262c..42b06eb 100644
--- a/src/kernel/user/syscall.c
+++ b/src/kernel/user/syscall.c
@@ -307,7 +307,7 @@ uint32_t select_sc(sc_args_t args) {
uint64_t select_begin_time = get_kernel_time();
void** wait_objs = (void**)malloc((n+1) * sizeof(void*));
- if (!wait_objs) return false;
+ if (wait_objs == 0) return false;
bool ret = false;
diff --git a/src/kernel/user/vfs.c b/src/kernel/user/vfs.c
index a967f70..db01888 100644
--- a/src/kernel/user/vfs.c
+++ b/src/kernel/user/vfs.c
@@ -42,6 +42,7 @@ fs_t *make_fs(const char* drv_name, fs_handle_t *source, const char* opts) {
if (fs->root == 0) goto fail;
fs->refs = 1;
+ fs->lock = MUTEX_UNLOCKED;
fs->from_fs = 0;
fs->ok_modes = FM_ALL_MODES;
fs->root->refs = 1;
@@ -49,6 +50,8 @@ fs_t *make_fs(const char* drv_name, fs_handle_t *source, const char* opts) {
fs->root->parent = 0;
fs->root->children = 0;
+ dbg_printf("sREF1m0x%p\n", fs);
+
// Look for driver
for(fs_driver_t *i = drivers; i != 0; i = i->next) {
if ((drv_name != 0 && strcmp(i->name, drv_name) == 0) || (drv_name == 0 && source != 0)) {
@@ -75,6 +78,8 @@ fs_t *fs_subfs(fs_t *fs, const char* root, int ok_modes) {
if (subfs == 0) return 0;
subfs->refs = 1;
+ subfs->lock = MUTEX_UNLOCKED;
+
subfs->from_fs = fs;
subfs->ok_modes = ok_modes & fs->ok_modes;
@@ -83,6 +88,8 @@ fs_t *fs_subfs(fs_t *fs, const char* root, int ok_modes) {
subfs->root = new_root;
+ dbg_printf("sREF1s0x%p\n", fs);
+
return subfs;
}
@@ -91,10 +98,20 @@ bool fs_add_source(fs_t *fs, fs_handle_t *source, const char* opts) {
}
void ref_fs(fs_t *fs) {
+ dbg_printf("sREF++0x%p(%d)\n", fs, fs->refs);
+
+ mutex_lock(&fs->lock);
+
fs->refs++;
+
+ mutex_unlock(&fs->lock);
}
void unref_fs(fs_t *fs) {
+ dbg_printf("sREF--0x%p(%d)\n", fs, fs->refs);
+
+ mutex_lock(&fs->lock);
+
fs->refs--;
if (fs->refs == 0) {
if (fs->from_fs != 0) {
@@ -105,6 +122,8 @@ void unref_fs(fs_t *fs) {
}
if (fs->ops->shutdown) fs->ops->shutdown(fs->data);
free(fs);
+ } else {
+ mutex_unlock(&fs->lock);
}
}
@@ -432,10 +451,13 @@ fs_handle_t* fs_open(fs_t *fs, const char* file, int mode) {
if (!open_ok) goto error;
h->refs = 1;
+ h->lock = MUTEX_UNLOCKED;
h->fs = fs;
h->node = n;
h->mode = mode;
+ dbg_printf("hREF1o0x%p\n", h);
+
// our reference to node n is transferred to the file handle
mutex_unlock(&n->lock);
ref_fs(fs);
@@ -449,16 +471,28 @@ error:
}
void ref_file(fs_handle_t *file) {
+ dbg_printf("hREF++0x%p(%d)\n", file, file->refs);
+
+ mutex_lock(&file->lock);
+
file->refs++;
+
+ mutex_unlock(&file->lock);
}
void unref_file(fs_handle_t *file) {
+ dbg_printf("hREF--0x%p(%d)\n", file, file->refs);
+
+ mutex_lock(&file->lock);
+
file->refs--;
if (file->refs == 0) {
if (file->node->ops->close) file->node->ops->close(file);
unref_fs_node(file->node);
if (file->fs) unref_fs(file->fs);
free(file);
+ } else {
+ mutex_unlock(&file->lock);
}
}