eventhandler.h revision 138439
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 138439 2004-12-06 10:53:40Z jkoshy $ 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 9250107Smsmith/* 9366205Smsmith * Slow handlers are entirely dynamic; lists are created 9450107Smsmith * when entries are added to them, and thus have no concept of "owner", 9550107Smsmith * 9666205Smsmith * Slow handlers need to be declared, but do not need to be defined. The 9750107Smsmith * declaration must be in scope wherever the handler is to be invoked. 9850107Smsmith */ 9995193Smarkm#define EVENTHANDLER_DECLARE(name, type) \ 10095193Smarkmstruct eventhandler_entry_ ## name \ 10195193Smarkm{ \ 10295193Smarkm struct eventhandler_entry ee; \ 10395193Smarkm type eh_func; \ 10495193Smarkm}; \ 10556093Sbdestruct __hack 10650107Smsmith 107100111Smarkm#define EVENTHANDLER_INVOKE(name, ...) \ 10895193Smarkmdo { \ 10995193Smarkm struct eventhandler_list *_el; \ 11095193Smarkm \ 111112111Sjhb if ((_el = eventhandler_find_list(#name)) != NULL) \ 112112111Sjhb _EVENTHANDLER_INVOKE(name, _el , ## __VA_ARGS__); \ 11356093Sbde} while (0) 11450107Smsmith 11595193Smarkm#define EVENTHANDLER_REGISTER(name, func, arg, priority) \ 11695193Smarkm eventhandler_register(NULL, #name, func, arg, priority) 11750107Smsmith 11895193Smarkm#define EVENTHANDLER_DEREGISTER(name, tag) \ 11995193Smarkmdo { \ 12095193Smarkm struct eventhandler_list *_el; \ 12195193Smarkm \ 12295193Smarkm if ((_el = eventhandler_find_list(#name)) != NULL) \ 12395193Smarkm eventhandler_deregister(_el, tag); \ 12456093Sbde} while(0) 12550107Smsmith 12650107Smsmith 127112111Sjhbeventhandler_tag eventhandler_register(struct eventhandler_list *list, 128138439Sjkoshy const char *name, void *func, void *arg, int priority); 129112111Sjhbvoid eventhandler_deregister(struct eventhandler_list *list, 130112111Sjhb eventhandler_tag tag); 131138439Sjkoshystruct eventhandler_list *eventhandler_find_list(const char *name); 132112111Sjhbvoid eventhandler_prune_list(struct eventhandler_list *list); 13350107Smsmith 13450107Smsmith/* 13550107Smsmith * Standard system event queues. 13650107Smsmith */ 13750107Smsmith 138112563Sjhb/* Generic priority levels */ 139112563Sjhb#define EVENTHANDLER_PRI_FIRST 0 140112563Sjhb#define EVENTHANDLER_PRI_ANY 10000 141112563Sjhb#define EVENTHANDLER_PRI_LAST 20000 142112563Sjhb 14350107Smsmith/* Shutdown events */ 14492719Salfredtypedef void (*shutdown_fn)(void *, int); 14550107Smsmith 146112563Sjhb#define SHUTDOWN_PRI_FIRST EVENTHANDLER_PRI_FIRST 147112563Sjhb#define SHUTDOWN_PRI_DEFAULT EVENTHANDLER_PRI_ANY 148112565Sjhb#define SHUTDOWN_PRI_LAST EVENTHANDLER_PRI_LAST 14950107Smsmith 15050107SmsmithEVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn); /* before fs sync */ 15150107SmsmithEVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn); /* after fs sync */ 15250107SmsmithEVENTHANDLER_DECLARE(shutdown_final, shutdown_fn); 15350107Smsmith 154107136Sjeff/* Low memory event */ 155107136Sjefftypedef void (*vm_lowmem_handler_t)(void *, int); 156112563Sjhb#define LOWMEM_PRI_DEFAULT EVENTHANDLER_PRI_FIRST 157107136SjeffEVENTHANDLER_DECLARE(vm_lowmem, vm_lowmem_handler_t); 15866205Smsmith 159126940Speter/* 160126940Speter * Process events 161126941Speter * process_fork and exit handlers are called without Giant. 162126941Speter * exec handlers are called with Giant, but that is by accident. 163126940Speter */ 164112564Sjhbstruct proc; 165112564Sjhb 166112564Sjhbtypedef void (*exitlist_fn)(void *, struct proc *); 167112564Sjhbtypedef void (*forklist_fn)(void *, struct proc *, struct proc *, int); 168112564Sjhbtypedef void (*execlist_fn)(void *, struct proc *); 169112564Sjhb 170112564SjhbEVENTHANDLER_DECLARE(process_exit, exitlist_fn); 171112564SjhbEVENTHANDLER_DECLARE(process_fork, forklist_fn); 172112564SjhbEVENTHANDLER_DECLARE(process_exec, execlist_fn); 173112564Sjhb 17450107Smsmith#endif /* SYS_EVENTHANDLER_H */ 175