3 * \brief Process management service.
7 * Copyright (c) 2017, ETH Zurich.
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
16 #include <barrelfish/barrelfish.h>
17 #include <barrelfish/nameservice_client.h>
18 #include <barrelfish/proc_mgmt_client.h>
19 #include <barrelfish/spawn_client.h>
20 #include <if/monitor_defs.h>
21 #include <if/proc_mgmt_defs.h>
24 #include "spawnd_state.h"
26 static void add_spawnd_handler(struct proc_mgmt_binding *b, coreid_t core_id,
29 if (spawnd_state_exists(core_id)) {
30 DEBUG_ERR(PROC_MGMT_ERR_SPAWND_EXISTS, "spawnd_state_exists");
34 // Bind with the spawnd.
35 struct spawn_binding *spawnb;
36 errval_t err = spawn_bind_iref(iref, &spawnb);
37 if (err_is_fail(err)) {
38 DEBUG_ERR(err, "spawn_bind_iref");
42 err = spawnd_state_alloc(core_id, spawnb);
43 if (err_is_fail(err)) {
44 DEBUG_ERR(err, "spawnd_state_alloc");
47 debug_printf("Process manager bound with spawnd.%u on iref %u\n", core_id,
50 err = spawnd_state_get_binding(core_id)->rpc_tx_vtbl.echo(
51 spawnd_state_get_binding(core_id),
53 disp_get_current_core_id());
54 if (err_is_fail(err)) {
55 USER_PANIC_ERR(err, "spawnd echo request failed");
59 static void add_spawnd_handler_non_monitor(struct proc_mgmt_binding *b,
60 coreid_t core_id, iref_t iref)
62 debug_printf("Ignoring add_spawnd call: %s\n",
63 err_getstring(PROC_MGMT_ERR_NOT_MONITOR));
66 // static errval_t spawn_handler(struct proc_mgmt_binding *b,
69 // const char *argvbuf,
71 // const char *envbuf,
75 // struct capref *domainid_cap)
77 // return LIB_ERR_NOT_IMPLEMENTED;
80 // static errval_t span_handler(struct proc_mgmt_binding *b,
81 // struct capref domainid_cap,
83 // struct capref vroot,
84 // struct capref disp_mem,
87 // return LIB_ERR_NOT_IMPLEMENTED;
90 // static errval_t kill_handler(struct proc_mgmt_binding *b,
91 // struct capref domainid_cap,
94 // return LIB_ERR_NOT_IMPLEMENTED;
97 static struct proc_mgmt_rx_vtbl monitor_vtbl = {
98 .add_spawnd = add_spawnd_handler
101 static struct proc_mgmt_rx_vtbl non_monitor_vtbl = {
102 .add_spawnd = add_spawnd_handler_non_monitor
105 static errval_t alloc_ep_for_monitor(struct capref *ep)
107 struct proc_mgmt_lmp_binding *lmpb =
108 malloc(sizeof(struct proc_mgmt_lmp_binding));
109 assert(lmpb != NULL);
111 // setup our end of the binding
112 errval_t err = proc_mgmt_client_lmp_accept(lmpb, get_default_waitset(),
113 DEFAULT_LMP_BUF_WORDS);
114 if (err_is_fail(err)) {
116 return err_push(err, LIB_ERR_PROC_MGMT_CLIENT_ACCEPT);
119 *ep = lmpb->chan.local_cap;
120 lmpb->b.rx_vtbl = monitor_vtbl;
125 static void export_cb(void *st, errval_t err, iref_t iref)
127 if (err_is_fail(err)) {
128 USER_PANIC_ERR(err, "export failed");
131 // Allocate an endpoint for the local monitor, who will use it to inform
132 // us about new spawnd irefs on behalf of other monitors.
134 err = alloc_ep_for_monitor(&ep);
135 if (err_is_fail(err)) {
136 USER_PANIC_ERR(err, "failed to allocate LMP EP for local monitor");
139 // Send the endpoint to the monitor, so it can finish the handshake.
140 struct monitor_binding *mb = get_monitor_binding();
141 err = mb->tx_vtbl.set_proc_mgmt_ep_request(mb, NOP_CONT, ep);
142 if (err_is_fail(err)) {
143 USER_PANIC_ERR(err, "failed to send set_proc_mgmt_ep_request to "
147 // Also register this iref with the name service, for arbitrary client
148 // domains to use for spawn-related ops.
149 err = nameservice_register(SERVICE_BASENAME, iref);
150 if (err_is_fail(err)) {
151 USER_PANIC_ERR(err, "nameservice_register failed");
155 static errval_t connect_cb(void *st, struct proc_mgmt_binding *b)
157 b->rx_vtbl = non_monitor_vtbl;
161 errval_t start_service(void)
163 return proc_mgmt_export(NULL, export_cb, connect_cb, get_default_waitset(),
164 IDC_EXPORT_FLAGS_DEFAULT);