Add synchornization primitives, `waiting` to task
diff --git a/src/kernel/task.c b/src/kernel/task.c
index c8068c4..116e4a2 100644
--- a/src/kernel/task.c
+++ b/src/kernel/task.c
@@ -53,6 +53,7 @@
.ebp = kernel_ebp,
.eip = kernel_eip,
.id = next_task_id++,
+ .waiting = false,
};
tasks_initialized = true;
@@ -105,6 +106,7 @@
task->id = next_task_id++;
task->ebp = task->esp = new_stack_base_v;
task->eip = (uint)function;
+ task->waiting = false;
last_task->next = ll_task;
ll_task->prev = last_task;
@@ -172,15 +174,42 @@
current_task->task.esp = esp;
current_task->task.eip = eip;
- if (current_task->next == NULL)
+ struct ll_task_i *original = current_task;
+
+ do
{
- current_task = first_task;
+ if (current_task->next == NULL)
+ {
+ current_task = first_task;
+ }
+ else
+ {
+ // Continue the next task
+ current_task = current_task->next;
+ }
}
- else
+ while (current_task->task.waiting);
+
+ if (current_task == original && original->task.waiting)
{
- // Continue the next task
- current_task = current_task->next;
+ kpanic("All tasks are waiting for I/O. There must be at least 1 task using CPU at all times.");
}
switch_to_task(¤t_task->task);
}
+
+void set_waiting(int tid, bool waiting)
+{
+ asm("cli");
+
+ for (struct ll_task_i *t = first_task; t != NULL; t = t->next)
+ {
+ if (t->task.id == tid)
+ {
+ t->task.waiting = waiting;
+ break;
+ }
+ }
+
+ asm("sti");
+}