eventhandler.h revision 167905
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 167905 2007-03-26 18:03:29Z njl $ 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 107167905Snjl#define EVENTHANDLER_DEFINE(name, func, arg, priority) \ 108167905Snjl static eventhandler_tag name ## _tag; \ 109167905Snjl static void name ## _evh_init(void *ctx) \ 110167905Snjl { \ 111167905Snjl name ## _tag = EVENTHANDLER_REGISTER(name, func, ctx, \ 112167905Snjl priority); \ 113167905Snjl } \ 114167905Snjl SYSINIT(name ## _evh_init, SI_SUB_CONFIGURE, SI_ORDER_ANY, \ 115167905Snjl name ## _evh_init, arg) \ 116167905Snjl struct __hack 117167905Snjl 118100111Smarkm#define EVENTHANDLER_INVOKE(name, ...) \ 11995193Smarkmdo { \ 12095193Smarkm struct eventhandler_list *_el; \ 12195193Smarkm \ 122112111Sjhb if ((_el = eventhandler_find_list(#name)) != NULL) \ 123112111Sjhb _EVENTHANDLER_INVOKE(name, _el , ## __VA_ARGS__); \ 12456093Sbde} while (0) 12550107Smsmith 12695193Smarkm#define EVENTHANDLER_REGISTER(name, func, arg, priority) \ 12795193Smarkm eventhandler_register(NULL, #name, func, arg, priority) 12850107Smsmith 12995193Smarkm#define EVENTHANDLER_DEREGISTER(name, tag) \ 13095193Smarkmdo { \ 13195193Smarkm struct eventhandler_list *_el; \ 13295193Smarkm \ 13395193Smarkm if ((_el = eventhandler_find_list(#name)) != NULL) \ 13495193Smarkm eventhandler_deregister(_el, tag); \ 13556093Sbde} while(0) 13650107Smsmith 13750107Smsmith 138112111Sjhbeventhandler_tag eventhandler_register(struct eventhandler_list *list, 139138439Sjkoshy const char *name, void *func, void *arg, int priority); 140112111Sjhbvoid eventhandler_deregister(struct eventhandler_list *list, 141112111Sjhb eventhandler_tag tag); 142138439Sjkoshystruct eventhandler_list *eventhandler_find_list(const char *name); 143112111Sjhbvoid eventhandler_prune_list(struct eventhandler_list *list); 14450107Smsmith 14550107Smsmith/* 14650107Smsmith * Standard system event queues. 14750107Smsmith */ 14850107Smsmith 149112563Sjhb/* Generic priority levels */ 150112563Sjhb#define EVENTHANDLER_PRI_FIRST 0 151112563Sjhb#define EVENTHANDLER_PRI_ANY 10000 152112563Sjhb#define EVENTHANDLER_PRI_LAST 20000 153112563Sjhb 15450107Smsmith/* Shutdown events */ 15592719Salfredtypedef void (*shutdown_fn)(void *, int); 15650107Smsmith 157112563Sjhb#define SHUTDOWN_PRI_FIRST EVENTHANDLER_PRI_FIRST 158112563Sjhb#define SHUTDOWN_PRI_DEFAULT EVENTHANDLER_PRI_ANY 159112565Sjhb#define SHUTDOWN_PRI_LAST EVENTHANDLER_PRI_LAST 16050107Smsmith 16150107SmsmithEVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn); /* before fs sync */ 16250107SmsmithEVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn); /* after fs sync */ 16350107SmsmithEVENTHANDLER_DECLARE(shutdown_final, shutdown_fn); 16450107Smsmith 165107136Sjeff/* Low memory event */ 166107136Sjefftypedef void (*vm_lowmem_handler_t)(void *, int); 167112563Sjhb#define LOWMEM_PRI_DEFAULT EVENTHANDLER_PRI_FIRST 168107136SjeffEVENTHANDLER_DECLARE(vm_lowmem, vm_lowmem_handler_t); 16966205Smsmith 170126940Speter/* 171126940Speter * Process events 172126941Speter * process_fork and exit handlers are called without Giant. 173126941Speter * exec handlers are called with Giant, but that is by accident. 174126940Speter */ 175112564Sjhbstruct proc; 176161302Snetchildstruct image_params; 177112564Sjhb 178112564Sjhbtypedef void (*exitlist_fn)(void *, struct proc *); 179112564Sjhbtypedef void (*forklist_fn)(void *, struct proc *, struct proc *, int); 180161302Snetchildtypedef void (*execlist_fn)(void *, struct proc *, struct image_params *); 181112564Sjhb 182112564SjhbEVENTHANDLER_DECLARE(process_exit, exitlist_fn); 183112564SjhbEVENTHANDLER_DECLARE(process_fork, forklist_fn); 184112564SjhbEVENTHANDLER_DECLARE(process_exec, execlist_fn); 185112564Sjhb 186157927Spstypedef void (*uma_zone_chfn)(void *); 187157927SpsEVENTHANDLER_DECLARE(nmbclusters_change, uma_zone_chfn); 188157927SpsEVENTHANDLER_DECLARE(maxsockets_change, uma_zone_chfn); 189161302Snetchild 190161302Snetchildtypedef void(*schedtail_fn)(void *, struct proc *); 191161302SnetchildEVENTHANDLER_DECLARE(schedtail, schedtail_fn); 19250107Smsmith#endif /* SYS_EVENTHANDLER_H */ 193