pthread_exit(PTHREAD_CANCELED);
__pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
int sem_timedwait(sem_t *sem, const struct timespec *abstime){  pthread_descr self = thread_self();  pthread_extricate_if extr;  int already_canceled = 0;  int spurious_wakeup_count;  __pthread_lock((struct _pthread_fastlock *) &sem->__sem_lock, self);  if (sem->__sem_value > 0) {    --sem->__sem_value;    __pthread_unlock((struct _pthread_fastlock *) &sem->__sem_lock);    return 0;  }  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) {    /* The standard requires that if the function would block and the       time value is illegal, the function returns with an error.  */    __pthread_unlock((struct _pthread_fastlock *) &sem->__sem_lock);    return EINVAL;  }  /* Set up extrication interface */  extr.pu_object = sem;  extr.pu_extricate_func = new_sem_extricate_func;  /* Register extrication interface */  THREAD_SETMEM(self, p_sem_avail, 0);  __pthread_set_own_extricate_if(self, &extr);  /* Enqueue only if not already cancelled. */  if (!(THREAD_GETMEM(self, p_canceled)      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))    enqueue(&sem->__sem_waiting, self);  else    already_canceled = 1;  __pthread_unlock((struct _pthread_fastlock *) &sem->__sem_lock);  if (already_canceled) {    __pthread_set_own_extricate_if(self, 0);    pthread_exit(PTHREAD_CANCELED);  }  spurious_wakeup_count = 0;  while (1)    {      if (timedsuspend(self, abstime) == 0) {	int was_on_queue;	/* __pthread_lock will queue back any spurious restarts that	   may happen to it. */	__pthread_lock((struct _pthread_fastlock *)&sem->__sem_lock, self);	was_on_queue = remove_from_queue(&sem->__sem_waiting, self);	__pthread_unlock((struct _pthread_fastlock *)&sem->__sem_lock);	if (was_on_queue) {	  __pthread_set_own_extricate_if(self, 0);	  return ETIMEDOUT;	}	/* Eat the outstanding restart() from the signaller */	suspend(self);      }      if (THREAD_GETMEM(self, p_sem_avail) == 0	  && (THREAD_GETMEM(self, p_woken_by_cancel) == 0	      || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))	{	  /* Count resumes that don't belong to us. */	  spurious_wakeup_count++;	  continue;	}      break;    } __pthread_set_own_extricate_if(self, 0);  /* Terminate only if the wakeup came from cancellation. */  /* Otherwise ignore cancellation because we got the semaphore. */  if (THREAD_GETMEM(self, p_woken_by_cancel)      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {    THREAD_SETMEM(self, p_woken_by_cancel, 0);    pthread_exit(PTHREAD_CANCELED);  }  /* We got the semaphore */  return 0;}