From owner-freebsd-arch Wed Jul 10 14:20:19 2002 Delivered-To: freebsd-arch@freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 7F9F937B400; Wed, 10 Jul 2002 14:20:13 -0700 (PDT) Received: from rwcrmhc52.attbi.com (rwcrmhc52.attbi.com [216.148.227.88]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1946743E09; Wed, 10 Jul 2002 14:20:13 -0700 (PDT) (envelope-from julian@elischer.org) Received: from InterJet.elischer.org ([12.232.206.8]) by rwcrmhc52.attbi.com (InterMail vM.4.01.03.27 201-229-121-127-20010626) with ESMTP id <20020710212012.BEAG8262.rwcrmhc52.attbi.com@InterJet.elischer.org>; Wed, 10 Jul 2002 21:20:12 +0000 Received: from localhost (localhost.elischer.org [127.0.0.1]) by InterJet.elischer.org (8.9.1a/8.9.1) with ESMTP id OAA42297; Wed, 10 Jul 2002 14:03:49 -0700 (PDT) Date: Wed, 10 Jul 2002 14:03:47 -0700 (PDT) From: Julian Elischer To: Archie Cobbs Cc: John Baldwin , davidx@viasoft.com.cn, freebsd-arch@FreeBSD.org Subject: Re: Timeout and SMP race In-Reply-To: <200207101815.g6AIFDm28655@arch20m.dellroad.org> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-arch@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG On Wed, 10 Jul 2002, Archie Cobbs wrote: > > [ NOTE: I'm moving this discussion to freebsd-arch@freebsd.org ] > 1. The caller supplies a pointer to the 'handle', which must initially > be NULL. The handle != NULL if and only if the timer is running. The pointer is NULL or the pointee (tm) is NULL? Why would you have to send a pointer if it must be NULL? SO assuming that the handle is what is NULL, what IS it when it is not NULL?? An integer? a pointer? a magic number? I'm assuming it is an 'int' that makes some sense only to the callout system. > 2. timer_cancel() guarantees that tfunc() will not be called subsequently how? By use of a mutex? If the cancel holds the mutex when the timeout tries to get it, how do you ensure that the timeout gets scheduled and notices, before the timeout handle is re-used? > 3. *handlep is set to NULL by timer_cancel() and by the timer expiring. > So when *handlep is NULL when tfunc() is invoked (unless > TIMER_RECURRING). > 4. Calling timer_start() or timer_stop() from within tfunc() is OK. > 5. If TIMER_RECURRING, timer started again before calling tfunc() > 6. If TIMER_OWN_THREAD, timer runs in a newly created thread (rather > than the timer service thread), which means that tfunc() may sleep > or be canceled. If tfunc() sleeps or the thread is canceled but > TIMER_OWN_THREAD was not set -> panic. > 7. If mutexp != NULL, *mutexp is acquired before calling tfunc() and > released after it returns. > > Items 1, and 2 are guaranteed only if mutexp != NULL and the caller > acquires *mutexp before any calls to timer_start() or timer_cancel() > (you would normally be doing this anyway). What if the timeout handle was a structure that included the mutex? > > Errors: > > - timer_start() returns EBUSY if *handlep != NULL > - timer_remaining() returns ESRCH if handle != NULL > > The model is: you have some object that has an associated lock and > one or more associated timers. The object is to be locked whenever > you muck with it (including when you start, stop, or handle a timer): > > struct foobar { > struct lock mutex; > timer_handle_t timer1; > timer_handle_t timer2; > ... > }; > > Then all calls to the timer_* routines are "well behaved" and the > timeout thread caling tfunc() never races with any other thread > that may be stopping or starting the timer, or destroying the object. > E.g., to destroy the object, the following suffices: > > void > foobar_destroy(struct foobar *f) > { > mutex_lock(&f->mutex); > timer_cancel(&f->timer1); > timer_cancel(&f->timer2); > mutex_unlock(&f->mutex); > free(f); > } > > The only remaining complexity for the caller is that if you have > any TIMER_OWN_THREAD handlers which unlock the object (e.g., in order > to go to sleep), then you need to reference count the object and > have a FOOBAR_INVALID flag. > > If you are working under a different model then this API may not > be appropriate, but at least in my multi-threading experience this > model is very typical. > > -Archie > > __________________________________________________________________________ > Archie Cobbs * Packet Design * http://www.packetdesign.com > > To Unsubscribe: send mail to majordomo@FreeBSD.org > with "unsubscribe freebsd-current" in the body of the message > To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-arch" in the body of the message