Fixes sys_change_to memory clobber
[akaros.git] / user / parlib / vcore.c
1 #include <arch/arch.h>
2 #include <stdbool.h>
3 #include <errno.h>
4 #include <vcore.h>
5 #include <mcs.h>
6 #include <sys/param.h>
7 #include <parlib.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <sys/mman.h>
11 #include <stdio.h>
12 #include <event.h>
13 #include <uthread.h>
14 #include <ucq.h>
15 #include <ros/arch/membar.h>
16
17 /* starting with 1 since we alloc vcore0's stacks and TLS in vcore_init(). */
18 static size_t _max_vcores_ever_wanted = 1;
19 atomic_t nr_new_vcores_wanted;
20 atomic_t vc_req_being_handled;
21
22 extern void** vcore_thread_control_blocks;
23 __thread struct syscall __vcore_one_sysc = {.flags = (atomic_t)SC_DONE, 0};
24
25 /* TODO: probably don't want to dealloc.  Considering caching */
26 static void free_transition_tls(int id)
27 {
28         if(vcore_thread_control_blocks[id])
29         {
30                 free_tls(vcore_thread_control_blocks[id]);
31                 vcore_thread_control_blocks[id] = NULL;
32         }
33 }
34
35 static int allocate_transition_tls(int id)
36 {
37         /* We want to free and then reallocate the tls rather than simply 
38          * reinitializing it because its size may have changed.  TODO: not sure if
39          * this is right.  0-ing is one thing, but freeing and reallocating can be
40          * expensive, esp if syscalls are involved.  Check out glibc's
41          * allocatestack.c for what might work. */
42         free_transition_tls(id);
43
44         void *tcb = allocate_tls();
45
46         if ((vcore_thread_control_blocks[id] = tcb) == NULL) {
47                 errno = ENOMEM;
48                 return -1;
49         }
50         return 0;
51 }
52
53 static void free_transition_stack(int id)
54 {
55         // don't actually free stacks
56 }
57
58 static int allocate_transition_stack(int id)
59 {
60         struct preempt_data *vcpd = vcpd_of(id);
61         if (vcpd->transition_stack)
62                 return 0; // reuse old stack
63
64         void* stackbot = mmap(0, TRANSITION_STACK_SIZE,
65                               PROT_READ|PROT_WRITE|PROT_EXEC,
66                               MAP_POPULATE|MAP_ANONYMOUS, -1, 0);
67
68         if(stackbot == MAP_FAILED)
69                 return -1; // errno set by mmap
70
71         vcpd->transition_stack = (uintptr_t)stackbot + TRANSITION_STACK_SIZE;
72
73         return 0;
74 }
75
76 int vcore_init()
77 {
78         static int initialized = 0;
79         uintptr_t mmap_block;
80         /* Note this is racy, but okay.  The only time it'll be 0 is the first time
81          * through, when we are _S */
82         if(initialized)
83                 return 0;
84
85         vcore_thread_control_blocks = (void**)calloc(max_vcores(),sizeof(void*));
86
87         if(!vcore_thread_control_blocks)
88                 goto vcore_init_fail;
89
90         /* Need to alloc vcore0's transition stuff here (technically, just the TLS)
91          * so that schedulers can use vcore0's transition TLS before it comes up in
92          * vcore_entry() */
93         if(allocate_transition_stack(0) || allocate_transition_tls(0))
94                 goto vcore_init_tls_fail;
95
96         /* Initialize our VCPD event queues' ucqs, two pages per ucq, 4 per vcore */
97         mmap_block = (uintptr_t)mmap(0, PGSIZE * 4 * max_vcores(),
98                                      PROT_WRITE | PROT_READ,
99                                      MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
100         /* Yeah, this doesn't fit in the error-handling scheme, but this whole
101          * system doesn't really handle failure, and needs a rewrite involving less
102          * mmaps/munmaps. */
103         assert(mmap_block);
104         /* Note we may end up doing vcore 0's elsewhere, for _Ss, or else have a
105          * separate ev_q for that. */
106         for (int i = 0; i < max_vcores(); i++) {
107                 /* four pages total for both ucqs from the big block (2 pages each) */
108                 ucq_init_raw(&vcpd_of(i)->ev_mbox_public.ev_msgs,
109                              mmap_block + (4 * i    ) * PGSIZE,
110                              mmap_block + (4 * i + 1) * PGSIZE);
111                 ucq_init_raw(&vcpd_of(i)->ev_mbox_private.ev_msgs,
112                              mmap_block + (4 * i + 2) * PGSIZE,
113                              mmap_block + (4 * i + 3) * PGSIZE);
114         }
115         atomic_init(&vc_req_being_handled, 0);
116         assert(!in_vcore_context());
117         initialized = 1;
118         /* no longer need to enable notifs on vcore 0, it is set like that by
119          * default (so you drop into vcore context immediately on transtioning to
120          * _M) */
121         return 0;
122 vcore_init_tls_fail:
123         free(vcore_thread_control_blocks);
124 vcore_init_fail:
125         errno = ENOMEM;
126         return -1;
127 }
128
129 /* this, plus tricking gcc into thinking this is -u (undefined), AND including
130  * the event_init in it, causes the linker to need to check parlib.a and see the
131  * strong symbol... */
132 void force_parlib_symbols(void)
133 {
134         vcore_event_init();
135         assert(0);
136 }
137
138 /* This gets called in glibc before calling the programs 'main'.  Need to set
139  * ourselves up so that thread0 is a uthread, and then register basic signals to
140  * go to vcore 0. */
141 void vcore_event_init(void)
142 {
143         /* set up our thread0 as a uthread */
144         uthread_slim_init();
145         /* TODO: register for other kevents/signals and whatnot (can probably reuse
146          * the simple ev_q).  Could also do this via explicit functions from the
147          * program. */
148 }
149
150 /* Helper, picks some sane defaults and changes the process into an MCP */
151 void vcore_change_to_m(void)
152 {
153         __procdata.res_req[RES_CORES].amt_wanted = 1;
154         __procdata.res_req[RES_CORES].amt_wanted_min = 1;       /* whatever */
155         assert(!in_multi_mode());
156         assert(!in_vcore_context());
157         assert(!sys_change_to_m());
158         assert(in_multi_mode());
159         assert(!in_vcore_context());
160 }
161
162 /* Returns -1 with errno set on error, or 0 on success.  This does not return
163  * the number of cores actually granted (though some parts of the kernel do
164  * internally).
165  *
166  * This tries to get "more vcores", based on the number we currently have.
167  * We'll probably need smarter 2LSs in the future that just directly set
168  * amt_wanted.  What happens is we can have a bunch of 2LS vcore contexts
169  * trying to get "another vcore", which currently means more than num_vcores().
170  * If you have someone ask for two more, and then someone else ask for one more,
171  * how many you ultimately ask for depends on if the kernel heard you and
172  * adjusted num_vcores in between the two calls.  Or maybe your amt_wanted
173  * already was num_vcores + 5, so neither call is telling the kernel anything
174  * new.  It comes down to "one more than I have" vs "one more than I've already
175  * asked for".
176  *
177  * So for now, this will keep the older behavior (one more than I have).  It
178  * will try to accumulate any concurrent requests, and adjust amt_wanted up.
179  * Interleaving, repetitive calls (everyone asking for one more) may get
180  * ignored.
181  *
182  * Note the doesn't block or anything (despite the min number requested is
183  * 1), since the kernel won't block the call.
184  *
185  * There are a few concurrency concerns.  We have _max_vcores_ever_wanted,
186  * initialization of new vcore stacks/TLSs, making sure we don't ask for too
187  * many (minor point), and most importantly not asking the kernel for too much
188  * or otherwise miscommunicating our desires to the kernel.  Remember, the
189  * kernel wants just one answer from the process about what it wants, and it is
190  * up to the process to figure that out.
191  *
192  * So we basically have one thread do the submitting/prepping/bookkeeping, and
193  * other threads come in just update the number wanted and make sure someone
194  * is sorting things out.  This will perform a bit better too, since only one
195  * vcore makes syscalls (which hammer the proc_lock).  This essentially has
196  * cores submit work, and one core does the work (like Eric's old delta
197  * functions).
198  *
199  * There's a slight semantic change: this will return 0 (success) for the
200  * non-submitters, and 0 if we submitted.  -1 only if the submitter had some
201  * non-kernel failure.
202  *
203  * Also, beware that this (like the old version) doesn't protect with races on
204  * num_vcores().  num_vcores() is how many you have now or very soon (accounting
205  * for messages in flight that will take your cores), not how many you told the
206  * kernel you want. */
207 int vcore_request(long nr_new_vcores)
208 {
209         long nr_to_prep_now, nr_vcores_wanted;
210
211         if (vcore_init() < 0)
212                 return -1;      /* consider ERRNO */
213         /* Early sanity checks */
214         if ((nr_new_vcores < 0) || (nr_new_vcores + num_vcores() > max_vcores()))
215                 return -1;      /* consider ERRNO */
216         /* Post our desires (ROS atomic_add() conflicts with glibc) */
217         atomic_fetch_and_add(&nr_new_vcores_wanted, nr_new_vcores);
218 try_handle_it:
219         cmb();  /* inc before swap.  the atomic is a CPU mb() */
220         if (atomic_swap(&vc_req_being_handled, 1)) {
221                 /* We got a 1 back, so someone else is already working on it */
222                 return 0;
223         }
224         /* So now we're the ones supposed to handle things.  This does things in the
225          * "increment based on the number we have", vs "increment on the number we
226          * said we want".
227          *
228          * Figure out how many we have, though this is racy.  Yields/preempts/grants
229          * will change this over time, and we may end up asking for less than we
230          * had. */
231         nr_vcores_wanted = num_vcores();
232         /* Pull all of the vcores wanted into our local variable, where we'll deal
233          * with prepping/requesting that many vcores.  Keep doing this til we think
234          * no more are wanted. */
235         while ((nr_to_prep_now = atomic_swap(&nr_new_vcores_wanted, 0))) {
236                 nr_vcores_wanted += nr_to_prep_now;
237                 /* Don't bother prepping or asking for more than we can ever get */
238                 nr_vcores_wanted = MIN(nr_vcores_wanted, max_vcores());
239                 /* Make sure all we might ask for are prepped */
240                 for (long i = _max_vcores_ever_wanted; i < nr_vcores_wanted; i++) {
241                         if (allocate_transition_stack(i) || allocate_transition_tls(i)) {
242                                 atomic_set(&vc_req_being_handled, 0);   /* unlock and bail out*/
243                                 return -1;
244                         }
245                         _max_vcores_ever_wanted++;      /* done in the loop to handle failures*/
246                 }
247         }
248         cmb();  /* force a reread of num_vcores() */
249         /* Update amt_wanted if we now want *more* than what the kernel already
250          * knows.  See notes in the func doc. */
251         if (nr_vcores_wanted > __procdata.res_req[RES_CORES].amt_wanted)
252                 __procdata.res_req[RES_CORES].amt_wanted = nr_vcores_wanted;
253         /* If num_vcores isn't what we want, we can poke the ksched.  Due to some
254          * races with yield, our desires may be old.  Not a big deal; any vcores
255          * that pop up will just end up yielding (or get preempt messages.)  */
256         if (nr_vcores_wanted > num_vcores())
257                 sys_poke_ksched(RES_CORES);
258         /* Unlock, (which lets someone else work), and check to see if more work
259          * needs to be done.  If so, we'll make sure it gets handled. */
260         atomic_set(&vc_req_being_handled, 0);   /* unlock, to allow others to try */
261         wrmb();
262         /* check for any that might have come in while we were out */
263         if (atomic_read(&nr_new_vcores_wanted))
264                 goto try_handle_it;
265         return 0;
266 }
267
268 /* This can return, if you failed to yield due to a concurrent event.  Note
269  * we're atomicly setting the CAN_RCV flag, and aren't bothering with CASing
270  * (either with the kernel or uthread's handle_indirs()).  We don't particularly
271  * care what other code does - we intend to set those flags no matter what. */
272 void vcore_yield(bool preempt_pending)
273 {
274         uint32_t vcoreid = vcore_id();
275         struct preempt_data *vcpd = vcpd_of(vcoreid);
276         __sync_fetch_and_and(&vcpd->flags, ~VC_CAN_RCV_MSG);
277         /* no wrmb() necessary, clear_notif() has an mb() */
278         /* Clears notif pending.  If we had an event outstanding, this will handle
279          * it and return TRUE, at which point we want to unwind and return to the
280          * 2LS loop (where we may not want to yield anymore).  Note that the kernel
281          * only cares about CAN_RCV_MSG for the desired vcore, not for a FALLBACK.
282          * We need to deal with this notif_pending business regardless of
283          * CAN_RCV_MSG.  We just want to avoid a yield syscall if possible.  It is
284          * important that clear_notif_pending will handle_events().  That is
285          * necessary to do/check after turning off CAN_RCV_MSG. */
286         if (clear_notif_pending(vcoreid)) {
287                 __sync_fetch_and_or(&vcpd->flags, VC_CAN_RCV_MSG);
288                 return;
289         }
290         /* If we are yielding since we don't want the core, tell the kernel we want
291          * one less vcore.  If yield fails (slight race), we may end up having more
292          * vcores than amt_wanted for a while, and might lose one later on (after a
293          * preempt/timeslicing) - the 2LS will have to notice eventually if it
294          * actually needs more vcores (which it already needs to do).  We need to
295          * atomically decrement, though I don't want the kernel's data type here to
296          * be atomic_t (only userspace cares in this one case). */
297         if (!preempt_pending)
298                 __sync_fetch_and_sub(&__procdata.res_req[RES_CORES].amt_wanted, 1);
299         /* We can probably yield.  This may pop back up if notif_pending became set
300          * by the kernel after we cleared it and we lost the race. */
301         sys_yield(preempt_pending);
302         __sync_fetch_and_or(&vcpd->flags, VC_CAN_RCV_MSG);
303 }
304
305 /* Clear pending, and try to handle events that came in between a previous call
306  * to handle_events() and the clearing of pending.  While it's not a big deal,
307  * we'll loop in case we catch any.  Will break out of this once there are no
308  * events, and we will have send pending to 0. 
309  *
310  * Note that this won't catch every race/case of an incoming event.  Future
311  * events will get caught in pop_ros_tf() or proc_yield().
312  *
313  * Also note that this handles events, which may change your current uthread or
314  * might not return!  Be careful calling this.  Check run_uthread for an example
315  * of how to use this. */
316 bool clear_notif_pending(uint32_t vcoreid)
317 {
318         bool handled_event = FALSE;
319         do {
320                 vcpd_of(vcoreid)->notif_pending = 0;
321                 /* need a full mb(), since handle events might be just a read or might
322                  * be a write, either way, it needs to happen after notif_pending */
323                 mb();
324                 handled_event = handle_events(vcoreid);
325         } while (handled_event);
326         return handled_event;
327 }
328
329 /* Enables notifs, and deals with missed notifs by self notifying.  This should
330  * be rare, so the syscall overhead isn't a big deal.  The other alternative
331  * would be to uthread_yield(), which would require us to revert some uthread
332  * interface changes. */
333 void enable_notifs(uint32_t vcoreid)
334 {
335         __enable_notifs(vcoreid);
336         wrmb(); /* need to read after the write that enabled notifs */
337         /* Note we could get migrated before executing this.  If that happens, our
338          * vcore had gone into vcore context (which is what we wanted), and this
339          * self_notify to our old vcore is spurious and harmless. */
340         if (vcpd_of(vcoreid)->notif_pending)
341                 sys_self_notify(vcoreid, EV_NONE, 0, TRUE);
342 }
343
344 /* Helper to disable notifs.  It simply checks to make sure we disabled uthread
345  * migration, which is a common mistake. */
346 void disable_notifs(uint32_t vcoreid)
347 {
348         if (!in_vcore_context() && current_uthread)
349                 assert(current_uthread->flags & UTHREAD_DONT_MIGRATE);
350         __disable_notifs(vcoreid);
351 }
352
353 /* Like smp_idle(), this will put the core in a state that it can only be woken
354  * up by an IPI.  In the future, we may halt or something. */
355 void __attribute__((noreturn)) vcore_idle(void)
356 {
357         uint32_t vcoreid = vcore_id();
358         clear_notif_pending(vcoreid);
359         enable_notifs(vcoreid);
360         while (1) {
361                 cpu_relax();
362         }
363 }
364
365 /* Helper, that actually makes sure a vcore is running.  Call this is you really
366  * want vcoreid.  More often, you'll want to call the regular version. */
367 static void __ensure_vcore_runs(uint32_t vcoreid)
368 {
369         if (vcore_is_preempted(vcoreid)) {
370                 printd("[vcore]: VC %d changing to VC %d\n", vcore_id(), vcoreid);
371                 /* Note that at this moment, the vcore could still be mapped (we're
372                  * racing with __preempt.  If that happens, we'll just fail the
373                  * sys_change_vcore(), and next time __ensure runs we'll get it. */
374                 /* We want to recover them from preemption.  Since we know they have
375                  * notifs disabled, they will need to be directly restarted, so we can
376                  * skip the other logic and cut straight to the sys_change_vcore() */
377                 sys_change_vcore(vcoreid, FALSE);
378         }
379 }
380
381 /* Helper, looks for any preempted vcores, making sure each of them runs at some
382  * point.  This is pretty heavy-weight, and should be used to help get out of
383  * weird deadlocks (spinning in vcore context, waiting on another vcore).  If
384  * you might know which vcore you are waiting on, use ensure_vc_runs. */
385 static void __ensure_all_run(void)
386 {
387         for (int i = 0; i < max_vcores(); i++)
388                 __ensure_vcore_runs(i);
389 }
390
391 /* Makes sure a vcore is running.  If it is preempted, we'll switch to
392  * it.  This will return, either immediately if the vcore is running, or later
393  * when someone preempt-recovers us.
394  *
395  * If you pass in your own vcoreid, this will make sure all other preempted
396  * vcores run. */
397 void ensure_vcore_runs(uint32_t vcoreid)
398 {
399         /* if the vcoreid is ourselves, make sure everyone else is running */
400         if (vcoreid == vcore_id()) {
401                 __ensure_all_run();
402                 return;
403         }
404         __ensure_vcore_runs(vcoreid);
405 }
406
407 #define NR_RELAX_SPINS 1000
408 /* If you are spinning in vcore context and it is likely that you don't know who
409  * you are waiting on, call this.  It will spin for a bit before firing up the
410  * potentially expensive __ensure_all_run().  Don't call this from uthread
411  * context.  sys_change_vcore will probably mess you up. */
412 void cpu_relax_vc(uint32_t vcoreid)
413 {
414         static __thread unsigned int spun;              /* vcore TLS */
415         assert(in_vcore_context());
416         spun = 0;
417         if (spun++ >= NR_RELAX_SPINS) {
418                 /* if vcoreid == vcore_id(), this might be expensive */
419                 ensure_vcore_runs(vcoreid);
420                 spun = 0;
421         }
422         cpu_relax();
423 }
424
425 /* Check with the kernel to determine what vcore we are.  Normally, you should
426  * never call this, since your vcoreid is stored in your TLS.  Also, if you call
427  * it from a uthread, you could get migrated, so you should drop into some form
428  * of vcore context (DONT_MIGRATE on) */
429 uint32_t get_vcoreid(void)
430 {
431         if (!in_vcore_context()) {
432                 assert(current_uthread);
433                 assert(current_uthread->flags & UTHREAD_DONT_MIGRATE);
434         }
435         return __get_vcoreid();
436 }
437
438 /* Debugging helper.  Pass in the string you want printed if your vcoreid is
439  * wrong, and pass in what vcoreid you think you are.  Don't call from uthread
440  * context unless migrations are disabled.  Will print some stuff and return
441  * FALSE if you were wrong. */
442 bool check_vcoreid(const char *str, uint32_t vcoreid)
443 {
444         uint32_t kvcoreid = get_vcoreid();
445         if (vcoreid != kvcoreid) {
446                 ros_debug("%s: VC %d thought it was VC %d\n", str, kvcoreid, vcoreid);
447                 return FALSE;
448         }
449         return TRUE;
450 }