1/**
2 * \file
3 * \brief Monitor's connection with the dispatchers on the same core
4 */
5
6/*
7 * Copyright (c) 2009, 2010, ETH Zurich.
8 * All rights reserved.
9 *
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.
13 */
14
15#include "monitor.h"
16#include <barrelfish/debug.h> // XXX: To set the cap_identify_reply handler
17#include <barrelfish/sys_debug.h> // XXX: for sys_debug_send_ipi
18#include <trace/trace.h>
19#include <if/mem_defs.h>
20#include <barrelfish/monitor_client.h>
21#include <if/monitor_loopback_defs.h>
22#include <notify_ipi.h>
23
24struct ipi_alloc_notify_reply_state {
25    struct monitor_msg_queue_elem elem;
26    struct monitor_ipi_alloc_notify_reply__tx_args args;
27};
28
29static void
30ipi_alloc_notify_reply_cont(struct monitor_binding *b,
31                            uintptr_t state, struct capref notify_cap,
32                            errval_t err);
33
34static void ipi_alloc_notify_reply_handler(struct monitor_binding *b,
35                                           struct monitor_msg_queue_elem *e)
36{
37    struct ipi_alloc_notify_reply_state *st =
38        (struct ipi_alloc_notify_reply_state *)e;
39    ipi_alloc_notify_reply_cont(b, st->args.state, st->args.notify,
40                                st->args.err);
41    free(st);
42}
43
44static void ipi_alloc_notify_reply_cont(struct monitor_binding *b,
45                                        uintptr_t state,
46                                        struct capref notify_cap,
47                                        errval_t reterr)
48{
49    errval_t err =
50        b->tx_vtbl.ipi_alloc_notify_reply(b, NOP_CONT, state,
51                                          notify_cap, reterr);
52
53    if(err_is_fail(err)) {
54        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
55            struct monitor_state *st = b->st;
56            struct ipi_alloc_notify_reply_state *me =
57                malloc(sizeof(struct ipi_alloc_notify_reply_state));
58            assert(me != NULL);
59            me->args.state = state;
60            me->args.notify = notify_cap;
61            me->args.err = reterr;
62            me->elem.cont = ipi_alloc_notify_reply_handler;
63            err = monitor_enqueue_send(b, &st->queue,
64                                       get_default_waitset(), &me->elem.queue);
65            if (err_is_fail(err)) {
66                USER_PANIC_ERR(err, "monitor_enqueue_send failed");
67            }
68            return;
69        }
70        USER_PANIC_ERR(err, "sending reply");
71    }
72    assert(err_is_ok(err));
73}
74
75static void ipi_alloc_notify_request(struct monitor_binding *st,
76                                     struct capref ep, uintptr_t state)
77{
78    errval_t err;
79    struct capref notify_cap = NULL_CAP;
80
81    // Allocate a local notify channel ID
82    int chanid;
83    err = notification_allocate(ep, &chanid);
84    if(err_is_fail(err)) {
85        goto out;
86    }
87
88    // Get my arch ID
89    uintptr_t my_arch_id = 0;
90    err = invoke_monitor_get_arch_id(&my_arch_id);
91    assert(err == SYS_ERR_OK);
92
93    // Create notify cap
94    err = notification_create_cap(chanid, my_arch_id, &notify_cap);
95
96 out:
97    // Return the notify cap or error
98    ipi_alloc_notify_reply_cont(st, state, notify_cap, err);
99}
100
101errval_t monitor_server_arch_init(struct monitor_binding *b)
102{
103    b->rx_vtbl.ipi_alloc_notify_request = ipi_alloc_notify_request;
104    return SYS_ERR_OK;
105}
106