8ccb931308009416b13dcfbd67519592eae07e21
[akaros.git] / kern / src / smp.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
7 #ifdef __SHARC__
8 #pragma nosharc
9 #endif
10
11 #include <arch/arch.h>
12 #include <atomic.h>
13 #include <smp.h>
14 #include <error.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <assert.h>
18 #include <pmap.h>
19 #include <process.h>
20 #include <manager.h>
21 #include <trap.h>
22
23 struct per_cpu_info per_cpu_info[MAX_NUM_CPUS];
24
25 // tracks number of global waits on smp_calls, must be <= NUM_HANDLER_WRAPPERS
26 atomic_t outstanding_calls = 0;
27
28 /* All cores end up calling this whenever there is nothing left to do.  Non-zero
29  * cores call it when they are done booting.  Other cases include after getting
30  * a DEATH IPI.
31  * - Management cores (core 0 for now) call manager, which should never return.
32  * - Worker cores halt and wake up when interrupted, do any work on their work
33  *   queue, then halt again.
34  *
35  * TODO: think about resetting the stack pointer at the beginning for worker
36  * cores. (keeps the stack from growing if we never go back to userspace).
37  * TODO: think about unifying the manager into a workqueue function, so we don't
38  * need to check mgmt_core in here.  it gets a little ugly, since there are
39  * other places where we check for mgmt and might not smp_idle / call manager.
40  */
41 void smp_idle(void)
42 {
43         int8_t state = 0;
44         per_cpu_info_t *myinfo = &per_cpu_info[core_id()];
45
46         if (!management_core()) {
47                 enable_irq();
48                 while (1) {
49                         process_routine_kmsg();
50                         cpu_halt();
51                 }
52         } else {
53                 /* techincally, this check is arch dependent.  i want to know if it
54                  * happens.  the enabling/disabling could be interesting. */
55                 enable_irqsave(&state);
56                 if (!STAILQ_EMPTY(&myinfo->immed_amsgs) ||
57                         !STAILQ_EMPTY(&myinfo->routine_amsgs)) 
58                         printk("[kernel] kmsgs in smp_idle() on a management core.\n");
59                 process_routine_kmsg();
60                 disable_irqsave(&state);
61                 manager();
62         }
63         assert(0);
64 }