pthread_descr self = thread_self(); pthread_descr joining; struct pthread_request request;   THREAD_SETMEM(self, p_canceled, 0);  __pthread_perform_cleanup(); __pthread_destroy_specifics();  __pthread_lock(THREAD_GETMEM(self, p_lock), self); THREAD_SETMEM(self, p_retval, retval);  if (THREAD_GETMEM(self, p_report_events)) {  int idx = __td_eventword (TD_DEATH); uint32_t mask = __td_eventmask (TD_DEATH);  if ((mask & (__pthread_threads_events.event_bits[idx] | THREAD_GETMEM_NC(self, p_eventbuf.eventmask.event_bits[idx]))) != 0) {  THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH); THREAD_SETMEM(self, p_eventbuf.eventdata, self); __pthread_last_event = self;   __linuxthreads_death_event(); } }  THREAD_SETMEM(self, p_terminated, 1);  joining = THREAD_GETMEM(self, p_joining); __pthread_unlock(THREAD_GETMEM(self, p_lock));  if (joining != NULL) restart(joining);  if (self == __pthread_main_thread && __pthread_manager_request >= 0) { request.req_thread = self; request.req_kind = REQ_MAIN_THREAD_EXIT; __libc_write(__pthread_manager_request, (char *)&request, sizeof(request)); suspend(self);  exit(0); }  _exit(0);
__pthread_do_exit (retval, CURRENT_STACK_FRAME);
void pthread_exit(void * retval){  pthread_descr self = thread_self();  pthread_descr joining;  struct pthread_request request;  /* Reset the cancellation flag to avoid looping if the cleanup handlers     contain cancellation points */  THREAD_SETMEM(self, p_canceled, 0);  /* Call cleanup functions and destroy the thread-specific data */  __pthread_perform_cleanup();  __pthread_destroy_specifics();  /* Store return value */  __pthread_lock(THREAD_GETMEM(self, p_lock), self);  THREAD_SETMEM(self, p_retval, retval);  /* See whether we have to signal the death.  */  if (THREAD_GETMEM(self, p_report_events))    {      /* See whether TD_DEATH is in any of the mask.  */      int idx = __td_eventword (TD_DEATH);      uint32_t mask = __td_eventmask (TD_DEATH);      if ((mask & (__pthread_threads_events.event_bits[idx]		   | THREAD_GETMEM_NC(self,				      p_eventbuf.eventmask.event_bits[idx])))	  != 0)	{	  /* Yep, we have to signal the death.  */	  THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH);	  THREAD_SETMEM(self, p_eventbuf.eventdata, self);	  __pthread_last_event = self;	  /* Now call the function to signal the event.  */	  __linuxthreads_death_event();	}    }  /* Say that we've terminated */  THREAD_SETMEM(self, p_terminated, 1);  /* See if someone is joining on us */  joining = THREAD_GETMEM(self, p_joining);  __pthread_unlock(THREAD_GETMEM(self, p_lock));  /* Restart joining thread if any */  if (joining != NULL) restart(joining);  /* If this is the initial thread, block until all threads have terminated.     If another thread calls exit, we'll be terminated from our signal     handler. */  if (self == __pthread_main_thread && __pthread_manager_request >= 0) {    request.req_thread = self;    request.req_kind = REQ_MAIN_THREAD_EXIT;    __libc_write(__pthread_manager_request, (char *)&request, sizeof(request));    suspend(self);    /* Main thread flushes stdio streams and runs atexit functions.       It also calls a handler within LinuxThreads which sends a process exit       request to the thread manager. */    exit(0);  }  /* Threads other than the main one  terminate without flushing stdio streams     or running atexit functions. */  _exit(0);}