From owner-freebsd-current Wed Oct 21 06:24:05 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id GAA15765 for freebsd-current-outgoing; Wed, 21 Oct 1998 06:24:05 -0700 (PDT) (envelope-from owner-freebsd-current@FreeBSD.ORG) Received: from ns.tar.com (ns.tar.com [204.95.187.2]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id GAA15757 for ; Wed, 21 Oct 1998 06:24:03 -0700 (PDT) (envelope-from lists@tar.com) Received: from ppro.tar.com (ppro.tar.com [204.95.187.9]) by ns.tar.com (8.9.1/8.8.7) with SMTP id FAA19064; Wed, 21 Oct 1998 05:52:48 -0500 (CDT) Message-Id: <199810211052.FAA19064@ns.tar.com> From: "Richard Seaman, Jr." To: "Daniel Eischen" Cc: "current@freebsd.org" Date: Wed, 21 Oct 98 05:52:47 -0500 Reply-To: "Richard Seaman, Jr." X-Mailer: PMMail 1.92 For OS/2 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Subject: Re: Another Serious libc_r problem Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG 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