Remove the return value from vcore_request_more()
[akaros.git] / user / parlib / vcore.c
1 #include <parlib/arch/arch.h>
2 #include <stdbool.h>
3 #include <errno.h>
4 #include <parlib/vcore.h>
5 #include <parlib/mcs.h>
6 #include <sys/param.h>
7 #include <parlib/parlib.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <sys/mman.h>
11 #include <stdio.h>
12 #include <parlib/event.h>
13 #include <parlib/uthread.h>
14 #include <parlib/ucq.h>
15 #include <ros/arch/membar.h>
16 #include <parlib/printf-ext.h>
17 #include <parlib/poke.h>
18
19 __thread int __vcoreid = 0;
20 __thread bool __vcore_context = FALSE;
21
22 __thread struct syscall __vcore_one_sysc = {.flags = (atomic_t)SC_DONE, 0};
23
24 /* Per vcore entery function used when reentering at the top of a vcore's stack */
25 static __thread void (*__vcore_reentry_func)(void) = NULL;
26
27 /* The default user vcore_entry function. */
28 void __attribute__((noreturn)) __vcore_entry(void)
29 {
30         extern void uthread_vcore_entry(void);
31         uthread_vcore_entry();
32         fprintf(stderr, "vcore_entry() should never return!\n");
33         abort();
34         __builtin_unreachable();
35 }
36 void vcore_entry(void) __attribute__((weak, alias ("__vcore_entry")));
37
38 /* TODO: probably don't want to dealloc.  Considering caching */
39 static void free_transition_tls(int id)
40 {
41         if (get_vcpd_tls_desc(id)) {
42                 /* Note we briefly have no TLS desc in VCPD.  This is fine so long as
43                  * that vcore doesn't get started fresh before we put in a new desc */
44                 free_tls(get_vcpd_tls_desc(id));
45                 set_vcpd_tls_desc(id, NULL);
46         }
47 }
48
49 static int allocate_transition_tls(int id)
50 {
51         /* Libc function to initialize TLS-based locale info for ctype functions. */
52         extern void __ctype_init(void);
53
54         /* We want to free and then reallocate the tls rather than simply 
55          * reinitializing it because its size may have changed.  TODO: not sure if
56          * this is right.  0-ing is one thing, but freeing and reallocating can be
57          * expensive, esp if syscalls are involved.  Check out glibc's
58          * allocatestack.c for what might work. */
59         free_transition_tls(id);
60
61         void *tcb = allocate_tls();
62         if (!tcb) {
63                 errno = ENOMEM;
64                 return -1;
65         }
66
67         /* Setup some intitial TLS data for the newly allocated transition tls. */
68         void *temp_tcb = get_tls_desc();
69         set_tls_desc(tcb);
70         begin_safe_access_tls_vars();
71         __vcoreid = id;
72         __vcore_context = TRUE;
73         __ctype_init();
74         end_safe_access_tls_vars();
75         set_tls_desc(temp_tcb);
76
77         /* Install the new tls into the vcpd. */
78         set_vcpd_tls_desc(id, tcb);
79         return 0;
80 }
81
82 static void free_vcore_stack(int id)
83 {
84         // don't actually free stacks
85 }
86
87 static int allocate_vcore_stack(int id)
88 {
89         struct preempt_data *vcpd = vcpd_of(id);
90         if (vcpd->vcore_stack)
91                 return 0; // reuse old stack
92
93         void* stackbot = mmap(0, TRANSITION_STACK_SIZE,
94                               PROT_READ|PROT_WRITE|PROT_EXEC,
95                               MAP_POPULATE|MAP_ANONYMOUS, -1, 0);
96
97         if(stackbot == MAP_FAILED)
98                 return -1; // errno set by mmap
99
100         vcpd->vcore_stack = (uintptr_t)stackbot + TRANSITION_STACK_SIZE;
101
102         return 0;
103 }
104
105 /* Helper, initializes a new vcore.  Do not call directly. */
106 static int __prep_new_vcore(int vcoreid)
107 {
108         if (allocate_vcore_stack(vcoreid))
109                 goto error_vc_stack;
110         if (allocate_transition_tls(vcoreid))
111                 goto error_tls;
112         return 0;
113
114 error_tls:
115         free_vcore_stack(vcoreid);
116 error_vc_stack:
117         return -1;
118 }
119
120 /* Initializes vcores before they are used, up to nr_total_vcores.
121  *
122  * Vcores need certain things, such as a stack and TLS.  These are determined by
123  * userspace.  Every vcore needs these set up before we drop into vcore context
124  * on that vcore.  This means we need to prep before asking the kernel for those
125  * vcores. */
126 static int prep_new_vcores(int nr_total_vcores)
127 {
128         static int _max_vcores_ever_wanted = 0;
129
130         for (int i = _max_vcores_ever_wanted; i < nr_total_vcores; i++) {
131                 if (__prep_new_vcore(i))
132                         return -1;
133                 _max_vcores_ever_wanted++;
134         }
135         return 0;
136 }
137
138 /* Run libc specific early setup code. */
139 static void vcore_libc_init(void)
140 {
141         register_printf_specifier('r', printf_errstr, printf_errstr_info);
142         /* TODO: register for other kevents/signals and whatnot (can probably reuse
143          * the simple ev_q).  Could also do this via explicit functions from the
144          * program. */
145 }
146
147 void __attribute__((constructor)) vcore_lib_init(void)
148 {
149         uintptr_t mmap_block;
150
151         /* Note this is racy, but okay.  The first time through, we are _S.
152          * Also, this is the "lowest" level constructor for now, so we don't need
153          * to call any other init functions after our run_once() call. This may
154          * change in the future. */
155         init_once_racy(return);
156
157         /* Need to alloc vcore0's transition stuff here (technically, just the TLS)
158          * so that schedulers can use vcore0's transition TLS before it comes up in
159          * vcore_entry() */
160         if (prep_new_vcores(1))
161                 goto vcore_lib_init_fail;
162
163         /* Initialize our VCPD event queues' ucqs, two pages per ucq, 4 per vcore */
164         mmap_block = (uintptr_t)mmap(0, PGSIZE * 4 * max_vcores(),
165                                      PROT_WRITE | PROT_READ,
166                                      MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
167         /* Yeah, this doesn't fit in the error-handling scheme, but this whole
168          * system doesn't really handle failure, and needs a rewrite involving less
169          * mmaps/munmaps. */
170         assert(mmap_block);
171         /* Note we may end up doing vcore 0's elsewhere, for _Ss, or else have a
172          * separate ev_q for that. */
173         for (int i = 0; i < max_vcores(); i++) {
174                 /* four pages total for both ucqs from the big block (2 pages each) */
175                 vcpd_of(i)->ev_mbox_public.type = EV_MBOX_UCQ;
176                 ucq_init_raw(&vcpd_of(i)->ev_mbox_public.ucq,
177                              mmap_block + (4 * i    ) * PGSIZE,
178                              mmap_block + (4 * i + 1) * PGSIZE);
179                 vcpd_of(i)->ev_mbox_private.type = EV_MBOX_UCQ;
180                 ucq_init_raw(&vcpd_of(i)->ev_mbox_private.ucq,
181                              mmap_block + (4 * i + 2) * PGSIZE,
182                              mmap_block + (4 * i + 3) * PGSIZE);
183                 /* Set the lowest level entry point for each vcore. */
184                 vcpd_of(i)->vcore_entry = (uintptr_t)__kernel_vcore_entry;
185         }
186         assert(!in_vcore_context());
187         vcore_libc_init();
188         return;
189 vcore_lib_init_fail:
190         assert(0);
191 }
192
193 /* Helper functions used to reenter at the top of a vcore's stack for an
194  * arbitrary function */
195 static void __attribute__((noinline, noreturn)) 
196 __vcore_reenter()
197 {
198   __vcore_reentry_func();
199   assert(0);
200 }
201
202 void vcore_reenter(void (*entry_func)(void))
203 {
204   assert(in_vcore_context());
205   struct preempt_data *vcpd = vcpd_of(vcore_id());
206
207   __vcore_reentry_func = entry_func;
208   set_stack_pointer((void*)vcpd->vcore_stack);
209   cmb();
210   __vcore_reenter();
211 }
212
213 /* Helper, picks some sane defaults and changes the process into an MCP */
214 void vcore_change_to_m(void)
215 {
216         int ret;
217         __procdata.res_req[RES_CORES].amt_wanted = 1;
218         __procdata.res_req[RES_CORES].amt_wanted_min = 1;       /* whatever */
219         assert(!in_multi_mode());
220         assert(!in_vcore_context());
221         ret = sys_change_to_m();
222         assert(!ret);
223         assert(in_multi_mode());
224         assert(!in_vcore_context());
225 }
226
227 static void __vc_req_poke(void *nr_vc_wanted)
228 {
229         long nr_vcores_wanted = *(long*)nr_vc_wanted;
230
231         if (prep_new_vcores(nr_vcores_wanted))
232                 panic("Unable to prep up to %d vcores!", nr_vcores_wanted);
233         if (nr_vcores_wanted > __procdata.res_req[RES_CORES].amt_wanted)
234                 __procdata.res_req[RES_CORES].amt_wanted = nr_vcores_wanted;
235         if (nr_vcores_wanted > num_vcores())
236                 sys_poke_ksched(0, RES_CORES);  /* 0 -> poke for ourselves */
237 }
238 static struct poke_tracker vc_req_poke = POKE_INITIALIZER(__vc_req_poke);
239
240 /* Requests the kernel that we have a total of nr_vcores_wanted.
241  *
242  * This is callable by multiple threads/vcores concurrently.  Exactly one of
243  * them will actually run __vc_req_poke.  The others will just return.
244  *
245  * This means that two threads could ask for differing amounts, and only one of
246  * them will succeed.  This is no different than a racy write to a shared
247  * variable.  The poke provides a single-threaded environment, so that we don't
248  * worry about racing on VCPDs or hitting the kernel with excessive SYS_pokes.
249  *
250  * Since we're using the post-and-poke style, we can do a 'last write wins'
251  * policy for the value used in the poke (and subsequent pokes). */
252 void vcore_request_total(long nr_vcores_wanted)
253 {
254         static long nr_vc_wanted;
255
256         if (nr_vcores_wanted == __procdata.res_req[RES_CORES].amt_wanted)
257                 return;
258
259         /* We race to "post our work" here.  Whoever handles the poke will get the
260          * latest value written here. */
261         nr_vc_wanted = nr_vcores_wanted;
262         poke(&vc_req_poke, &nr_vc_wanted);
263 }
264
265 /* This tries to get "more vcores", based on the number we currently have.
266  *
267  * What happens is we can have a bunch of threads trying to get "another vcore",
268  * which currently means more than num_vcores().  If you have someone ask for
269  * two more, and then someone else ask for one more, how many you ultimately ask
270  * for depends on if the kernel heard you and adjusted num_vcores in between the
271  * two calls.  Or maybe your amt_wanted already was num_vcores + 5, so neither
272  * call is telling the kernel anything new.  It comes down to "one more than I
273  * have" vs "one more than I've already asked for".
274  *
275  * So for now, this will keep the older behavior (one more than I have).  This
276  * is all quite racy, so we can just guess and request a total number of vcores.
277  */
278 void vcore_request_more(long nr_new_vcores)
279 {
280         vcore_request_total(nr_new_vcores + num_vcores());
281 }
282
283 /* This can return, if you failed to yield due to a concurrent event.  Note
284  * we're atomicly setting the CAN_RCV flag, and aren't bothering with CASing
285  * (either with the kernel or uthread's handle_indirs()).  We don't particularly
286  * care what other code does - we intend to set those flags no matter what. */
287 void vcore_yield(bool preempt_pending)
288 {
289         unsigned long old_nr;
290         uint32_t vcoreid = vcore_id();
291         struct preempt_data *vcpd = vcpd_of(vcoreid);
292         __sync_fetch_and_and(&vcpd->flags, ~VC_CAN_RCV_MSG);
293         /* no wrmb() necessary, handle_events() has an mb() if it is checking */
294         /* Clears notif pending and tries to handle events.  This is an optimization
295          * to avoid the yield syscall if we have an event pending.  If there is one,
296          * we want to unwind and return to the 2LS loop, where we may not want to
297          * yield anymore.
298          * Note that the kernel only cares about CAN_RCV_MSG for the desired vcore;
299          * when spamming, it relies on membership of lists within the kernel.  Look
300          * at spam_list_member() for more info (k/s/event.c). */
301         if (handle_events(vcoreid)) {
302                 __sync_fetch_and_or(&vcpd->flags, VC_CAN_RCV_MSG);
303                 return;
304         }
305         /* If we are yielding since we don't want the core, tell the kernel we want
306          * one less vcore (vc_yield assumes a dumb 2LS).
307          *
308          * If yield fails (slight race), we may end up having more vcores than
309          * amt_wanted for a while, and might lose one later on (after a
310          * preempt/timeslicing) - the 2LS will have to notice eventually if it
311          * actually needs more vcores (which it already needs to do).  amt_wanted
312          * could even be 0.
313          *
314          * In general, any time userspace decrements or sets to 0, it could get
315          * preempted, so the kernel will still give us at least one, until the last
316          * vcore properly yields without missing a message (and becomes a WAITING
317          * proc, which the ksched will not give cores to).
318          *
319          * I think it's possible for userspace to do this (lock, read amt_wanted,
320          * check all message queues for all vcores, subtract amt_wanted (not set to
321          * 0), unlock) so long as every event handler +1s the amt wanted, but that's
322          * a huge pain, and we already have event handling code making sure a
323          * process can't sleep (transition to WAITING) if a message arrives (can't
324          * yield if notif_pending, can't go WAITING without yielding, and the event
325          * posting the notif_pending will find the online VC or be delayed by
326          * spinlock til the proc is WAITING). */
327         if (!preempt_pending) {
328                 do {
329                         old_nr = __procdata.res_req[RES_CORES].amt_wanted;
330                         if (old_nr == 0)
331                                 break;
332                 } while (!__sync_bool_compare_and_swap(
333                              &__procdata.res_req[RES_CORES].amt_wanted,
334                              old_nr, old_nr - 1));
335         }
336         /* We can probably yield.  This may pop back up if notif_pending became set
337          * by the kernel after we cleared it and we lost the race. */
338         sys_yield(preempt_pending);
339         __sync_fetch_and_or(&vcpd->flags, VC_CAN_RCV_MSG);
340 }
341
342 /* Enables notifs, and deals with missed notifs by self notifying.  This should
343  * be rare, so the syscall overhead isn't a big deal.  The other alternative
344  * would be to uthread_yield(), which would require us to revert some uthread
345  * interface changes. */
346 void enable_notifs(uint32_t vcoreid)
347 {
348         __enable_notifs(vcoreid);
349         wrmb(); /* need to read after the write that enabled notifs */
350         /* Note we could get migrated before executing this.  If that happens, our
351          * vcore had gone into vcore context (which is what we wanted), and this
352          * self_notify to our old vcore is spurious and harmless. */
353         if (vcpd_of(vcoreid)->notif_pending)
354                 sys_self_notify(vcoreid, EV_NONE, 0, TRUE);
355 }
356
357 /* Helper to disable notifs.  It simply checks to make sure we disabled uthread
358  * migration, which is a common mistake. */
359 void disable_notifs(uint32_t vcoreid)
360 {
361         if (!in_vcore_context() && current_uthread)
362                 assert(current_uthread->flags & UTHREAD_DONT_MIGRATE);
363         __disable_notifs(vcoreid);
364 }
365
366 /* Like smp_idle(), this will put the core in a state that it can only be woken
367  * up by an IPI.  For now, this is a halt.  Maybe an mwait in the future.
368  *
369  * This will return if an event was pending (could be the one you were waiting
370  * for) or if the halt failed for some reason, such as a concurrent RKM.  If
371  * successful, this will not return at all, and the vcore will restart from the
372  * top next time it wakes.  Any sort of IRQ will wake the core.
373  *
374  * Alternatively, I might make this so it never returns, if that's easier to
375  * work with (similar issues with yield). */
376 void vcore_idle(void)
377 {
378         uint32_t vcoreid = vcore_id();
379         /* Once we enable notifs, the calling context will be treated like a uthread
380          * (saved into the uth slot).  We don't want to ever run it again, so we
381          * need to make sure there's no cur_uth. */
382         assert(!current_uthread);
383         /* This clears notif_pending (check, signal, check again pattern). */
384         if (handle_events(vcoreid))
385                 return;
386         /* This enables notifs, but also checks notif pending.  At this point, any
387          * new notifs will restart the vcore from the top. */
388         enable_notifs(vcoreid);
389         /* From now, til we get into the kernel, any notifs will permanently destroy
390          * this context and start the VC from the top.
391          *
392          * Once we're in the kernel, any messages (__notify, __preempt), will be
393          * RKMs.  halt will need to check for those atomically.  Checking for
394          * notif_pending in the kernel (sleep only if not set) is not enough, since
395          * not all reasons for the kernel to stay awak set notif_pending (e.g.,
396          * __preempts and __death).
397          *
398          * At this point, we're out of VC ctx, so anyone who sets notif_pending
399          * should also send an IPI / __notify */
400         sys_halt_core(0);
401         /* in case halt returns without actually restarting the VC ctx. */
402         disable_notifs(vcoreid);
403 }
404
405 /* Helper, that actually makes sure a vcore is running.  Call this is you really
406  * want vcoreid.  More often, you'll want to call the regular version. */
407 static void __ensure_vcore_runs(uint32_t vcoreid)
408 {
409         if (vcore_is_preempted(vcoreid)) {
410                 printd("[vcore]: VC %d changing to VC %d\n", vcore_id(), vcoreid);
411                 /* Note that at this moment, the vcore could still be mapped (we're
412                  * racing with __preempt.  If that happens, we'll just fail the
413                  * sys_change_vcore(), and next time __ensure runs we'll get it. */
414                 /* We want to recover them from preemption.  Since we know they have
415                  * notifs disabled, they will need to be directly restarted, so we can
416                  * skip the other logic and cut straight to the sys_change_vcore() */
417                 sys_change_vcore(vcoreid, FALSE);
418         }
419 }
420
421 /* Helper, looks for any preempted vcores, making sure each of them runs at some
422  * point.  This is pretty heavy-weight, and should be used to help get out of
423  * weird deadlocks (spinning in vcore context, waiting on another vcore).  If
424  * you might know which vcore you are waiting on, use ensure_vc_runs. */
425 static void __ensure_all_run(void)
426 {
427         for (int i = 0; i < max_vcores(); i++)
428                 __ensure_vcore_runs(i);
429 }
430
431 /* Makes sure a vcore is running.  If it is preempted, we'll switch to
432  * it.  This will return, either immediately if the vcore is running, or later
433  * when someone preempt-recovers us.
434  *
435  * If you pass in your own vcoreid, this will make sure all other preempted
436  * vcores run. */
437 void ensure_vcore_runs(uint32_t vcoreid)
438 {
439         /* if the vcoreid is ourselves, make sure everyone else is running */
440         if (vcoreid == vcore_id()) {
441                 __ensure_all_run();
442                 return;
443         }
444         __ensure_vcore_runs(vcoreid);
445 }
446
447 #define NR_RELAX_SPINS 1000
448 /* If you are spinning in vcore context and it is likely that you don't know who
449  * you are waiting on, call this.  It will spin for a bit before firing up the
450  * potentially expensive __ensure_all_run().  Don't call this from uthread
451  * context.  sys_change_vcore will probably mess you up. */
452 void cpu_relax_vc(uint32_t vcoreid)
453 {
454         static __thread unsigned int __vc_relax_spun = 0;
455         assert(in_vcore_context());
456         if (__vc_relax_spun++ >= NR_RELAX_SPINS) {
457                 /* if vcoreid == vcore_id(), this might be expensive */
458                 ensure_vcore_runs(vcoreid);
459                 __vc_relax_spun = 0;
460         }
461         cpu_relax();
462 }
463
464 /* Check with the kernel to determine what vcore we are.  Normally, you should
465  * never call this, since your vcoreid is stored in your TLS.  Also, if you call
466  * it from a uthread, you could get migrated, so you should drop into some form
467  * of vcore context (DONT_MIGRATE on) */
468 uint32_t get_vcoreid(void)
469 {
470         if (!in_vcore_context()) {
471                 assert(current_uthread);
472                 assert(current_uthread->flags & UTHREAD_DONT_MIGRATE);
473         }
474         return __get_vcoreid();
475 }
476
477 /* Debugging helper.  Pass in the string you want printed if your vcoreid is
478  * wrong, and pass in what vcoreid you think you are.  Don't call from uthread
479  * context unless migrations are disabled.  Will print some stuff and return
480  * FALSE if you were wrong. */
481 bool check_vcoreid(const char *str, uint32_t vcoreid)
482 {
483         uint32_t kvcoreid = get_vcoreid();
484         if (vcoreid != kvcoreid) {
485                 printf("%s: VC %d thought it was VC %d\n", str, kvcoreid, vcoreid);
486                 return FALSE;
487         }
488         return TRUE;
489 }
490
491 /* Helper.  Yields the vcore, or restarts it from scratch. */
492 void __attribute__((noreturn)) vcore_yield_or_restart(void)
493 {
494         struct preempt_data *vcpd = vcpd_of(vcore_id());
495
496         vcore_yield(FALSE);
497         /* If vcore_yield returns, we have an event.  Just restart vcore context. */
498         set_stack_pointer((void*)vcpd->vcore_stack);
499         vcore_entry();
500 }