Serialize printing during panic()
[akaros.git] / kern / src / manager.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
8 #include <ros/common.h>
9 #include <smp.h>
10 #include <arch/init.h>
11 #include <mm.h>
12 #include <elf.h>
13
14 #include <kmalloc.h>
15 #include <assert.h>
16 #include <manager.h>
17 #include <process.h>
18 #include <schedule.h>
19 #include <syscall.h>
20 #include <ktest.h>
21 #include <stdio.h>
22 #include <time.h>
23 #include <monitor.h>
24 #include <string.h>
25 #include <pmap.h>
26 #include <arch/console.h>
27 #include <time.h>
28
29 /*
30  * Currently, if you leave this function by way of proc_run (process_workqueue
31  * that proc_runs), you will never come back to where you left off, and the
32  * function will start from the top.  Hence the hack 'progress'.
33  */
34 void manager(void)
35 {
36         // LoL
37         #define MANAGER_FUNC(dev) PASTE(manager_,dev)
38
39         #if !defined(DEVELOPER_NAME) && \
40             (defined(CONFIG_KERNEL_TESTING) || \
41              defined(CONFIG_USERSPACE_TESTING))
42                 #define DEVELOPER_NAME jenkins
43         #endif
44
45         #ifndef DEVELOPER_NAME
46                 #define DEVELOPER_NAME brho
47         #endif
48
49         void MANAGER_FUNC(DEVELOPER_NAME)(void);
50         MANAGER_FUNC(DEVELOPER_NAME)();
51 }
52
53 char *p_argv[] = {0, 0, 0};
54 /* Helper macro for quickly running a process.  Pass it a string, *file, and a
55  * *proc. */
56 #define quick_proc_run(x, p, f)                                                  \
57         (f) = do_file_open((x), O_READ, 0);                                          \
58         assert((f));                                                                 \
59         p_argv[0] = file_name((f));                                                  \
60         (p) = proc_create((f), p_argv, NULL);                                        \
61         kref_put(&(f)->f_kref);                                                      \
62         spin_lock(&(p)->proc_lock);                                                  \
63         __proc_set_state((p), PROC_RUNNABLE_S);                                      \
64         spin_unlock(&(p)->proc_lock);                                                \
65         proc_run_s((p));                                                             \
66         proc_decref((p));
67
68 #define quick_proc_create(x, p, f)                                               \
69         (f) = do_file_open((x), O_READ, 0);                                          \
70         assert((f));                                                                 \
71         p_argv[0] = file_name((f));                                                  \
72         (p) = proc_create((f), p_argv, NULL);                                        \
73         kref_put(&(f)->f_kref);                                                      \
74         spin_lock(&(p)->proc_lock);                                                  \
75         __proc_set_state((p), PROC_RUNNABLE_S);                                      \
76         spin_unlock(&(p)->proc_lock);
77
78 #define quick_proc_color_run(x, p, c, f)                                         \
79         (f) = do_file_open((x), O_READ, 0);                                          \
80         assert((f));                                                                 \
81         p_argv[0] = file_name((f));                                                  \
82         (p) = proc_create((f), p_argv, NULL);                                        \
83         kref_put(&(f)->f_kref);                                                      \
84         spin_lock(&(p)->proc_lock);                                                  \
85         __proc_set_state((p), PROC_RUNNABLE_S);                                      \
86         spin_unlock(&(p)->proc_lock);                                                \
87         p->cache_colors_map = cache_colors_map_alloc();                              \
88         for (int i = 0; i < (c); i++)                                                \
89                 cache_color_alloc(llc_cache, p->cache_colors_map);                       \
90         proc_run_s((p));                                                             \
91         proc_decref((p));
92
93 #define quick_proc_color_create(x, p, c, f)                                      \
94         (f) = do_file_open((x), O_READ, 0);                                          \
95         assert((f));                                                                 \
96         p_argv[0] = file_name((f));                                                  \
97         (p) = proc_create((f), p_argv, NULL);                                        \
98         kref_put(&(f)->f_kref);                                                      \
99         spin_lock(&(p)->proc_lock);                                                  \
100         __proc_set_state((p), PROC_RUNNABLE_S);                                      \
101         spin_unlock(&(p)->proc_lock);                                                \
102         p->cache_colors_map = cache_colors_map_alloc();                              \
103         for (int i = 0; i < (c); i++)                                                \
104                 cache_color_alloc(llc_cache, p->cache_colors_map);
105
106 void manager_brho(void)
107 {
108         static bool first = TRUE;
109         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
110
111         if (first) {
112                 printk("*** IRQs must be enabled for input emergency codes ***\n");
113                 #ifdef CONFIG_X86
114                 printk("*** Hit ctrl-g to enter the monitor. ***\n");
115                 printk("*** Hit ctrl-q to force-enter the monitor. ***\n");
116                 printk("*** Hit ctrl-b for a backtrace of core 0 ***\n");
117                 #else
118                 printk("*** Hit ctrl-g to enter the monitor. ***\n");
119                 #warning "***** ctrl-g untested on riscv, check k/a/r/trap.c *****"
120                 #endif
121                 first = FALSE;
122         }
123         /* just idle, and deal with things via interrupts.  or via face. */
124         smp_idle();
125         /* whatever we do in the manager, keep in mind that we need to not do
126          * anything too soon (like make processes), since we'll drop in here during
127          * boot if the boot sequence required any I/O (like EXT2), and we need to
128          * PRKM() */
129         assert(0);
130
131 #if 0 /* ancient tests below: (keeping around til we ditch the manager) */
132         // for testing taking cores, check in case 1 for usage
133         uint32_t corelist[MAX_NUM_CORES];
134         uint32_t num = 3;
135         struct file *temp_f;
136         static struct proc *p;
137
138         static uint8_t RACY progress = 0;       /* this will wrap around. */
139         switch (progress++) {
140                 case 0:
141                         printk("Top of the manager to ya!\n");
142                         /* 124 is half of the available boxboro colors (with the kernel
143                          * getting 8) */
144                         //quick_proc_color_run("msr_dumb_while", p, 124, temp_f);
145                         quick_proc_run("/bin/hello", p, temp_f);
146                         #if 0
147                         // this is how you can transition to a parallel process manually
148                         // make sure you don't proc run first
149                         __proc_set_state(p, PROC_RUNNING_S);
150                         __proc_set_state(p, PROC_RUNNABLE_M);
151                         p->resources[RES_CORES].amt_wanted = 5;
152                         spin_unlock(&p->proc_lock);
153                         core_request(p);
154                         panic("This is okay");
155                         #endif
156                         break;
157                 case 1:
158                         #if 0
159                         udelay(10000000);
160                         // this is a ghetto way to test restarting an _M
161                                 printk("\nattempting to ghetto preempt...\n");
162                                 spin_lock(&p->proc_lock);
163                                 proc_take_allcores(p, __death);
164                                 __proc_set_state(p, PROC_RUNNABLE_M);
165                                 spin_unlock(&p->proc_lock);
166                                 udelay(5000000);
167                                 printk("\nattempting to restart...\n");
168                                 core_request(p); // proc still wants the cores
169                         panic("This is okay");
170                         // this tests taking some cores, and later killing an _M
171                                 printk("taking 3 cores from p\n");
172                                 for (int i = 0; i < num; i++)
173                                         corelist[i] = 7-i; // 7, 6, and 5
174                                 spin_lock(&p->proc_lock);
175                                 proc_take_cores(p, corelist, &num, __death);
176                                 spin_unlock(&p->proc_lock);
177                                 udelay(5000000);
178                                 printk("Killing p\n");
179                                 proc_destroy(p);
180                                 printk("Killed p\n");
181                         panic("This is okay");
182
183                         envs[0] = kfs_proc_create(kfs_lookup_path("roslib_hello"));
184                         __proc_set_state(envs[0], PROC_RUNNABLE_S);
185                         proc_run(envs[0]);
186                         warn("DEPRECATED");
187                         break;
188                         #endif
189                 case 2:
190                         /*
191                         test_smp_call_functions();
192                         test_checklists();
193                         test_barrier();
194                         test_print_info();
195                         test_lapic_status_bit();
196                         test_ipi_sending();
197                         test_pit();
198                         */
199                 default:
200                         printd("Manager Progress: %d\n", progress);
201                         // delay if you want to test rescheduling an MCP that yielded
202                         //udelay(15000000);
203                         run_scheduler();
204         }
205         panic("If you see me, then you probably screwed up");
206         monitor(0);
207
208         /*
209         printk("Servicing syscalls from Core 0:\n\n");
210         while (1) {
211                 process_generic_syscalls(&envs[0], 1);
212                 cpu_relax();
213         }
214         */
215         return;
216 #endif
217 }
218
219 void manager_jenkins()
220 {
221         #ifdef CONFIG_KERNEL_TESTING
222                 printk("<-- BEGIN_KERNEL_TESTS -->\n");
223                 run_registered_ktest_suites();
224                 printk("<-- END_KERNEL_TESTS -->\n");
225         #endif
226
227         // Run userspace tests (from config specified path).
228         #ifdef CONFIG_USERSPACE_TESTING
229         if (strlen(CONFIG_USERSPACE_TESTING_SCRIPT) != 0) {
230                 char exec[] = "/bin/ash";
231                 char *p_argv[] = {exec, CONFIG_USERSPACE_TESTING_SCRIPT, 0};
232
233                 struct file *program = do_file_open(exec, O_READ, 0);
234                 struct proc *p = proc_create(program, p_argv, NULL);
235                 proc_wakeup(p);
236                 proc_decref(p); /* let go of the reference created in proc_create() */
237                 kref_put(&program->f_kref);
238                 run_scheduler();
239             // Need a way to wait for p to finish
240         } else {
241                 printk("No user-space launcher file specified.\n");
242         }
243         #endif
244         smp_idle();
245         assert(0);
246 }
247
248 void manager_klueska()
249 {
250         static struct proc *envs[256];
251         static volatile uint8_t progress = 0;
252
253         if (progress == 0) {
254                 progress++;
255                 panic("what do you want to do?");
256                 //envs[0] = kfs_proc_create(kfs_lookup_path("fillmeup"));
257                 __proc_set_state(envs[0], PROC_RUNNABLE_S);
258                 proc_run_s(envs[0]);
259                 warn("DEPRECATED");
260         }
261         run_scheduler();
262
263         panic("DON'T PANIC");
264 }
265
266 void manager_waterman()
267 {
268         static bool first = true;
269         if (first)
270                 mon_shell(0, 0, 0);
271         smp_idle();
272         assert(0);
273 }
274
275 void manager_yuzhu()
276 {
277
278         static uint8_t progress = 0;
279         static struct proc *p;
280
281         // for testing taking cores, check in case 1 for usage
282         uint32_t corelist[MAX_NUM_CORES];
283         uint32_t num = 3;
284
285         //create_server(init_num_cores, loop);
286
287         monitor(0);
288
289         // quick_proc_run("hello", p);
290
291 }