2 * Copyright (c) 2012 ETH Zurich.
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
10 #include <barrelfish/barrelfish.h>
11 #include <if/intermon_defs.h>
18 #include "dom_invocations.h"
19 #include "monitor_invocations.h"
21 struct retrieve_rpc_st {
22 struct intermon_msg_queue_elem iqn;
24 struct capability rawcap;
25 move_result_handler_t result_handler;
30 struct retrieve_response_st {
31 struct intermon_msg_queue_elem iqn;
38 static void retrieve_owner__enq(struct retrieve_rpc_st *st);
39 static void retrieve_owner__send(struct intermon_binding *b,
40 struct intermon_msg_queue_elem *e);
41 static void retrieve_result__enq(errval_t status,
42 struct retrieve_response_st *st);
43 static void retrieve_result__send(struct intermon_binding *b,
44 struct intermon_msg_queue_elem *e);
45 static void retrieve_ownership_update__fin(void *st);
48 capops_retrieve(struct domcapref cap,
49 move_result_handler_t result_handler,
54 distcap_state_t state;
55 err = dom_cnode_get_state(cap, &state);
56 GOTO_IF_ERR(err, report_error);
57 if (distcap_state_is_busy(state)) {
58 err = MON_ERR_REMOTE_CAP_RETRY;
60 if (distcap_state_is_foreign(state)) {
61 err = MON_ERR_CAP_FOREIGN;
63 GOTO_IF_ERR(err, report_error);
65 err = monitor_lock_cap(cap.croot, cap.cptr, cap.bits);
66 GOTO_IF_ERR(err, report_error);
68 struct retrieve_rpc_st *rst = NULL;
69 err = calloce(1, sizeof(*rst), &rst);
70 GOTO_IF_ERR(err, unlock_cap);
73 rst->result_handler = result_handler;
76 err = monitor_get_domcap_owner(cap, &rst->prev_owner);
77 GOTO_IF_ERR(err, free_st);
79 if (rst->prev_owner == my_core_id) {
84 retrieve_owner__enq(rst);
95 result_handler(err, st);
99 retrieve_ownership__rx(errval_t status, struct retrieve_rpc_st *st)
101 caplock_unlock(st->cap);
102 st->result_handler(status, st->st);
107 retrieve_owner__enq(struct retrieve_rpc_st *st)
111 st->iqn.cont = retrieve_owner__send;
112 err = capsend_owner(st->cap, (struct msg_queue_elem*)st);
113 if (err_is_fail(err)) {
114 retrieve_ownership__rx(err, st);
119 retrieve_owner__send(struct intermon_binding *b,
120 struct intermon_msg_queue_elem *e)
123 struct retrieve_rpc_st *st = (struct retrieve_rpc_st*)e;
124 intermon_caprep_t caprep;
126 err = monitor_set_domcap_owner(st->cap, my_core_id);
127 GOTO_IF_ERR(err, report_error);
129 capability_to_caprep(&st->rawcap, &caprep);
130 err = intermon_capops_retrieve_request__tx(b, NOP_CONT, caprep, (lvaddr_t)st);
131 GOTO_IF_ERR(err, report_error);
136 retrieve_ownership__rx(err, st);
140 retrieve_request__rx(struct intermon_binding *b,
141 intermon_caprep_t caprep,
145 struct intermon_state *inter_st = (struct intermon_state*)b->st;
147 struct retrieve_response_st *rst;
148 err = calloce(1, sizeof(*rst), &rst);
149 PANIC_IF_ERR(err, "allocating retrieve respones state");
151 rst->from = inter_st->core_id;
153 struct capability rawcap;
154 caprep_to_capability(&caprep, &rawcap);
157 err = slot_alloc(&cap);
158 GOTO_IF_ERR(err, respond_err);
160 err = monitor_copy_if_exists(&rawcap, cap);
161 GOTO_IF_ERR(err, free_slot);
163 distcap_state_t state;
164 err = dom_cnode_get_state(get_cap_domref(cap), &state);
165 GOTO_IF_ERR(err, delete_cap);
167 if (distcap_state_is_busy(state)) {
168 err = MON_ERR_REMOTE_CAP_RETRY;
171 if (distcap_state_is_foreign(state)) {
172 err = MON_ERR_CAP_FOREIGN;
176 uint8_t relations, remote_relations;
177 err = monitor_cap_has_relations(cap, 0xFF, &relations);
178 GOTO_IF_ERR(err, delete_cap);
180 err = monitor_remote_relations(cap, 0, 0, &remote_relations);
181 GOTO_IF_ERR(err, delete_cap);
183 rst->relations = relations | remote_relations | RRELS_COPY_BIT;
185 err = monitor_set_cap_owner(cap_root, get_cap_addr(cap),
186 get_cap_valid_bits(cap),
190 err2 = cap_delete(cap);
191 DEBUG_IF_ERR(err2, "while deleting temp cap for retrieve");
194 err2 = slot_free(cap);
195 DEBUG_IF_ERR(err2, "freeing temp cap slot for retrieve");
198 retrieve_result__enq(err, rst);
202 retrieve_result__enq(errval_t status, struct retrieve_response_st *st)
206 st->iqn.cont = retrieve_result__send;
208 err = capsend_target(st->from, (struct msg_queue_elem*)st);
209 PANIC_IF_ERR(err, "enqueing retrieve result");
213 retrieve_result__send(struct intermon_binding *b,
214 struct intermon_msg_queue_elem *e)
217 struct retrieve_response_st *st = (struct retrieve_response_st*)e;
219 err = intermon_capops_retrieve_result__tx(b, NOP_CONT, st->status,
220 st->relations, st->st);
221 PANIC_IF_ERR(err, "sending retrieve result");
226 retrieve_result__rx(struct intermon_binding *b, errval_t status,
227 uint8_t relations, genvaddr_t st)
230 struct retrieve_rpc_st *rst = (struct retrieve_rpc_st*)(lvaddr_t)st;
232 if (err_is_fail(status)) {
237 err = monitor_domcap_remote_relations(rst->cap.croot, rst->cap.cptr,
238 rst->cap.bits, relations, 0xFF,
240 PANIC_IF_ERR(err, "setting rrels for retrieved cap");
242 struct event_closure updated_cont
243 = MKCONT(retrieve_ownership_update__fin, rst);
244 err = capsend_update_owner(rst->cap, updated_cont);
245 PANIC_IF_ERR(err, "updating retrieve ownership");
248 retrieve_ownership__rx(err, rst);
252 retrieve_ownership_update__fin(void *st)
254 struct retrieve_rpc_st *rst = (struct retrieve_rpc_st*)st;
256 retrieve_ownership__rx(SYS_ERR_OK, rst);