Added comment about danger of dropping into monitor()
[akaros.git] / kern / src / schedule.c
1 /*
2  * Copyright (c) 2009 The Regents of the University of California
3  * Barret Rhoden <brho@cs.berkeley.edu>
4  * See LICENSE for details.
5  *
6  * Scheduling and dispatching.
7  */
8
9 #ifdef __SHARC__
10 #pragma nosharc
11 #endif
12
13 #include <schedule.h>
14 #include <process.h>
15 #include <monitor.h>
16 #include <stdio.h>
17 #include <assert.h>
18 #include <atomic.h>
19 #include <sys/queue.h>
20
21 // This could be useful for making scheduling decisions.  
22 /* Physical coremap: each index is a physical core id, with a proc ptr for
23  * whoever *should be or is* running.  Very similar to current, which is what
24  * process is *really* running there. */
25 struct proc *pcoremap[MAX_NUM_CPUS];
26
27 void schedule_init(void)
28 {
29         TAILQ_INIT(&proc_runnablelist);
30         return;
31 }
32
33 void schedule_proc(struct proc *p)
34 {
35         p->env_refcnt++; // TODO (REF) (usually is called while locked)
36         //proc_incref(p, 1); /* up the refcnt since we are storing the reference */
37         spin_lock_irqsave(&runnablelist_lock);
38         printd("Scheduling PID: %d\n", p->pid);
39         TAILQ_INSERT_TAIL(&proc_runnablelist, p, proc_link);
40         spin_unlock_irqsave(&runnablelist_lock);
41         return;
42 }
43
44 /* TODO: race here.  it's possible that p was already removed from the
45  * list (by schedule()), while proc_destroy is trying to remove it from the
46  * list.  schedule()'s proc_run() won't actually run it (since it's DYING), but
47  * this code will probably fuck up. */
48 void deschedule_proc(struct proc *p)
49 {
50         spin_lock_irqsave(&runnablelist_lock);
51         printd("Descheduling PID: %d\n", p->pid);
52         TAILQ_REMOVE(&proc_runnablelist, p, proc_link);
53         spin_unlock_irqsave(&runnablelist_lock);
54         p->env_refcnt--; // TODO (REF) (usually is called while locked)
55         //proc_decref(p, 1); /* down the refcnt, since its no longer stored */
56         return;
57 }
58
59 /*
60  * FIFO - just pop the head from the list and run it.
61  * Using irqsave spinlocks for now, since this could be called from a timer
62  * interrupt handler (though ought to be in a bottom half or something).
63  */
64 void schedule(void)
65 {
66         struct proc *p;
67         
68         spin_lock_irqsave(&runnablelist_lock);
69         p = TAILQ_FIRST(&proc_runnablelist);
70         if (p) {
71                 TAILQ_REMOVE(&proc_runnablelist, p, proc_link);
72                 spin_unlock_irqsave(&runnablelist_lock);
73                 printd("PID of proc i'm running: %d\n", p->pid);
74                 /* proc_run will either eat the ref, or we'll decref manually. */
75                 proc_run(p);
76                 proc_decref(p, 1);
77         } else {
78                 spin_unlock_irqsave(&runnablelist_lock);
79                 /* while this is problematic, we really don't have anything to
80          * do and could run off the end of the kernel stack if we just
81          * smp_idle -> manager -> schedule -> smp_idle. */
82                 printk("No processes to schedule, enjoy the Monitor!\n");
83                 while (1)
84                         monitor(NULL);
85         }
86         return;
87 }
88
89 void dump_proclist(struct proc_list *list)
90 {
91         struct proc *p;
92         TAILQ_FOREACH(p, list, proc_link)
93                 printk("PID: %d\n", p->pid);
94         return;
95 }