Nucleus
Barry Exiting interrupt context on clone() child 571b85e (3 years, 3 months ago)
diff --git a/task/clone.c b/task/clone.c
index 4dd15e7..22d737b 100644
--- a/task/clone.c
+++ b/task/clone.c
@@ -7,6 +7,7 @@
#include <sys/sched.h>
#include <nucleus/task.h>
#include <nucleus/vfs.h>
+#include <io.h>
extern ObjectList *readyQueue[];
@@ -14,7 +15,7 @@ extern ObjectList *readyQueue[];
pid_t
clone(int flags)
{
- uintptr_t ints = irq_disable();
+ enter_critical_section();
Task *parent = current, *child = new(&taskType), *tmp;
pid_t tid = 0;
@@ -41,7 +42,12 @@ clone(int flags)
add(readyQueue[child->priority], child);
tid = child->tid;
put(child);
+ exit_critical_section();
end:
- irq_restore(ints);
+ if (!tid) {
+ outb(0x20, 0x20);
+ LAPIC(0xB0) = 0;
+ }
+
return tid;
}
diff --git a/task/scheduler.c b/task/scheduler.c
index 7b08fc2..1bc0f55 100644
--- a/task/scheduler.c
+++ b/task/scheduler.c
@@ -38,6 +38,8 @@ switch_to_task(Task *task)
"g" (current->ebp), "g" (current->pageDir)
);
end:
+ /* This prevents GCC from optimising the jump to be after the return */
+ __atomic_thread_fence(__ATOMIC_ACQ_REL);
}
/* Find the next schedulable ready queue */
@@ -56,6 +58,9 @@ highest_priority_queue(void)
void
schedule(void)
{
+ if (current->inCriticalSection)
+ return;
+
Task *task = current;
ObjectList *queue = highest_priority_queue();