summaryrefslogtreecommitdiff
path: root/kc/core/task.c
diff options
context:
space:
mode:
authorAda Christine <adachristine18@gmail.com>2026-05-23 13:50:05 +0000
committerAda Christine <adachristine18@gmail.com>2026-05-23 13:50:05 +0000
commit6fbb95277b736e3f271c9586a59a500f2a5ba48a (patch)
tree26c82cdf60353c9acc2848c9e12c609b9d75913b /kc/core/task.c
parent3bbd1849d38ed66afd1ba8abb59ac6cdb12138d6 (diff)
rewrote some ugly thread queueing code
Diffstat (limited to 'kc/core/task.c')
-rw-r--r--kc/core/task.c210
1 files changed, 109 insertions, 101 deletions
diff --git a/kc/core/task.c b/kc/core/task.c
index e5933bd..9e0e549 100644
--- a/kc/core/task.c
+++ b/kc/core/task.c
@@ -33,10 +33,6 @@ static void sleep_thread_until(uint64_t nanoseconds);
static int sleeping_thread_callback(uint64_t nanoseconds);
-static struct kc_thread *ready_thread_pop(void);
-static void ready_thread_push(struct kc_thread *thread);
-static void ready_thread_push_back(struct kc_thread *thread);
-
const struct timer_source * timesource;
/* static threads that are always present
@@ -46,9 +42,67 @@ static struct kc_thread *idle_thread;
// thread lists for the scheduler to manipulate
static struct kc_thread *current_thread;
-static struct kc_thread *first_ready_thread;
-static struct kc_thread *last_ready_thread;
-static struct kc_thread *sleeping_threads;
+
+struct thread_queue
+{
+ struct kc_thread
+ *first,
+ *last;
+};
+
+static void thread_queue_push(struct thread_queue *queue, struct kc_thread *thread);
+static void thread_queue_push_back(struct thread_queue *queue, struct kc_thread *thread);
+
+static void thread_queue_push(struct thread_queue *queue, struct kc_thread *thread)
+{
+ thread->next = queue->first;
+ queue->first = thread;
+
+ if (!queue->last)
+ {
+ thread_queue_push_back(queue, thread);
+ }
+}
+
+static void thread_queue_push_back(struct thread_queue *queue, struct kc_thread *thread)
+{
+ if (!queue->first)
+ {
+ thread_queue_push(queue, thread);
+ }
+ else if (queue->last)
+ {
+ queue->last->next = thread;
+ }
+
+ queue->last = thread;
+}
+
+struct kc_thread *thread_queue_pop(struct thread_queue *queue)
+{
+ if (!queue->first)
+ {
+ return nullptr;
+ }
+
+ struct kc_thread *thread = queue->first;
+ queue->first = thread->next;
+ thread->next = nullptr;
+ if (!queue->first)
+ {
+ queue->last = nullptr;
+ }
+
+ return thread;
+}
+
+bool thread_queue_any(struct thread_queue queue)
+{
+ return queue.first && queue.last;
+}
+
+static struct thread_queue ready_queue;
+static struct thread_queue sleep_queue;
static volatile atomic_uint_fast64_t preempt_switch_count = 0;
static volatile atomic_bool preempt_switch_flag = false;
@@ -102,10 +156,10 @@ noreturn void task_init(void)
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);
- ready_thread_push(sleepy_thread);
- ready_thread_push(sleepy_thread2);
+ 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) :);
- ready_thread_push(idle_thread);
+ 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");
@@ -124,33 +178,25 @@ static inline bool check_preempt_count()
void task_schedule(void)
{
- if (check_preempt_count())
- {
- preempt_switch_flag = true;
- return;
- }
+ if(check_preempt_count())
+ {
+ preempt_switch_flag = true;
+ return;
+ }
- if (first_ready_thread)
- {
- struct kc_thread *this_thread = ready_thread_pop();
+ struct kc_thread *t = thread_queue_pop(&ready_queue);
- if (this_thread == idle_thread)
- {
- if (first_ready_thread)
- {
- this_thread->status = READY;
- this_thread = ready_thread_pop();
- ready_thread_push(idle_thread);
- }
- else if (current_thread->status == RUNNING)
- {
- return;
- }
- }
- set_thread(this_thread);
- }
-}
+ if (t == idle_thread)
+ {
+ thread_queue_push_back(&ready_queue, t);
+ t = thread_queue_pop(&ready_queue);
+ }
+ if (t && current_thread->status != RUNNING)
+ {
+ set_thread(t);
+ }
+}
static void lock_scheduler(void)
{
@@ -223,11 +269,17 @@ static void destroy_thread(struct kc_thread *thread)
static void set_thread(struct kc_thread *thread)
{
+ if (thread == current_thread)
+ {
+ return;
+ }
+
if (atomic_load(&preempt_switch_count))
{
preempt_switch_flag = true;
return;
}
+
update_time();
struct kc_thread *previous_thread = current_thread;
current_thread = thread;
@@ -235,7 +287,7 @@ static void set_thread(struct kc_thread *thread)
if (previous_thread->status == RUNNING)
{
previous_thread->status = READY;
- ready_thread_push(previous_thread);
+ thread_queue_push(&ready_queue, previous_thread);
}
current_thread->status = RUNNING;
@@ -257,14 +309,14 @@ static void unblock_thread(struct kc_thread *thread)
thread->status = READY;
- if (!first_ready_thread || (current_thread == idle_thread))
+ if (!thread_queue_any(ready_queue) || (current_thread == idle_thread))
{
unlock_preempt();
set_thread(thread);
}
else
{
- ready_thread_push_back(thread);
+ thread_queue_push_back(&ready_queue, thread);
}
unlock_scheduler();
@@ -285,81 +337,38 @@ static void sleep_thread_until(uint64_t nanoseconds)
return;
}
- //kprintf("time elapsed is now %ld\r\n", timesource->nanoseconds_elapsed());
- //kprintf("thread will now sleep until %ld\r\n", nanoseconds);
current_thread->sleep_expiration = nanoseconds;
- current_thread->next = sleeping_threads;
- sleeping_threads = current_thread;
+
+ thread_queue_push_back(&sleep_queue, current_thread);
unlock_preempt();
block_thread(SLEEPING);
}
-static struct kc_thread *ready_thread_pop(void)
-{
- struct kc_thread *thread = first_ready_thread;
-
- if (thread)
- {
- first_ready_thread = thread->next;
- }
-
- if (!first_ready_thread)
- {
- last_ready_thread = NULL;
- }
-
- return thread;
-}
-
-static void ready_thread_push(struct kc_thread *thread)
-{
- thread->next = first_ready_thread;
- first_ready_thread = thread;
-
- if (!last_ready_thread)
- {
- last_ready_thread = first_ready_thread;
- }
-}
-
-static void ready_thread_push_back(struct kc_thread *thread)
-{
- if (last_ready_thread)
- {
- last_ready_thread->next = thread;
- }
- else
- {
- first_ready_thread = thread;
- }
- last_ready_thread = thread;
-}
-
-static int sleeping_thread_callback(uint64_t nanoseconds)
+static int sleeping_thread_callback(uint64_t timestamp)
{
lock_preempt();
- struct kc_thread *sleeping = sleeping_threads;
- sleeping_threads = NULL;
+ struct thread_queue queue = sleep_queue;
- while (sleeping != NULL)
- {
- struct kc_thread *this_thread = sleeping;
- sleeping = sleeping->next;
+ sleep_queue = (struct thread_queue){ nullptr, nullptr };
- if (this_thread->sleep_expiration <= nanoseconds)
- {
- this_thread->sleep_expiration = 0;
- unblock_thread(this_thread);
- }
- else
- {
- this_thread->next = sleeping_threads;
- sleeping_threads = this_thread;
- }
- }
+ {
+ struct kc_thread *t;
+ while((t = thread_queue_pop(&queue)) != nullptr)
+ {
+ if (t->sleep_expiration <= timestamp)
+ {
+ t->sleep_expiration = 0;
+ unblock_thread(t);
+ }
+ else
+ {
+ thread_queue_push(&sleep_queue, t);
+ }
+ }
+ }
unlock_preempt();
lock_scheduler();
@@ -369,7 +378,6 @@ static int sleeping_thread_callback(uint64_t nanoseconds)
return 0;
}
-
typedef void (locked_scheduler_action)(void *);
static void with_locked_scheduler(