Example #1
0
/*
 * Cancellation behavior:
 *   According to manual of close(), the file descriptor is always deleted.
 *   Here, thread is only canceled after the system call, so the file
 *   descriptor is always deleted despite whether the thread is canceled
 *   or not.
 */
int
__close(int fd)
{
	struct pthread	*curthread = _get_curthread();
	int	ret;

	_thr_cancel_enter2(curthread, 0);
	ret = __sys_close(fd);
	_thr_cancel_leave(curthread, 1);
	
	return (ret);
}
Example #2
0
/*
 * Cancellation behaivor:
 *   Thread may be canceled at start, if thread is canceled, it means it
 *   did not get a wakeup from pthread_cond_signal(), otherwise, it is
 *   not canceled.
 *   Thread cancellation never cause wakeup from pthread_cond_signal()
 *   to be lost.
 */
static int
cond_wait_kernel(struct pthread_cond *cvp, struct pthread_mutex *mp,
	const struct timespec *abstime, int cancel)
{
	struct pthread	*curthread = _get_curthread();
	int		recurse;
	int		error, error2 = 0;

	error = _mutex_cv_detach(mp, &recurse);
	if (error != 0)
		return (error);

	if (cancel) {
		_thr_cancel_enter2(curthread, 0);
		error = _thr_ucond_wait((struct ucond *)&cvp->__has_kern_waiters,
			(struct umutex *)&mp->m_lock, abstime,
			CVWAIT_ABSTIME|CVWAIT_CLOCKID);
		_thr_cancel_leave(curthread, 0);
	} else {
		error = _thr_ucond_wait((struct ucond *)&cvp->__has_kern_waiters,
			(struct umutex *)&mp->m_lock, abstime,
			CVWAIT_ABSTIME|CVWAIT_CLOCKID);
	}

	/*
	 * Note that PP mutex and ROBUST mutex may return
	 * interesting error codes.
	 */
	if (error == 0) {
		error2 = _mutex_cv_lock(mp, recurse);
	} else if (error == EINTR || error == ETIMEDOUT) {
		error2 = _mutex_cv_lock(mp, recurse);
		if (error2 == 0 && cancel)
			_thr_testcancel(curthread);
		if (error == EINTR)
			error = 0;
	} else {
		/* We know that it didn't unlock the mutex. */
		error2 = _mutex_cv_attach(mp, recurse);
		if (error2 == 0 && cancel)
			_thr_testcancel(curthread);
	}
	return (error2 != 0 ? error2 : error);
}
Example #3
0
void
_pthread_cancel_enter(int maycancel)
{
	_thr_cancel_enter2(_get_curthread(), maycancel);
}
Example #4
0
static int
cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
	const struct timespec *abstime, int cancel)
{
	struct pthread	*curthread = _get_curthread();
	struct sleepqueue *sq;
	int	recurse;
	int	error;

	if (curthread->wchan != NULL)
		PANIC("thread was already on queue.");

	if (cancel)
		_thr_testcancel(curthread);

	_sleepq_lock(cvp);
	/*
	 * set __has_user_waiters before unlocking mutex, this allows
	 * us to check it without locking in pthread_cond_signal().
	 */
	cvp->__has_user_waiters = 1; 
	curthread->will_sleep = 1;
	(void)_mutex_cv_unlock(mp, &recurse);
	curthread->mutex_obj = mp;
	_sleepq_add(cvp, curthread);
	for(;;) {
		_thr_clear_wake(curthread);
		_sleepq_unlock(cvp);

		if (cancel) {
			_thr_cancel_enter2(curthread, 0);
			error = _thr_sleep(curthread, cvp->__clock_id, abstime);
			_thr_cancel_leave(curthread, 0);
		} else {
			error = _thr_sleep(curthread, cvp->__clock_id, abstime);
		}

		_sleepq_lock(cvp);
		if (curthread->wchan == NULL) {
			error = 0;
			break;
		} else if (cancel && SHOULD_CANCEL(curthread)) {
			sq = _sleepq_lookup(cvp);
			cvp->__has_user_waiters = 
				_sleepq_remove(sq, curthread);
			_sleepq_unlock(cvp);
			curthread->mutex_obj = NULL;
			_mutex_cv_lock(mp, recurse);
			if (!THR_IN_CRITICAL(curthread))
				_pthread_exit(PTHREAD_CANCELED);
			else /* this should not happen */
				return (0);
		} else if (error == ETIMEDOUT) {
			sq = _sleepq_lookup(cvp);
			cvp->__has_user_waiters =
				_sleepq_remove(sq, curthread);
			break;
		}
	}
	_sleepq_unlock(cvp);
	curthread->mutex_obj = NULL;
	_mutex_cv_lock(mp, recurse);
	return (error);
}