1 #include <klibc/compiler.h> 2 #include <sys/cpu.h> 3 #include "thread.h" 4 #include "core.h" 5 #include <dprintf.h> 6 7 void (*sched_hook_func)(void); 8 9 /* 10 * __schedule() should only be called with interrupts locked out! 11 */ 12 void __schedule(void) 13 { 14 static bool in_sched_hook; 15 struct thread *curr = current(); 16 struct thread *st, *nt, *best; 17 18 #if DEBUG 19 if (__unlikely(irq_state() & 0x200)) { 20 dprintf("In __schedule with interrupts on!\n"); 21 kaboom(); 22 } 23 #endif 24 25 /* 26 * Are we called from inside sched_hook_func()? If so we'll 27 * schedule anyway on the way out. 28 */ 29 if (in_sched_hook) 30 return; 31 32 dprintf("Schedule "); 33 34 /* Possibly update the information on which we make 35 * scheduling decisions. 36 */ 37 if (sched_hook_func) { 38 in_sched_hook = true; 39 sched_hook_func(); 40 in_sched_hook = false; 41 } 42 43 /* 44 * The unusual form of this walk is because we have to start with 45 * the thread *following* curr, and curr may not actually be part 46 * of the list anymore (in the case of __exit_thread). 47 */ 48 best = NULL; 49 nt = st = container_of(curr->list.next, struct thread, list); 50 do { 51 if (__unlikely(nt->thread_magic != THREAD_MAGIC)) { 52 dprintf("Invalid thread on thread list %p magic = 0x%08x\n", 53 nt, nt->thread_magic); 54 kaboom(); 55 } 56 57 dprintf("Thread %p (%s) ", nt, nt->name); 58 if (!nt->blocked) { 59 dprintf("runnable priority %d\n", nt->prio); 60 if (!best || nt->prio < best->prio) 61 best = nt; 62 } else { 63 dprintf("blocked\n"); 64 } 65 nt = container_of(nt->list.next, struct thread, list); 66 } while (nt != st); 67 68 if (!best) 69 kaboom(); /* No runnable thread */ 70 71 if (best != curr) { 72 uint64_t tsc; 73 74 asm volatile("rdtsc" : "=A" (tsc)); 75 76 dprintf("@ %llu -> %p (%s)\n", tsc, best, best->name); 77 __switch_to(best); 78 } else { 79 dprintf("no change\n"); 80 } 81 } 82 83 /* 84 * This can be called from "normal" code... 85 */ 86 void thread_yield(void) 87 { 88 irq_state_t irq = irq_save(); 89 __schedule(); 90 irq_restore(irq); 91 } 92