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$ 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 37 struct 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 44 #ifdef VIMAGE 45 struct eventhandler_entry_vimage { 46 void (* func)(void); /* Original function registered. */ 47 void *ee_arg; /* Original argument registered. */ 48 void *sparep[2]; 49 }; 50 #endif 51 52 struct eventhandler_list { 53 char *el_name; 54 int el_flags; 55 #define EHL_INITTED (1<<0) 56 u_int el_runcount; 57 struct mtx el_lock; 58 TAILQ_ENTRY(eventhandler_list) el_link; 59 TAILQ_HEAD(,eventhandler_entry) el_entries; 60 }; 61 62 typedef struct eventhandler_entry *eventhandler_tag; 63 64 #define EHL_LOCK(p) mtx_lock(&(p)->el_lock) 65 #define EHL_UNLOCK(p) mtx_unlock(&(p)->el_lock) 66 #define EHL_LOCK_ASSERT(p, x) mtx_assert(&(p)->el_lock, x) 67 68 /* 69 * Macro to invoke the handlers for a given event. 70 */ 71 #define _EVENTHANDLER_INVOKE(name, list, ...) do { \ 72 struct eventhandler_entry *_ep; \ 73 struct eventhandler_entry_ ## name *_t; \ 74 \ 75 KASSERT((list)->el_flags & EHL_INITTED, \ 76 ("eventhandler_invoke: running non-inited list")); \ 77 EHL_LOCK_ASSERT((list), MA_OWNED); \ 78 (list)->el_runcount++; \ 79 KASSERT((list)->el_runcount > 0, \ 80 ("eventhandler_invoke: runcount overflow")); \ 81 CTR0(KTR_EVH, "eventhandler_invoke(\"" __STRING(name) "\")"); \ 82 TAILQ_FOREACH(_ep, &((list)->el_entries), ee_link) { \ 83 if (_ep->ee_priority != EHE_DEAD_PRIORITY) { \ 84 EHL_UNLOCK((list)); \ 85 _t = (struct eventhandler_entry_ ## name *)_ep; \ 86 CTR1(KTR_EVH, "eventhandler_invoke: executing %p", \ 87 (void *)_t->eh_func); \ 88 _t->eh_func(_ep->ee_arg , ## __VA_ARGS__); \ 89 EHL_LOCK((list)); \ 90 } \ 91 } \ 92 KASSERT((list)->el_runcount > 0, \ 93 ("eventhandler_invoke: runcount underflow")); \ 94 (list)->el_runcount--; \ 95 if ((list)->el_runcount == 0) \ 96 eventhandler_prune_list(list); \ 97 EHL_UNLOCK((list)); \ 98 } while (0) 99 100 /* 101 * Slow handlers are entirely dynamic; lists are created 102 * when entries are added to them, and thus have no concept of "owner", 103 * 104 * Slow handlers need to be declared, but do not need to be defined. The 105 * declaration must be in scope wherever the handler is to be invoked. 106 */ 107 #define EVENTHANDLER_DECLARE(name, type) \ 108 struct eventhandler_entry_ ## name \ 109 { \ 110 struct eventhandler_entry ee; \ 111 type eh_func; \ 112 }; \ 113 struct __hack 114 115 #define EVENTHANDLER_DEFINE(name, func, arg, priority) \ 116 static eventhandler_tag name ## _tag; \ 117 static void name ## _evh_init(void *ctx) \ 118 { \ 119 name ## _tag = EVENTHANDLER_REGISTER(name, func, ctx, \ 120 priority); \ 121 } \ 122 SYSINIT(name ## _evh_init, SI_SUB_CONFIGURE, SI_ORDER_ANY, \ 123 name ## _evh_init, arg); \ 124 struct __hack 125 126 #define EVENTHANDLER_INVOKE(name, ...) \ 127 do { \ 128 struct eventhandler_list *_el; \ 129 \ 130 if ((_el = eventhandler_find_list(#name)) != NULL) \ 131 _EVENTHANDLER_INVOKE(name, _el , ## __VA_ARGS__); \ 132 } while (0) 133 134 #define EVENTHANDLER_REGISTER(name, func, arg, priority) \ 135 eventhandler_register(NULL, #name, func, arg, priority) 136 137 #define EVENTHANDLER_DEREGISTER(name, tag) \ 138 do { \ 139 struct eventhandler_list *_el; \ 140 \ 141 if ((_el = eventhandler_find_list(#name)) != NULL) \ 142 eventhandler_deregister(_el, tag); \ 143 } while(0) 144 145 146 eventhandler_tag eventhandler_register(struct eventhandler_list *list, 147 const char *name, void *func, void *arg, int priority); 148 void eventhandler_deregister(struct eventhandler_list *list, 149 eventhandler_tag tag); 150 struct eventhandler_list *eventhandler_find_list(const char *name); 151 void eventhandler_prune_list(struct eventhandler_list *list); 152 153 #ifdef VIMAGE 154 typedef void (*vimage_iterator_func_t)(void *, ...); 155 156 eventhandler_tag vimage_eventhandler_register(struct eventhandler_list *list, 157 const char *name, void *func, void *arg, int priority, 158 vimage_iterator_func_t); 159 #endif 160 161 /* 162 * Standard system event queues. 163 */ 164 165 /* Generic priority levels */ 166 #define EVENTHANDLER_PRI_FIRST 0 167 #define EVENTHANDLER_PRI_ANY 10000 168 #define EVENTHANDLER_PRI_LAST 20000 169 170 /* Shutdown events */ 171 typedef void (*shutdown_fn)(void *, int); 172 173 #define SHUTDOWN_PRI_FIRST EVENTHANDLER_PRI_FIRST 174 #define SHUTDOWN_PRI_DEFAULT EVENTHANDLER_PRI_ANY 175 #define SHUTDOWN_PRI_LAST EVENTHANDLER_PRI_LAST 176 177 EVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn); /* before fs sync */ 178 EVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn); /* after fs sync */ 179 EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn); 180 181 /* Power state change events */ 182 typedef void (*power_change_fn)(void *); 183 EVENTHANDLER_DECLARE(power_resume, power_change_fn); 184 EVENTHANDLER_DECLARE(power_suspend, power_change_fn); 185 186 /* Low memory event */ 187 typedef void (*vm_lowmem_handler_t)(void *, int); 188 #define LOWMEM_PRI_DEFAULT EVENTHANDLER_PRI_FIRST 189 EVENTHANDLER_DECLARE(vm_lowmem, vm_lowmem_handler_t); 190 191 /* Root mounted event */ 192 typedef void (*mountroot_handler_t)(void *); 193 EVENTHANDLER_DECLARE(mountroot, mountroot_handler_t); 194 195 /* File system mount events */ 196 struct mount; 197 struct vnode; 198 struct thread; 199 typedef void (*vfs_mounted_notify_fn)(void *, struct mount *, struct vnode *, 200 struct thread *); 201 typedef void (*vfs_unmounted_notify_fn)(void *, struct mount *, 202 struct thread *); 203 EVENTHANDLER_DECLARE(vfs_mounted, vfs_mounted_notify_fn); 204 EVENTHANDLER_DECLARE(vfs_unmounted, vfs_unmounted_notify_fn); 205 206 /* 207 * Process events 208 * process_fork and exit handlers are called without Giant. 209 * exec handlers are called with Giant, but that is by accident. 210 */ 211 struct proc; 212 struct image_params; 213 214 typedef void (*exitlist_fn)(void *, struct proc *); 215 typedef void (*forklist_fn)(void *, struct proc *, struct proc *, int); 216 typedef void (*execlist_fn)(void *, struct proc *, struct image_params *); 217 typedef void (*proc_ctor_fn)(void *, struct proc *); 218 typedef void (*proc_dtor_fn)(void *, struct proc *); 219 typedef void (*proc_init_fn)(void *, struct proc *); 220 typedef void (*proc_fini_fn)(void *, struct proc *); 221 EVENTHANDLER_DECLARE(process_ctor, proc_ctor_fn); 222 EVENTHANDLER_DECLARE(process_dtor, proc_dtor_fn); 223 EVENTHANDLER_DECLARE(process_init, proc_init_fn); 224 EVENTHANDLER_DECLARE(process_fini, proc_fini_fn); 225 EVENTHANDLER_DECLARE(process_exit, exitlist_fn); 226 EVENTHANDLER_DECLARE(process_fork, forklist_fn); 227 EVENTHANDLER_DECLARE(process_exec, execlist_fn); 228 229 /* 230 * application dump event 231 */ 232 typedef void (*app_coredump_start_fn)(void *, struct thread *, char *name); 233 typedef void (*app_coredump_progress_fn)(void *, struct thread *td, int byte_count); 234 typedef void (*app_coredump_finish_fn)(void *, struct thread *td); 235 typedef void (*app_coredump_error_fn)(void *, struct thread *td, char *msg, ...); 236 237 EVENTHANDLER_DECLARE(app_coredump_start, app_coredump_start_fn); 238 EVENTHANDLER_DECLARE(app_coredump_progress, app_coredump_progress_fn); 239 EVENTHANDLER_DECLARE(app_coredump_finish, app_coredump_finish_fn); 240 EVENTHANDLER_DECLARE(app_coredump_error, app_coredump_error_fn); 241 242 typedef void (*thread_ctor_fn)(void *, struct thread *); 243 typedef void (*thread_dtor_fn)(void *, struct thread *); 244 typedef void (*thread_fini_fn)(void *, struct thread *); 245 typedef void (*thread_init_fn)(void *, struct thread *); 246 EVENTHANDLER_DECLARE(thread_ctor, thread_ctor_fn); 247 EVENTHANDLER_DECLARE(thread_dtor, thread_dtor_fn); 248 EVENTHANDLER_DECLARE(thread_init, thread_init_fn); 249 EVENTHANDLER_DECLARE(thread_fini, thread_fini_fn); 250 251 typedef void (*uma_zone_chfn)(void *); 252 EVENTHANDLER_DECLARE(nmbclusters_change, uma_zone_chfn); 253 EVENTHANDLER_DECLARE(nmbufs_change, uma_zone_chfn); 254 EVENTHANDLER_DECLARE(maxsockets_change, uma_zone_chfn); 255 256 /* Kernel linker file load and unload events */ 257 struct linker_file; 258 typedef void (*kld_load_fn)(void *, struct linker_file *); 259 typedef void (*kld_unload_fn)(void *, const char *, caddr_t, size_t); 260 typedef void (*kld_unload_try_fn)(void *, struct linker_file *, int *); 261 EVENTHANDLER_DECLARE(kld_load, kld_load_fn); 262 EVENTHANDLER_DECLARE(kld_unload, kld_unload_fn); 263 EVENTHANDLER_DECLARE(kld_unload_try, kld_unload_try_fn); 264 265 /* Generic graphics framebuffer interface */ 266 struct fb_info; 267 typedef void (*register_framebuffer_fn)(void *, struct fb_info *); 268 typedef void (*unregister_framebuffer_fn)(void *, struct fb_info *); 269 EVENTHANDLER_DECLARE(register_framebuffer, register_framebuffer_fn); 270 EVENTHANDLER_DECLARE(unregister_framebuffer, unregister_framebuffer_fn); 271 272 #endif /* _SYS_EVENTHANDLER_H_ */ 273