Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 01 Dec 2007 22:19:05 +0000
From:      Poul-Henning Kamp <phk@phk.freebsd.dk>
To:        arch@freebsd.org
Subject:   New "timeout" api, to replace callout
Message-ID:  <15391.1196547545@critter.freebsd.dk>

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

Here is my proposed new timeout API for 8.x.

The primary objective is to make it possible to have multiple timeout
"providers" of possibly different kind, so that we can have per-cpu
or per-net-stack timeout handing.

A secondary goal, is to shove the anti-race handling in destruction of
timeouts back into the implemenation, rather than force users to spend
20+ lines doing that.

A third goal is to enable deadline scheduling of timeouts using hardware
like HPET when and where we have it.

Comments in general (only B/W) and pointers to client code of
particular interest is most welcome.

Poul-Henning

PS: I decided to revert to the old "timeout" prefix, so that we avoid
redefining anything and can coexist with the callout_ API as long as
necessary.


/*-
 * Copyright (c) 2007 Poul-Henning Kamp
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 */

#ifndef _SYS_TIMEOUT_H_
#define _SYS_TIMEOUT_H_

/*
 * A provider of timeout services, opaque to users.
 * We are likely to have a "default" provider and possibly one for
 * each cpu, but subsystems might have their own provider instances as well.
 */
struct timeout_p;

/*
 * A duration of time, represented in the optimal way for a given provider
 * or family of providers (ie: per cpu).
 */
typedef int timeout_time;

/*
 * An instance of a timeout
 */
struct timeout;

/*
 * Flag values,
 * can be used as return from the function or as argument to timeout_arm()
 */
#define TIMEOUT_REARM		(1<<0)
	/* return: Rearm with timeout from last arming */
	/* return + timeout_arm(): Likely to be rearmed when firing */
#define TIMEOUT_SAFE		(1<<1)
	/* return: Do not rearm */
	/* timeout_arm: Not likely to be rearmed when firing */
#define TIMEOUT_RETURNUNLOCKED	(1<<2)
	/* return: released lock along the way */
#define TIMEOUT_UNLIKELY	(1<<3)
	/* timeout_arm: Unlikely to fire before safed */

/*
 * The function prototype for timeout functions.
 * A mutex will be held over the call to this function, preventing
 * accidental use of msleep(9) and similar.
 * Calling timeout_arm() on itself is legal.
 * Manipulating other timeouts is illegal, (until documented need.)
 */
typedef int timeout_f(struct timeout *, void *priv);

/*
 * The struct is defined here, so that allocations can be made at
 * compile-time as part of softc's etc.
 * No user-serviceable parts inside.
 */
struct timeout {
	timeout_p	*_prov;
	timeout_time	_time;
	timeout_f	*_func;
	void		*_priv;
	uintptr_t	_reserved[4];	/* XXX: for some value of 4 */
};
	
/*
 * Convert various human compatible time-units to internal units
 * Since these are potentially expensive (as in multiple integer divisions)
 * caching the return value is adviced for heavy use.
 * Choice of function indicates level of precision requested, so 
 * timeout_ms_time(1000) may be different from timeout_s_time(1), depending
 * on the implementation.
 */
timeout_time timeout_ns_time(struct timeout_p *, unsigned nsec);
timeout_time timeout_us_time(struct timeout_p *, unsigned usec);
timeout_time timeout_ms_time(struct timeout_p *, unsigned msec);
timeout_time timeout_s_time(struct timeout_p *, unsigned sec);

/*
 * Initialize a timeout to safed state.
 * Call timeout_cleanup() before calling again.
 */
void timeout_init(struct timeout_p *, struct timeout *, struct lock_object *, timeout_f *, void *);

/*
 * Arm the timeout.
 * If timeout is already running, ignore its return value and any
 * timeout_arm() calls it makes on itself and wait (on a mutex) for it to
 * return.
 * The timeout will be armed with the parameters given on return.
 */
void timeout_arm(struct timeout *, timeout_time, int flags);

/*
 * Safe the timeout.
 * If timeout is already running, ignore its return value and any
 * timeout_arm() calls it makes on itself and wait (on a mutex) for it to
 * return.
 * The timeout will always be safed on return.
 */
void timeout_safe(struct timeout *);

/*
 * Cleanup the timeout.
 * Should always be called on any timeout ever armed.
 * Can be called on any timeout which have been init'ed.
 * Will timeout_safe the timeout if armed.
 * The memory backing the argument structure and the lock registered with
 * timeout_init() can be safely destroyed on return.
 */
void timeout_cleanup(struct timeout *);

#endif /* _SYS_TIMEOUT_H_ */
-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk@FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.



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