int _pthread_once(pthread_once_t *once_control, void (*init_routine) (void)) { int wakeup = 0; if (once_control->state == ONCE_DONE) return (0); _pthread_mutex_lock(&once_lock); while (*(volatile int *)&(once_control->state) == ONCE_IN_PROGRESS) _pthread_cond_wait(&once_cv, &once_lock); /* * If previous thread was canceled, then the state still * could be ONCE_NEVER_DONE, we need to check it again. */ if (*(volatile int *)&(once_control->state) == ONCE_NEVER_DONE) { once_control->state = ONCE_IN_PROGRESS; _pthread_mutex_unlock(&once_lock); _pthread_cleanup_push(once_cancel_handler, once_control); init_routine(); _pthread_cleanup_pop(0); _pthread_mutex_lock(&once_lock); once_control->state = ONCE_DONE; wakeup = 1; } _pthread_mutex_unlock(&once_lock); if (wakeup) _pthread_cond_broadcast(&once_cv); return (0); }
int _sem_wait(sem_t *sem) { struct pthread *curthread; int retval; if (sem_check_validity(sem) != 0) return (-1); curthread = _get_curthread(); if ((*sem)->syssem != 0) { _thr_cancel_enter(curthread); retval = ksem_wait((*sem)->semid); _thr_cancel_leave(curthread, retval != 0); } else { _pthread_testcancel(); _pthread_mutex_lock(&(*sem)->lock); while ((*sem)->count <= 0) { (*sem)->nwaiters++; THR_CLEANUP_PUSH(curthread, decrease_nwaiters, sem); _pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock); THR_CLEANUP_POP(curthread, 0); (*sem)->nwaiters--; } (*sem)->count--; _pthread_mutex_unlock(&(*sem)->lock); retval = 0; } return (retval); }
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { return (_pthread_cond_wait(cond, mutex, abstime)); }
int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = _pthread_cond_wait(cond, mutex); _thr_cancel_leave(curthread, 1); return (ret); }
int _pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) { pthread_rwlock_t prwlock; int ret; if (rwlock == NULL) return(EINVAL); prwlock = *rwlock; /* check for static initialization */ if (prwlock == NULL) { if ((ret = init_static(rwlock)) != 0) return(ret); prwlock = *rwlock; } /* grab the monitor lock */ if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0) return(ret); while (prwlock->state != 0) { prwlock->blocked_writers++; ret = _pthread_cond_wait(&prwlock->write_signal, &prwlock->lock); if (ret != 0) { prwlock->blocked_writers--; _pthread_mutex_unlock(&prwlock->lock); return(ret); } prwlock->blocked_writers--; } /* indicate we are locked for writing */ prwlock->state = -1; /* see the comment on this in pthread_rwlock_rdlock */ _pthread_mutex_unlock(&prwlock->lock); return (ret); }
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { int conforming; #if __DARWIN_UNIX03 if (__unix_conforming == 0) __unix_conforming = 1; #ifdef VARIANT_CANCELABLE conforming = 1; #else /* !VARIANT_CANCELABLE */ conforming = -1; #endif /* VARIANT_CANCELABLE */ #else /* __DARWIN_UNIX03 */ conforming = 0; #endif /* __DARWIN_UNIX03 */ return (_pthread_cond_wait(cond, mutex, (struct timespec *)NULL, 0, conforming)); }
int _pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) { pthread_rwlock_t prwlock; struct pthread *curthread; int ret; if (rwlock == NULL) return(EINVAL); prwlock = *rwlock; /* check for static initialization */ if (prwlock == NULL) { if ((ret = init_static(rwlock)) != 0) return(ret); prwlock = *rwlock; } /* grab the monitor lock */ if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0) return(ret); /* check lock count */ if (prwlock->state == MAX_READ_LOCKS) { _pthread_mutex_unlock(&prwlock->lock); return (EAGAIN); } curthread = _get_curthread(); if ((curthread->rdlock_count > 0) && (prwlock->state > 0)) { /* * To avoid having to track all the rdlocks held by * a thread or all of the threads that hold a rdlock, * we keep a simple count of all the rdlocks held by * a thread. If a thread holds any rdlocks it is * possible that it is attempting to take a recursive * rdlock. If there are blocked writers and precedence * is given to them, then that would result in the thread * deadlocking. So allowing a thread to take the rdlock * when it already has one or more rdlocks avoids the * deadlock. I hope the reader can follow that logic ;-) */ ; /* nothing needed */ } else { /* give writers priority over readers */ while (prwlock->blocked_writers || prwlock->state < 0) { ret = _pthread_cond_wait(&prwlock->read_signal, &prwlock->lock); if (ret != 0) { /* can't do a whole lot if this fails */ _pthread_mutex_unlock(&prwlock->lock); return(ret); } } } curthread->rdlock_count++; prwlock->state++; /* indicate we are locked for reading */ /* * Something is really wrong if this call fails. Returning * error won't do because we've already obtained the read * lock. Decrementing 'state' is no good because we probably * don't have the monitor lock. */ _pthread_mutex_unlock(&prwlock->lock); return (ret); }
int pthread_cond_timedwait_relative_np(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { return _pthread_cond_wait(cond, mutex, abstime, 1, 0); }
void* horse_thread(void *arg) { struct horse *horse = (struct horse *)arg; struct service *service = horse->service; _pthread_detach(pthread_self()); start: _pthread_mutex_lock(horse->mutex); while(!horse->running) { // restore strenght if (horse->strength < HORSE_START_STRENGTH) { horse->strength = (horse->strength + horse_restore_strength(horse->strength)); if (horse->strength >= HORSE_START_STRENGTH) horse->strength = HORSE_START_STRENGTH; fprintf(stderr, "horse %s strength = %d\n", horse->name, horse->strength); } _pthread_cond_wait(horse->cond, horse->mutex); } _pthread_mutex_unlock(horse->mutex); while(horse->running) { _pthread_mutex_lock(service->mfinished); if (service->finished) { _pthread_mutex_unlock(service->mfinished); break; } _pthread_mutex_unlock(service->mfinished); // make step horse->distance += horse_make_step(horse); fprintf(stderr, "horse %s: %u distance, strength = %d\n", horse->name, horse->distance, horse->strength); // means that horse has finished a track if (horse->distance >= TRACK_DISTANCE) { fprintf(stderr, "horse %s: got a distance, strength = %d\n", horse->name, horse->strength); _pthread_mutex_lock(service->mfinished); if (service->finished) { _pthread_mutex_unlock(service->mfinished); break; } fprintf(stderr, "horse %s: WON THE RACE\n", horse->name); service->win = horse; service->finished = 1; _pthread_mutex_unlock(service->mfinished); break; } _pthread_cond_wait(horse->cond, horse->mutex); _pthread_mutex_unlock(horse->mutex); } // continue waiting after finishing a run fprintf(stderr, "horse %s had finished\n", horse->name); horse->running = 0; horse->distance = 0; _pthread_mutex_lock(service->mcur_run); --service->cur_run; _pthread_mutex_unlock(service->mcur_run); goto start; return NULL; }
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { return (_pthread_cond_wait(cond, mutex, (struct timespec *)NULL)); }