BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / ca4f3abc7b46ecf67b6a72e75989dc6eccead09a / task

// Related

Nucleus

Barry Multi-core scheduling ca4f3ab (3 years, 3 months ago)
diff --git a/task/clone.c b/task/clone.c
index 22d737b..c9a6dc0 100644
--- a/task/clone.c
+++ b/task/clone.c
@@ -46,7 +46,8 @@ clone(int flags)
 end:
 	if (!tid) {
 		outb(0x20, 0x20);
-		LAPIC(0xB0) = 0;
+		if (apic)
+			LAPIC(0xB0) = 0;
 	}
 
 	return tid;
diff --git a/task/scheduler.c b/task/scheduler.c
index 1bc0f55..5cb1440 100644
--- a/task/scheduler.c
+++ b/task/scheduler.c
@@ -17,15 +17,18 @@ ObjectList *readyQueue[PRIORITY_COUNT];
 static void
 switch_to_task(Task *task)
 {
-	lock(current);
-	asm volatile("mov %%esp, %0" : "=r" (current->esp));
-	asm volatile("mov %%ebp, %0" : "=r" (current->ebp));
-	current->eip = (uintptr_t) &&end;
-	unlock(current);
+	/* Save current task state */
+	if (__builtin_expect(!!current, 1)) {
+		lock(current);
+		asm volatile("mov %%esp, %0" : "=r" (current->esp));
+		asm volatile("mov %%ebp, %0" : "=r" (current->ebp));
+		current->eip = (uintptr_t) &&end;
+		unlock(current);
+		put(current);
+	}
 
-	put(current);
+	/* Switch to new context */
 	current = task; /* Use the passed reference */
-
 	asm volatile (
 		"cli;"
 		"movl %0, %%ecx;"
@@ -39,7 +42,7 @@ switch_to_task(Task *task)
 	);
 end:
 	/* This prevents GCC from optimising the jump to be after the return */
-	__atomic_thread_fence(__ATOMIC_ACQ_REL);
+	asm volatile("":::"memory");
 }
 
 /* Find the next schedulable ready queue */
@@ -58,33 +61,32 @@ highest_priority_queue(void)
 void
 schedule(void)
 {
-	if (current->inCriticalSection)
+	if (current && current->inCriticalSection)
 		return;
 
 	Task *task = current;
 	ObjectList *queue = highest_priority_queue();
 
-	/* Next schedulable task */
-	if (queue) {
-		task = pop_from_start(queue);
-		task->state = RUNNING;
-		if (current->state == RUNNING) {
-			current->state = READY;
-			add(readyQueue[current->priority], current);
-		}
-		switch_to_task(task);
-	/* Idle */
-	} else if (current->state != RUNNING) {
+	/* Idle if necessary */
+	if (!queue) {
+		if (current && current->state == RUNNING)
+			return;
 		current = NULL;
 		asm volatile("sti");
 		while (!(queue = highest_priority_queue()))
 			asm volatile("hlt");
 		asm volatile("cli");
 		current = task;
-		task = pop_from_start(queue);
-		task->state = RUNNING;
-		switch_to_task(task);
 	}
+
+	/* Schedule next task */
+	task = pop_from_start(queue);
+	task->state = RUNNING;
+	if (current && current->state == RUNNING) {
+		current->state = READY;
+		add(readyQueue[current->priority], current);
+	}
+	switch_to_task(task);
 }
 
 /* Initialise the scheduler */
diff --git a/task/time.c b/task/time.c
index 345b491..3f5a50a 100644
--- a/task/time.c
+++ b/task/time.c
@@ -15,14 +15,15 @@ uint8_t slice[MAX_CPUS] = {0};
 void
 timer_handler(struct InterruptFrame *frame)
 {
-	monotonic++;
+	if (CPUID == 0)
+		monotonic++;
 
 	if (!current)
 		return;
 	slice[CPUID]++;
 
 	/* Call scheduler */
-	if (slice[CPUID] < current->priority)
+	if (slice[CPUID] < (current->priority * 10))
 		return;
 	slice[CPUID] = 0;
 	schedule();