release(self->p_spinlock);
__pthread_unlock(self->p_lock);
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 */  self->p_canceled = 0;  /* Call cleanup functions and destroy the thread-specific data */  __pthread_perform_cleanup();  __pthread_destroy_specifics();  /* Store return value */  acquire(self->p_spinlock);  self->p_retval = retval;  /* Say that we've terminated */  self->p_terminated = 1;  /* See if someone is joining on us */  joining = self->p_joining;  release(self->p_spinlock);  /* 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);  }  /* Exit the process (but don't flush stdio streams, and don't run     atexit functions). */  _exit(0);}