eventhandler.h revision 126941
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: head/sys/sys/eventhandler.h 126941 2004-03-14 02:06:28Z peter $ 27 */ 28 29#ifndef SYS_EVENTHANDLER_H 30#define SYS_EVENTHANDLER_H 31 32#include <sys/lock.h> 33#include <sys/ktr.h> 34#include <sys/mutex.h> 35#include <sys/queue.h> 36 37struct eventhandler_entry { 38 TAILQ_ENTRY(eventhandler_entry) ee_link; 39 int ee_priority; 40#define EHE_DEAD_PRIORITY (-1) 41 void *ee_arg; 42}; 43 44struct eventhandler_list { 45 char *el_name; 46 int el_flags; 47#define EHL_INITTED (1<<0) 48 u_int el_runcount; 49 struct mtx el_lock; 50 TAILQ_ENTRY(eventhandler_list) el_link; 51 TAILQ_HEAD(,eventhandler_entry) el_entries; 52}; 53 54typedef struct eventhandler_entry *eventhandler_tag; 55 56#define EHL_LOCK(p) mtx_lock(&(p)->el_lock) 57#define EHL_UNLOCK(p) mtx_unlock(&(p)->el_lock) 58#define EHL_LOCK_ASSERT(p, x) mtx_assert(&(p)->el_lock, x) 59 60/* 61 * Macro to invoke the handlers for a given event. 62 */ 63#define _EVENTHANDLER_INVOKE(name, list, ...) do { \ 64 struct eventhandler_entry *_ep; \ 65 struct eventhandler_entry_ ## name *_t; \ 66 \ 67 KASSERT((list)->el_flags & EHL_INITTED, \ 68 ("eventhandler_invoke: running non-inited list")); \ 69 EHL_LOCK_ASSERT((list), MA_OWNED); \ 70 (list)->el_runcount++; \ 71 KASSERT((list)->el_runcount > 0, \ 72 ("eventhandler_invoke: runcount overflow")); \ 73 CTR0(KTR_EVH, "eventhandler_invoke(\"" __STRING(name) "\")"); \ 74 TAILQ_FOREACH(_ep, &((list)->el_entries), ee_link) { \ 75 if (_ep->ee_priority != EHE_DEAD_PRIORITY) { \ 76 EHL_UNLOCK((list)); \ 77 _t = (struct eventhandler_entry_ ## name *)_ep; \ 78 CTR1(KTR_EVH, "eventhandler_invoke: executing %p", \ 79 (void *)_t->eh_func); \ 80 _t->eh_func(_ep->ee_arg , ## __VA_ARGS__); \ 81 EHL_LOCK((list)); \ 82 } \ 83 } \ 84 KASSERT((list)->el_runcount > 0, \ 85 ("eventhandler_invoke: runcount underflow")); \ 86 (list)->el_runcount--; \ 87 if ((list)->el_runcount == 0) \ 88 eventhandler_prune_list(list); \ 89 EHL_UNLOCK((list)); \ 90} while (0) 91 92/* 93 * Slow handlers are entirely dynamic; lists are created 94 * when entries are added to them, and thus have no concept of "owner", 95 * 96 * Slow handlers need to be declared, but do not need to be defined. The 97 * declaration must be in scope wherever the handler is to be invoked. 98 */ 99#define EVENTHANDLER_DECLARE(name, type) \ 100struct eventhandler_entry_ ## name \ 101{ \ 102 struct eventhandler_entry ee; \ 103 type eh_func; \ 104}; \ 105struct __hack 106 107#define EVENTHANDLER_INVOKE(name, ...) \ 108do { \ 109 struct eventhandler_list *_el; \ 110 \ 111 if ((_el = eventhandler_find_list(#name)) != NULL) \ 112 _EVENTHANDLER_INVOKE(name, _el , ## __VA_ARGS__); \ 113} while (0) 114 115#define EVENTHANDLER_REGISTER(name, func, arg, priority) \ 116 eventhandler_register(NULL, #name, func, arg, priority) 117 118#define EVENTHANDLER_DEREGISTER(name, tag) \ 119do { \ 120 struct eventhandler_list *_el; \ 121 \ 122 if ((_el = eventhandler_find_list(#name)) != NULL) \ 123 eventhandler_deregister(_el, tag); \ 124} while(0) 125 126 127eventhandler_tag eventhandler_register(struct eventhandler_list *list, 128 char *name, void *func, void *arg, int priority); 129void eventhandler_deregister(struct eventhandler_list *list, 130 eventhandler_tag tag); 131struct eventhandler_list *eventhandler_find_list(char *name); 132void eventhandler_prune_list(struct eventhandler_list *list); 133 134/* 135 * Standard system event queues. 136 */ 137 138/* Generic priority levels */ 139#define EVENTHANDLER_PRI_FIRST 0 140#define EVENTHANDLER_PRI_ANY 10000 141#define EVENTHANDLER_PRI_LAST 20000 142 143/* Shutdown events */ 144typedef void (*shutdown_fn)(void *, int); 145 146#define SHUTDOWN_PRI_FIRST EVENTHANDLER_PRI_FIRST 147#define SHUTDOWN_PRI_DEFAULT EVENTHANDLER_PRI_ANY 148#define SHUTDOWN_PRI_LAST EVENTHANDLER_PRI_LAST 149 150EVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn); /* before fs sync */ 151EVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn); /* after fs sync */ 152EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn); 153 154/* Low memory event */ 155typedef void (*vm_lowmem_handler_t)(void *, int); 156#define LOWMEM_PRI_DEFAULT EVENTHANDLER_PRI_FIRST 157EVENTHANDLER_DECLARE(vm_lowmem, vm_lowmem_handler_t); 158 159/* 160 * Process events 161 * process_fork and exit handlers are called without Giant. 162 * exec handlers are called with Giant, but that is by accident. 163 */ 164struct proc; 165 166typedef void (*exitlist_fn)(void *, struct proc *); 167typedef void (*forklist_fn)(void *, struct proc *, struct proc *, int); 168typedef void (*execlist_fn)(void *, struct proc *); 169 170EVENTHANDLER_DECLARE(process_exit, exitlist_fn); 171EVENTHANDLER_DECLARE(process_fork, forklist_fn); 172EVENTHANDLER_DECLARE(process_exec, execlist_fn); 173 174#endif /* SYS_EVENTHANDLER_H */ 175