hw: simplify IPC node's state model (fix #1691)

Merge the Ipc_node class' state PREPARE_AND_AWAIT_REPLY and AWAIT_REPLY,
as well as PREPARE_REPLY ans INACTIVE into one.
This commit is contained in:
Stefan Kalkowski 2015-09-15 13:20:35 +02:00 committed by Christian Helmuth
parent 5d434944eb
commit 37bae7bc1f
3 changed files with 21 additions and 41 deletions

View File

@ -42,11 +42,9 @@ class Kernel::Ipc_node : public Ipc_node_queue::Element
enum State enum State
{ {
INACTIVE = 1, INACTIVE = 1,
AWAIT_REPLY = 2, AWAIT_REPLY = 2,
AWAIT_REQUEST = 3, AWAIT_REQUEST = 3,
PREPARE_REPLY = 4,
PREPARE_AND_AWAIT_REPLY = 5,
}; };
void _init(Genode::Native_utcb * utcb, Ipc_node * callee); void _init(Genode::Native_utcb * utcb, Ipc_node * callee);
@ -170,12 +168,11 @@ class Kernel::Ipc_node : public Ipc_node_queue::Element
template <typename F> void for_each_helper(F f) template <typename F> void for_each_helper(F f)
{ {
/* if we have a helper in the receive buffer, call 'f' for it */ /* if we have a helper in the receive buffer, call 'f' for it */
if (_state == PREPARE_REPLY || _state == PREPARE_AND_AWAIT_REPLY) { if (_caller && _caller->_help) f(_caller);
if (_caller->_help) { f(_caller); } }
/* call 'f' for each helper in our request queue */ /* call 'f' for each helper in our request queue */
_request_queue.for_each([f] (Ipc_node * const node) { _request_queue.for_each([f] (Ipc_node * const node) {
if (node->_help) { f(node); } }); if (node->_help) f(node); });
} }
/** /**

View File

@ -86,15 +86,14 @@ void Ipc_node::_receive_request(Ipc_node * const caller)
{ {
copy_msg(caller); copy_msg(caller);
_caller = caller; _caller = caller;
_state = PREPARE_REPLY; _state = INACTIVE;
} }
void Ipc_node::_receive_reply(Ipc_node * callee) void Ipc_node::_receive_reply(Ipc_node * callee)
{ {
copy_msg(callee); copy_msg(callee);
_state = (_state != PREPARE_AND_AWAIT_REPLY) ? INACTIVE _state = INACTIVE;
: PREPARE_REPLY;
_send_request_succeeded(); _send_request_succeeded();
} }
@ -151,16 +150,12 @@ void Ipc_node::_outbuf_request_cancelled()
if (_callee == nullptr) return; if (_callee == nullptr) return;
_callee = nullptr; _callee = nullptr;
_state = (!_caller) ? INACTIVE : PREPARE_REPLY; _state = INACTIVE;
_send_request_failed(); _send_request_failed();
} }
bool Ipc_node::_helps_outbuf_dst() bool Ipc_node::_helps_outbuf_dst() { return (_state == AWAIT_REPLY) && _help; }
{
return (_state == PREPARE_AND_AWAIT_REPLY ||
_state == AWAIT_REPLY) && _help;
}
void Ipc_node::_init(Genode::Native_utcb * utcb, Ipc_node * starter) void Ipc_node::_init(Genode::Native_utcb * utcb, Ipc_node * starter)
@ -177,16 +172,15 @@ void Ipc_node::_init(Genode::Native_utcb * utcb, Ipc_node * starter)
void Ipc_node::send_request(Ipc_node * const callee, capid_t capid, bool help, void Ipc_node::send_request(Ipc_node * const callee, capid_t capid, bool help,
unsigned rcv_caps) unsigned rcv_caps)
{ {
/* assertions */ if (_state != INACTIVE) {
assert(_state == INACTIVE || _state == PREPARE_REPLY); PERR("IPC send request: bad state");
return;
}
Genode::Allocator &slab = pd()->platform_pd()->capability_slab(); Genode::Allocator &slab = pd()->platform_pd()->capability_slab();
for (unsigned i = 0; i < rcv_caps; i++) for (unsigned i = 0; i < rcv_caps; i++)
_obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference)); _obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
/* update state */ _state = AWAIT_REPLY;
_state = (_state != PREPARE_REPLY) ? AWAIT_REPLY
: PREPARE_AND_AWAIT_REPLY;
_callee = callee; _callee = callee;
_capid = capid; _capid = capid;
_help = false; _help = false;
@ -205,9 +199,10 @@ Ipc_node * Ipc_node::helping_sink() {
bool Ipc_node::await_request(unsigned rcv_caps) bool Ipc_node::await_request(unsigned rcv_caps)
{ {
/* assertions */ if (_state != INACTIVE) {
assert(_state == INACTIVE); PERR("IPC await request: bad state");
return true;
}
Genode::Allocator &slab = pd()->platform_pd()->capability_slab(); Genode::Allocator &slab = pd()->platform_pd()->capability_slab();
for (unsigned i = 0; i < rcv_caps; i++) for (unsigned i = 0; i < rcv_caps; i++)
_obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference)); _obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
@ -229,12 +224,9 @@ bool Ipc_node::await_request(unsigned rcv_caps)
void Ipc_node::send_reply() void Ipc_node::send_reply()
{ {
/* reply to the last request if we have to */ /* reply to the last request if we have to */
if (_state == PREPARE_REPLY) { if (_state == INACTIVE && _caller) {
if (_caller != nullptr) { _caller->_receive_reply(this);
_caller->_receive_reply(this); _caller = nullptr;
_caller = nullptr;
}
_state = INACTIVE;
} }
} }
@ -251,10 +243,6 @@ void Ipc_node::cancel_waiting()
_state = INACTIVE; _state = INACTIVE;
_await_request_failed(); _await_request_failed();
break; break;
case PREPARE_AND_AWAIT_REPLY:
_cancel_outbuf_request();
_state = PREPARE_REPLY;
_send_request_failed();
return; return;
default: return; default: return;
} }

View File

@ -455,11 +455,6 @@ void Thread::_print_activity_when_awaits_ipc()
case AWAIT_REQUEST: { case AWAIT_REQUEST: {
Genode::printf("\033[32m await REQ\033[0m"); Genode::printf("\033[32m await REQ\033[0m");
break; } break; }
case PREPARE_AND_AWAIT_REPLY: {
Thread * const server = dynamic_cast<Thread *>(Ipc_node::callee());
Genode::printf("\033[32m prep RPL await RPL %s -> %s\033[0m",
server->pd_label(), server->label());
break; }
default: break; default: break;
} }
} }