Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Oct 98 05:52:47 -0500
From:      "Richard Seaman, Jr." <lists@tar.com>
To:        "Daniel Eischen" <eischen@vigrid.com>
Cc:        "current@freebsd.org" <current@FreeBSD.ORG>
Subject:   Re: Another Serious libc_r problem
Message-ID:  <199810211052.FAA19064@ns.tar.com>

next in thread | raw e-mail | index | archive | help

On Tue, 20 Oct 1998 22:00:30 -0400 (EDT), Daniel Eischen wrote:

>Yes, it seems that we need a method of disabling task scheduing
>while we enqueue the condition variable and call the thread
>kern scheduler.  You should be able to do this by setting
>_thread_kern_in_sched = 1.  Something like this (from
>pthread_cond_timedwait):

[snip]

>Calling _thread_kern_sched_state will end up clearing _thread_kern_in_sched,
>(and so will pthread_yield).  The signal handler will not cause a
>reschedule when _thread_kern_sched_state is non-zero.

Bear with me while I try to understand this.  Between the time you
set _thread_kern_in_sched = 1 and the call to _thread_kern_sched_state
(or pthread_yield) you call pthread_mutex_unlock, which does a spinlock.
Also, before calling pthread_yield you also do a spinlock.  Isn't a
spinlock a potential yield call to the kernel scheduler, which in
turn could set _thread_kern_in_sched = 0, and thus still leave you
vulnerable to the scheduling window you are concerned about?

If I understand, and I may not, what you are concerned about is that
after you unlock the condition spinlock, and before you yield to
the scheduler, you could be pre-empted, and that the condition could
be signaled (thus causing you to wait on a condition that has already
been signaled, a mistake?).  The condition can only be signaled when
the condition spinlock is not held.  So... why wouldn't you hold the
condition spinlock as long as possible (ie. after the mutex unlock)
and *then* set _thread_kern_in_sched = 1 after all the spinlocks have
been done?

Or, using your code snippet, why not this?

		/* Lock the condition variable structure: */
		_SPINLOCK(&(*cond)->lock);

		/* Process according to condition variable type: */
		switch ((*cond)->c_type) {
		/* Fast condition variable: */
		case COND_TYPE_FAST:

			/* Set the wakeup time: */
			_thread_run->wakeup_time.tv_sec = abstime->tv_sec;
			_thread_run->wakeup_time.tv_nsec = abstime->tv_nsec;

			/* Reset the timeout flag: */
			_thread_run->timeout = 0;

			/*
			 * Queue the running thread for the condition
			 * variable:
			 */
			_thread_queue_enq(&(*cond)->c_queue, _thread_run);

			/* Unlock the mutex: */
			if ((rval = pthread_mutex_unlock(mutex)) != 0) {
				/* Lock the condition variable structure: */
				_SPINLOCK(&(*cond)->lock);

				/*
				 * Cannot unlock the mutex, so remove the
				 * running thread from the condition
				 * variable queue: 
				 */
				_thread_queue_deq(&(*cond)->c_queue);

 			 	/*
			 	 * Disable thread scheduling.
				 */
				_thread_kern_in_sched = 1;

				/* Unlock the condition variable structure: */
				_SPINUNLOCK(&(*cond)->lock);

				/*
				 * There could have had a SIGVTALRM between
				 * here and where we disabled thread
				 * scheduling; force a reschedule.
				 */
				pthread_yield();

			} else {

 			 	/*
			 	 * Disable thread scheduling.
				 */
				_thread_kern_in_sched = 1;

				/* Unlock the condition variable structure: */
				_SPINUNLOCK(&(*cond)->lock);

				/* Schedule the next thread: */
				_thread_kern_sched_state(PS_COND_WAIT,
				    __FILE__, __LINE__);

				/* Lock the mutex: */
				if ((rval = pthread_mutex_lock(mutex)) != 0) {
				}
				/* Check if the wait timed out: */
				else if (_thread_run->timeout) {
					/* Return a timeout error: */
					rval = ETIMEDOUT;
				}
			}
			break;

		/* Trap invalid condition variable types: */
		default:
			/* Unlock the condition variable structure: */
			_SPINUNLOCK(&(*cond)->lock);

			/* Return an invalid argument error: */
			rval = EINVAL;
			break;
		}





To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199810211052.FAA19064>