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 DEBUG_CAPOPS("%s ## start transfer ownership \n", __FUNCTION__);
56 distcap_state_t state;
57 err = dom_cnode_get_state(cap, &state);
58 GOTO_IF_ERR(err, report_error);
59 if (distcap_state_is_busy(state)) {
60 err = MON_ERR_REMOTE_CAP_RETRY;
62 GOTO_IF_ERR(err, report_error);
64 err = monitor_lock_cap(cap.croot, cap.cptr, cap.bits);
65 GOTO_IF_ERR(err, report_error);
67 struct retrieve_rpc_st *rst = NULL;
68 err = calloce(1, sizeof(*rst), &rst);
69 GOTO_IF_ERR(err, unlock_cap);
72 rst->result_handler = result_handler;
75 err = monitor_domains_cap_identify(cap.croot, cap.cptr, cap.bits, &rst->rawcap);
76 GOTO_IF_ERR(err, free_st);
78 err = monitor_get_domcap_owner(cap, &rst->prev_owner);
79 GOTO_IF_ERR(err, free_st);
81 if (rst->prev_owner == my_core_id) {
86 retrieve_owner__enq(rst);
97 result_handler(err, st);
101 retrieve_ownership__rx(errval_t status, struct retrieve_rpc_st *st)
103 DEBUG_CAPOPS("%s ## transfer ownership done. calling %p\n", __FUNCTION__,
106 caplock_unlock(st->cap);
107 st->result_handler(status, st->st);
112 retrieve_owner__enq(struct retrieve_rpc_st *st)
116 st->iqn.cont = retrieve_owner__send;
117 err = capsend_owner(st->cap, (struct msg_queue_elem*)st);
118 if (err_is_fail(err)) {
119 retrieve_ownership__rx(err, st);
124 retrieve_owner__send(struct intermon_binding *b,
125 struct intermon_msg_queue_elem *e)
128 struct retrieve_rpc_st *st = (struct retrieve_rpc_st*)e;
129 intermon_caprep_t caprep;
131 err = monitor_set_domcap_owner(st->cap, my_core_id);
132 GOTO_IF_ERR(err, report_error);
134 capability_to_caprep(&st->rawcap, &caprep);
135 err = intermon_capops_retrieve_request__tx(b, NOP_CONT, caprep, (lvaddr_t)st);
136 GOTO_IF_ERR(err, report_error);
141 DEBUG_CAPOPS("%s failed \n", __FUNCTION__);
142 retrieve_ownership__rx(err, st);
146 retrieve_request__rx(struct intermon_binding *b,
147 intermon_caprep_t caprep,
151 struct intermon_state *inter_st = (struct intermon_state*)b->st;
153 DEBUG_CAPOPS("%s ## transfer ownership request\n", __FUNCTION__);
155 struct retrieve_response_st *rst;
156 err = calloce(1, sizeof(*rst), &rst);
157 PANIC_IF_ERR(err, "allocating retrieve respones state");
159 rst->from = inter_st->core_id;
161 struct capability rawcap;
162 caprep_to_capability(&caprep, &rawcap);
165 err = slot_alloc(&cap);
166 GOTO_IF_ERR(err, respond_err);
168 err = monitor_copy_if_exists(&rawcap, cap);
169 GOTO_IF_ERR(err, free_slot);
171 distcap_state_t state;
172 err = dom_cnode_get_state(get_cap_domref(cap), &state);
173 GOTO_IF_ERR(err, delete_cap);
175 if (distcap_state_is_busy(state)) {
176 err = MON_ERR_REMOTE_CAP_RETRY;
179 if (distcap_state_is_foreign(state)) {
180 err = MON_ERR_CAP_FOREIGN;
184 uint8_t relations, remote_relations;
185 err = monitor_cap_has_relations(cap, 0xFF, &relations);
186 GOTO_IF_ERR(err, delete_cap);
188 err = monitor_remote_relations(cap, 0, 0, &remote_relations);
189 GOTO_IF_ERR(err, delete_cap);
191 rst->relations = relations | remote_relations | RRELS_COPY_BIT;
193 err = monitor_set_cap_owner(cap_root, get_cap_addr(cap),
194 get_cap_valid_bits(cap),
198 err2 = cap_delete(cap);
199 DEBUG_IF_ERR(err2, "while deleting temp cap for retrieve");
202 err2 = slot_free(cap);
203 DEBUG_IF_ERR(err2, "freeing temp cap slot for retrieve");
206 retrieve_result__enq(err, rst);
210 retrieve_result__enq(errval_t status, struct retrieve_response_st *st)
214 st->iqn.cont = retrieve_result__send;
216 err = capsend_target(st->from, (struct msg_queue_elem*)st);
217 PANIC_IF_ERR(err, "enqueing retrieve result");
221 retrieve_result__send(struct intermon_binding *b,
222 struct intermon_msg_queue_elem *e)
225 struct retrieve_response_st *st = (struct retrieve_response_st*)e;
227 err = intermon_capops_retrieve_result__tx(b, NOP_CONT, st->status,
228 st->relations, st->st);
229 PANIC_IF_ERR(err, "sending retrieve result");
234 retrieve_result__rx(struct intermon_binding *b, errval_t status,
235 uint8_t relations, genvaddr_t st)
238 struct retrieve_rpc_st *rst = (struct retrieve_rpc_st*)(lvaddr_t)st;
240 DEBUG_CAPOPS("%s ## ownership transferred: %s \n", __FUNCTION__,
241 err_getstring(status));
243 if (err_is_fail(status)) {
248 err = monitor_domcap_remote_relations(rst->cap.croot, rst->cap.cptr,
249 rst->cap.bits, relations, 0xFF,
251 PANIC_IF_ERR(err, "setting rrels for retrieved cap");
253 DEBUG_CAPOPS("%s broadcast updates to other monitors.\n", __FUNCTION__);
255 struct event_closure updated_cont
256 = MKCONT(retrieve_ownership_update__fin, rst);
257 err = capsend_update_owner(rst->cap, updated_cont);
258 PANIC_IF_ERR(err, "updating retrieve ownership");
263 retrieve_ownership__rx(err, rst);
267 retrieve_ownership_update__fin(void *st)
269 struct retrieve_rpc_st *rst = (struct retrieve_rpc_st*)st;
271 DEBUG_CAPOPS("%s updated in ownership broadcasted.\n", __FUNCTION__);
273 retrieve_ownership__rx(SYS_ERR_OK, rst);