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