3 * \brief Client for interacting with the process management server.
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.
15 #include <barrelfish/barrelfish.h>
16 #include <barrelfish/proc_mgmt_client.h>
17 #include <if/proc_mgmt_defs.h>
19 static void error_handler(struct proc_mgmt_binding *b, errval_t err)
21 #if defined(__x86_64__) || defined(__i386__)
22 debug_printf("%p %p %p %p\n", __builtin_return_address(0), __builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3));
24 debug_err(__FILE__, __func__, __LINE__, err,
25 "error in proc_mgmt binding");
29 static void proc_mgmt_accept_recv_handler(void *arg)
31 struct proc_mgmt_lmp_binding *b = arg;
32 struct lmp_recv_msg msg = LMP_RECV_MSG_INIT;
36 // try to retrieve a message from the channel
37 err = lmp_chan_recv(&b->chan, &msg, &cap);
38 if (err_is_fail(err)) {
39 if (err_no(err) == LIB_ERR_NO_LMP_MSG) {
40 // nothing there, re-register
41 struct event_closure recv_handler = {
42 .handler = proc_mgmt_accept_recv_handler,
45 err = lmp_chan_register_recv(&b->chan, b->b.waitset, recv_handler);
46 b->b.error_handler(&b->b,
47 err_push(err, LIB_ERR_CHAN_REGISTER_RECV));
49 // real error, report to user
50 b->b.error_handler(&b->b, err_push(err, LIB_ERR_LMP_CHAN_RECV));
55 // if we're the monitor, we might be waiting for the other side's cap
56 // TODO(razvan): Or the process manager, which for uses LMP_MONITOR_ACCEPT
58 assert(b->chan.connstate == LMP_MONITOR_ACCEPT);
59 assert(!capref_is_null(cap));
60 b->chan.remote_cap = cap;
61 b->chan.connstate = LMP_CONNECTED;
63 // Allocate a new receive slot.
64 // TODO(razvan): Whom is the receive slot for? Is it one of the spawnds?
65 // Or is it some arbitrary non-spawnd client domain? Need a way to tell.
66 err = lmp_chan_alloc_recv_slot(&b->chan);
67 if (err_is_fail(err)) {
68 // XXX: report the error, but continue
69 b->b.error_handler(&b->b, err_push(err, LIB_ERR_LMP_ALLOC_RECV_SLOT));
72 // Run the RX handler; has a side-effect of registering for receive events.
73 proc_mgmt_lmp_rx_handler(b);
76 static errval_t init_lmp_binding(struct proc_mgmt_lmp_binding *lmpb,
77 struct waitset *ws, size_t buflen_words)
81 proc_mgmt_lmp_init(lmpb, ws);
83 /* allocate a cap slot for the new endpoint cap */
84 err = slot_alloc(&lmpb->chan.local_cap);
85 if (err_is_fail(err)) {
86 return err_push(err, LIB_ERR_SLOT_ALLOC);
89 /* allocate a local endpoint */
90 err = lmp_endpoint_create_in_slot(buflen_words, lmpb->chan.local_cap,
91 &lmpb->chan.endpoint);
92 if (err_is_fail(err)) {
93 /* TODO: free cap slot */
94 return err_push(err, LIB_ERR_ENDPOINT_CREATE);
97 /* allocate an initial receive slot */
98 err = lmp_chan_alloc_recv_slot(&lmpb->chan);
99 if (err_is_fail(err)) {
103 /* setup error handler */
104 lmpb->b.error_handler = error_handler;
106 /* setup initial receive handlers */
107 // lmpb->b.rx_vtbl = proc_mgmt_rx_vtbl;
110 lmpb->b.change_waitset(&lmpb->b, lmpb->b.waitset);
115 * \brief Accept a new LMP binding in a client from the process manager.
117 * Should only be used in the process manager.
119 * \param pmcb Storage for binding state
120 * \param ws Waitset for handling incoming messages
121 * \param buflen_words Size of incoming buffer, in number of words
123 errval_t proc_mgmt_client_lmp_accept(struct proc_mgmt_lmp_binding *lmpb,
124 struct waitset *ws, size_t lmp_buflen_words)
126 errval_t err = init_lmp_binding(lmpb, ws, lmp_buflen_words);
127 if (err_is_fail(err)) {
131 // TODO(razvan): This should probably be something like LMP_PROC_MGMT_ACCEPT
132 lmpb->chan.connstate = LMP_MONITOR_ACCEPT;
133 lmpb->chan.remote_cap = NULL_CAP; // will be sent to us by the client
135 // Register for receive notification on our special handler.
136 struct event_closure receive_handler = {
137 .handler = proc_mgmt_accept_recv_handler,
140 err = lmp_chan_register_recv(&lmpb->chan, ws, receive_handler);
141 if (err_is_fail(err)) {
142 return err; // TODO: cleanup?