summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAda Christine <adachristine18@gmail.com>2026-05-23 15:08:09 +0000
committerAda Christine <adachristine18@gmail.com>2026-05-23 15:08:09 +0000
commitbcf31cb0ae9edc136de6e6069bfefbd8f144e5d9 (patch)
treedbc88987f956b72cae372dce7bfda6f244d10145
parent6fbb95277b736e3f271c9586a59a500f2a5ba48a (diff)
thread waiting works now
-rw-r--r--kc/core/task.c111
-rw-r--r--kc/core/task.h8
2 files changed, 90 insertions, 29 deletions
diff --git a/kc/core/task.c b/kc/core/task.c
index 9e0e549..5eaa3fb 100644
--- a/kc/core/task.c
+++ b/kc/core/task.c
@@ -103,6 +103,7 @@ bool thread_queue_any(struct thread_queue queue)
static struct thread_queue ready_queue;
static struct thread_queue sleep_queue;
+static struct thread_queue wait_queue;
static volatile atomic_uint_fast64_t preempt_switch_count = 0;
static volatile atomic_bool preempt_switch_flag = false;
@@ -138,33 +139,9 @@ static void *sleepy_thread_entry(void *p)
return nullptr;
}
-static uint64_t scheduler_flags;
-noreturn void task_init(void)
-{
- struct kc_thread boot_thread;
- boot_thread.status = RUNNING;
- current_thread = &boot_thread;
- timesource = &pit8253_timer_source;
- timesource->append_callback(sleeping_thread_callback);
- timesource->start();
- kprintf(
- "starting task management, timesource delta %luns\n",
- timesource->nanoseconds_delta());
-
- idle_thread = create_thread(idle_thread_entry, nullptr);
- struct kc_thread *sleepy_thread = create_thread(sleepy_thread_entry, (void *)3000000000);
- struct kc_thread *sleepy_thread2 = create_thread(sleepy_thread_entry, (void *)5000000000);
- thread_queue_push(&ready_queue, sleepy_thread);
- thread_queue_push(&ready_queue, sleepy_thread2);
- __asm__ volatile ("movq %%rsp, %0" : "=g"(boot_thread.kernel_stack_pointer) :);
- thread_queue_push(&ready_queue, idle_thread);
- block_thread(BLOCKED);
- // shouldn't ever get here
- kprintf("the idle thread exited somehow. we're back in the boot thread. this is not good.\n");
- PANIC(DEAD_END);
-}
+static uint64_t scheduler_flags;
static inline bool check_preempt_count()
{
@@ -292,7 +269,6 @@ static void set_thread(struct kc_thread *thread)
current_thread->status = RUNNING;
arch_swap_thread(previous_thread, current_thread);
-
}
static void block_thread(enum kc_thread_status reason)
@@ -394,8 +370,32 @@ static void terminate_action(void *result)
union kc_thread_result *result_value = result;
current_thread->result = *result_value;
current_thread->kernel_stack_pointer = current_thread->kernel_stack_head;
- // TODO: wake threads waiting
- // TODO: write waitng thread code
+
+ struct thread_queue queue = wait_queue;
+
+ lock_preempt();
+
+ wait_queue = (struct thread_queue) { nullptr, nullptr };
+
+ {
+ struct kc_thread *t;
+ while((t = thread_queue_pop(&queue)) != nullptr)
+ {
+ if (t->wait_target == current_thread)
+ {
+ t->wait_target = nullptr;
+ t->status = READY;
+ thread_queue_push_back(&ready_queue, t);
+ }
+ else
+ {
+ thread_queue_push(&wait_queue, t);
+ }
+ }
+ }
+
+ unlock_preempt();
+
block_thread(TERMINATED);
}
@@ -404,3 +404,58 @@ void kct_terminate(union kc_thread_result result)
with_locked_scheduler(terminate_action, &result);
}
+union kc_thread_result kct_wait(struct kc_thread *target)
+{
+ current_thread->wait_target = target;
+ thread_queue_push_back(&wait_queue, current_thread);
+ block_thread(WAITING);
+ return target->result;
+}
+
+static void *waited_thread_test(void *)
+{
+ kprintf("worker thread, sleeping for some time...\n");
+ sleep_thread(30000000000);
+ return (void *)1;
+}
+
+static void *waiting_thread_test(void *)
+{
+ kprintf("waiting thread\n");
+ struct kc_thread *t = create_thread(waited_thread_test, nullptr);
+ t->status = READY;
+ thread_queue_push_back(&ready_queue, t);
+ union kc_thread_result r = kct_wait(t);
+ kprintf("waited thread terminated result: %d\n", r);
+ return nullptr;
+}
+
+noreturn void task_init(void)
+{
+ struct kc_thread boot_thread;
+ boot_thread.status = RUNNING;
+ current_thread = &boot_thread;
+
+ timesource = &pit8253_timer_source;
+ timesource->append_callback(sleeping_thread_callback);
+ timesource->start();
+ kprintf(
+ "starting task management, timesource delta %luns\n",
+ timesource->nanoseconds_delta());
+
+ idle_thread = create_thread(idle_thread_entry, nullptr);
+ struct kc_thread *sleepy_thread = create_thread(sleepy_thread_entry, (void *)3000000000);
+ struct kc_thread *sleepy_thread2 = create_thread(sleepy_thread_entry, (void *)5000000000);
+ struct kc_thread *waiting_thread = create_thread(waiting_thread_test, nullptr);
+ thread_queue_push(&ready_queue, sleepy_thread);
+ thread_queue_push(&ready_queue, sleepy_thread2);
+ thread_queue_push_back(&ready_queue, waiting_thread);
+ __asm__ volatile ("movq %%rsp, %0" : "=g"(boot_thread.kernel_stack_pointer) :);
+ thread_queue_push(&ready_queue, idle_thread);
+ block_thread(BLOCKED);
+ // shouldn't ever get here
+ kprintf("the idle thread exited somehow. we're back in the boot thread. this is not good.\n");
+ PANIC(DEAD_END);
+}
+
+
diff --git a/kc/core/task.h b/kc/core/task.h
index eae38bb..5d9f39f 100644
--- a/kc/core/task.h
+++ b/kc/core/task.h
@@ -10,6 +10,7 @@ enum kc_thread_status
RUNNING,
SLEEPING,
BLOCKED,
+ WAITING,
TERMINATED
};
@@ -27,10 +28,15 @@ struct kc_thread
union kc_thread_result result;
enum kc_thread_status status;
struct kc_thread *next;
- uint64_t sleep_expiration;
+ union
+ {
+ uint64_t sleep_expiration;
+ struct kc_thread *wait_target;
+ };
};
void task_init(void);
void kct_terminate(union kc_thread_result result);
+union kc_thread_result kct_wait(struct kc_thread *target);