]> Zhao Yanbai Git Server - minix.git/commitdiff
Resolve boot-time VM/RS deadlock 09/3109/1
authorDavid van Moolenbroek <david@minix3.org>
Fri, 4 Sep 2015 05:04:17 +0000 (07:04 +0200)
committerDavid van Moolenbroek <david@minix3.org>
Thu, 17 Sep 2015 13:27:05 +0000 (13:27 +0000)
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

minix/include/minix/sef.h
minix/lib/libsys/sef_init.c
minix/servers/rs/main.c
minix/servers/vm/main.c

index dc5a1beed6e24f63606ce21d8e43da1799f291a8..4613610cec6315f7d39893b0f438736af40aa3e1 100644 (file)
@@ -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
index 876e35f45c523cea2d33dfddb5f4eaecbf2b2b19..7b229717be77d38fd3c93221d215b19e055c1f07 100644 (file)
@@ -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;
+}
index ce3f320c2e14f3537a7f659f7bc92f28292d936a..6fd432bf71b9bb75199c696563235e885bff06a4 100644 (file)
@@ -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;
index 29ead3174c9dc091a0de054ef6b8a9ef32c7fa30..38800f498678c4e9e1a5a0cfcd6a0d20033b8190 100644 (file)
@@ -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);