Пример #1
0
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);
}
Пример #2
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);
}
Пример #3
0
int       
pthread_cond_timedwait(pthread_cond_t *cond, 
		       pthread_mutex_t *mutex,
		       const struct timespec *abstime)
{
	return (_pthread_cond_wait(cond, mutex, abstime));
}
Пример #4
0
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);
}
Пример #5
0
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));
}
Пример #7
0
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);
}
Пример #8
0
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);
}
Пример #9
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;
}
Пример #10
0
int       
pthread_cond_wait(pthread_cond_t *cond, 
		  pthread_mutex_t *mutex)
{
	return (_pthread_cond_wait(cond, mutex, (struct timespec *)NULL));
}