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_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_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_reply(message *m_ptr);
|
||||||
|
int sef_cb_init_response_rs_asyn_once(message *m_ptr);
|
||||||
|
|
||||||
/* Macros for predefined callback implementations. */
|
/* Macros for predefined callback implementations. */
|
||||||
#define SEF_CB_INIT_FRESH_NULL sef_cb_init_null
|
#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;
|
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);
|
panic("unable to complete init for service: %d", m.m_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a reply to unblock the service. */
|
/* Send a reply to unblock the service, except to VM, which sent the reply
|
||||||
m.m_type = OK;
|
* asynchronously. Synchronous replies could lead to deadlocks there.
|
||||||
reply(m.m_source, rp, &m);
|
*/
|
||||||
|
if (m.m_source != VM_PROC_NR) {
|
||||||
|
m.m_type = OK;
|
||||||
|
reply(m.m_source, rp, &m);
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark the slot as no longer initializing. */
|
/* Mark the slot as no longer initializing. */
|
||||||
rp->r_flags &= ~RS_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_fresh(sef_cb_init_fresh);
|
||||||
sef_setcb_init_lu(sef_cb_init_lu_restart);
|
sef_setcb_init_lu(sef_cb_init_lu_restart);
|
||||||
sef_setcb_init_restart(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. */
|
/* Register signal callbacks. */
|
||||||
sef_setcb_signal_handler(sef_cb_signal_handler);
|
sef_setcb_signal_handler(sef_cb_signal_handler);
|
||||||
|
|
Loading…
Reference in a new issue