Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Jul 2002 14:03:47 -0700 (PDT)
From:      Julian Elischer <julian@elischer.org>
To:        Archie Cobbs <archie@dellroad.org>
Cc:        John Baldwin <jhb@FreeBSD.org>, davidx@viasoft.com.cn, freebsd-arch@FreeBSD.org
Subject:   Re: Timeout and SMP race
Message-ID:  <Pine.BSF.4.21.0207101348170.41638-100000@InterJet.elischer.org>
In-Reply-To: <200207101815.g6AIFDm28655@arch20m.dellroad.org>

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


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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0207101348170.41638-100000>