eventhandler.h revision 112564
150107Smsmith/*- 250107Smsmith * Copyright (c) 1999 Michael Smith <msmith@freebsd.org> 350107Smsmith * All rights reserved. 450107Smsmith * 550107Smsmith * Redistribution and use in source and binary forms, with or without 650107Smsmith * modification, are permitted provided that the following conditions 750107Smsmith * are met: 850107Smsmith * 1. Redistributions of source code must retain the above copyright 950107Smsmith * notice, this list of conditions and the following disclaimer. 1050107Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1150107Smsmith * notice, this list of conditions and the following disclaimer in the 1250107Smsmith * documentation and/or other materials provided with the distribution. 1350107Smsmith * 1450107Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1550107Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1650107Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1750107Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1850107Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1950107Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2050107Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2150107Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2250107Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2350107Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2450107Smsmith * SUCH DAMAGE. 2550107Smsmith * 2650477Speter * $FreeBSD: head/sys/sys/eventhandler.h 112564 2003-03-24 21:15:35Z jhb $ 2750107Smsmith */ 2850107Smsmith 2967535Sjhb#ifndef SYS_EVENTHANDLER_H 3067535Sjhb#define SYS_EVENTHANDLER_H 3167535Sjhb 3293615Salfred#include <sys/lock.h> 33112111Sjhb#include <sys/ktr.h> 34112111Sjhb#include <sys/mutex.h> 3550107Smsmith#include <sys/queue.h> 3650107Smsmith 3795193Smarkmstruct eventhandler_entry { 3895193Smarkm TAILQ_ENTRY(eventhandler_entry) ee_link; 3995193Smarkm int ee_priority; 40112111Sjhb#define EHE_DEAD_PRIORITY (-1) 4195193Smarkm void *ee_arg; 4250107Smsmith}; 4350107Smsmith 4495193Smarkmstruct eventhandler_list { 4595193Smarkm char *el_name; 4695193Smarkm int el_flags; 47112111Sjhb#define EHL_INITTED (1<<0) 48112111Sjhb u_int el_runcount; 49112111Sjhb struct mtx el_lock; 5095193Smarkm TAILQ_ENTRY(eventhandler_list) el_link; 5195193Smarkm TAILQ_HEAD(,eventhandler_entry) el_entries; 5250107Smsmith}; 5350107Smsmith 5450107Smsmithtypedef struct eventhandler_entry *eventhandler_tag; 5550107Smsmith 56112111Sjhb#define EHL_LOCK(p) mtx_lock(&(p)->el_lock) 57112111Sjhb#define EHL_UNLOCK(p) mtx_unlock(&(p)->el_lock) 58112111Sjhb#define EHL_LOCK_ASSERT(p, x) mtx_assert(&(p)->el_lock, x) 5993615Salfred 60112111Sjhb/* 61112111Sjhb * Macro to invoke the handlers for a given event. 62112111Sjhb */ 63112111Sjhb#define _EVENTHANDLER_INVOKE(name, list, ...) do { \ 64112111Sjhb struct eventhandler_entry *_ep; \ 65112111Sjhb struct eventhandler_entry_ ## name *_t; \ 66112111Sjhb \ 67112111Sjhb KASSERT((list)->el_flags & EHL_INITTED, \ 68112111Sjhb ("eventhandler_invoke: running non-inited list")); \ 69112111Sjhb EHL_LOCK_ASSERT((list), MA_OWNED); \ 70112111Sjhb (list)->el_runcount++; \ 71112111Sjhb KASSERT((list)->el_runcount > 0, \ 72112111Sjhb ("eventhandler_invoke: runcount overflow")); \ 73112111Sjhb CTR0(KTR_EVH, "eventhandler_invoke(\"" __STRING(name) "\")"); \ 74112111Sjhb TAILQ_FOREACH(_ep, &((list)->el_entries), ee_link) { \ 75112111Sjhb if (_ep->ee_priority != EHE_DEAD_PRIORITY) { \ 76112111Sjhb EHL_UNLOCK((list)); \ 77112111Sjhb _t = (struct eventhandler_entry_ ## name *)_ep; \ 78112111Sjhb CTR1(KTR_EVH, "eventhandler_invoke: executing %p", \ 79112111Sjhb (void *)_t->eh_func); \ 80112111Sjhb _t->eh_func(_ep->ee_arg , ## __VA_ARGS__); \ 81112111Sjhb EHL_LOCK((list)); \ 82112111Sjhb } \ 83112111Sjhb } \ 84112111Sjhb KASSERT((list)->el_runcount > 0, \ 85112111Sjhb ("eventhandler_invoke: runcount underflow")); \ 86112111Sjhb (list)->el_runcount--; \ 87112111Sjhb if ((list)->el_runcount == 0) \ 88112111Sjhb eventhandler_prune_list(list); \ 89112111Sjhb EHL_UNLOCK((list)); \ 90112111Sjhb} while (0) 91112111Sjhb 92112111Sjhb 9350107Smsmith/* 9450107Smsmith * Fast handler lists require the eventhandler list be present 9550107Smsmith * at link time. They don't allow addition of entries to 9650107Smsmith * unknown eventhandler lists, ie. each list must have an 9750107Smsmith * "owner". 9850107Smsmith * 9950107Smsmith * Fast handler lists must be defined once by the owner 10050107Smsmith * of the eventhandler list, and the declaration must be in 10150107Smsmith * scope at any point the list is manipulated. 10250107Smsmith */ 10395193Smarkm#define EVENTHANDLER_FAST_DECLARE(name, type) \ 10495193Smarkmextern struct eventhandler_list Xeventhandler_list_ ## name ; \ 10595193Smarkmstruct eventhandler_entry_ ## name { \ 10695193Smarkm struct eventhandler_entry ee; \ 10795193Smarkm type eh_func; \ 10895193Smarkm}; \ 10956093Sbdestruct __hack 11050107Smsmith 11156093Sbde#define EVENTHANDLER_FAST_DEFINE(name, type) \ 11256093Sbdestruct eventhandler_list Xeventhandler_list_ ## name = { #name }; \ 11356093Sbdestruct __hack 11450107Smsmith 115112111Sjhb#define EVENTHANDLER_FAST_INVOKE(name, ...) do { \ 11695193Smarkm struct eventhandler_list *_el = &Xeventhandler_list_ ## name ; \ 11795193Smarkm \ 118112111Sjhb if (_el->el_flags & EHL_INITTED) { \ 119112111Sjhb EHL_LOCK(_el); \ 120112111Sjhb _EVENTHANDLER_INVOKE(name, _el , ## __VA_ARGS__); \ 12195193Smarkm } \ 12256093Sbde} while (0) 12350107Smsmith 12495193Smarkm#define EVENTHANDLER_FAST_REGISTER(name, func, arg, priority) \ 12595193Smarkm eventhandler_register(&Xeventhandler_list_ ## name, \ 12695193Smarkm #name, func, arg, priority) 12750107Smsmith 128112111Sjhb#define EVENTHANDLER_FAST_DEREGISTER(name, tag) do { \ 129112111Sjhb struct eventhandler_list *_el = &Xeventhandler_list_ ## name ; \ 130112111Sjhb \ 131112111Sjhb KASSERT(_el->el_flags & EHL_INITTED, \ 132112111Sjhb ("eventhandler_fast_deregister on un-inited list %s", ## name)); \ 133112111Sjhb EHL_LOCK(_el); \ 134112111Sjhb eventhandler_deregister(_el, tag); \ 135112111Sjhb} while (0) 13650107Smsmith 13750107Smsmith/* 13866205Smsmith * Slow handlers are entirely dynamic; lists are created 13950107Smsmith * when entries are added to them, and thus have no concept of "owner", 14050107Smsmith * 14166205Smsmith * Slow handlers need to be declared, but do not need to be defined. The 14250107Smsmith * declaration must be in scope wherever the handler is to be invoked. 14350107Smsmith */ 14495193Smarkm#define EVENTHANDLER_DECLARE(name, type) \ 14595193Smarkmstruct eventhandler_entry_ ## name \ 14695193Smarkm{ \ 14795193Smarkm struct eventhandler_entry ee; \ 14895193Smarkm type eh_func; \ 14995193Smarkm}; \ 15056093Sbdestruct __hack 15150107Smsmith 152100111Smarkm#define EVENTHANDLER_INVOKE(name, ...) \ 15395193Smarkmdo { \ 15495193Smarkm struct eventhandler_list *_el; \ 15595193Smarkm \ 156112111Sjhb if ((_el = eventhandler_find_list(#name)) != NULL) \ 157112111Sjhb _EVENTHANDLER_INVOKE(name, _el , ## __VA_ARGS__); \ 15856093Sbde} while (0) 15950107Smsmith 16095193Smarkm#define EVENTHANDLER_REGISTER(name, func, arg, priority) \ 16195193Smarkm eventhandler_register(NULL, #name, func, arg, priority) 16250107Smsmith 16395193Smarkm#define EVENTHANDLER_DEREGISTER(name, tag) \ 16495193Smarkmdo { \ 16595193Smarkm struct eventhandler_list *_el; \ 16695193Smarkm \ 16795193Smarkm if ((_el = eventhandler_find_list(#name)) != NULL) \ 16895193Smarkm eventhandler_deregister(_el, tag); \ 16956093Sbde} while(0) 17050107Smsmith 17150107Smsmith 172112111Sjhbeventhandler_tag eventhandler_register(struct eventhandler_list *list, 173112111Sjhb char *name, void *func, void *arg, int priority); 174112111Sjhbvoid eventhandler_deregister(struct eventhandler_list *list, 175112111Sjhb eventhandler_tag tag); 176112111Sjhbstruct eventhandler_list *eventhandler_find_list(char *name); 177112111Sjhbvoid eventhandler_prune_list(struct eventhandler_list *list); 17850107Smsmith 17950107Smsmith/* 18050107Smsmith * Standard system event queues. 18150107Smsmith */ 18250107Smsmith 183112563Sjhb/* Generic priority levels */ 184112563Sjhb#define EVENTHANDLER_PRI_FIRST 0 185112563Sjhb#define EVENTHANDLER_PRI_ANY 10000 186112563Sjhb#define EVENTHANDLER_PRI_LAST 20000 187112563Sjhb 18850107Smsmith/* Shutdown events */ 18992719Salfredtypedef void (*shutdown_fn)(void *, int); 19050107Smsmith 191112563Sjhb#define SHUTDOWN_PRI_FIRST EVENTHANDLER_PRI_FIRST 192112563Sjhb#define SHUTDOWN_PRI_DEFAULT EVENTHANDLER_PRI_ANY 193112563Sjhb#define SHUTDOWN_PRI_LAST EVENTHANDLER_PRI_FIRST 19450107Smsmith 19550107SmsmithEVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn); /* before fs sync */ 19650107SmsmithEVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn); /* after fs sync */ 19750107SmsmithEVENTHANDLER_DECLARE(shutdown_final, shutdown_fn); 19850107Smsmith 19966205Smsmith/* Idle process event */ 20092719Salfredtypedef void (*idle_eventhandler_t)(void *, int); 20166205Smsmith 202112563Sjhb#define IDLE_PRI_FIRST EVENTHANDLER_PRI_FIRST 203112563Sjhb#define IDLE_PRI_LAST EVENTHANDLER_PRI_LAST 20466205SmsmithEVENTHANDLER_FAST_DECLARE(idle_event, idle_eventhandler_t); 20566205Smsmith 206107136Sjeff/* Low memory event */ 207107136Sjefftypedef void (*vm_lowmem_handler_t)(void *, int); 208112563Sjhb#define LOWMEM_PRI_DEFAULT EVENTHANDLER_PRI_FIRST 209107136SjeffEVENTHANDLER_DECLARE(vm_lowmem, vm_lowmem_handler_t); 21066205Smsmith 211112564Sjhb/* Process events */ 212112564Sjhbstruct proc; 213112564Sjhb 214112564Sjhbtypedef void (*exitlist_fn)(void *, struct proc *); 215112564Sjhbtypedef void (*forklist_fn)(void *, struct proc *, struct proc *, int); 216112564Sjhbtypedef void (*execlist_fn)(void *, struct proc *); 217112564Sjhb 218112564SjhbEVENTHANDLER_DECLARE(process_exit, exitlist_fn); 219112564SjhbEVENTHANDLER_DECLARE(process_fork, forklist_fn); 220112564SjhbEVENTHANDLER_DECLARE(process_exec, execlist_fn); 221112564Sjhb 22250107Smsmith#endif /* SYS_EVENTHANDLER_H */ 223