Home | History | Annotate | Download | only in thread
      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