int retsleep, already_canceled, was_signalled;
int already_canceled = 0; int was_signalled = 0;
pthread_cond_timedwait_relative_new(pthread_cond_t *cond,				pthread_mutex_t *mutex,				const struct timespec * abstime){  volatile pthread_descr self = thread_self();  sigset_t unblock, initial_mask;  int retsleep, already_canceled, was_signalled;  sigjmp_buf jmpbuf;  pthread_extricate_if extr;  struct timeval now;  struct timespec reltime; requeue_and_wait_again:  /* Compute a time offset relative to now.  */  __gettimeofday (&now, NULL);  reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;  reltime.tv_sec = abstime->tv_sec - now.tv_sec;  if (reltime.tv_nsec < 0) {    reltime.tv_nsec += 1000000000;    reltime.tv_sec -= 1;  }  if (reltime.tv_sec < 0)    return ETIMEDOUT;  retsleep = 0;  already_canceled = 0;  was_signalled = 0;  /* Set up extrication interface */  extr.pu_object = cond;  extr.pu_extricate_func = cond_extricate_func;  /* Register extrication interface */  __pthread_set_own_extricate_if(self, &extr);  /* Enqueue to wait on the condition and check for cancellation. */  __pthread_lock(&cond->__c_lock, self);  if (!(THREAD_GETMEM(self, p_canceled)      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))    enqueue(&cond->__c_waiting, self);  else    already_canceled = 1;  __pthread_unlock(&cond->__c_lock);  if (already_canceled) {    __pthread_set_own_extricate_if(self, 0);    pthread_exit(PTHREAD_CANCELED);  }  pthread_mutex_unlock(mutex);  /* Set up a longjmp handler for the restart signal, unblock     the signal and sleep. */  if (sigsetjmp(jmpbuf, 1) == 0) {    THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);    THREAD_SETMEM(self, p_signal, 0);    /* Unblock the restart signal */    sigemptyset(&unblock);    sigaddset(&unblock, __pthread_sig_restart);    sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);    /* Sleep for the required duration */    retsleep = __libc_nanosleep(&reltime, NULL);    /* Block the restart signal again */    sigprocmask(SIG_SETMASK, &initial_mask, NULL);    was_signalled = 0;  } else {    retsleep = -1;    was_signalled = 1;  }  THREAD_SETMEM(self, p_signal_jmp, NULL);  /* Now was_signalled is true if we exited the above code     due to the delivery of a restart signal.  In that case,     everything is cool. We have been removed from the queue     by the other thread, and consumed its signal.     Otherwise we this thread woke up spontaneously, or due to a signal other     than restart. The next thing to do is to try to remove the thread     from the queue. This may fail due to a race against another thread     trying to do the same. In the failed case, we know we were signalled,     and we may also have to consume a restart signal. */  if (!was_signalled) {    int was_on_queue;    /* __pthread_lock will queue back any spurious restarts that       may happen to it. */    __pthread_lock(&cond->__c_lock, self);    was_on_queue = remove_from_queue(&cond->__c_waiting, self);    __pthread_unlock(&cond->__c_lock);    if (was_on_queue) {      __pthread_set_own_extricate_if(self, 0);      pthread_mutex_lock(mutex);      if (retsleep == 0)	return ETIMEDOUT;      /* Woken by a signal: resume waiting as required by Single Unix	 Specification.  */      goto requeue_and_wait_again;    }    /* Eat the outstanding restart() from the signaller */    suspend(self);  }  __pthread_set_own_extricate_if(self, 0);  /* The remaining logic is the same as in other cancellable waits,     such as pthread_join sem_wait or pthread_cond wait. */  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_mutex_lock(mutex);    pthread_exit(PTHREAD_CANCELED);  }  pthread_mutex_lock(mutex);  return 0;}