From 512356ac2de7dbf7ebdffcd61d7bf5955e8787de Mon Sep 17 00:00:00 2001 From: Max Wash Date: Wed, 1 Apr 2026 18:17:05 +0100 Subject: [PATCH] sched: enforce ref-counting on current task/thread pointers --- arch/x86_64/panic.c | 6 +++-- arch/x86_64/pmap.c | 12 ++++----- arch/x86_64/thread.c | 19 +++++++++----- include/kernel/sched.h | 6 +++-- init/main.c | 4 +-- kernel/channel.c | 10 +++++--- kernel/futex.c | 26 ++++++++++++++++--- kernel/object.c | 3 ++- kernel/panic.c | 7 ++++-- kernel/port.c | 16 +++++++++--- sched/core.c | 6 +++-- sched/task.c | 24 ++++++++++++++---- sched/thread.c | 18 ++++++++++--- sched/timer.c | 3 ++- sched/wait.c | 14 +++++++++-- syscall/address-space.c | 38 +++++++++++++++++++++++----- syscall/config.c | 15 +++++++---- syscall/futex.c | 8 ++++-- syscall/handle.c | 15 ++++++++--- syscall/log.c | 6 +++-- syscall/msg.c | 56 ++++++++++++++++++++++++++++++++++------- syscall/object.c | 14 ++++++++--- syscall/task.c | 55 ++++++++++++++++++++++++++++++++-------- syscall/vm-controller.c | 38 +++++++++++++++++++++++----- syscall/vm-object.c | 31 ++++++++++++++++++----- vm/address-space.c | 8 +++--- vm/vm-controller.c | 6 +++-- vm/vm-object.c | 3 ++- 28 files changed, 364 insertions(+), 103 deletions(-) diff --git a/arch/x86_64/panic.c b/arch/x86_64/panic.c index a3f24c3..15b9e2a 100644 --- a/arch/x86_64/panic.c +++ b/arch/x86_64/panic.c @@ -217,16 +217,18 @@ static void print_stack_trace( void ml_print_stack_trace(uintptr_t ip) { - struct task *task = current_task(); + struct task *task = get_current_task(); struct address_space *space = task ? task->t_address_space : NULL; uintptr_t bp; asm volatile("mov %%rbp, %0" : "=r"(bp)); print_stack_trace(space, ip, bp); + put_current_task(task); } void ml_print_stack_trace_irq(struct ml_cpu_context *ctx) { - struct task *task = current_task(); + struct task *task = get_current_task(); struct address_space *space = task ? task->t_address_space : NULL; print_stack_trace(space, ctx->rip, ctx->rbp); + put_current_task(task); } diff --git a/arch/x86_64/pmap.c b/arch/x86_64/pmap.c index d1fbe02..5ba7fbd 100644 --- a/arch/x86_64/pmap.c +++ b/arch/x86_64/pmap.c @@ -496,11 +496,7 @@ kern_status_t pmap_handle_fault( { // log_fault(fault_addr, flags); - if (flags & PMAP_FAULT_PRESENT) { - return KERN_FATAL_ERROR; - } - - struct task *task = current_task(); + struct task *task = get_current_task(); if (!task) { return KERN_FATAL_ERROR; } @@ -511,7 +507,11 @@ kern_status_t pmap_handle_fault( } /* this must be called with `space` unlocked. */ - return address_space_demand_map(space, fault_addr, flags); + kern_status_t status + = address_space_demand_map(space, fault_addr, flags); + + put_current_task(task); + return status; } kern_status_t pmap_add( diff --git a/arch/x86_64/thread.c b/arch/x86_64/thread.c index 952f8d2..51a3824 100644 --- a/arch/x86_64/thread.c +++ b/arch/x86_64/thread.c @@ -95,25 +95,30 @@ kern_status_t ml_thread_config_set( const void *ptr, size_t len) { + struct thread *self = get_current_thread(); + kern_status_t status = KERN_OK; + switch (key) { case THREAD_CFG_FSBASE: if (len != sizeof(thread->tr_ml.tr_fsbase)) { - return KERN_INVALID_ARGUMENT; + status = KERN_INVALID_ARGUMENT; + break; } thread->tr_ml.tr_fsbase = *(virt_addr_t *)ptr; - if (thread == current_thread()) { + if (thread == self) { wrmsr(MSR_FS_BASE, thread->tr_ml.tr_fsbase); } break; case THREAD_CFG_GSBASE: if (len != sizeof(thread->tr_ml.tr_gsbase)) { - return KERN_INVALID_ARGUMENT; + status = KERN_INVALID_ARGUMENT; + break; } thread->tr_ml.tr_gsbase = *(virt_addr_t *)ptr; - if (thread == current_thread()) { + if (thread == self) { /* we're in the kernel right now, so the user and kernel * gs-base registers are swapped. when we return to * usermode, this value will be swapped back into @@ -123,8 +128,10 @@ kern_status_t ml_thread_config_set( break; default: - return KERN_INVALID_ARGUMENT; + status = KERN_INVALID_ARGUMENT; + break; } - return KERN_OK; + put_current_thread(self); + return status; } diff --git a/include/kernel/sched.h b/include/kernel/sched.h index 47a5e22..13b576d 100644 --- a/include/kernel/sched.h +++ b/include/kernel/sched.h @@ -76,8 +76,10 @@ extern struct runqueue *cpu_rq(unsigned int cpu); extern cycles_t default_quantum(void); extern bool need_resched(void); -extern struct task *current_task(void); -extern struct thread *current_thread(void); +extern struct task *get_current_task(void); +extern struct thread *get_current_thread(void); +extern void put_current_task(struct task *task); +extern void put_current_thread(struct thread *thread); extern struct runqueue *select_rq_for_thread(struct thread *thr); extern void schedule_thread_on_cpu(struct thread *thr); diff --git a/init/main.c b/init/main.c index 8f01d80..db74020 100644 --- a/init/main.c +++ b/init/main.c @@ -44,8 +44,8 @@ static void hang(void) void background_thread(void) { - struct task *self = current_task(); - struct thread *thread = current_thread(); + struct task *self = get_current_task(); + struct thread *thread = get_current_thread(); printk("background_thread() running on processor %u", this_cpu()); milli_sleep(1000); diff --git a/kernel/channel.c b/kernel/channel.c index ff4828d..aee168a 100644 --- a/kernel/channel.c +++ b/kernel/channel.c @@ -139,7 +139,6 @@ extern kern_status_t channel_recv_msg( kern_msg_t *out_msg, unsigned long *irq_flags) { - struct thread *self = current_thread(); struct msg *msg = NULL; unsigned long msg_lock_flags; @@ -170,7 +169,7 @@ extern kern_status_t channel_recv_msg( } struct task *sender = msg->msg_sender_thread->tr_parent; - struct task *receiver = self->tr_parent; + struct task *receiver = get_current_task(); struct address_space *src = sender->t_address_space, *dst = receiver->t_address_space; @@ -192,6 +191,7 @@ extern kern_status_t channel_recv_msg( if (status != KERN_OK) { kmsg_reply_error(msg, status, &msg_lock_flags); + put_current_task(receiver); return status; } @@ -216,6 +216,7 @@ extern kern_status_t channel_recv_msg( &receiver->t_handles_lock, f); address_space_unlock_pair_irqrestore(src, dst, f); + put_current_task(receiver); if (status != KERN_OK) { kmsg_reply_error(msg, status, &msg_lock_flags); @@ -250,11 +251,10 @@ extern kern_status_t channel_reply_msg( return KERN_INVALID_ARGUMENT; } - struct thread *self = current_thread(); /* the task that is about to receive the response */ struct task *receiver = msg->msg_sender_thread->tr_parent; /* the task that is about to send the response */ - struct task *sender = self->tr_parent; + struct task *sender = get_current_task(); struct address_space *src = sender->t_address_space, *dst = receiver->t_address_space; @@ -275,6 +275,7 @@ extern kern_status_t channel_reply_msg( if (status != KERN_OK) { kmsg_reply_error(msg, status, &msg_lock_flags); + put_current_task(sender); return status; } @@ -299,6 +300,7 @@ extern kern_status_t channel_reply_msg( &receiver->t_handles_lock, f); address_space_unlock_pair_irqrestore(src, dst, f); + put_current_task(sender); if (status != KERN_OK) { kmsg_reply_error(msg, status, &msg_lock_flags); diff --git a/kernel/futex.c b/kernel/futex.c index 7122ff9..41c408d 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -32,8 +32,10 @@ static kern_status_t get_data( { spin_lock_t *lock = NULL; struct btree *futex_list = NULL; + struct task *self = NULL; + if (flags & FUTEX_PRIVATE) { - struct task *self = current_task(); + self = get_current_task(); lock = &self->t_base.ob_lock; futex_list = &self->t_futex; } else if (flags & FUTEX_SHARED) { @@ -48,12 +50,20 @@ static kern_status_t get_data( if (!futex && !(flags & FUTEX_CREATE)) { spin_unlock_irqrestore(lock, *irq_flags); + if (self) { + put_current_task(self); + } + return KERN_NO_ENTRY; } futex = vm_cache_alloc(&futex_cache, VM_NORMAL); if (!futex) { spin_unlock_irqrestore(lock, *irq_flags); + if (self) { + put_current_task(self); + } + return KERN_NO_MEMORY; } @@ -61,6 +71,10 @@ static kern_status_t get_data( put_futex(futex_list, futex); + if (self) { + put_current_task(self); + } + *out = futex; *out_lock = lock; return KERN_OK; @@ -68,9 +82,10 @@ static kern_status_t get_data( static kern_status_t cleanup_data(struct futex *futex, unsigned int flags) { + struct task *self = NULL; struct btree *futex_list = NULL; if (flags & FUTEX_PRIVATE) { - struct task *self = current_task(); + self = get_current_task(); futex_list = &self->t_futex; } else if (flags & FUTEX_SHARED) { futex_list = &shared_futex_list; @@ -81,12 +96,16 @@ static kern_status_t cleanup_data(struct futex *futex, unsigned int flags) btree_delete(futex_list, &futex->f_node); vm_cache_free(&futex_cache, futex); + if (self) { + put_current_task(self); + } + return KERN_OK; } static kern_status_t futex_get_shared(kern_futex_t *futex, futex_key_t *out) { - struct task *self = current_task(); + struct task *self = get_current_task(); struct address_space *space = self->t_address_space; unsigned long flags; @@ -97,6 +116,7 @@ static kern_status_t futex_get_shared(kern_futex_t *futex, futex_key_t *out) out, &flags); address_space_unlock_irqrestore(space, flags); + put_current_task(self); return status; } diff --git a/kernel/object.c b/kernel/object.c index 58cff40..74d4609 100644 --- a/kernel/object.c +++ b/kernel/object.c @@ -175,7 +175,7 @@ void object_wait_signal( uint32_t signals, unsigned long *irq_flags) { - struct thread *self = current_thread(); + struct thread *self = get_current_thread(); struct wait_item waiter; wait_item_init(&waiter, self); for (;;) { @@ -189,4 +189,5 @@ void object_wait_signal( object_lock_irqsave(obj, irq_flags); } thread_wait_end(&waiter, &obj->ob_wq); + put_current_thread(self); } diff --git a/kernel/panic.c b/kernel/panic.c index 9dc9a8c..78f83f0 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -19,8 +19,8 @@ void panic_irq(struct ml_cpu_context *ctx, const char *fmt, ...) printk("---[ kernel panic: %s", buf); printk("kernel: " BUILD_ID ", compiler version: " __VERSION__); - struct task *task = current_task(); - struct thread *thr = current_thread(); + struct task *task = get_current_task(); + struct thread *thr = get_current_thread(); if (task && thr) { printk("task: %s (id: %d, thread: %d)", @@ -31,6 +31,9 @@ void panic_irq(struct ml_cpu_context *ctx, const char *fmt, ...) printk("task: [bootstrap]"); } + put_current_thread(thr); + put_current_task(task); + printk("cpu: %u", this_cpu()); ml_print_cpu_state(ctx); diff --git a/kernel/port.c b/kernel/port.c index f633f2c..058b818 100644 --- a/kernel/port.c +++ b/kernel/port.c @@ -37,7 +37,7 @@ struct port *port_cast(struct object *obj) static void wait_for_reply(struct msg *msg, unsigned long *lock_flags) { struct wait_item waiter; - struct thread *self = current_thread(); + struct thread *self = get_current_thread(); wait_item_init(&waiter, self); for (;;) { @@ -52,6 +52,7 @@ static void wait_for_reply(struct msg *msg, unsigned long *lock_flags) } self->tr_state = THREAD_READY; + put_current_thread(self); } struct port *port_create(void) @@ -83,9 +84,12 @@ kern_status_t port_connect(struct port *port, struct channel *remote) msg->msg_status = KMSG_ASYNC; msg->msg_type = KERN_MSG_TYPE_EVENT; msg->msg_event = KERN_MSG_EVENT_CONNECTION; - msg->msg_sender_thread_id = current_thread()->tr_id; msg->msg_sender_port_id = port->p_base.ob_id; + struct thread *self = get_current_thread(); + msg->msg_sender_thread_id = self->tr_id; + put_current_thread(self); + unsigned long flags; channel_lock_irqsave(remote, &flags); channel_enqueue_msg(remote, msg); @@ -112,9 +116,12 @@ kern_status_t port_disconnect(struct port *port) msg->msg_status = KMSG_ASYNC; msg->msg_type = KERN_MSG_TYPE_EVENT; msg->msg_event = KERN_MSG_EVENT_DISCONNECTION; - msg->msg_sender_thread_id = current_thread()->tr_id; msg->msg_sender_port_id = port->p_base.ob_id; + struct thread *self = get_current_thread(); + msg->msg_sender_thread_id = self->tr_id; + put_current_thread(self); + unsigned long flags; channel_lock_irqsave(port->p_remote, &flags); channel_enqueue_msg(port->p_remote, msg); @@ -136,7 +143,7 @@ kern_status_t port_send_msg( return KERN_BAD_STATE; } - struct thread *self = current_thread(); + struct thread *self = get_current_thread(); struct msg msg; memset(&msg, 0x0, sizeof msg); msg.msg_type = KERN_MSG_TYPE_DATA; @@ -156,6 +163,7 @@ kern_status_t port_send_msg( channel_lock_irqsave(port->p_remote, &flags); btree_delete(&port->p_remote->c_msg, &msg.msg_node); channel_unlock_irqrestore(port->p_remote, flags); + put_current_thread(self); return msg.msg_result; } diff --git a/sched/core.c b/sched/core.c index 277b826..ce5b3aa 100644 --- a/sched/core.c +++ b/sched/core.c @@ -215,18 +215,19 @@ void schedule_thread_on_cpu(struct thread *thr) void start_charge_period(void) { - struct thread *self = current_thread(); + struct thread *self = get_current_thread(); if (!self) { return; } self->tr_charge_period_start = get_cycles(); + put_current_thread(self); } void end_charge_period(void) { preempt_disable(); - struct thread *self = current_thread(); + struct thread *self = get_current_thread(); if (!self) { return; } @@ -244,6 +245,7 @@ void end_charge_period(void) } self->tr_charge_period_start = 0; + put_current_thread(self); // printk("%llu cycles charged to %s/%u", charge, // self->tr_parent->t_name, self->tr_parent->t_id); diff --git a/sched/task.c b/sched/task.c index f5e70c2..53c9414 100644 --- a/sched/task.c +++ b/sched/task.c @@ -282,7 +282,7 @@ struct task *task_from_tid(tid_t id) void task_exit(int status) { - struct task *self = current_task(); + struct task *self = get_current_task(); unsigned long flags; task_lock_irqsave(self, &flags); struct task *parent = self->t_parent; @@ -295,7 +295,7 @@ void task_exit(int status) task_unlock(parent); } - struct thread *cur_thread = current_thread(); + struct thread *cur_thread = get_current_thread(); self->t_state = TASK_STOPPED; cur_thread->tr_state = THREAD_STOPPED; @@ -340,6 +340,9 @@ void task_exit(int status) self->t_base.ob_refcount); spin_unlock_irqrestore(handles_lock, flags); + put_current_thread(cur_thread); + put_current_task(self); + while (1) { schedule(SCHED_NORMAL); } @@ -410,8 +413,19 @@ struct thread *task_create_thread(struct task *parent) return thread; } -struct task *current_task(void) +struct task *get_current_task(void) { - struct thread *thr = current_thread(); - return thr ? thr->tr_parent : NULL; + struct thread *thr = get_current_thread(); + if (!thr) { + return NULL; + } + + struct task *out = task_ref(thr->tr_parent); + put_current_thread(thr); + return out; +} + +void put_current_task(struct task *task) +{ + task_unref(task); } diff --git a/sched/thread.c b/sched/thread.c index ee14374..d08a8e7 100644 --- a/sched/thread.c +++ b/sched/thread.c @@ -105,7 +105,7 @@ void thread_free(struct thread *thr) { } -struct thread *current_thread(void) +struct thread *get_current_thread(void) { struct cpu_data *cpu = get_this_cpu(); if (!cpu) { @@ -113,13 +113,24 @@ struct thread *current_thread(void) } struct thread *out = cpu->c_rq.rq_cur; + object_ref(&out->tr_base); + put_cpu(cpu); return out; } +void put_current_thread(struct thread *thr) +{ + object_unref(&thr->tr_base); +} + bool need_resched(void) { - return (current_thread()->tr_flags & THREAD_F_NEED_RESCHED) != 0; + struct thread *thr = get_current_thread(); + bool result = (thr->tr_flags & THREAD_F_NEED_RESCHED) != 0; + put_current_thread(thr); + + return result; } int thread_priority(struct thread *thr) @@ -143,7 +154,7 @@ void thread_awaken(struct thread *thr) void thread_exit(void) { - struct thread *self = current_thread(); + struct thread *self = get_current_thread(); unsigned long flags; thread_lock_irqsave(self, &flags); self->tr_state = THREAD_STOPPED; @@ -153,6 +164,7 @@ void thread_exit(void) self->tr_parent->t_id, self->tr_id); thread_unlock_irqrestore(self, flags); + put_current_thread(self); while (1) { schedule(SCHED_NORMAL); diff --git a/sched/timer.c b/sched/timer.c index e865e3e..a37e4f4 100644 --- a/sched/timer.c +++ b/sched/timer.c @@ -44,7 +44,7 @@ unsigned long schedule_timeout(unsigned long ticks) { struct timer timer; - struct thread *self = current_thread(); + struct thread *self = get_current_thread(); timer.t_entry = QUEUE_ENTRY_INIT; timer.t_expiry = clock_ticks + ticks; @@ -58,6 +58,7 @@ unsigned long schedule_timeout(unsigned long ticks) schedule(SCHED_NORMAL); remove_timer(&timer); + put_current_thread(self); return 0; } diff --git a/sched/wait.c b/sched/wait.c index af025e8..563a51c 100644 --- a/sched/wait.c +++ b/sched/wait.c @@ -110,7 +110,7 @@ void wakeup_one(struct waitqueue *q) void sleep_forever(void) { - struct thread *thr = current_thread(); + struct thread *thr = get_current_thread(); struct runqueue *rq = thr->tr_rq; unsigned long flags; @@ -121,7 +121,17 @@ void sleep_forever(void) rq_unlock(rq, flags); - while (thr->tr_state == THREAD_SLEEPING) { + put_current_thread(thr); + + while (1) { + thr = get_current_thread(); + bool sleep = (thr->tr_state == THREAD_SLEEPING); + put_current_thread(thr); + + if (!sleep) { + break; + } + schedule(SCHED_NORMAL); } } diff --git a/syscall/address-space.c b/syscall/address-space.c index 190c78a..a577ae6 100644 --- a/syscall/address-space.c +++ b/syscall/address-space.c @@ -11,13 +11,15 @@ kern_status_t sys_address_space_read( size_t count, size_t *nr_read) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_w(self, dst, count)) { + put_current_task(self); return KERN_MEMORY_FAULT; } if (nr_read && !validate_access_w(self, nr_read, sizeof *nr_read)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -30,12 +32,14 @@ kern_status_t sys_address_space_read( = task_resolve_handle(self, region_handle, &obj, &handle_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } struct address_space *region = address_space_cast(obj); if (!region) { task_unlock_irqrestore(self, flags); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -52,6 +56,7 @@ kern_status_t sys_address_space_read( address_space_unlock_irqrestore(region, flags); object_unref(obj); + put_current_task(self); return status; } @@ -63,14 +68,16 @@ kern_status_t sys_address_space_write( size_t count, size_t *nr_written) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_r(self, src, count)) { + put_current_task(self); return KERN_MEMORY_FAULT; } if (nr_written && !validate_access_w(self, nr_written, sizeof *nr_written)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -83,12 +90,14 @@ kern_status_t sys_address_space_write( = task_resolve_handle(self, region_handle, &obj, &handle_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } struct address_space *region = address_space_cast(obj); if (!region) { task_unlock_irqrestore(self, flags); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -105,6 +114,7 @@ kern_status_t sys_address_space_write( address_space_unlock_irqrestore(region, flags); object_unref(obj); + put_current_task(self); return status; } @@ -118,13 +128,14 @@ kern_status_t sys_address_space_map( vm_prot_t prot, virt_addr_t *out_base_address) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (out_base_address && !validate_access_r( self, out_base_address, sizeof *out_base_address)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -141,24 +152,28 @@ kern_status_t sys_address_space_map( ®ion_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } status = task_resolve_handle(self, object_handle, &vmo_obj, &vmo_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } struct address_space *region = address_space_cast(region_obj); if (!region) { task_unlock_irqrestore(self, flags); + put_current_task(self); return KERN_INVALID_ARGUMENT; } struct vm_object *vmo = vm_object_cast(vmo_obj); if (!vmo) { task_unlock_irqrestore(self, flags); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -177,6 +192,7 @@ kern_status_t sys_address_space_map( object_unref(vmo_obj); object_unref(region_obj); + put_current_task(self); return status; } @@ -186,7 +202,7 @@ kern_status_t sys_address_space_unmap( virt_addr_t base, size_t length) { - struct task *self = current_task(); + struct task *self = get_current_task(); kern_status_t status = KERN_OK; unsigned long flags; @@ -201,12 +217,14 @@ kern_status_t sys_address_space_unmap( ®ion_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } struct address_space *region = address_space_cast(region_obj); if (!region) { task_unlock_irqrestore(self, flags); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -215,6 +233,7 @@ kern_status_t sys_address_space_unmap( status = address_space_unmap(region, base, length); object_unref(region_obj); + put_current_task(self); return status; } @@ -225,13 +244,14 @@ kern_status_t sys_address_space_reserve( size_t length, virt_addr_t *out_base_address) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (out_base_address && !validate_access_r( self, out_base_address, sizeof *out_base_address)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -248,12 +268,14 @@ kern_status_t sys_address_space_reserve( ®ion_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } struct address_space *region = address_space_cast(region_obj); if (!region) { task_unlock_irqrestore(self, flags); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -268,6 +290,7 @@ kern_status_t sys_address_space_reserve( address_space_unlock_irqrestore(region, flags); object_unref(region_obj); + put_current_task(self); return status; } @@ -277,7 +300,7 @@ kern_status_t sys_address_space_release( virt_addr_t base, size_t length) { - struct task *self = current_task(); + struct task *self = get_current_task(); kern_status_t status = KERN_OK; unsigned long flags; @@ -292,12 +315,14 @@ kern_status_t sys_address_space_release( ®ion_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } struct address_space *region = address_space_cast(region_obj); if (!region) { task_unlock_irqrestore(self, flags); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -308,6 +333,7 @@ kern_status_t sys_address_space_release( address_space_unlock_irqrestore(region, flags); object_unref(region_obj); + put_current_task(self); return status; } diff --git a/syscall/config.c b/syscall/config.c index d8e020b..5e41c84 100644 --- a/syscall/config.c +++ b/syscall/config.c @@ -3,21 +3,26 @@ kern_status_t sys_kern_config_get(kern_config_key_t key, void *ptr, size_t len) { - struct task *self = current_task(); + struct task *self = get_current_task(); + kern_status_t status = KERN_OK; switch (key) { case KERN_CFG_PAGE_SIZE: if (!validate_access_w(self, ptr, sizeof(uintptr_t))) { - return KERN_MEMORY_FAULT; + status = KERN_MEMORY_FAULT; + break; } *(uint32_t *)ptr = VM_PAGE_SIZE; - return KERN_OK; + status = KERN_OK; + break; default: - return KERN_INVALID_ARGUMENT; + status = KERN_INVALID_ARGUMENT; + break; } - return KERN_UNSUPPORTED; + put_current_task(self); + return status; } kern_status_t sys_kern_config_set( diff --git a/syscall/futex.c b/syscall/futex.c index c698b36..9008239 100644 --- a/syscall/futex.c +++ b/syscall/futex.c @@ -8,18 +8,22 @@ kern_status_t sys_futex_wait( kern_futex_t new_val, unsigned int flags) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_r(self, futex, sizeof *futex)) { + put_current_task(self); return KERN_MEMORY_FAULT; } futex_key_t key; kern_status_t status = futex_get(futex, &key, flags); if (status != KERN_OK) { + put_current_task(self); return status; } - return futex_wait(key, new_val, flags); + status = futex_wait(key, new_val, flags); + put_current_task(self); + return status; } kern_status_t sys_futex_wake( diff --git a/syscall/handle.c b/syscall/handle.c index 88ea28e..eadc631 100644 --- a/syscall/handle.c +++ b/syscall/handle.c @@ -3,9 +3,13 @@ kern_status_t sys_kern_handle_close(kern_handle_t handle) { - struct task *self = current_task(); + struct task *self = get_current_task(); - return task_close_handle(self, handle); + kern_status_t status = task_close_handle(self, handle); + + put_current_task(self); + + return status; } kern_status_t sys_kern_handle_transfer( @@ -24,10 +28,11 @@ kern_status_t sys_kern_handle_transfer( return KERN_INVALID_ARGUMENT; } - struct task *self = current_task(); + struct task *self = get_current_task(); if (out_handle && !validate_access_w(self, out_handle, sizeof *out_handle)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -120,6 +125,8 @@ kern_status_t sys_kern_handle_transfer( *out_handle = dest_handle; } + put_current_task(self); + return KERN_OK; cleanup: @@ -135,5 +142,7 @@ cleanup: object_unref(src_object); } + put_current_task(self); + return status; } diff --git a/syscall/log.c b/syscall/log.c index c7c2ab4..c6fb10b 100644 --- a/syscall/log.c +++ b/syscall/log.c @@ -6,9 +6,11 @@ kern_status_t sys_kern_log(const char *s) { #ifdef TRACE - struct task *task = current_task(); - struct thread *thread = current_thread(); + struct task *task = get_current_task(); + struct thread *thread = get_current_thread(); printk("%s[%d.%d]: %s", task->t_name, task->t_id, thread->tr_id, s); + put_current_thread(thread); + put_current_task(task); #else printk("%s", s); #endif diff --git a/syscall/msg.c b/syscall/msg.c index 4c59bfb..d820c40 100644 --- a/syscall/msg.c +++ b/syscall/msg.c @@ -7,13 +7,15 @@ kern_status_t sys_channel_create(unsigned int id, kern_handle_t *out) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_w(self, out, sizeof *out)) { + put_current_task(self); return KERN_MEMORY_FAULT; } struct channel *channel = channel_create(); if (!channel) { + put_current_task(self); return KERN_NO_MEMORY; } @@ -22,6 +24,7 @@ kern_status_t sys_channel_create(unsigned int id, kern_handle_t *out) if (task_get_channel(self, id)) { task_unlock_irqrestore(self, irq_flags); + put_current_task(self); return KERN_NAME_EXISTS; } @@ -31,11 +34,13 @@ kern_status_t sys_channel_create(unsigned int id, kern_handle_t *out) if (status != KERN_OK) { task_unlock_irqrestore(self, irq_flags); object_unref(&channel->c_base); + put_current_task(self); return status; } task_add_channel(self, channel, id); task_unlock_irqrestore(self, irq_flags); + put_current_task(self); *out = handle; return KERN_OK; @@ -43,13 +48,15 @@ kern_status_t sys_channel_create(unsigned int id, kern_handle_t *out) kern_status_t sys_port_create(kern_handle_t *out) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_w(self, out, sizeof *out)) { + put_current_task(self); return KERN_MEMORY_FAULT; } struct port *port = port_create(); if (!port) { + put_current_task(self); return KERN_NO_MEMORY; } @@ -61,6 +68,7 @@ kern_status_t sys_port_create(kern_handle_t *out) = task_open_handle(self, &port->p_base, 0, &handle); task_unlock_irqrestore(self, irq_flags); object_unref(&port->p_base); + put_current_task(self); if (status != KERN_OK) { return status; @@ -77,7 +85,7 @@ kern_status_t sys_port_connect( { unsigned long flags; - struct task *self = current_task(); + struct task *self = get_current_task(); task_lock_irqsave(self, &flags); struct object *port_obj = NULL; @@ -88,6 +96,7 @@ kern_status_t sys_port_connect( &port_obj, &port_handle_flags); if (status != KERN_OK) { + put_current_task(self); return status; } @@ -96,6 +105,7 @@ kern_status_t sys_port_connect( struct task *remote_task = task_from_tid(task_id); if (!remote_task) { + put_current_task(self); return KERN_NO_ENTRY; } @@ -104,6 +114,7 @@ kern_status_t sys_port_connect( struct channel *remote = task_get_channel(remote_task, channel_id); if (!remote) { task_unlock_irqrestore(remote_task, flags); + put_current_task(self); return KERN_NO_ENTRY; } @@ -115,6 +126,7 @@ kern_status_t sys_port_connect( port_unlock_irqrestore(port, flags); object_unref(&remote->c_base); object_unref(port_obj); + put_current_task(self); return KERN_OK; } @@ -123,7 +135,7 @@ kern_status_t sys_port_disconnect(kern_handle_t port_handle) { unsigned long flags; - struct task *self = current_task(); + struct task *self = get_current_task(); task_lock_irqsave(self, &flags); struct object *port_obj = NULL; @@ -134,6 +146,7 @@ kern_status_t sys_port_disconnect(kern_handle_t port_handle) &port_obj, &port_handle_flags); if (status != KERN_OK) { + put_current_task(self); return status; } @@ -142,6 +155,7 @@ kern_status_t sys_port_disconnect(kern_handle_t port_handle) struct port *port = port_cast(port_obj); if (!port) { object_unref(port_obj); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -149,6 +163,7 @@ kern_status_t sys_port_disconnect(kern_handle_t port_handle) port_lock_irqsave(port, &flags); status = port_disconnect(port); port_unlock_irqrestore(port, flags); + put_current_task(self); return status; } @@ -219,13 +234,15 @@ kern_status_t sys_msg_send( const kern_msg_t *msg, kern_msg_t *out_reply) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_msg(self, msg, false)) { + put_current_task(self); return KERN_MEMORY_FAULT; } if (!validate_msg(self, out_reply, true)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -243,12 +260,14 @@ kern_status_t sys_msg_send( task_unlock_irqrestore(self, flags); if (status != KERN_OK) { + put_current_task(self); return status; } struct port *port = port_cast(port_obj); if (!port) { object_unref(port_obj); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -256,15 +275,17 @@ kern_status_t sys_msg_send( status = port_send_msg(port, msg, out_reply, &flags); port_unlock_irqrestore(port, flags); object_unref(port_obj); + put_current_task(self); return status; } kern_status_t sys_msg_recv(kern_handle_t channel_handle, kern_msg_t *out_msg) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_msg(self, out_msg, true)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -280,6 +301,7 @@ kern_status_t sys_msg_recv(kern_handle_t channel_handle, kern_msg_t *out_msg) &channel_obj, &channel_handle_flags); if (status != KERN_OK) { + put_current_task(self); return status; } @@ -288,6 +310,7 @@ kern_status_t sys_msg_recv(kern_handle_t channel_handle, kern_msg_t *out_msg) struct channel *channel = channel_cast(channel_obj); if (!channel) { object_unref(channel_obj); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -295,6 +318,7 @@ kern_status_t sys_msg_recv(kern_handle_t channel_handle, kern_msg_t *out_msg) status = channel_recv_msg(channel, out_msg, &flags); channel_unlock_irqrestore(channel, flags); object_unref(channel_obj); + put_current_task(self); return status; } @@ -304,9 +328,10 @@ kern_status_t sys_msg_reply( msgid_t id, const kern_msg_t *reply) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_msg(self, reply, true)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -322,6 +347,7 @@ kern_status_t sys_msg_reply( &channel_obj, &channel_handle_flags); if (status != KERN_OK) { + put_current_task(self); return status; } @@ -330,6 +356,7 @@ kern_status_t sys_msg_reply( struct channel *channel = channel_cast(channel_obj); if (!channel) { object_unref(channel_obj); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -337,6 +364,7 @@ kern_status_t sys_msg_reply( status = channel_reply_msg(channel, id, reply, &flags); channel_unlock_irqrestore(channel, flags); object_unref(channel_obj); + put_current_task(self); return status; } @@ -349,13 +377,15 @@ kern_status_t sys_msg_read( size_t iov_count, size_t *nr_read) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (nr_read && !validate_access_w(self, nr_read, sizeof *nr_read)) { + put_current_task(self); return KERN_MEMORY_FAULT; } if (!validate_iovec(self, iov, iov_count, true)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -371,6 +401,7 @@ kern_status_t sys_msg_read( &channel_obj, &channel_handle_flags); if (status != KERN_OK) { + put_current_task(self); return status; } @@ -379,6 +410,7 @@ kern_status_t sys_msg_read( struct channel *channel = channel_cast(channel_obj); if (!channel) { object_unref(channel_obj); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -393,6 +425,7 @@ kern_status_t sys_msg_read( nr_read); channel_unlock_irqrestore(channel, flags); object_unref(channel_obj); + put_current_task(self); return status; } @@ -405,14 +438,16 @@ kern_status_t sys_msg_write( size_t iov_count, size_t *nr_written) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (nr_written && !validate_access_w(self, nr_written, sizeof *nr_written)) { + put_current_task(self); return KERN_MEMORY_FAULT; } if (!validate_iovec(self, iov, iov_count, false)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -428,6 +463,7 @@ kern_status_t sys_msg_write( &channel_obj, &channel_handle_flags); if (status != KERN_OK) { + put_current_task(self); return status; } @@ -436,6 +472,7 @@ kern_status_t sys_msg_write( struct channel *channel = channel_cast(channel_obj); if (!channel) { object_unref(channel_obj); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -450,6 +487,7 @@ kern_status_t sys_msg_write( nr_written); channel_unlock_irqrestore(channel, flags); object_unref(channel_obj); + put_current_task(self); return status; } diff --git a/syscall/object.c b/syscall/object.c index 0d3ffc1..a9e1e80 100644 --- a/syscall/object.c +++ b/syscall/object.c @@ -13,12 +13,13 @@ kern_status_t sys_kern_object_wait(kern_wait_item_t *items, size_t nr_items) return KERN_INVALID_ARGUMENT; } - struct task *self = current_task(); - struct thread *self_thread = current_thread(); + struct task *self = get_current_task(); if (!validate_access_rw(self, items, nr_items * sizeof *items)) { + put_current_task(self); return KERN_MEMORY_FAULT; } + struct thread *self_thread = get_current_thread(); self_thread->tr_state = THREAD_SLEEPING; kern_status_t status = KERN_OK; @@ -78,6 +79,9 @@ cleanup: } self_thread->tr_state = THREAD_READY; + put_current_thread(self_thread); + put_current_task(self); + return status; } @@ -85,13 +89,15 @@ kern_status_t sys_kern_object_query( kern_handle_t object_handle, kern_object_info_t *out) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!out) { + put_current_task(self); return KERN_INVALID_ARGUMENT; } if (!validate_access_w(self, out, sizeof *out)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -100,12 +106,14 @@ kern_status_t sys_kern_object_query( kern_status_t status = task_resolve_handle(self, object_handle, &obj, &flags); if (status != KERN_OK) { + put_current_task(self); return status; } out->obj_id = obj->ob_id; object_unref(obj); + put_current_task(self); return KERN_OK; } diff --git a/syscall/task.c b/syscall/task.c index e436d8a..8480620 100644 --- a/syscall/task.c +++ b/syscall/task.c @@ -9,8 +9,9 @@ extern kern_status_t sys_task_exit(int status) { #if defined(TRACE) - struct task *self = current_task(); + struct task *self = get_current_task(); printk("%s[%d]: task_exit(%d)", self->t_name, self->t_id, status); + put_current_task(self); #endif task_exit(status); return KERN_FATAL_ERROR; @@ -18,8 +19,9 @@ extern kern_status_t sys_task_exit(int status) kern_status_t sys_task_self(kern_handle_t *out) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_w(self, out, sizeof *out)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -36,11 +38,13 @@ kern_status_t sys_task_self(kern_handle_t *out) task_unlock_irqrestore(self, flags); if (status != KERN_OK) { + put_current_task(self); return status; } object_ref(&self->t_base); handle_slot->h_object = &self->t_base; + put_current_task(self); *out = handle; return KERN_OK; @@ -54,13 +58,15 @@ kern_status_t sys_task_create( kern_handle_t *out_address_space) { unsigned long flags; - struct task *self = current_task(); + struct task *self = get_current_task(); if (name_len && !validate_access_r(self, name, name_len)) { + put_current_task(self); return KERN_MEMORY_FAULT; } if (!validate_access_w(self, out_task, sizeof *out_task)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -68,6 +74,7 @@ kern_status_t sys_task_create( self, out_address_space, sizeof *out_address_space)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -81,6 +88,7 @@ kern_status_t sys_task_create( &parent_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -96,6 +104,7 @@ kern_status_t sys_task_create( if (status != KERN_OK) { object_unref(parent_obj); task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -108,6 +117,7 @@ kern_status_t sys_task_create( object_unref(parent_obj); handle_table_free_handle(self->t_handles, child_handle); task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -121,6 +131,7 @@ kern_status_t sys_task_create( handle_table_free_handle(self->t_handles, child_handle); handle_table_free_handle(self->t_handles, space_handle); task_unlock_irqrestore(self, flags); + put_current_task(self); return KERN_NO_MEMORY; } @@ -136,6 +147,7 @@ kern_status_t sys_task_create( object_ref(&child->t_address_space->s_base); object_unref(parent_obj); + put_current_task(self); *out_task = child_handle; *out_address_space = space_handle; @@ -152,13 +164,15 @@ kern_status_t sys_task_create_thread( kern_handle_t *out_thread) { unsigned long flags; - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_r(self, args, nr_args * sizeof(uintptr_t))) { + put_current_task(self); return KERN_MEMORY_FAULT; } if (!validate_access_w(self, out_thread, sizeof *out_thread)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -169,6 +183,7 @@ kern_status_t sys_task_create_thread( = task_resolve_handle(self, task, &target_obj, &target_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -184,6 +199,7 @@ kern_status_t sys_task_create_thread( if (status != KERN_OK) { object_unref(target_obj); task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -198,6 +214,7 @@ kern_status_t sys_task_create_thread( task_lock_irqsave(self, &flags); handle_table_free_handle(self->t_handles, out_handle); task_unlock_irqrestore(self, flags); + put_current_task(self); return KERN_NO_MEMORY; } @@ -207,6 +224,7 @@ kern_status_t sys_task_create_thread( task_unlock_irqrestore(target, flags); object_unref(target_obj); + put_current_task(self); *out_thread = out_handle; return KERN_OK; @@ -216,8 +234,9 @@ kern_status_t sys_task_get_address_space( kern_handle_t task_handle, kern_handle_t *out) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_w(self, out, sizeof *out)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -235,6 +254,7 @@ kern_status_t sys_task_get_address_space( &handle_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -246,6 +266,7 @@ kern_status_t sys_task_get_address_space( if (status != KERN_OK) { object_unref(task_obj); task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -255,6 +276,7 @@ kern_status_t sys_task_get_address_space( object_unref(task_obj); handle_table_free_handle(self->t_handles, handle); task_unlock_irqrestore(self, flags); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -262,6 +284,7 @@ kern_status_t sys_task_get_address_space( object_ref(&task->t_address_space->s_base); task_unlock_irqrestore(self, flags); object_unref(task_obj); + put_current_task(self); *out = handle; return KERN_OK; @@ -269,12 +292,13 @@ kern_status_t sys_task_get_address_space( kern_status_t sys_thread_self(kern_handle_t *out) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_w(self, out, sizeof *out)) { + put_current_task(self); return KERN_MEMORY_FAULT; } - struct thread *self_thread = current_thread(); + struct thread *self_thread = get_current_thread(); unsigned long flags; task_lock_irqsave(self, &flags); @@ -289,11 +313,15 @@ kern_status_t sys_thread_self(kern_handle_t *out) task_unlock_irqrestore(self, flags); if (status != KERN_OK) { + put_current_thread(self_thread); + put_current_task(self); return status; } object_ref(&self_thread->tr_base); handle_slot->h_object = &self_thread->tr_base; + put_current_thread(self_thread); + put_current_task(self); *out = handle; return KERN_OK; @@ -302,7 +330,7 @@ kern_status_t sys_thread_self(kern_handle_t *out) kern_status_t sys_thread_start(kern_handle_t thread_handle) { unsigned long flags; - struct task *self = current_task(); + struct task *self = get_current_task(); struct object *thread_obj; handle_flags_t thread_flags; @@ -314,6 +342,7 @@ kern_status_t sys_thread_start(kern_handle_t thread_handle) &thread_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -322,6 +351,7 @@ kern_status_t sys_thread_start(kern_handle_t thread_handle) schedule_thread_on_cpu(thread); object_unref(thread_obj); + put_current_task(self); return KERN_OK; } @@ -340,9 +370,10 @@ kern_status_t sys_thread_config_get( size_t len) { unsigned long flags; - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_w(self, ptr, len)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -356,6 +387,7 @@ kern_status_t sys_thread_config_get( &thread_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -365,6 +397,7 @@ kern_status_t sys_thread_config_get( status = thread_config_get(thread, key, ptr, len); object_unref(thread_obj); + put_current_task(self); return status; } @@ -376,9 +409,10 @@ kern_status_t sys_thread_config_set( size_t len) { unsigned long flags; - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_w(self, ptr, len)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -392,6 +426,7 @@ kern_status_t sys_thread_config_set( &thread_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } diff --git a/syscall/vm-controller.c b/syscall/vm-controller.c index 807891a..5c3ddf2 100644 --- a/syscall/vm-controller.c +++ b/syscall/vm-controller.c @@ -7,18 +7,21 @@ kern_status_t sys_vm_controller_create(kern_handle_t *out) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_w(self, out, sizeof *out)) { + put_current_task(self); return KERN_MEMORY_FAULT; } struct vm_controller *ctrl = vm_controller_create(); if (!ctrl) { + put_current_task(self); return KERN_NO_MEMORY; } kern_status_t status = task_open_handle(self, &ctrl->vc_base, 0, out); + put_current_task(self); if (status != KERN_OK) { object_unref(&ctrl->vc_base); return status; @@ -31,9 +34,10 @@ kern_status_t sys_vm_controller_recv( kern_handle_t ctrl_handle, equeue_packet_page_request_t *out) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_w(self, out, sizeof *out)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -50,6 +54,7 @@ kern_status_t sys_vm_controller_recv( &handle_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -57,6 +62,7 @@ kern_status_t sys_vm_controller_recv( task_unlock_irqrestore(self, flags); if (!ctrl) { object_unref(ctrl_obj); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -65,6 +71,7 @@ kern_status_t sys_vm_controller_recv( vm_controller_unlock_irqrestore(ctrl, flags); object_unref(ctrl_obj); + put_current_task(self); return status; } @@ -74,7 +81,7 @@ kern_status_t sys_vm_controller_recv_async( kern_handle_t eq_handle, equeue_key_t key) { - struct task *self = current_task(); + struct task *self = get_current_task(); kern_status_t status = KERN_OK; unsigned long flags; @@ -85,6 +92,7 @@ kern_status_t sys_vm_controller_recv_async( status = task_resolve_handle(self, ctrl_handle, &ctrl_obj, &ctrl_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -92,6 +100,7 @@ kern_status_t sys_vm_controller_recv_async( if (status != KERN_OK) { object_unref(ctrl_obj); task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -102,6 +111,7 @@ kern_status_t sys_vm_controller_recv_async( if (!ctrl || !eq) { object_unref(ctrl_obj); object_unref(eq_obj); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -111,6 +121,7 @@ kern_status_t sys_vm_controller_recv_async( object_unref(ctrl_obj); object_unref(eq_obj); + put_current_task(self); return status; } @@ -124,13 +135,15 @@ kern_status_t sys_vm_controller_create_object( vm_prot_t prot, kern_handle_t *out) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_r(self, name, name_len)) { + put_current_task(self); return KERN_MEMORY_FAULT; } if (!validate_access_w(self, out, sizeof *out)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -147,6 +160,7 @@ kern_status_t sys_vm_controller_create_object( &handle_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -162,6 +176,7 @@ kern_status_t sys_vm_controller_create_object( task_unlock_irqrestore(self, flags); if (!ctrl) { object_unref(ctrl_obj); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -183,10 +198,12 @@ kern_status_t sys_vm_controller_create_object( task_lock_irqsave(self, &flags); handle_table_free_handle(self->t_handles, out_handle); task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } out_slot->h_object = &out_vmo->vo_base; + put_current_task(self); *out = out_handle; return KERN_OK; @@ -196,7 +213,7 @@ kern_status_t sys_vm_controller_detach_object( kern_handle_t ctrl_handle, kern_handle_t vmo_handle) { - struct task *self = current_task(); + struct task *self = get_current_task(); kern_status_t status = KERN_OK; unsigned long flags; @@ -207,6 +224,7 @@ kern_status_t sys_vm_controller_detach_object( status = task_resolve_handle(self, ctrl_handle, &ctrl_obj, &ctrl_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -214,6 +232,7 @@ kern_status_t sys_vm_controller_detach_object( if (status != KERN_OK) { object_unref(ctrl_obj); task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -224,6 +243,7 @@ kern_status_t sys_vm_controller_detach_object( if (!ctrl || !vmo) { object_unref(ctrl_obj); object_unref(vmo_obj); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -235,6 +255,7 @@ kern_status_t sys_vm_controller_detach_object( object_unref(ctrl_obj); object_unref(vmo_obj); + put_current_task(self); return status; } @@ -247,7 +268,7 @@ kern_status_t sys_vm_controller_supply_pages( off_t src_offset, size_t count) { - struct task *self = current_task(); + struct task *self = get_current_task(); kern_status_t status = KERN_OK; unsigned long flags; @@ -258,6 +279,7 @@ kern_status_t sys_vm_controller_supply_pages( status = task_resolve_handle(self, ctrl_handle, &ctrl_obj, &ctrl_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -265,6 +287,7 @@ kern_status_t sys_vm_controller_supply_pages( if (status != KERN_OK) { object_unref(ctrl_obj); task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -273,6 +296,7 @@ kern_status_t sys_vm_controller_supply_pages( object_unref(ctrl_obj); object_unref(dst_obj); task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } @@ -285,6 +309,7 @@ kern_status_t sys_vm_controller_supply_pages( object_unref(ctrl_obj); object_unref(dst_obj); object_unref(src_obj); + put_current_task(self); return KERN_INVALID_ARGUMENT; } @@ -303,6 +328,7 @@ kern_status_t sys_vm_controller_supply_pages( object_unref(ctrl_obj); object_unref(dst_obj); object_unref(src_obj); + put_current_task(self); return status; } diff --git a/syscall/vm-object.c b/syscall/vm-object.c index 383acfa..4101c5d 100644 --- a/syscall/vm-object.c +++ b/syscall/vm-object.c @@ -11,13 +11,15 @@ kern_status_t sys_vm_object_create( vm_prot_t prot, kern_handle_t *out_handle) { - struct task *self = current_task(); + struct task *self = get_current_task(); if ((name || name_len) && !validate_access_r(self, name, name_len)) { + put_current_task(self); return KERN_MEMORY_FAULT; } if (!validate_access_w(self, out_handle, sizeof *out_handle)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -30,6 +32,7 @@ kern_status_t sys_vm_object_create( kern_status_t status = task_open_handle(self, &obj->vo_base, 0, out_handle); object_unref(&obj->vo_base); + put_current_task(self); return status; } @@ -41,13 +44,15 @@ kern_status_t sys_vm_object_read( size_t count, size_t *nr_read) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_w(self, dst, count)) { + put_current_task(self); return KERN_MEMORY_FAULT; } if (nr_read && !validate_access_w(self, nr_read, sizeof *nr_read)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -55,15 +60,19 @@ kern_status_t sys_vm_object_read( handle_flags_t flags = 0; kern_status_t status = task_resolve_handle(self, object, &obj, &flags); if (status != KERN_OK) { + put_current_task(self); return status; } struct vm_object *vmo = vm_object_cast(obj); if (!vmo) { + put_current_task(self); return KERN_INVALID_ARGUMENT; } - return vm_object_read(vmo, dst, offset, count, nr_read); + status = vm_object_read(vmo, dst, offset, count, nr_read); + put_current_task(self); + return status; } kern_status_t sys_vm_object_write( @@ -73,14 +82,16 @@ kern_status_t sys_vm_object_write( size_t count, size_t *nr_written) { - struct task *self = current_task(); + struct task *self = get_current_task(); if (!validate_access_r(self, src, count)) { + put_current_task(self); return KERN_MEMORY_FAULT; } if (nr_written && !validate_access_w(self, nr_written, sizeof *nr_written)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -88,15 +99,19 @@ kern_status_t sys_vm_object_write( handle_flags_t flags = 0; kern_status_t status = task_resolve_handle(self, object, &obj, &flags); if (status != KERN_OK) { + put_current_task(self); return status; } struct vm_object *vmo = vm_object_cast(obj); if (!vmo) { + put_current_task(self); return KERN_INVALID_ARGUMENT; } - return vm_object_write(vmo, src, offset, count, nr_written); + status = vm_object_write(vmo, src, offset, count, nr_written); + put_current_task(self); + return status; } kern_status_t sys_vm_object_copy( @@ -114,10 +129,11 @@ kern_status_t sys_vm_object_copy( src_offset, count, nr_copied); - struct task *self = current_task(); + struct task *self = get_current_task(); if (nr_copied && !validate_access_w(self, nr_copied, sizeof *nr_copied)) { + put_current_task(self); return KERN_MEMORY_FAULT; } @@ -131,16 +147,19 @@ kern_status_t sys_vm_object_copy( status = task_resolve_handle(self, dst, &dst_obj, &dst_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } status = task_resolve_handle(self, src, &src_obj, &src_flags); if (status != KERN_OK) { task_unlock_irqrestore(self, flags); + put_current_task(self); return status; } task_unlock_irqrestore(self, flags); + put_current_task(self); struct vm_object *dst_vmo = vm_object_cast(dst_obj); struct vm_object *src_vmo = vm_object_cast(src_obj); diff --git a/vm/address-space.c b/vm/address-space.c index 891fca7..77dd5e8 100644 --- a/vm/address-space.c +++ b/vm/address-space.c @@ -1261,9 +1261,11 @@ static kern_status_t request_missing_page( /* here: * `region` is locked. * `object` is unlocked. - * `irq_flags` must be restored when `region` is unlocked. - * the relevant page in `object` may or may not be committed. - * if it isn't, it needs to be requested. + * `irq_flags` must be restored when `region` is + * unlocked. + * the relevant page in `object` may or may + * not be committed. if it isn't, it needs to be + * requested. */ vm_object_lock(object); address_space_unlock(region); diff --git a/vm/vm-controller.c b/vm/vm-controller.c index 15d8a18..82fef0e 100644 --- a/vm/vm-controller.c +++ b/vm/vm-controller.c @@ -159,6 +159,7 @@ kern_status_t vm_controller_recv( spin_unlock(&req->req_lock); if (req->req_status == PAGE_REQUEST_ASYNC) { + put_current_thread(req->req_sender); vm_cache_free(&page_request_cache, req); } @@ -220,7 +221,7 @@ kern_status_t vm_controller_detach_object( req->req_type = PAGE_REQUEST_DETACH; req->req_status = PAGE_REQUEST_ASYNC; req->req_object = vmo->vo_key; - req->req_sender = current_thread(); + req->req_sender = get_current_thread(); send_request_async(ctrl, req); vmo->vo_ctrl = NULL; @@ -236,7 +237,7 @@ static void wait_for_reply( unsigned long *lock_flags) { struct wait_item waiter; - struct thread *self = current_thread(); + struct thread *self = get_current_thread(); wait_item_init(&waiter, self); for (;;) { @@ -251,6 +252,7 @@ static void wait_for_reply( } self->tr_state = THREAD_READY; + put_current_thread(self); } static void fulfill_requests( diff --git a/vm/vm-object.c b/vm/vm-object.c index a84d516..ef77efc 100644 --- a/vm/vm-object.c +++ b/vm/vm-object.c @@ -376,7 +376,7 @@ static kern_status_t request_page( req.req_type = PAGE_REQUEST_READ; req.req_offset = offset; req.req_length = vm_page_order_to_bytes(VM_PAGE_4K); - req.req_sender = current_thread(); + req.req_sender = get_current_thread(); object_ref(&vo->vo_base); req.req_object = vo->vo_key; @@ -388,6 +388,7 @@ static kern_status_t request_page( kern_status_t status = vm_controller_send_request(ctrl, &req, irq_flags); + put_current_thread(req.req_sender); spin_unlock(&req.req_lock); vm_controller_unlock_irqrestore(ctrl, *irq_flags); object_unref(&vo->vo_base);