1/*- 2 * Copyright (c) 1999 Michael Smith <msmith@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: src/sys/sys/eventhandler.h,v 1.33.2.1 2006/05/16 07:27:49 ps Exp $ 27 */ 28#ifndef SYS_EVENTHANDLER_H 29#define SYS_EVENTHANDLER_H 30 31#include <sys/lock.h> 32#include <sys/ktr.h> 33#include <sys/mutex.h> 34#include <sys/queue.h> 35 36struct eventhandler_entry { 37 TAILQ_ENTRY(eventhandler_entry) ee_link; 38 int ee_priority; 39#define EHE_DEAD_PRIORITY (-1) 40 void *ee_arg; 41}; 42 43struct eventhandler_list { 44 char *el_name; 45 int el_flags; 46#define EHL_INITTED (1<<0) 47 u_int el_runcount; 48 struct mtx el_lock; 49 TAILQ_ENTRY(eventhandler_list) el_link; 50 TAILQ_HEAD(,eventhandler_entry) el_entries; 51}; 52 53typedef struct eventhandler_entry *eventhandler_tag; 54 55#define EHL_LOCK(p) mtx_lock(&(p)->el_lock) 56#define EHL_UNLOCK(p) mtx_unlock(&(p)->el_lock) 57#define EHL_LOCK_ASSERT(p, x) mtx_assert(&(p)->el_lock, x) 58 59/* 60 * Macro to invoke the handlers for a given event. 61 */ 62#define _EVENTHANDLER_INVOKE(name, list, ...) do { \ 63 struct eventhandler_entry *_ep; \ 64 struct eventhandler_entry_ ## name *_t; \ 65 \ 66 KASSERT((list)->el_flags & EHL_INITTED, \ 67 ("eventhandler_invoke: running non-inited list")); \ 68 EHL_LOCK_ASSERT((list), MA_OWNED); \ 69 (list)->el_runcount++; \ 70 KASSERT((list)->el_runcount > 0, \ 71 ("eventhandler_invoke: runcount overflow")); \ 72 CTR0(KTR_EVH, "eventhandler_invoke(\"" __STRING(name) "\")"); \ 73 TAILQ_FOREACH(_ep, &((list)->el_entries), ee_link) { \ 74 if (_ep->ee_priority != EHE_DEAD_PRIORITY) { \ 75 EHL_UNLOCK((list)); \ 76 _t = (struct eventhandler_entry_ ## name *)_ep; \ 77 CTR1(KTR_EVH, "eventhandler_invoke: executing %p", \ 78 (void *)_t->eh_func); \ 79 _t->eh_func(_ep->ee_arg , ## __VA_ARGS__); \ 80 EHL_LOCK((list)); \ 81 } \ 82 } \ 83 KASSERT((list)->el_runcount > 0, \ 84 ("eventhandler_invoke: runcount underflow")); \ 85 (list)->el_runcount--; \ 86 if ((list)->el_runcount == 0) \ 87 eventhandler_prune_list(list); \ 88 EHL_UNLOCK((list)); \ 89} while (0) 90 91/* 92 * Slow handlers are entirely dynamic; lists are created 93 * when entries are added to them, and thus have no concept of "owner", 94 * 95 * Slow handlers need to be declared, but do not need to be defined. The 96 * declaration must be in scope wherever the handler is to be invoked. 97 */ 98#define EVENTHANDLER_DECLARE(name, type) \ 99struct eventhandler_entry_ ## name \ 100{ \ 101 struct eventhandler_entry ee; \ 102 type eh_func; \ 103}; \ 104struct __hack 105 106#define EVENTHANDLER_INVOKE(name, ...) \ 107do { \ 108 struct eventhandler_list *_el; \ 109 \ 110 if ((_el = eventhandler_find_list(#name)) != NULL) \ 111 _EVENTHANDLER_INVOKE(name, _el , ## __VA_ARGS__); \ 112} while (0) 113 114#define EVENTHANDLER_REGISTER(name, func, arg, priority) \ 115 eventhandler_register(NULL, #name, func, arg, priority) 116 117#define EVENTHANDLER_DEREGISTER(name, tag) \ 118do { \ 119 struct eventhandler_list *_el; \ 120 \ 121 if ((_el = eventhandler_find_list(#name)) != NULL) \ 122 eventhandler_deregister(_el, tag); \ 123} while(0) 124 125 126eventhandler_tag eventhandler_register(struct eventhandler_list *list, 127 const char *name, void *func, void *arg, int priority); 128void eventhandler_deregister(struct eventhandler_list *list, 129 eventhandler_tag tag); 130struct eventhandler_list *eventhandler_find_list(const char *name); 131void eventhandler_prune_list(struct eventhandler_list *list); 132 133/* 134 * Standard system event queues. 135 */ 136 137/* Generic priority levels */ 138#define EVENTHANDLER_PRI_FIRST 0 139#define EVENTHANDLER_PRI_ANY 10000 140#define EVENTHANDLER_PRI_LAST 20000 141 142/* Shutdown events */ 143typedef void (*shutdown_fn)(void *, int); 144 145#define SHUTDOWN_PRI_FIRST EVENTHANDLER_PRI_FIRST 146#define SHUTDOWN_PRI_DEFAULT EVENTHANDLER_PRI_ANY 147#define SHUTDOWN_PRI_LAST EVENTHANDLER_PRI_LAST 148 149EVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn); /* before fs sync */ 150EVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn); /* after fs sync */ 151EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn); 152 153/* Low memory event */ 154typedef void (*vm_lowmem_handler_t)(void *, int); 155#define LOWMEM_PRI_DEFAULT EVENTHANDLER_PRI_FIRST 156EVENTHANDLER_DECLARE(vm_lowmem, vm_lowmem_handler_t); 157 158/* 159 * Process events 160 * process_fork and exit handlers are called without Giant. 161 * exec handlers are called with Giant, but that is by accident. 162 */ 163struct proc; 164 165typedef void (*exitlist_fn)(void *, struct proc *); 166typedef void (*forklist_fn)(void *, struct proc *, struct proc *, int); 167typedef void (*execlist_fn)(void *, struct proc *); 168 169EVENTHANDLER_DECLARE(process_exit, exitlist_fn); 170EVENTHANDLER_DECLARE(process_fork, forklist_fn); 171EVENTHANDLER_DECLARE(process_exec, execlist_fn); 172 173typedef void (*uma_zone_chfn)(void *); 174EVENTHANDLER_DECLARE(nmbclusters_change, uma_zone_chfn); 175EVENTHANDLER_DECLARE(maxsockets_change, uma_zone_chfn); 176#endif /* SYS_EVENTHANDLER_H */ 177