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
					
				@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user