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