long oldstatus, newstatus; volatile pthread_descr self = thread_self(); pthread_descr * th;
volatile pthread_descr self;
int sem_wait(sem_t * sem){  long oldstatus, newstatus;  volatile pthread_descr self = thread_self();  pthread_descr * th;  while (1) {    do {      oldstatus = sem->sem_status;      if ((oldstatus & 1) && (oldstatus != 1))        newstatus = oldstatus - 2;      else {        newstatus = (long) self;        self->p_nextwaiting = (pthread_descr) oldstatus;      }    }    while (! sem_compare_and_swap(sem, oldstatus, newstatus));    if (newstatus & 1)      /* We got the semaphore. */      return 0;    /* Wait for sem_post or cancellation */    suspend_with_cancellation(self);    /* This is a cancellation point */    if (self->p_canceled && self->p_cancelstate == PTHREAD_CANCEL_ENABLE) {      /* Remove ourselves from the waiting list if we're still on it */      /* First check if we're at the head of the list. */      do {        oldstatus = sem->sem_status;        if (oldstatus != (long) self) break;        newstatus = (long) self->p_nextwaiting;      }      while (! sem_compare_and_swap(sem, oldstatus, newstatus));      /* Now, check if we're somewhere in the list.         There's a race condition with sem_post here, but it does not matter:         the net result is that at the time pthread_exit is called,         self is no longer reachable from sem->sem_status. */      if (oldstatus != (long) self && (oldstatus & 1) == 0) {	for (th = &(((pthread_descr) oldstatus)->p_nextwaiting);	     *th != NULL && *th != (pthread_descr) 1;	     th = &((*th)->p_nextwaiting)) {          if (*th == self) {            *th = self->p_nextwaiting;            break;          }        }      }      pthread_exit(PTHREAD_CANCELED);    }  }}