| 
					
				 | 
			
			
				@@ -805,40 +805,36 @@ next: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define IPC_HELPER_STACK_SIZE       (allocsize * 4) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define IPC_HELPER_LIST_INIT_SIZE   32 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void shim_ipc_helper (void * arg) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void shim_ipc_helper_end(struct shim_thread * self) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /* set ipc helper thread */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    struct shim_thread * self = (struct shim_thread *) arg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!arg) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* Put our handle map reference */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (self->handle_map) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        put_handle_map(self->handle_map); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    __libc_tcb_t tcb; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    allocate_tls(&tcb, false, self); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    debug_setbuf(&tcb.shim_tcb, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    debug("set tcb to %p\n", &tcb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* Another thread may be calling shim_clean(). Lower the chances of our 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * IPC helper thread and another thread competing on shim_clean/shim_terminate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * (which is benign due to protection via ipc_helper_lock) by adding a barrier 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * to ensure reading the latest IPC helper state. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    COMPILER_BARRIER(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (ipc_helper_state == HELPER_HANDEDOVER) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        debug("ipc helper thread is the last thread, process exiting\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        shim_terminate(0); // Same as shim_clean(), but this is the official termination function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     lock(&ipc_helper_lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    bool notme = (self != ipc_helper_thread); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ipc_helper_state = HELPER_NOTALIVE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ipc_helper_thread = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     unlock(&ipc_helper_lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    put_thread(self); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    debug("ipc helper thread terminated\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (notme) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        put_thread(self); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        DkThreadExit(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    debug("ipc helper thread started\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void * stack = allocate_stack(IPC_HELPER_STACK_SIZE, allocsize, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!stack) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        goto end; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    DkThreadExit(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    self->stack_top = stack + IPC_HELPER_STACK_SIZE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    self->stack = stack; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    SWITCH_STACK(stack + IPC_HELPER_STACK_SIZE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    self = get_cur_thread(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    stack = self->stack; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void __shim_ipc_helper (void * dummy) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    struct shim_thread * self = get_cur_thread(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    void * stack = self->stack; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int port_num = 0, port_size = IPC_HELPER_LIST_INIT_SIZE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     struct shim_ipc_port ** local_pobjs = stack, * pobj; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1020,28 +1016,43 @@ update_list: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 end: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /* DP: Put our handle map reference */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (self->handle_map) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        put_handle_map(self->handle_map); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    shim_ipc_helper_end(self); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /* shim_clean ultimately calls del_all_ipc_ports(), which reacquires the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * helper lock.  Err on the side of caution by adding a barrier to ensure 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * reading the latest ipc helper state. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    COMPILER_BARRIER(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (ipc_helper_state == HELPER_HANDEDOVER) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        debug("ipc helper thread is the last thread, process exiting\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        shim_terminate(0); // Same as shim_clean(), but this is the official termination function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void shim_ipc_helper (void * arg) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* set ipc helper thread */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    struct shim_thread * self = (struct shim_thread *) arg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!arg) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    __libc_tcb_t tcb; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    allocate_tls(&tcb, false, self); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    debug_setbuf(&tcb.shim_tcb, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    debug("set tcb to %p\n", &tcb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     lock(&ipc_helper_lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ipc_helper_state = HELPER_NOTALIVE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ipc_helper_thread = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bool notme = (self != ipc_helper_thread); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     unlock(&ipc_helper_lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    put_thread(self); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    debug("ipc helper thread terminated\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    DkThreadExit(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (notme) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        put_thread(self); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        DkThreadExit(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    debug("ipc helper thread started\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    void * stack = allocate_stack(IPC_HELPER_STACK_SIZE, allocsize, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!stack) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        shim_ipc_helper_end(self); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    self->stack_top = stack + IPC_HELPER_STACK_SIZE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    self->stack = stack; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    __SWITCH_STACK(self->stack_top, __shim_ipc_helper, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* This function shoudl be called with the ipc_helper_lock held */ 
			 |