From owner-freebsd-bugs Fri Oct 23 21:40:08 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id VAA13421 for freebsd-bugs-outgoing; Fri, 23 Oct 1998 21:40:08 -0700 (PDT) (envelope-from owner-freebsd-bugs@FreeBSD.ORG) Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id VAA13408 for ; Fri, 23 Oct 1998 21:40:04 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.8.8/8.8.5) id VAA11277; Fri, 23 Oct 1998 21:40:00 -0700 (PDT) Date: Fri, 23 Oct 1998 21:40:00 -0700 (PDT) Message-Id: <199810240440.VAA11277@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.ORG From: Daniel Eischen Subject: Re: kern/8375: pthread_cond_wait() spins the CPU Reply-To: Daniel Eischen Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org The following reply was made to PR kern/8375; it has been noted by GNATS. From: Daniel Eischen 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