Esempio n. 1
0
void play(pthread_cond_t *cond, struct service *service, struct horse *horses, size_t horse_num) {
	init_race(service);

	while(run) {
		_pthread_mutex_lock(service->mfinished);
		if (service->finished) {
			_pthread_mutex_unlock(service->mfinished);

			// send if someone is waiting
			_pthread_cond_broadcast(cond);
check_for_horses:
			_pthread_mutex_lock(service->mcur_run);
			if (!service->cur_run) {
				_pthread_mutex_unlock(service->mcur_run);	
				break;
			}
			else {
				_pthread_mutex_unlock(service->mcur_run);
				_sleep(1, 0);
				goto check_for_horses;
			}
		}
		_pthread_mutex_unlock(service->mfinished);	
		_sleep(1, 0);
		_pthread_cond_broadcast(cond);
	}

	post_race(service, horses, horse_num);
} 
Esempio n. 2
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);
}
Esempio n. 3
0
void init_race(struct service *service) {
	// copy horse bets
	_pthread_mutex_lock(service->mhb);
	memcpy(service->copy_horse_bet, service->horse_bet, sizeof(unsigned int) * HORSE_RUN);	
	_pthread_mutex_unlock(service->mhb);
	
	// be sure that noone is using value
	_pthread_mutex_lock(service->mfinished);
	service->finished = 0;
	_pthread_mutex_unlock(service->mfinished);

	start_horses(service);
}
Esempio n. 4
0
void update_money(struct user *user, unsigned int *_money) {
	if (user->horse && !strcmp(user->horse->name, user->service->win->name)) {
		_pthread_mutex_lock(user->service->mbank);

		_pthread_mutex_lock(user->service->mhb);	
		*_money = user->service->bank / user->service->copy_horse_bet[user->id];
		--user->service->copy_horse_bet[user->id];	
		user->service->bank -= *_money;
		user->money += *_money;
		
		_pthread_mutex_unlock(user->service->mhb);
		_pthread_mutex_unlock(user->service->mbank);			
	} 
}
int
_pthread_mutex_setprioceiling(pthread_mutex_t *mutex,
			      int prioceiling, int *old_ceiling)
{
	int ret = 0;
	int tmp;

	if ((mutex == NULL) || (*mutex == NULL))
		ret = EINVAL;
	else if ((*mutex)->m_protocol != PTHREAD_PRIO_PROTECT)
		ret = EINVAL;
	/* Lock the mutex: */
	else if ((ret = _pthread_mutex_lock(mutex)) == 0) {
		tmp = (*mutex)->m_prio;
		/* Set the new ceiling: */
		(*mutex)->m_prio = prioceiling;

		/* Unlock the mutex: */
		ret = _pthread_mutex_unlock(mutex);

		/* Return the old ceiling: */
		*old_ceiling = tmp;
	}
	return(ret);
}
Esempio n. 6
0
int
_pthread_rwlock_trywrlock (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);

	if (prwlock->state != 0)
		ret = EBUSY;
	else
		/* 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);
}
Esempio n. 7
0
/*
 * Reclaim memory for telldir cookies which weren't used.
 */
void
_reclaim_telldir(DIR *dirp)
{
    struct ddloc *lp;
    struct ddloc **prevlp;
    int i;

    if (__isthreaded)
        _pthread_mutex_lock(&dd_hash_lock);
    for (i = 0; i < NDIRHASH; i++) {
        prevlp = &dd_hash[i];
        lp = *prevlp;
        while (lp != NULL) {
            if (lp->loc_dirp == dirp) {
                *prevlp = lp->loc_next;
                free((caddr_t)lp);
                lp = *prevlp;
                continue;
            }
            prevlp = &lp->loc_next;
            lp = lp->loc_next;
        }
    }
    if (__isthreaded)
        _pthread_mutex_unlock(&dd_hash_lock);
}
Esempio n. 8
0
char* get_next_race_time(struct service *service) {
	char *ret;
	_pthread_mutex_lock(service->mnr);
	ret = ctime(&service->next_race);
	_pthread_mutex_unlock(service->mnr);
	return ret;	
}
Esempio n. 9
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);
}
Esempio n. 10
0
/*
 * seek to an entry in a directory.
 * Only values returned by "telldir" should be passed to seekdir.
 */
void
_seekdir(DIR *dirp, long loc)
{
    struct ddloc *lp;
    struct dirent *dp;

    if (__isthreaded)
        _pthread_mutex_lock(&dd_hash_lock);
    for (lp = dd_hash[LOCHASH(loc)]; lp; lp = lp->loc_next) {
        if (lp->loc_dirp == dirp && lp->loc_index == loc)
            break;
    }
    if (__isthreaded)
        _pthread_mutex_unlock(&dd_hash_lock);
    if (lp == NULL)
        return;
    if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek)
        return;
    lseek(dirp->dd_fd, lp->loc_seek, SEEK_SET);
    dirp->dd_seek = lp->loc_seek;
    dirp->dd_loc = 0;
    dirp->dd_lastseek = loc;

    /*
     * Scan the buffer until we find dd_loc.  If the directory
     * changed between the tell and seek it is possible to
     * load a new buffer or for dd_loc to not match directly.
     */
    while (dirp->dd_loc < lp->loc_loc && dirp->dd_seek == lp->loc_seek) {
        dp = _readdir_unlocked(dirp, 0);
        if (dp == NULL)
            break;
    }
}
Esempio n. 11
0
struct tm *
gmtime(const time_t * const timep)
{
	static pthread_mutex_t gmtime_mutex = PTHREAD_MUTEX_INITIALIZER;
	static pthread_key_t gmtime_key = -1;
	struct tm *p_tm;

	if (__isthreaded != 0) {
		if (gmtime_key < 0) {
			_pthread_mutex_lock(&gmtime_mutex);
			if (gmtime_key < 0) {
				if (_pthread_key_create(&gmtime_key, free) < 0) {
					_pthread_mutex_unlock(&gmtime_mutex);
					return(NULL);
				}
			}
			_pthread_mutex_unlock(&gmtime_mutex);
		}
		/*
		 * Changed to follow POSIX.1 threads standard, which
		 * is what BSD currently has.
		 */
		if ((p_tm = _pthread_getspecific(gmtime_key)) == NULL) {
			if ((p_tm = (struct tm *)malloc(sizeof(struct tm)))
			    == NULL) {
				return(NULL);
			}
			_pthread_setspecific(gmtime_key, p_tm);
		}
		return gmtsub(timep, 0L, p_tm);
	} else {
		return gmtsub(timep, 0L, &tm);
	}
}
Esempio n. 12
0
/*
 * Seek to an entry in a directory.
 * _seekdir is in telldir.c so that it can share opaque data structures.
 */
void
seekdir(DIR *dirp, long loc)
{
    if (__isthreaded)
        _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
    _seekdir(dirp, loc);
    if (__isthreaded)
        _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
}
Esempio n. 13
0
/*
 * return a pointer into a directory
 */
long
telldir(DIR *dirp)
{
    long index;
    struct ddloc *lp;

    if (__isthreaded) {
        _pthread_mutex_lock(&dirp->dd_lock);
        _pthread_mutex_lock(&dd_hash_lock);
    }

    /*
     * Reduce memory use by reusing a ddloc that might already exist
     * for this position.
     */
    for (lp = dd_hash[LOCHASH(dirp->dd_lastseek)]; lp; lp = lp->loc_next) {
        if (lp->loc_dirp == dirp && lp->loc_seek == dirp->dd_seek &&
                lp->loc_loc == dirp->dd_loc) {
            index = lp->loc_index;
            goto done;
        }
    }

    if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL) {
        index = -1;
        goto done;
    }
    index = dd_loccnt++;
    lp->loc_index = index;
    lp->loc_seek = dirp->dd_seek;
    lp->loc_loc = dirp->dd_loc;
    lp->loc_dirp = dirp;

    lp->loc_next = dd_hash[LOCHASH(index)];
    dd_hash[LOCHASH(index)] = lp;

done:
    if (__isthreaded) {
        _pthread_mutex_unlock(&dd_hash_lock);
        _pthread_mutex_unlock(&dirp->dd_lock);
    }
    return (index);
}
Esempio n. 14
0
static void
once_cancel_handler(void *arg)
{
	pthread_once_t *once_control = arg;

	_pthread_mutex_lock(&once_lock);
	once_control->state = ONCE_NEVER_DONE;
	_pthread_mutex_unlock(&once_lock);
	_pthread_cond_broadcast(&once_cv);
}
Esempio n. 15
0
void set_next_race_time(struct service *service) {
	time_t now = time(NULL);
	struct tm *tm_now = localtime(&now);
	if (!tm_now)
		ERR("localtime");
	struct tm tm_then = *tm_now;
	tm_then.tm_sec += service->delay;
	_pthread_mutex_lock(service->mnr);
	service->next_race = mktime(&tm_then);
	_pthread_mutex_unlock(service->mnr);				
}
Esempio n. 16
0
int
_pthread_once(pthread_once_t * once_control, void (*init_routine) (void))
{
	if (once_control->state == PTHREAD_NEEDS_INIT) {
		if (_thread_initial == NULL)
			_thread_init();
		_pthread_mutex_lock(&(once_control->mutex));
		if (once_control->state == PTHREAD_NEEDS_INIT) {
			init_routine();
			once_control->state = PTHREAD_DONE_INIT;
		}
		_pthread_mutex_unlock(&(once_control->mutex));
	}
	return (0);
}
Esempio n. 17
0
void post_race(struct service *service, struct horse *horses, size_t horse_num) {
	_pthread_mutex_lock(service->mcur_run);
	service->cur_run = HORSE_RUN;
	_pthread_mutex_unlock(service->mcur_run);

	// choose new horses
	memset(service->current_run, 0, sizeof(struct horse *) * HORSE_RUN);
	choose_run_horses(horses, horse_num, service);	
	memset(service->horse_bet, 0, sizeof(unsigned int) * HORSE_RUN);
	
	// set new time for next run
	set_next_race_time(service);		

	run = 0; 

	alarm(service->delay);
}
Esempio n. 18
0
void
_flockfile(FILE *fp)
{
	pthread_t curthread = _pthread_self();

	if (fp->_lock->fl_owner == curthread)
		fp->_lock->fl_count++;
	else {
		/*
		 * Make sure this mutex is treated as a private
		 * internal mutex:
		 */
		_pthread_mutex_lock(&fp->_lock->fl_mutex);
		fp->_lock->fl_owner = curthread;
		fp->_lock->fl_count = 1;
	}
}
Esempio n. 19
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);
}
Esempio n. 20
0
int
_pthread_rwlock_tryrdlock (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);

	curthread = _get_curthread();
	if (prwlock->state == MAX_READ_LOCKS)
		ret = EAGAIN; /* too many read locks acquired */
	else if ((curthread->rdlock_count > 0) && (prwlock->state > 0)) {
		/* see comment for pthread_rwlock_rdlock() */
		curthread->rdlock_count++;
		prwlock->state++;
	}
	/* give writers priority over readers */
	else if (prwlock->blocked_writers || prwlock->state < 0)
		ret = EBUSY;
	else {
		prwlock->state++; /* indicate we are locked for reading */
		curthread->rdlock_count++;
	}

	/* see the comment on this in pthread_rwlock_rdlock */
	_pthread_mutex_unlock(&prwlock->lock);

	return (ret);
}
Esempio n. 21
0
void
rewinddir(DIR *dirp)
{

	if (__isthreaded)
		_pthread_mutex_lock(&dirp->dd_lock);
	dirp->dd_flags &= ~__DTF_SKIPREAD; /* current contents are invalid */
	if (dirp->dd_flags & __DTF_READALL)
		_filldir(dirp, false);
	else {
		(void) lseek(dirp->dd_fd, 0, SEEK_SET);
		dirp->dd_seek = 0;
	}
	dirp->dd_loc = 0;
	_reclaim_telldir(dirp);
	if (__isthreaded)
		_pthread_mutex_unlock(&dirp->dd_lock);
}
Esempio n. 22
0
/*
 * close a directory.
 */
int
fdclosedir(DIR *dirp)
{
	int fd;

	if (__isthreaded)
		_pthread_mutex_lock(&dirp->dd_lock);
	fd = dirp->dd_fd;
	dirp->dd_fd = -1;
	dirp->dd_loc = 0;
	free((void *)dirp->dd_buf);
	_reclaim_telldir(dirp);
	if (__isthreaded) {
		_pthread_mutex_unlock(&dirp->dd_lock);
		_pthread_mutex_destroy(&dirp->dd_lock);
	}
	free((void *)dirp);
	return (fd);
}
Esempio n. 23
0
int
_pthread_atfork(void (*prepare)(void), void (*parent)(void),
                void (*child)(void))
{
    struct pthread_atfork *af;

    if (_thr_initial == NULL)
        _libpthread_init(NULL);

    if ((af = malloc(sizeof(struct pthread_atfork))) == NULL)
        return (ENOMEM);

    af->prepare = prepare;
    af->parent = parent;
    af->child = child;
    _pthread_mutex_lock(&_thr_atfork_mutex);
    TAILQ_INSERT_TAIL(&_thr_atfork_list, af, qe);
    _pthread_mutex_unlock(&_thr_atfork_mutex);
    return (0);
}
Esempio n. 24
0
int
_pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
{
	pthread_rwlock_t prwlock;
	struct pthread *curthread;
	int ret;

	if (rwlock == NULL)
		return(EINVAL);

	prwlock = *rwlock;

	if (prwlock == NULL)
		return(EINVAL);

	/* grab the monitor lock */
	if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0)
		return(ret);

	curthread = _get_curthread();
	if (prwlock->state > 0) {
		curthread->rdlock_count--;
		prwlock->state--;
		if (prwlock->state == 0 && prwlock->blocked_writers)
			ret = _pthread_cond_signal(&prwlock->write_signal);
	} else if (prwlock->state < 0) {
		prwlock->state = 0;

		if (prwlock->blocked_writers)
			ret = _pthread_cond_signal(&prwlock->write_signal);
		else
			ret = _pthread_cond_broadcast(&prwlock->read_signal);
	} else
		ret = EINVAL;

	/* see the comment on this in pthread_rwlock_rdlock */
	_pthread_mutex_unlock(&prwlock->lock);

	return (ret);
}
Esempio n. 25
0
struct tm *
localtime(const time_t * const timep)
{
	static pthread_mutex_t localtime_mutex = PTHREAD_MUTEX_INITIALIZER;
	static pthread_key_t localtime_key = -1;
	struct tm *p_tm;

	if (__isthreaded != 0) {
		if (localtime_key < 0) {
			_pthread_mutex_lock(&localtime_mutex);
			if (localtime_key < 0) {
				if (_pthread_key_create(&localtime_key, free) < 0) {
					_pthread_mutex_unlock(&localtime_mutex);
					return(NULL);
				}
			}
			_pthread_mutex_unlock(&localtime_mutex);
		}
		p_tm = _pthread_getspecific(localtime_key);
		if (p_tm == NULL) {
			if ((p_tm = (struct tm *)malloc(sizeof(struct tm)))
			    == NULL)
				return(NULL);
			_pthread_setspecific(localtime_key, p_tm);
		}
		_RWLOCK_RDLOCK(&lcl_rwlock);
		tzset_basic(1);
		localsub(timep, 0L, p_tm);
		_RWLOCK_UNLOCK(&lcl_rwlock);
		return(p_tm);
	} else {
		tzset_basic(0);
		localsub(timep, 0L, &tm);
		return(&tm);
	}
}
Esempio n. 26
0
static void
sem_prefork()
{
	
	_pthread_mutex_lock(&sem_llock);
}
Esempio n. 27
0
void* client_thread(void *arg) {
	struct user *__user = (struct user *)arg; 
	struct user user;
	int sockfd = *(__user->sockfd), ret;
	size_t n;
	int nready;
	char buf[MSG_MAXLEN + 1];
	char horse_buf[(HORSE_NAME + 13) * (HORSE_RUN + 1)];
	char *resp;
	unsigned int _money;
	byte send_win = 0;
	fd_set rset, active;
	struct timeval tv, active_tv = { 0, 100 };

	FD_ZERO(&active);
	FD_SET(sockfd, &active);

	init_client(&user, __user);
	_pthread_detach(pthread_self());	

	while (work || run) {
		if (!run) {
			send_win = 0;
			rset = active;
			tv = active_tv;

			nready = select(sockfd + 1, &rset, NULL, NULL, &tv);
			if ((nready < 0 && errno == EINTR) || !nready)
				continue;
		
			// someone wants to write	
			// write on client terminal
			if (!(n = read(sockfd, buf, MSG_MAXLEN))) {
				if (errno == EINTR)
					continue;
				break;
			}
			else {
				buf[n < MSG_MAXLEN ? n : MSG_MAXLEN] = 0;
				if (buf[0] == '\r' || buf[0] == '\n')
					continue;
				ret = parse_request(buf, n, &resp, &user);
				// send response
				_write(sockfd, (void *)resp, strlen(resp));
				if (!ret)
					free(resp);
			}
		}
		// send current state of run, and money after
		else {
			if (send_win)
				continue;

			_pthread_mutex_lock(user.service->mfinished);	
			if (!user.service->finished)
				send_horse_cur_info(sockfd, horse_buf, &user);
			else {
				_money = 0;
				update_money(&user, &_money);
				
				snprintf(buf, MSG_MAXLEN * 2, "Winner: %s; you won %u; your current accout: %u\n", user.service->win->name, _money, user.money);
				_write(sockfd, (void *)buf, strlen(buf));
				
				send_win = 1;
				user.horse = NULL;
				user.bet = 0;
			}	
			_pthread_mutex_unlock(user.service->mfinished);	
			
			_sleep(1, 0);
		}

	}

	_close(sockfd);

	return NULL;
}
Esempio n. 28
0
void
_pthread_exit(void *status)
{
	struct pthread	*curthread = _get_curthread();
	pthread_t pthread;

	/* Check if this thread is already in the process of exiting: */
	if ((curthread->flags & PTHREAD_EXITING) != 0) {
		char msg[128];
		snprintf(msg, sizeof(msg), "Thread %p has called pthread_exit() from a destructor. POSIX 1003.1 1996 s16.2.5.2 does not allow this!",curthread);
		PANIC(msg);
	}

	/* Flag this thread as exiting: */
	curthread->flags |= PTHREAD_EXITING;

	/* Save the return value: */
	curthread->ret = status;

	while (curthread->cleanup != NULL) {
		pthread_cleanup_pop(1);
	}
	if (curthread->attr.cleanup_attr != NULL) {
		curthread->attr.cleanup_attr(curthread->attr.arg_attr);
	}
	/* Check if there is thread specific data: */
	if (curthread->specific != NULL) {
		/* Run the thread-specific data destructors: */
		_thread_cleanupspecific();
	}

	/* Free thread-specific poll_data structure, if allocated: */
	if (curthread->poll_data.fds != NULL) {
		free(curthread->poll_data.fds);
		curthread->poll_data.fds = NULL;
	}

	/*
	 * Lock the garbage collector mutex to ensure that the garbage
	 * collector is not using the dead thread list.
	 */
	if (_pthread_mutex_lock(&_gc_mutex) != 0)
		PANIC("Cannot lock gc mutex");

	/* Add this thread to the list of dead threads. */
	TAILQ_INSERT_HEAD(&_dead_list, curthread, dle);

	/*
	 * Signal the garbage collector thread that there is something
	 * to clean up.
	 */
	if (_pthread_cond_signal(&_gc_cond) != 0)
		PANIC("Cannot signal gc cond");

	/*
	 * Avoid a race condition where a scheduling signal can occur
	 * causing the garbage collector thread to run.  If this happens,
	 * the current thread can be cleaned out from under us.
	 */
	_thread_kern_sig_defer();

	/* Unlock the garbage collector mutex: */
	if (_pthread_mutex_unlock(&_gc_mutex) != 0)
		PANIC("Cannot unlock gc mutex");

	/* Check if there is a thread joining this one: */
	if (curthread->joiner != NULL) {
		pthread = curthread->joiner;
		curthread->joiner = NULL;

		/* Make the joining thread runnable: */
		PTHREAD_NEW_STATE(pthread, PS_RUNNING);

		/* Set the return value for the joining thread: */
		pthread->join_status.ret = curthread->ret;
		pthread->join_status.error = 0;
		pthread->join_status.thread = NULL;

		/* Make this thread collectable by the garbage collector. */
		PTHREAD_ASSERT(((curthread->attr.flags & PTHREAD_DETACHED) ==
		    0), "Cannot join a detached thread");
		curthread->attr.flags |= PTHREAD_DETACHED;
	}

	/* Remove this thread from the thread list: */
	TAILQ_REMOVE(&_thread_list, curthread, tle);

	/* This thread will never be re-scheduled. */
	_thread_kern_sched_state(PS_DEAD, __FILE__, __LINE__);

	/* This point should not be reached. */
	PANIC("Dead thread has resumed");
}
Esempio n. 29
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;
}
Esempio n. 30
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);
}