Subject: Re: merge of freebsd eventhandler
To: Brett Lymn <blymn@baesystems.com.au>
From: Brett Lymn <blymn@baesystems.com.au>
List: tech-kern
Date: 06/02/2006 15:40:35
--fdj2RfSjLxBAspz7
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Folks,
Attached is the updated eventhandler.h, all the other code remains
unchanged.
--
Brett Lymn
--fdj2RfSjLxBAspz7
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="eventhandler.h"
/*-
* Copyright (c) 1999 Michael Smith <msmith@freebsd.org>
* 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: /repoman/r/ncvs/src/sys/sys/eventhandler.h,v 1.34 2006/04/21 09:25:40 ps Exp $
*/
#ifndef SYS_EVENTHANDLER_H
#define SYS_EVENTHANDLER_H
#include <sys/lock.h>
#include <sys/queue.h>
struct eventhandler_entry {
TAILQ_ENTRY(eventhandler_entry) ee_link;
int ee_priority;
#define EHE_DEAD_PRIORITY (-1)
void *ee_arg;
};
struct eventhandler_list {
char *el_name;
int el_flags;
#define EHL_INITTED (1<<0)
#define EHL_ONCE (1<<1)
u_int el_runcount;
struct lock el_lock;
int (*el_mask_fn)(void *);
TAILQ_ENTRY(eventhandler_list) el_link;
TAILQ_HEAD(eventhandler_entries_head ,eventhandler_entry) el_entries;
};
typedef struct eventhandler_entry *eventhandler_tag;
#define EHL_LOCK(p) lockmgr(&(p)->el_lock, LK_EXCLUSIVE, NULL)
#define EHL_UNLOCK(p) lockmgr(&(p)->el_lock, LK_RELEASE, NULL)
#define EHL_LOCK_ASSERT(p,x) KASSERT(lockstatus(&(p)->el_lock) == (x));
/*#define EVENTHANDLER_DEBUG 1 */
#ifdef EVENTHANDLER_DEBUG
extern int eventhandlerdebug;
#define EH_PRINTF(x) if (eventhandlerdebug) printf (x)
#define EH_PRINTFN(n,x) if (eventhandlerdebug>(n)) printf x
#else
#define EH_PRINTF(x)
#define EH_PRINTFN(n,x, ...)
#endif
/*
* Macro to invoke the handlers for a given event. The list must be
* exclusively locked on entry, it will be unlocked on exit.
*/
#define _EVENTHANDLER_INVOKE(name, list, ...) do { \
struct eventhandler_entry *_ep; \
struct eventhandler_entry_ ## name *_t; \
\
KASSERT((list)->el_flags & EHL_INITTED); \
EHL_LOCK_ASSERT((list), LK_EXCLUSIVE); \
++(list)->el_runcount; \
KASSERT((list)->el_runcount > 0); \
EH_PRINTF("eventhandler_invoke(\"" __STRING(name) "\")\n"); \
TAILQ_FOREACH(_ep, &((list)->el_entries), ee_link) { \
if (_ep->ee_priority == EHE_DEAD_PRIORITY) \
continue; \
if (((list)->el_flags & EHL_ONCE) == EHL_ONCE) { \
_ep->ee_priority = EHE_DEAD_PRIORITY; \
} \
EHL_UNLOCK((list)); \
if (((list)->el_mask_fn == NULL) || \
(((list)->el_mask_fn != NULL) && \
((list)->el_mask_fn(_ep->ee_arg) != 0))) { \
_t = (struct eventhandler_entry_ ## name *)_ep; \
EH_PRINTFN(1, ("eventhandler_invoke: executing %p\n", \
_t->eh_func)); \
_t->eh_func(_ep->ee_arg , ## __VA_ARGS__); \
} \
EHL_LOCK((list)); \
} \
KASSERT((list)->el_runcount > 0); \
--(list)->el_runcount; \
if ((list)->el_runcount == 0) \
eventhandler_prune_list(list); \
EHL_UNLOCK((list)); \
} while (0)
/*
* Macro to invoke the handlers for a given event, the handler list is
* traversed in reverse order. The list must be exclusively locked on
* entry, it will be unlocked on exit.
*/
#define _EVENTHANDLER_INVOKE_REVERSE(name, list, ...) do { \
struct eventhandler_entry *_ep; \
struct eventhandler_entry_ ## name *_t; \
\
KASSERT((list)->el_flags & EHL_INITTED); \
EHL_LOCK_ASSERT((list), LK_EXCLUSIVE); \
++(list)->el_runcount; \
KASSERT((list)->el_runcount > 0); \
EH_PRINTF("eventhandler_invoke(\"" __STRING(name) "\")\n"); \
TAILQ_FOREACH_REVERSE(_ep, &((list)->el_entries), \
eventhandler_entries_head, ee_link) { \
if (_ep->ee_priority == EHE_DEAD_PRIORITY) \
continue; \
if (((list)->el_flags & EHL_ONCE) == EHL_ONCE) { \
_ep->ee_priority = EHE_DEAD_PRIORITY; \
} \
EHL_UNLOCK((list)); \
if (((list)->el_mask_fn == NULL) || \
(((list)->el_mask_fn != NULL) && \
((list)->el_mask_fn(_ep->ee_arg) != 0))) { \
_t = (struct eventhandler_entry_ ## name *)_ep; \
EH_PRINTFN(1, ("eventhandler_invoke_reverse: executing %p\n", \
_t->eh_func)); \
_t->eh_func(_ep->ee_arg , ## __VA_ARGS__); \
} \
EHL_LOCK((list)); \
} \
KASSERT((list)->el_runcount > 0); \
--(list)->el_runcount; \
if ((list)->el_runcount == 0) \
eventhandler_prune_list(list); \
EHL_UNLOCK((list)); \
} while (0)
/*
* Macro to invoke the handlers for a given event. The list must be
* exclusively locked on entry, it will be unlocked on exit.
*/
#define _EVENTHANDLER_FAST_INVOKE(name, list, ...) do { \
struct eventhandler_entry *_ep; \
struct eventhandler_entry_ ## name *_t; \
\
TAILQ_FOREACH(_ep, &((list)->el_entries), ee_link) { \
_t = (struct eventhandler_entry_ ## name *)_ep; \
_t->eh_func(_ep->ee_arg , ## __VA_ARGS__); \
} \
EHL_UNLOCK((list)); \
} while (0)
/*
* Macro to invoke the handlers for a given event, the handler list is
* traversed in reverse order. The list must be exclusively locked on
* entry, it will be unlocked on exit.
*/
#define _EVENTHANDLER_FAST_INVOKE_REVERSE(name, list, ...) do { \
struct eventhandler_entry *_ep; \
struct eventhandler_entry_ ## name *_t; \
\
TAILQ_FOREACH_REVERSE(_ep, &((list)->el_entries), list, ee_link) { \
_t = (struct eventhandler_entry_ ## name *)_ep; \
_t->eh_func(_ep->ee_arg , ## __VA_ARGS__); \
} \
EHL_UNLOCK((list)); \
} while (0)
/*
* Handlers need to be declared, but do not need to be defined. The
* declaration must be in scope wherever the handler is to be invoked.
*/
#define EVENTHANDLER_DECLARE(name, type) \
struct eventhandler_entry_ ## name \
{ \
struct eventhandler_entry ee; \
type eh_func; \
}; \
#define EVENTHANDLER_INVOKE(name, ...) \
do { \
struct eventhandler_list *_el; \
\
if ((_el = eventhandler_find_list(#name)) != NULL) \
_EVENTHANDLER_INVOKE(name, _el , ## __VA_ARGS__); \
} while (0)
#define EVENTHANDLER_INVOKE_REVERSE(name, ...) \
do { \
struct eventhandler_list *_el; \
\
if ((_el = eventhandler_find_list(#name)) != NULL) \
_EVENTHANDLER_INVOKE_REVERSE(name, _el , ## __VA_ARGS__); \
} while (0)
#define EVENTHANDLER_FAST_INVOKE(name, ...) \
do { \
struct eventhandler_list *_el; \
\
if ((_el = eventhandler_find_list(#name)) != NULL) \
_EVENTHANDLER_FAST_INVOKE(name, _el , ## __VA_ARGS__); \
} while (0)
#define EVENTHANDLER_FAST_INVOKE_REVERSE(name, ...) \
do { \
struct eventhandler_list *_el; \
\
if ((_el = eventhandler_find_list(#name)) != NULL) \
_EVENTHANDLER_FAST_INVOKE_REVERSE(name, _el , ## __VA_ARGS__); \
} while (0)
#define EVENTHANDLER_REGISTER(name, func, arg, priority) \
eventhandler_register(NULL, #name, func, arg, priority)
#define EVENTHANDLER_DEREGISTER(name, tag) \
do { \
struct eventhandler_list *_el; \
\
if ((_el = eventhandler_find_list(#name)) != NULL) \
eventhandler_deregister(_el, tag); \
} while(0)
#define EVENTHANDLER_FLAGS(name, flags) \
do { \
struct eventhandler_list *_el; \
\
if ((_el = eventhandler_find_list(#name)) != NULL) \
eventhandler_set_list_flags(_el, flags); \
} while(0)
#define EVENTHANDLER_MASK_FN(name, mask_fn) \
do { \
struct eventhandler_list *_el; \
\
if ((_el = eventhandler_find_list(#name)) != NULL) \
eventhandler_set_mask(_el, mask_fn); \
} while(0)
void eventhandler_init(void);
eventhandler_tag eventhandler_register(struct eventhandler_list *,
const char *, void *, void *, int);
void eventhandler_deregister(struct eventhandler_list *,
eventhandler_tag);
struct eventhandler_list *eventhandler_find_list(const char *);
void eventhandler_prune_list(struct eventhandler_list *);
void eventhandler_set_list_flags(struct eventhandler_list *, int);
void eventhandler_set_mask(struct eventhandler_list *, int (*)(void *));
/*
* Standard system event queues.
*/
/* Generic priority levels */
#define EVENTHANDLER_PRI_FIRST 0
#define EVENTHANDLER_PRI_ANY 10000
#define EVENTHANDLER_PRI_LAST 20000
/* Shutdown events */
typedef void (*shutdown_fn)(void *);
EVENTHANDLER_DECLARE(shutdown, shutdown_fn);
/* Mount root event */
struct device;
typedef void (*mountroot_fn)(struct device *);
EVENTHANDLER_DECLARE(mountroot_list, mountroot_fn);
/*
* Process events
*/
struct proc;
typedef void (*exitlist_fn)(void *, struct proc *);
typedef void (*forklist_fn)(void *, struct proc *, struct proc *);
typedef void (*execlist_fn)(void *, struct proc *);
EVENTHANDLER_DECLARE(process_exit, exitlist_fn);
EVENTHANDLER_DECLARE(process_fork, forklist_fn);
EVENTHANDLER_DECLARE(process_exec, execlist_fn);
typedef void (*powerlist_fn)(void *, int);
EVENTHANDLER_DECLARE(power_list, powerlist_fn);
#endif /* SYS_EVENTHANDLER_H */
--fdj2RfSjLxBAspz7--