Resolve boot-time VM/RS deadlock
VM used to call sendrec to send a boot-time RS_INIT reply to RS, but RS could run into a pagefault at the same time, thus spawning a message to VM, resulting in a deadlock. We resolve this situation by making VM acknowledge RS_INIT asynchronously at boot time, while retaining the synchronous sendrec for subsequent RS_INIT responses. Change-Id: I3cb72d7f8d6b9bfdc59a85958ada739c37fa3bde
This commit is contained in:
parent
0e78c0166c
commit
37489f8a24
4 changed files with 29 additions and 3 deletions
|
@ -73,6 +73,7 @@ int sef_cb_init_identity_state_transfer(int type, sef_init_info_t *info);
|
|||
int sef_cb_init_lu_identity_as_restart(int type, sef_init_info_t *info);
|
||||
int sef_cb_init_lu_generic(int type, sef_init_info_t *info);
|
||||
int sef_cb_init_response_rs_reply(message *m_ptr);
|
||||
int sef_cb_init_response_rs_asyn_once(message *m_ptr);
|
||||
|
||||
/* Macros for predefined callback implementations. */
|
||||
#define SEF_CB_INIT_FRESH_NULL sef_cb_init_null
|
||||
|
|
|
@ -434,3 +434,19 @@ int sef_cb_init_response_rs_reply(message *m_ptr)
|
|||
return r;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_cb_init_response_rs_asyn_once *
|
||||
*===========================================================================*/
|
||||
int sef_cb_init_response_rs_asyn_once(message *m_ptr)
|
||||
{
|
||||
/* This response function is used by VM to avoid a boot-time deadlock. */
|
||||
int r;
|
||||
|
||||
/* Inform RS that we completed initialization, asynchronously. */
|
||||
r = asynsend3(RS_PROC_NR, m_ptr, AMF_NOREPLY);
|
||||
|
||||
/* Use a blocking reply call next time. */
|
||||
sef_setcb_init_response(SEF_CB_INIT_RESPONSE_DEFAULT);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -807,9 +807,13 @@ endpoint_t endpoint;
|
|||
panic("unable to complete init for service: %d", m.m_source);
|
||||
}
|
||||
|
||||
/* Send a reply to unblock the service. */
|
||||
m.m_type = OK;
|
||||
reply(m.m_source, rp, &m);
|
||||
/* Send a reply to unblock the service, except to VM, which sent the reply
|
||||
* asynchronously. Synchronous replies could lead to deadlocks there.
|
||||
*/
|
||||
if (m.m_source != VM_PROC_NR) {
|
||||
m.m_type = OK;
|
||||
reply(m.m_source, rp, &m);
|
||||
}
|
||||
|
||||
/* Mark the slot as no longer initializing. */
|
||||
rp->r_flags &= ~RS_INITIALIZING;
|
||||
|
|
|
@ -200,6 +200,11 @@ static void sef_local_startup(void)
|
|||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||
sef_setcb_init_lu(sef_cb_init_lu_restart);
|
||||
sef_setcb_init_restart(sef_cb_init_lu_restart);
|
||||
/* In order to avoid a deadlock at boot time, send the first RS_INIT
|
||||
* reply to RS asynchronously. After that, use sendrec as usual.
|
||||
*/
|
||||
if (__vm_init_fresh)
|
||||
sef_setcb_init_response(sef_cb_init_response_rs_asyn_once);
|
||||
|
||||
/* Register signal callbacks. */
|
||||
sef_setcb_signal_handler(sef_cb_signal_handler);
|
||||
|
|
Loading…
Reference in a new issue