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
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;
+}
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;
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);