Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Oct 1998 21:40:00 -0700 (PDT)
From:      Daniel Eischen <eischen@vigrid.com>
To:        freebsd-bugs@FreeBSD.ORG
Subject:   Re: kern/8375: pthread_cond_wait() spins the CPU
Message-ID:  <199810240440.VAA11277@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/8375; it has been noted by GNATS.

From: Daniel Eischen <eischen@vigrid.com>
To: dima@tejblum.dnttm.rssi.ru, eischen@vigrid.com
Cc: freebsd-gnats-submit@FreeBSD.ORG, jb@FreeBSD.ORG
Subject: Re: kern/8375: pthread_cond_wait() spins the CPU
Date: Sat, 24 Oct 1998 00:28:38 -0400 (EDT)

 > IMO, your _thread_kern_sched_[un]lock() is a bad idea. Theses functions 
 > defeat the idea of spinlocks. What is the need to do _SPINLOCK/_SPINUNLOCK 
 > when scheduling is blocked? Your code do it a lot. OTOH, spinlocks are 
 > designed exactly to make rescheduling harmless. And they works; the only 
 > problem is that spinlocks are released in a bit wrong time. (BTW, why you 
 > disable scheduling in pthread_cond_signal and pthread_cond_broadcast?)
 
 I don't see any other way of making pthread_cond_[timed]wait     
 bulletproof without disabling scheduling.  You shouldn't    
 allow nesting of spinlocks being taken if there is a chance
 of creating a deadlock.  Let's assume that you do not nest
 the condition variable and mutex spinlocks.  Then pthread_cond_wait
 looks something like 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 condition variable structure: */
 			_SPINUNLOCK(&(*cond)->lock);
 
 			/* Unlock the mutex: */
 			if ((rval = pthread_mutex_unlock(mutex)) != 0) {
 
 What happens if you get a SIGVTALRM right after the spinunlock
 of the condition lock and before the pthread_mutex_lock?  Another
 thread can get scheduled and possibly dequeue the thread that
 you just placed on the condition variable queue.  When this
 thread comes back and unlocks the mutex, his state will change
 to PS_COND_WAIT but he'll never be woken up because he's not 
 in the queue anymore.
 
 You need to disable thread scheduling.  The way I've done it,
 it doesn't hurt anything and will prevent needless thrashing
 of threads.  You want mutex_lock and cond_wait and friends
 to be atomic and this does that without needless thrashing.
 Note that _thread_kern_sched_lock will *not* block scheduling
 when the thread waits during a spinlock or other blocking
 operations that invoke the thread scheduler.
 
 > The whole concept of disabling the scheduler is suspicious. There are data 
 > structures, they has to be locked sometimes to provide atomic access to 
 > them; why ever disable scheduling? Just lock and unlock properly...
 
 Sure, where you can.  BTW, I didn't invent this idea myself.
 I stole it from VxWorks and it has the same semantics as
 taskLock and taskUnlock do in VxWorks.  This is also how
 pthread_mutex_lock and pthread_cond_wait are implemented.
 
 Perhaps I was a little overzealous in my usage of _thread_kern_sched_lock
 in pthread_cond_signal and pthread_cond_broadcast.  They are
 probably not needed there, but they would let the operation
 continue without causing needless thrashing.
 
 I didn't take out the spinlocks because I thought they would
 work across processes, whereas locking out thread scheduling,
 at least as implemented here, only works within the process.
 
 Dan Eischen
 eischen@vigrid.com

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



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