Changes for nameservice. Use RPC client for NS functionality.
[barrelfish] / lib / barrelfish / domain.c
1 /**
2  * \file
3  * \brief Manage domain spanning cores
4  *
5  * \bug Need to specify how big the default thread on the spanned dispatcher
6  * should be because we cannot dynamically grow our stacks
7  *
8  * \bug Can only do domain_new_dispatcher() when no other dispatchers have
9  * threads (except for the internal interdisp-thread).
10  */
11
12 /*
13  * Copyright (c) 2009, 2010, 2011, ETH Zurich.
14  * All rights reserved.
15  *
16  * This file is distributed under the terms in the attached LICENSE file.
17  * If you do not find this file, copies can be found by writing to:
18  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
19  */
20
21 #include <stdio.h>
22 #include <barrelfish/barrelfish.h>
23 #include <barrelfish/curdispatcher_arch.h>
24 #include <barrelfish/dispatcher_arch.h>
25 #include <arch/registers.h>
26 #include <barrelfish/dispatch.h>
27 #include <if/interdisp_defs.h>
28 #include "arch/threads.h"
29 #include "init.h"
30 #include <if/monitor_defs.h>
31 #include "threads.h"
32 #include "waitset_chan.h"
33
34 ///< Struct to maintain per dispatcher domain library state
35 struct domain_state {
36     iref_t iref;  ///< Iref for the interdisp service
37     struct interdisp_binding *b[MAX_CPUS];
38     struct waitset interdisp_ws;
39     struct thread *default_waitset_handler;
40     struct thread *remote_wakeup_queue;
41     struct waitset_chanstate remote_wakeup_event;
42     bool conditional;
43 };
44
45 ///< Struct to send init information to the dispatcher that was spanned
46 struct remote_core_state {
47     iref_t iref;                  ///< Iref of the interdisp service to connect to
48     uint8_t core_id;              ///< Core id of the domain that spanned this dispatcher
49     struct span_domain_state *span_domain_state; ///< Reference to the span_domain_state of the "server"
50     bool initialized;             ///< true if remote core is fully initialized
51     int cnt;                      ///< Used to count dispatcher connected
52 };
53
54 ///< Struct for spanning domains state machine
55 struct span_domain_state {
56     struct thread *thread;              ///< Thread to run on remote core
57     uint8_t core_id;                    ///< Id of the remote core
58     errval_t err;                       ///< To propagate error value
59     domain_spanned_callback_t callback; ///< Callback for when domain has spanned
60     void *callback_arg;                 ///< Optional argument to pass with callback
61     struct capref frame;                ///< Dispatcher frame
62     struct capref vroot;                ///< VRoot cap
63     struct event_queue_node event_qnode;       ///< Event queue node
64     struct waitset_chanstate initev;    ///< Dispatcher initialized event
65     bool initialized;                   ///< True if remote initialized
66 };
67
68 ///< Array of all interdisp IREFs in the domain
69 static iref_t allirefs[MAX_CPUS];
70
71 static void dispatcher_initialized_handler(void *arg)
72 {
73     struct span_domain_state *span_domain_state = arg;
74 #if 0
75     struct domain_state *domain_state = get_domain_state();
76
77     // XXX: Tell currently active interdisp-threads to handle default waitset
78     for(int i = 0; i < MAX_CPUS; i++) {
79         struct interdisp_binding *b = domain_state->b[i];
80
81         if(disp_get_core_id() != i &&
82            span_domain_state->core_id != i && b != NULL) {
83             errval_t err = b->tx_vtbl.span_slave_done(b, NOP_CONT);
84             assert(err_is_ok(err));
85         }
86     }
87 #endif
88
89     /* Upcall into the domain_new_dispatcher callback if registered */
90     if (span_domain_state->callback) {
91         span_domain_state->callback(span_domain_state->callback_arg, SYS_ERR_OK);
92     }
93
94     free(span_domain_state);
95 }
96
97 /**
98  * \brief Handled for dispatcher_initialized msg type
99  *
100  * Called when a recently spanned dispatcher has initialized.
101  * Store it's connection object, and upcall into the registered callback
102  */
103 static void dispatcher_initialized(struct interdisp_binding *st, genvaddr_t id)
104 {
105     struct span_domain_state *span_domain_state = (struct span_domain_state*)(uintptr_t)id;
106
107     // Signal the default waitset of this event
108     struct event_closure closure = {
109         .handler = dispatcher_initialized_handler,
110         .arg = span_domain_state,
111     };
112     waitset_chanstate_init(&span_domain_state->initev, CHANTYPE_EVENT_QUEUE);
113     errval_t err = waitset_chan_trigger_closure(get_default_waitset(),
114                                                 &span_domain_state->initev,
115                                                 closure);
116     if(err_is_fail(err)) {
117         USER_PANIC_ERR(err, "Triggering default waitset");
118     }
119 }
120
121 static void send_cap_request(struct interdisp_binding *st,
122                              struct capref cap, genvaddr_t info)
123 {
124     errval_t err = SYS_ERR_OK, err2;
125     struct capref *dest = (struct capref *)(uintptr_t)info;
126
127     err = cap_copy(*dest, cap);
128     if(err_is_fail(err)) {
129         err_push(err, LIB_ERR_CAP_COPY_FAIL);
130         DEBUG_ERR(err, "cap_copy");
131         abort();
132         goto send_reply;
133     }
134     err = cap_destroy(cap);
135     if(err_is_fail(err)) {
136         err_push(err, LIB_ERR_CAP_DELETE_FAIL);
137         DEBUG_ERR(err, "cap_destroy default");
138         abort();
139         goto send_reply;
140     }
141
142  send_reply:
143     err2 = st->tx_vtbl.send_cap_reply(st, NOP_CONT, err);
144     if (err_is_fail(err2)) {
145         DEBUG_ERR(err, "Failed to send send_cap_reply");
146     }
147 }
148
149 static errval_t send_cap_err = SYS_ERR_OK;
150 static bool cap_received = false;
151
152 static void send_cap_reply(struct interdisp_binding *st, errval_t err)
153 {
154     send_cap_err = err;
155     cap_received = true;
156 }
157
158 static void create_thread_request(struct interdisp_binding *b,
159                                   genvaddr_t funcaddr, genvaddr_t argaddr,
160                                   uint64_t stacksize)
161 {
162     thread_func_t start_func = (thread_func_t)(uintptr_t)funcaddr;
163     void *arg = (void *)(uintptr_t)argaddr;
164     struct thread *newthread;
165
166     // XXX: Probably want to return pointer to thread struct to caller
167     if(stacksize > 0) {
168         newthread = thread_create_varstack(start_func, arg, stacksize);
169     } else {
170         newthread = thread_create(start_func, arg);
171     }
172     assert(newthread != NULL);
173 }
174
175 static void wakeup_thread_request(struct interdisp_binding *b,
176                                   genvaddr_t taddr)
177 {
178     coreid_t core_id = disp_get_core_id();
179     struct thread *wakeup = (struct thread *)(uintptr_t)taddr;
180     dispatcher_handle_t handle = disp_disable();
181     struct dispatcher_generic *disp_gen = get_dispatcher_generic(handle);
182     /* assert_disabled(wakeup->disp == handle); */
183     assert_disabled(wakeup->coreid == core_id);
184     wakeup->disp = handle;
185     thread_enqueue(wakeup, &disp_gen->runq);
186     disp_enable(handle);
187 }
188
189 /*
190  * XXX: The whole span_slave*() thing is a hack to allow all
191  * dispatchers to wait on both the monitor and interdisp waitsets
192  * while we bind to all.
193  */
194
195 static int span_slave_thread(void *arg)
196 {
197     errval_t err = thread_detach(thread_self());
198     assert(err_is_ok(err));
199
200     for(;;) {
201         event_dispatch(get_default_waitset());
202     }
203
204     return 0;
205 }
206
207 static void span_slave_request(struct interdisp_binding *b)
208 {
209     USER_PANIC("shouldn't be called");
210     thread_create(span_slave_thread, NULL);
211 }
212
213 static void span_slave_done_handler(void *cs)
214 {
215     USER_PANIC("shouldn't be called");
216     free(cs);
217     thread_exit();
218 }
219
220 static void span_slave_done_request(struct interdisp_binding *b)
221 {
222     USER_PANIC("shouldn't be called");
223     struct waitset_chanstate *cs = malloc(sizeof(struct waitset_chanstate));
224
225     // Signal the default waitset of this event
226     struct event_closure closure = {
227         .handler = span_slave_done_handler,
228         .arg = cs,
229     };
230     waitset_chanstate_init(cs, CHANTYPE_EVENT_QUEUE);
231     errval_t err = waitset_chan_trigger_closure(get_default_waitset(), cs,
232                                                 closure);
233     if(err_is_fail(err)) {
234         USER_PANIC_ERR(err, "Triggering default waitset");
235     }
236 }
237
238 static void span_eager_connect_request(struct interdisp_binding *b,
239                                        coreid_t core_id)
240 {
241     struct domain_state *domain_state = get_domain_state();
242
243     /* Store the sending core's connection */
244     domain_state->b[core_id] = b;
245 }
246
247 static struct interdisp_rx_vtbl interdisp_vtbl = {
248     .dispatcher_initialized = dispatcher_initialized,
249
250     .send_cap_request = send_cap_request,
251     .send_cap_reply = send_cap_reply,
252
253     .wakeup_thread    = wakeup_thread_request,
254     .create_thread    = create_thread_request,
255
256     // XXX: Hack to allow domain_new_dispatcher() to proceed when not all
257     // default waitsets are serviced
258     .span_slave       = span_slave_request,
259     .span_slave_done  = span_slave_done_request,
260     .span_eager_connect = span_eager_connect_request,
261 };
262
263 /**
264  * \brief Called when the "client" connects to "server"
265  *
266  * Make the connection a "server" connection, free unnecessary state.
267  * Send init msg to the dispatcher that spanned this dispatcher.
268  */
269 static void client_connected(void *st, errval_t err,
270                              struct interdisp_binding *b)
271 {
272     struct remote_core_state *state = (struct remote_core_state*)st;
273     struct domain_state *domain_state = get_domain_state();
274
275     if(err_is_fail(err)) {
276         DEBUG_ERR(err, "binding to interdisp service");
277         abort();
278     }
279
280     /* Set it on the domain library state */
281     b->rx_vtbl = interdisp_vtbl;
282     domain_state->b[state->cnt] = b;
283
284     // Send it our core id
285     err = b->tx_vtbl.span_eager_connect(b, NOP_CONT, disp_get_core_id());
286     if(err_is_fail(err)) {
287         USER_PANIC_ERR(err, "sending span_eager_connect");
288     }
289
290     // Connect to next active dispatcher
291     do {
292         state->cnt++;
293         if(state->cnt == disp_get_core_id()) {
294             state->cnt++;
295         }
296     } while(allirefs[state->cnt] == NULL_IREF && state->cnt < MAX_CPUS);
297
298     if(state->cnt < MAX_CPUS) {
299         err = interdisp_bind(allirefs[state->cnt], client_connected,
300                              state, &domain_state->interdisp_ws,
301                              IDC_BIND_FLAGS_DEFAULT);
302         if(err_is_fail(err)) {
303             USER_PANIC_ERR(err, "Binding to inter-dispatcher service");
304         }
305     } else {
306         struct interdisp_binding *sb = domain_state->b[state->core_id];
307         /* Send initialized msg to the dispatcher that spanned us */
308         errval_t err2 = sb->tx_vtbl.
309             dispatcher_initialized(sb, NOP_CONT,
310                                    (uintptr_t)state->span_domain_state);
311         if (err_is_fail(err2)) {
312             DEBUG_ERR(err, "failed to send initalized msg");
313             abort();
314         }
315
316         state->initialized = true;
317     }
318 }
319
320 static errval_t server_connected(void *st, struct interdisp_binding *b)
321 {
322     b->rx_vtbl = interdisp_vtbl;
323     return SYS_ERR_OK;
324 }
325
326 /**
327  * \brief Called when domain gets a interdisp service.
328  * It will set it on the domain_state.
329  */
330 static void server_listening(void *st, errval_t err, iref_t iref)
331 {
332     if(err_is_fail(err)) {
333         DEBUG_ERR(err, "interdisp service export");
334         abort();
335     }
336
337     struct domain_state *domain_state = get_domain_state();
338     domain_state->iref = iref;
339
340     // Also set in the global array
341     allirefs[disp_get_core_id()] = iref;
342     domain_state->conditional = true;
343 }
344
345 /**
346  * \brief Called on the inter-disp handler thread, when another thread
347  * on this dispatcher wants to wakeup a thread on a foreign dispatcher.
348  */
349 static void handle_wakeup_on(void *arg)
350 {
351     struct domain_state *domain_state = get_domain_state();
352     errval_t err;
353
354     assert(domain_state != NULL);
355
356     // Dequeue all (disable to ensure mutual exclusion -- per dispatcher)
357     for(;;) {
358         struct thread *thread = NULL;
359
360         dispatcher_handle_t disp = disp_disable();
361         if(domain_state->remote_wakeup_queue != NULL) {
362             thread = thread_dequeue(&domain_state->remote_wakeup_queue);
363         }
364         disp_enable(disp);
365
366         // Break if queue empty
367         if(thread == NULL) {
368             break;
369         }
370
371         // XXX: Hack
372         /* coreid_t core_id = disp_handle_get_core_id(thread->disp); */
373         coreid_t core_id = thread->coreid;
374
375         assert(domain_state->b[core_id] != NULL);
376
377         struct interdisp_binding *b = domain_state->b[core_id];
378         err = b->tx_vtbl.wakeup_thread(b, NOP_CONT, (genvaddr_t)(uintptr_t)thread);
379         if (err_is_fail(err)) {
380             USER_PANIC_ERR(err, "wakeup_thread");
381         }
382     }
383 }
384
385 /**
386  * \brief Handler thread for inter-dispatcher messages
387  * \param arg   Pointer to inter-dispatcher waitset
388  * \return 0 on successful exit
389  */
390 static int interdisp_msg_handler(void *arg)
391 {
392     struct waitset *ws = arg;
393     assert(ws != NULL);
394
395     for(;;) {
396         errval_t err = event_dispatch(ws);
397         if(err_is_fail(err)) {
398             USER_PANIC_ERR(err, "error on event dispatch");
399         }
400     }
401
402     return 0;
403 }
404
405 /**
406  * \brief Runs enabled on the remote core to initialize the dispatcher
407  */
408 static int remote_core_init_enabled(void *arg)
409 {
410     errval_t err;
411     struct remote_core_state *remote_core_state =
412         (struct remote_core_state*)arg;
413
414     /* Initialize the barrelfish library */
415     err = barrelfish_init_onthread(NULL);
416     if (err_is_fail(err)) {
417         DEBUG_ERR(err, "barrelfish_init_onthread failed");
418         abort();
419         return -1;
420     }
421
422     // Connect to all dispatchers eagerly
423     remote_core_state->cnt = 0;
424     while(allirefs[remote_core_state->cnt] == NULL_IREF && remote_core_state->cnt < MAX_CPUS) {
425         remote_core_state->cnt++;
426         if(remote_core_state->cnt == disp_get_core_id()) {
427             remote_core_state->cnt++;
428         }
429     }
430     // Don't move before barrelfish_init_onthread()
431     struct domain_state *st = get_domain_state();
432     if(remote_core_state->cnt != MAX_CPUS) {
433         err = interdisp_bind(allirefs[remote_core_state->cnt], client_connected,
434                              remote_core_state, &st->interdisp_ws,
435                              IDC_BIND_FLAGS_DEFAULT);
436         if(err_is_fail(err)) {
437             USER_PANIC_ERR(err, "Failure binding to inter-dispatcher service");
438         }
439     }
440
441     while(!remote_core_state->initialized) {
442         event_dispatch(get_default_waitset());
443     }
444
445     /* Free unnecessary state */
446     free(remote_core_state);
447
448     /* XXX: create a thread that will handle the default waitset */
449     st->default_waitset_handler = thread_create(span_slave_thread, NULL);
450     assert(st->default_waitset_handler != NULL);
451
452     return interdisp_msg_handler(&st->interdisp_ws);
453 }
454
455 /**
456  * \brief Runs disabled on the remote core to initialize
457  */
458 static void remote_core_init_disabled(struct thread *thread)
459 {
460     dispatcher_handle_t disp = thread->disp;
461
462     /* Initialize the dispatcher */
463     disp_init_disabled(disp);
464
465     /* Initialize the threads library, and call remote_core_init_enabled */
466     thread_init_remote(disp, thread);
467 }
468
469 /**
470  * \brief Initialize the domain library
471  *
472  * Registers a iref with the monitor to offer the interdisp service on this core
473  * Does not block for completion.
474  */
475 errval_t domain_init(void)
476 {
477     errval_t err;
478     struct domain_state *domain_state = malloc(sizeof(struct domain_state));
479     if (!domain_state) {
480         return LIB_ERR_MALLOC_FAIL;
481     }
482     set_domain_state(domain_state);
483
484     domain_state->iref = 0;
485     domain_state->default_waitset_handler = NULL;
486     domain_state->remote_wakeup_queue = NULL;
487     waitset_chanstate_init(&domain_state->remote_wakeup_event,
488                            CHANTYPE_EVENT_QUEUE);
489     for (int i = 0; i < MAX_CPUS; i++) {
490         domain_state->b[i] = NULL;
491     }
492
493     waitset_init(&domain_state->interdisp_ws);
494     domain_state->conditional = false;
495     err = interdisp_export(NULL, server_listening, server_connected,
496                            &domain_state->interdisp_ws, IDC_EXPORT_FLAGS_DEFAULT);
497     if (err_is_fail(err)) {
498         return err;
499     }
500
501     // XXX: Wait for the export to finish before returning
502     while(!domain_state->conditional) {
503         messages_wait_and_handle_next();
504     }
505
506     return SYS_ERR_OK;
507 }
508
509 /**
510  * \brief Handler to continue spanning domain state machine
511  */
512 static void span_domain_reply(struct monitor_binding *mb,
513                               errval_t msgerr, uintptr_t domain_id)
514 {
515     errval_t err;
516     struct span_domain_state *span_domain_state =
517         (struct span_domain_state*)domain_id;
518
519     /* Check if span_domain_request failed */
520     if (err_is_fail(msgerr)) {
521         err = msgerr;
522         goto error;
523     }
524
525     /* Free the dispatcher frame */
526     err = cap_destroy(span_domain_state->frame);
527     if (err_is_fail(err)) {
528         err_push(err, LIB_ERR_CAP_DESTROY);
529         goto error;
530     }
531
532     return;
533
534  error:
535     if (span_domain_state->callback) { /* Use the callback to return error */
536         span_domain_state->callback(span_domain_state->callback_arg, err);
537     } else { /* Use debug_err if no callback registered */
538         DEBUG_ERR(err, "Failure in span_domain_reply");
539     }
540     free(span_domain_state);
541 }
542
543 static void span_domain_request_sender(void *arg)
544 {
545     struct monitor_binding *mb = arg;
546     struct span_domain_state *st = mb->st;
547
548     errval_t err = mb->tx_vtbl.
549         span_domain_request(mb, NOP_CONT, (uintptr_t)st, st->core_id, st->vroot,
550                             st->frame);
551     if (err_is_ok(err)) {
552         event_mutex_unlock(&mb->mutex);
553     } else if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
554         /* Wait to use the monitor binding */
555         err = mb->register_send(mb, mb->waitset,
556                                 MKCONT(span_domain_request_sender,mb));
557         if(err_is_fail(err)) { // shouldn't fail, as we have the mutex
558             USER_PANIC_ERR(err, "register_send");
559         }
560     } else { // permanent error
561         event_mutex_unlock(&mb->mutex);
562         err = err_push(err, MON_CLIENT_ERR_SPAN_DOMAIN_REQUEST);
563         DEBUG_ERR(err, "span_domain_request");
564     }
565 }
566
567 static void span_domain_request_sender_wrapper(void *st)
568 {
569     struct monitor_binding *mb = get_monitor_binding();
570     mb->st = st;
571     span_domain_request_sender(mb);
572 }
573
574 /**
575  * \brief Since we cannot dynamically grow our stack yet, we need a
576  * verion that will create threads on remote core with variable stack size
577  *
578  * \bug this is a hack
579  */
580 static errval_t domain_new_dispatcher_varstack(coreid_t core_id,
581                                                domain_spanned_callback_t callback,
582                                                void *callback_arg, size_t stack_size)
583 {
584     assert(core_id != disp_get_core_id());
585
586     errval_t err;
587     struct domain_state *domain_state = get_domain_state();
588     struct monitor_binding *mb = get_monitor_binding();
589     assert(domain_state != NULL);
590
591     /* Set reply handler */
592     mb->rx_vtbl.span_domain_reply = span_domain_reply;
593
594     while(domain_state->iref == 0) { /* If not initialized, wait */
595         messages_wait_and_handle_next();
596     }
597
598     /* Create the remote_core_state passed to the new dispatcher */
599     struct remote_core_state *remote_core_state =
600         calloc(1, sizeof(struct remote_core_state));
601     if (!remote_core_state) {
602         return LIB_ERR_MALLOC_FAIL;
603     }
604     remote_core_state->core_id = disp_get_core_id();
605     remote_core_state->iref    = domain_state->iref;
606
607     /* Create the thread for the new dispatcher to init on */
608     struct thread *newthread =
609         thread_create_unrunnable(remote_core_init_enabled,
610                                  (void*)remote_core_state, stack_size);
611     if (newthread == NULL) {
612         return LIB_ERR_THREAD_CREATE;
613     }
614
615     /* Save the state for later steps of the spanning state machine */
616     struct span_domain_state *span_domain_state =
617         malloc(sizeof(struct span_domain_state));
618     if (!span_domain_state) {
619         return LIB_ERR_MALLOC_FAIL;
620     }
621     span_domain_state->thread       = newthread;
622     span_domain_state->core_id      = core_id;
623     span_domain_state->callback     = callback;
624     span_domain_state->callback_arg = callback_arg;
625
626     /* Give remote_core_state pointer to span_domain_state */
627     remote_core_state->span_domain_state = span_domain_state;
628
629     /* Start spanning domain state machine by sending vroot to the monitor */
630     struct capref vroot = {
631         .cnode = cnode_page,
632         .slot = 0
633     };
634
635     /* Create new dispatcher frame */
636     struct capref frame;
637     size_t dispsize = ((size_t)1) << DISPATCHER_FRAME_BITS;
638     err = frame_alloc(&frame, dispsize, &dispsize);
639     if (err_is_fail(err)) {
640         return err_push(err, LIB_ERR_FRAME_ALLOC);
641     }
642     lvaddr_t dispaddr;
643
644     err = vspace_map_one_frame((void **)&dispaddr, dispsize, frame, NULL, NULL);
645     if (err_is_fail(err)) {
646         return err_push(err, LIB_ERR_VSPACE_MAP);
647     }
648
649     dispatcher_handle_t handle = dispaddr;
650     struct dispatcher_shared_generic *disp =
651         get_dispatcher_shared_generic(handle);
652     struct dispatcher_generic *disp_gen = get_dispatcher_generic(handle);
653     arch_registers_state_t *disabled_area =
654         dispatcher_get_disabled_save_area(handle);
655
656     /* Set dispatcher on the newthread */
657     span_domain_state->thread->disp = handle;
658     span_domain_state->frame = frame;
659     span_domain_state->vroot = vroot;
660
661     /* Setup dispatcher */
662     disp->udisp = (lvaddr_t)handle;
663     disp->disabled = true;
664     disp->fpu_trap = 1;
665     disp_gen->core_id = span_domain_state->core_id;
666     // Setup the dispatcher to run remote_core_init_disabled
667     // and pass the created thread as an argument
668     registers_set_initial(disabled_area, span_domain_state->thread,
669                           (lvaddr_t)remote_core_init_disabled,
670                           (lvaddr_t)&disp_gen->stack[DISPATCHER_STACK_WORDS],
671                           (uintptr_t)span_domain_state->thread, 0, 0, 0);
672     // Give dispatcher a unique name for debugging
673     snprintf(disp->name, DISP_NAME_LEN, "%s%d", disp_name(),
674              span_domain_state->core_id);
675
676 #ifdef __x86_64__
677     // XXX: share LDT state between all dispatchers
678     // this needs to happen before the remote core starts, otherwise the segment
679     // selectors in the new thread state are invalid
680     struct dispatcher_shared_x86_64 *disp_x64
681         = get_dispatcher_shared_x86_64(handle);
682     struct dispatcher_shared_x86_64 *mydisp_x64
683         = get_dispatcher_shared_x86_64(curdispatcher());
684
685     disp_x64->ldt_base = mydisp_x64->ldt_base;
686     disp_x64->ldt_npages = mydisp_x64->ldt_npages;
687 #endif
688
689     threads_prepare_to_span(handle);
690
691     // Setup new local thread for inter-dispatcher messages, if not already done
692     static struct thread *interdisp_thread = NULL;
693     if(interdisp_thread == NULL) {
694         interdisp_thread = thread_create(interdisp_msg_handler,
695                                          &domain_state->interdisp_ws);
696         err = thread_detach(interdisp_thread);
697         assert(err_is_ok(err));
698     }
699
700 #if 0
701     // XXX: Tell currently active interdisp-threads to handle default waitset
702     for(int i = 0; i < MAX_CPUS; i++) {
703         struct interdisp_binding *b = domain_state->b[i];
704
705         if(disp_get_core_id() != i && b != NULL) {
706             err = b->tx_vtbl.span_slave(b, NOP_CONT);
707             assert(err_is_ok(err));
708         }
709     }
710 #endif
711
712     /* XXX: create a thread that will handle the default waitset */
713     if (domain_state->default_waitset_handler == NULL) {
714         domain_state->default_waitset_handler
715             = thread_create(span_slave_thread, NULL);
716         assert(domain_state->default_waitset_handler != NULL);
717     }
718
719     /* Wait to use the monitor binding */
720     struct monitor_binding *mcb = get_monitor_binding();
721     event_mutex_enqueue_lock(&mcb->mutex, &span_domain_state->event_qnode,
722                              (struct event_closure) {
723                                  .handler = span_domain_request_sender_wrapper,
724                                      .arg = span_domain_state });
725
726 #if 0
727     while(!span_domain_state->initialized) {
728         event_dispatch(get_default_waitset());
729     }
730
731     /* Free state */
732     free(span_domain_state);
733 #endif
734
735     return SYS_ERR_OK;
736 }
737
738 /**
739  * \brief Creates a dispatcher on a remote core
740  *
741  * \param core_id   Id of the core to create the dispatcher on
742  * \param callback  Callback to use when new dispatcher is created
743  *
744  * The new dispatcher is created with the same vroot, sharing the same vspace.
745  * The new dispatcher also has a urpc connection to the core that created it.
746  */
747 errval_t domain_new_dispatcher(coreid_t core_id,
748                                domain_spanned_callback_t callback,
749                                void *callback_arg)
750 {
751     return domain_new_dispatcher_varstack(core_id, callback, callback_arg,
752                                           THREADS_DEFAULT_STACK_BYTES);
753 }
754
755 errval_t domain_send_cap(coreid_t core_id, struct capref cap)
756 {
757     errval_t err;
758     struct domain_state *domain_state = get_domain_state();
759     if (!domain_state->b[core_id]) {
760         return LIB_ERR_NO_SPANNED_DISP;
761     }
762
763     send_cap_err = SYS_ERR_OK;
764     cap_received = false;
765
766     struct interdisp_binding *b = domain_state->b[core_id];
767     err = b->tx_vtbl.send_cap_request(b, NOP_CONT, cap, (uintptr_t)&cap);
768     if (err_is_fail(err)) {
769         return err_push(err, LIB_ERR_SEND_CAP_REQUEST);
770     }
771
772     assert(!"NYI");
773     // TODO: Handled on different thread
774     /* while(!cap_received) { */
775     /*     messages_wait_and_handle_next(); */
776     /* } */
777
778     return send_cap_err;
779 }
780
781 /**
782  * \brief Wakeup a thread on a foreign dispatcher while disabled.
783  *
784  * \param core_id       Core ID to wakeup on
785  * \param thread        Pointer to thread to wakeup
786  * \param mydisp        Dispatcher this function is running on
787  *
788  * \return SYS_ERR_OK on success.
789  */
790 static errval_t domain_wakeup_on_coreid_disabled(coreid_t core_id,
791                                                  struct thread *thread,
792                                                  dispatcher_handle_t mydisp)
793 {
794     struct domain_state *ds = get_domain_state();
795
796     // XXX: Ugly hack to allow waking up on a core id we don't have a
797     // dispatcher handler for
798     thread->coreid = core_id;
799
800     // Catch this early
801     assert_disabled(ds != NULL);
802     if (ds->b[core_id] == NULL) {
803         return LIB_ERR_NO_SPANNED_DISP;
804     }
805
806     thread_enqueue(thread, &ds->remote_wakeup_queue);
807
808     // Signal the inter-disp waitset of this event
809     struct event_closure closure = {
810         .handler = handle_wakeup_on
811     };
812     errval_t err =
813         waitset_chan_trigger_closure_disabled(&ds->interdisp_ws,
814                                               &ds->remote_wakeup_event,
815                                               closure,
816                                               mydisp);
817     assert_disabled(err_is_ok(err) ||
818                     err_no(err) == LIB_ERR_CHAN_ALREADY_REGISTERED);
819
820     return SYS_ERR_OK;
821 }
822
823 errval_t domain_wakeup_on_disabled(dispatcher_handle_t disp,
824                                    struct thread *thread,
825                                    dispatcher_handle_t mydisp)
826 {
827     coreid_t core_id = disp_handle_get_core_id(disp);
828
829     // TODO: Can't wakeup on anyone else than the owning dispatcher yet
830     assert_disabled(disp == thread->disp);
831
832     return domain_wakeup_on_coreid_disabled(core_id, thread, mydisp);
833 }
834
835 errval_t domain_wakeup_on(dispatcher_handle_t disp,
836                           struct thread *thread)
837 {
838     dispatcher_handle_t mydisp = disp_disable();
839     errval_t err = domain_wakeup_on_disabled(disp, thread, mydisp);
840     disp_enable(mydisp);
841     return err;
842 }
843
844 errval_t domain_thread_move_to(struct thread *thread, coreid_t core_id)
845 {
846     assert(thread == thread_self());
847     dispatcher_handle_t mydisp = disp_disable();
848     struct dispatcher_generic *disp_gen = get_dispatcher_generic(mydisp);
849     struct dispatcher_shared_generic *disp =
850         get_dispatcher_shared_generic(mydisp);
851
852     struct thread *next = thread->next;
853     thread_remove_from_queue(&disp_gen->runq, thread);
854
855     errval_t err = domain_wakeup_on_coreid_disabled(core_id, thread, mydisp);
856     if(err_is_fail(err)) {
857         thread_enqueue(thread, &disp_gen->runq);
858         disp_enable(mydisp);
859         return err;
860     }
861
862     // run the next thread, if any
863     if (next != thread) {
864         disp_gen->current = next;
865         disp_resume(mydisp, &next->regs);
866     } else {
867         disp_gen->current = NULL;
868         disp->haswork = havework_disabled(mydisp);
869         disp_yield_disabled(mydisp);
870     }
871
872     USER_PANIC("should never be reached");
873 }
874
875 errval_t domain_thread_create_on_varstack(coreid_t core_id,
876                                           thread_func_t start_func,
877                                           void *arg, size_t stacksize)
878 {
879     if (disp_get_core_id() == core_id) {
880         struct thread *th = NULL;
881         if (stacksize == 0) {
882             th = thread_create(start_func, arg);
883         } else {
884             th = thread_create_varstack(start_func, arg, stacksize);
885         }
886         if (th != NULL) {
887             return SYS_ERR_OK;
888         } else {
889             return LIB_ERR_THREAD_CREATE;
890         }
891     } else {
892         struct domain_state *domain_state = get_domain_state();
893         errval_t err;
894     
895         if (domain_state->b[core_id] == NULL) {
896             return LIB_ERR_NO_SPANNED_DISP;
897         }
898     
899         struct interdisp_binding *b = domain_state->b[core_id];
900         err = b->tx_vtbl.create_thread(b, NOP_CONT,
901                                        (genvaddr_t)(uintptr_t)start_func,
902                                        (genvaddr_t)(uintptr_t)arg,
903                                        stacksize);
904         if (err_is_fail(err)) {
905             return err;
906         }
907     
908         return SYS_ERR_OK;
909     }
910 }
911
912 errval_t domain_thread_create_on(coreid_t core_id, thread_func_t start_func,
913                                  void *arg)
914 {
915     return domain_thread_create_on_varstack(core_id, start_func, arg, 0);
916 }
917
918 /**
919  * \brief set the core_id.
920  *
921  * Code using this should do a kernel_cap invocation to get the core_id first.
922  */
923 void disp_set_core_id(coreid_t core_id)
924 {
925     dispatcher_handle_t handle = curdispatcher();
926     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
927     disp->core_id = core_id;
928 }
929
930 /**
931  * \brief returns the core_id stored in disp_priv struct
932  */
933 coreid_t disp_get_core_id(void)
934 {
935     dispatcher_handle_t handle = curdispatcher();
936     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
937     return disp->core_id;
938 }
939
940 /**
941  * \brief returns the domain_id stored in disp_priv struct
942  */
943 domainid_t disp_get_domain_id(void)
944 {
945     dispatcher_handle_t handle = curdispatcher();
946     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
947     return disp->domain_id;
948 }
949
950 /**
951  * \brief returns the core_id stored in disp_priv struct
952  */
953 coreid_t disp_handle_get_core_id(dispatcher_handle_t handle)
954 {
955     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
956     return disp->core_id;
957 }
958
959 struct waitset *get_default_waitset(void)
960 {
961     dispatcher_handle_t handle = curdispatcher();
962     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
963     return &disp->core_state.c.default_waitset;
964 }
965
966 /**
967  * \brief set the monitor client binding on the dispatcher priv
968  */
969 void set_monitor_binding(struct monitor_binding *b)
970 {
971     dispatcher_handle_t handle = curdispatcher();
972     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
973     disp->core_state.c.monitor_binding = b;
974 }
975
976 /**
977  * \brief Returns the monitor client binding on the dispatcher priv
978  */
979 struct monitor_binding *get_monitor_binding(void)
980 {
981     dispatcher_handle_t handle = curdispatcher();
982     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
983     return disp->core_state.c.monitor_binding;
984 }
985
986
987 /**
988  * \brief set the  blocking rpc monitor client binding on the dispatcher priv
989  */
990 void set_monitor_blocking_rpc_client(struct monitor_blocking_rpc_client *st)
991 {
992     dispatcher_handle_t handle = curdispatcher();
993     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
994     disp->core_state.c.monitor_blocking_rpc_client = st;
995 }
996
997 /**
998  * \brief Returns the blocking rpc monitor client binding on the 
999  * dispatcher priv
1000  */
1001 struct monitor_blocking_rpc_client *get_monitor_blocking_rpc_client(void)
1002 {
1003     dispatcher_handle_t handle = curdispatcher();
1004     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1005     return disp->core_state.c.monitor_blocking_rpc_client;
1006 }
1007
1008 /**
1009  * \brief set the mem client on the dispatcher priv
1010  */
1011 void set_mem_client(struct mem_rpc_client *st)
1012 {
1013     dispatcher_handle_t handle = curdispatcher();
1014     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1015     disp->core_state.c.mem_st = st;
1016 }
1017
1018 /**
1019  * \brief Returns the mem client on the dispatcher priv
1020  */
1021 struct mem_rpc_client *get_mem_client(void)
1022 {
1023     dispatcher_handle_t handle = curdispatcher();
1024     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1025     return disp->core_state.c.mem_st;
1026 }
1027
1028 /**
1029  * \brief Returns a pointer to the current vspace on the dispatcher priv
1030  */
1031 struct vspace *get_current_vspace(void)
1032 {
1033     dispatcher_handle_t handle = curdispatcher();
1034     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1035     return &disp->core_state.vspace_state.vspace;
1036 }
1037
1038 /**
1039  * \brief Returns a pointer to the current pinned state on the dispatcher priv
1040  */
1041 struct pinned_state *get_current_pinned_state(void)
1042 {
1043     dispatcher_handle_t handle = curdispatcher();
1044     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1045     return &disp->core_state.pinned_state;
1046 }
1047
1048 /**
1049  * \brief Returns a pointer to the current pmap on the dispatcher priv
1050  */
1051 struct pmap *get_current_pmap(void)
1052 {
1053     dispatcher_handle_t handle = curdispatcher();
1054     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1055     return (struct pmap*)&disp->core_state.vspace_state.pmap;
1056 }
1057
1058 /**
1059  * \brief Returns a pointer to the morecore state on the dispatcher priv
1060  */
1061 struct morecore_state *get_morecore_state(void)
1062 {
1063     dispatcher_handle_t handle = curdispatcher();
1064     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1065     return &disp->core_state.c.morecore_state;
1066 }
1067
1068 /**
1069  * \brief Returns a pointer to the ram_alloc state on the dispatcher priv
1070  */
1071 struct ram_alloc_state *get_ram_alloc_state(void)
1072 {
1073     dispatcher_handle_t handle = curdispatcher();
1074     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1075     return &disp->core_state.c.ram_alloc_state;
1076 }
1077
1078 /**
1079  * \brief Returns a pointer to the ram_alloc state on the dispatcher priv
1080  */
1081 struct skb_state *get_skb_state(void)
1082 {
1083     dispatcher_handle_t handle = curdispatcher();
1084     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1085     return &disp->core_state.c.skb_state;
1086 }
1087
1088 /**
1089  * \brief Returns a pointer to the chips_context state on the dispatcher priv
1090  */
1091 struct dist2_rpc_client *get_nameservice_rpc_client(void)
1092 {
1093     dispatcher_handle_t handle = curdispatcher();
1094     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1095     return disp->core_state.c.nameservice_rpc_client;
1096 }
1097
1098 /**
1099  * \brief set the chips_context state on the dispatcher priv
1100  */
1101 void set_nameservice_rpc_client(struct dist2_rpc_client *c)
1102 {
1103     dispatcher_handle_t handle = curdispatcher();
1104     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1105     disp->core_state.c.nameservice_rpc_client = c;
1106 }
1107
1108 /**
1109  * \brief Returns a pointer to the chips_context state on the dispatcher priv
1110  */
1111 struct spawn_rpc_client *get_spawn_rpc_client(coreid_t core)
1112 {
1113     dispatcher_handle_t handle = curdispatcher();
1114     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1115     assert(core < MAX_CPUS);
1116     return disp->core_state.c.spawn_rpc_clients[core];
1117 }
1118
1119 /**
1120  * \brief set the chips_context state on the dispatcher priv
1121  */
1122 void set_spawn_rpc_client(coreid_t core, struct spawn_rpc_client *c)
1123 {
1124     dispatcher_handle_t handle = curdispatcher();
1125     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1126     assert(core < MAX_CPUS);
1127     disp->core_state.c.spawn_rpc_clients[core] = c;
1128 }
1129
1130 /**
1131  * \brief Returns a pointer to the terminal state on the dispatcher priv
1132  */
1133 struct terminal_state *get_terminal_state(void)
1134 {
1135     dispatcher_handle_t handle = curdispatcher();
1136     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1137     return disp->core_state.c.terminal_state;
1138 }
1139
1140 /**
1141  * \brief set the terminal state on the dispatcher priv
1142  */
1143 void set_terminal_state(struct terminal_state *st)
1144 {
1145     dispatcher_handle_t handle = curdispatcher();
1146     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1147     disp->core_state.c.terminal_state = st;
1148 }
1149
1150 /**
1151  * \brief Returns a pointer to the domain state on the dispatcher priv
1152  */
1153 struct domain_state *get_domain_state(void)
1154 {
1155     dispatcher_handle_t handle = curdispatcher();
1156     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1157     return disp->core_state.c.domain_state;
1158 }
1159
1160 /**
1161  * \brief set the domain state on the dispatcher priv
1162  */
1163 void set_domain_state(struct domain_state *st)
1164 {
1165     dispatcher_handle_t handle = curdispatcher();
1166     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1167     disp->core_state.c.domain_state = st;
1168 }
1169
1170 /**
1171  * \brief Returns a pointer to the spawn state on the dispatcher priv
1172  */
1173 struct spawn_state *get_spawn_state(void)
1174 {
1175     dispatcher_handle_t handle = curdispatcher();
1176     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1177     return disp->core_state.c.spawn_state;
1178 }
1179
1180 /**
1181  * \brief set the spawn state on the dispatcher priv
1182  */
1183 void set_spawn_state(struct spawn_state *st)
1184 {
1185     dispatcher_handle_t handle = curdispatcher();
1186     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1187     disp->core_state.c.spawn_state = st;
1188 }
1189
1190 /**
1191  * \brief Returns a pointer to the spawn state on the dispatcher priv
1192  */
1193 struct slot_alloc_state *get_slot_alloc_state(void)
1194 {
1195     dispatcher_handle_t handle = curdispatcher();
1196     struct dispatcher_generic* disp = get_dispatcher_generic(handle);
1197     return &disp->core_state.c.slot_alloc_state;
1198 }