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; /* Unused. */ 55 u_int el_runcount; 56 struct mtx el_lock; 57 TAILQ_ENTRY(eventhandler_list) el_link; 58 TAILQ_HEAD(,eventhandler_entry) el_entries; 59 }; 60 61 typedef struct eventhandler_entry *eventhandler_tag; 62 63 #define EHL_LOCK(p) mtx_lock(&(p)->el_lock) 64 #define EHL_UNLOCK(p) mtx_unlock(&(p)->el_lock) 65 #define EHL_LOCK_ASSERT(p, x) mtx_assert(&(p)->el_lock, x) 66 67 /* 68 * Macro to invoke the handlers for a given event. 69 */ 70 #define _EVENTHANDLER_INVOKE(name, list, ...) do { \ 71 struct eventhandler_entry *_ep; \ 72 struct eventhandler_entry_ ## name *_t; \ 73 \ 74 EHL_LOCK_ASSERT((list), MA_OWNED); \ 75 (list)->el_runcount++; \ 76 KASSERT((list)->el_runcount > 0, \ 77 ("eventhandler_invoke: runcount overflow")); \ 78 CTR0(KTR_EVH, "eventhandler_invoke(\"" __STRING(name) "\")"); \ 79 TAILQ_FOREACH(_ep, &((list)->el_entries), ee_link) { \ 80 if (_ep->ee_priority != EHE_DEAD_PRIORITY) { \ 81 EHL_UNLOCK((list)); \ 82 _t = (struct eventhandler_entry_ ## name *)_ep; \ 83 CTR1(KTR_EVH, "eventhandler_invoke: executing %p", \ 84 (void *)_t->eh_func); \ 85 _t->eh_func(_ep->ee_arg , ## __VA_ARGS__); \ 86 EHL_LOCK((list)); \ 87 } \ 88 } \ 89 KASSERT((list)->el_runcount > 0, \ 90 ("eventhandler_invoke: runcount underflow")); \ 91 (list)->el_runcount--; \ 92 if ((list)->el_runcount == 0) \ 93 eventhandler_prune_list(list); \ 94 EHL_UNLOCK((list)); \ 95 } while (0) 96 97 /* 98 * You can optionally use the EVENTHANDLER_LIST and EVENTHANDLER_DIRECT macros 99 * to pre-define a symbol for the eventhandler list. This symbol can be used by 100 * EVENTHANDLER_DIRECT_INVOKE, which has the advantage of not needing to do a 101 * locked search of the global list of eventhandler lists. At least 102 * EVENTHANDLER_LIST_DEFINE must be be used for EVENTHANDLER_DIRECT_INVOKE to 103 * work. EVENTHANDLER_LIST_DECLARE is only needed if the call to 104 * EVENTHANDLER_DIRECT_INVOKE is in a different compilation unit from 105 * EVENTHANDLER_LIST_DEFINE. If the events are even relatively high frequency 106 * it is suggested that you directly define a list for them. 107 */ 108 #define EVENTHANDLER_LIST_DECLARE(name) \ 109 extern struct eventhandler_list *_eventhandler_list_ ## name \ 110 111 #define EVENTHANDLER_LIST_DEFINE(name) \ 112 struct eventhandler_list *_eventhandler_list_ ## name ; \ 113 static void _ehl_init_ ## name (void * ctx __unused) \ 114 { \ 115 _eventhandler_list_ ## name = eventhandler_create_list(#name); \ 116 } \ 117 SYSINIT(name ## _ehl_init, SI_SUB_EVENTHANDLER, SI_ORDER_ANY, \ 118 _ehl_init_ ## name, NULL); \ 119 struct __hack 120 121 #define EVENTHANDLER_DIRECT_INVOKE(name, ...) do { \ 122 struct eventhandler_list *_el; \ 123 \ 124 _el = _eventhandler_list_ ## name ; \ 125 if (!TAILQ_EMPTY(&_el->el_entries)) { \ 126 EHL_LOCK(_el); \ 127 _EVENTHANDLER_INVOKE(name, _el , ## __VA_ARGS__); \ 128 } \ 129 } while (0) 130 131 /* 132 * Event handlers need to be declared, but do not need to be defined. The 133 * declaration must be in scope wherever the handler is to be invoked. 134 */ 135 #define EVENTHANDLER_DECLARE(name, type) \ 136 struct eventhandler_entry_ ## name \ 137 { \ 138 struct eventhandler_entry ee; \ 139 type eh_func; \ 140 }; \ 141 struct __hack 142 143 #define EVENTHANDLER_DEFINE(name, func, arg, priority) \ 144 static eventhandler_tag name ## _tag; \ 145 static void name ## _evh_init(void *ctx) \ 146 { \ 147 name ## _tag = EVENTHANDLER_REGISTER(name, func, ctx, \ 148 priority); \ 149 } \ 150 SYSINIT(name ## _evh_init, SI_SUB_CONFIGURE, SI_ORDER_ANY, \ 151 name ## _evh_init, arg); \ 152 struct __hack 153 154 #define EVENTHANDLER_INVOKE(name, ...) \ 155 do { \ 156 struct eventhandler_list *_el; \ 157 \ 158 if ((_el = eventhandler_find_list(#name)) != NULL) \ 159 _EVENTHANDLER_INVOKE(name, _el , ## __VA_ARGS__); \ 160 } while (0) 161 162 #define EVENTHANDLER_REGISTER(name, func, arg, priority) \ 163 eventhandler_register(NULL, #name, func, arg, priority) 164 165 #define EVENTHANDLER_DEREGISTER(name, tag) \ 166 do { \ 167 struct eventhandler_list *_el; \ 168 \ 169 if ((_el = eventhandler_find_list(#name)) != NULL) \ 170 eventhandler_deregister(_el, tag); \ 171 } while(0) 172 173 #define EVENTHANDLER_DEREGISTER_NOWAIT(name, tag) \ 174 do { \ 175 struct eventhandler_list *_el; \ 176 \ 177 if ((_el = eventhandler_find_list(#name)) != NULL) \ 178 eventhandler_deregister_nowait(_el, tag); \ 179 } while(0) 180 181 eventhandler_tag eventhandler_register(struct eventhandler_list *list, 182 const char *name, void *func, void *arg, int priority); 183 void eventhandler_deregister(struct eventhandler_list *list, 184 eventhandler_tag tag); 185 void eventhandler_deregister_nowait(struct eventhandler_list *list, 186 eventhandler_tag tag); 187 struct eventhandler_list *eventhandler_find_list(const char *name); 188 void eventhandler_prune_list(struct eventhandler_list *list); 189 struct eventhandler_list *eventhandler_create_list(const char *name); 190 191 #ifdef VIMAGE 192 typedef void (*vimage_iterator_func_t)(void *, ...); 193 194 eventhandler_tag vimage_eventhandler_register(struct eventhandler_list *list, 195 const char *name, void *func, void *arg, int priority, 196 vimage_iterator_func_t); 197 #endif 198 199 /* 200 * Standard system event queues. 201 */ 202 203 /* Generic priority levels */ 204 #define EVENTHANDLER_PRI_FIRST 0 205 #define EVENTHANDLER_PRI_ANY 10000 206 #define EVENTHANDLER_PRI_LAST 20000 207 208 /* Shutdown events */ 209 typedef void (*shutdown_fn)(void *, int); 210 211 #define SHUTDOWN_PRI_FIRST EVENTHANDLER_PRI_FIRST 212 #define SHUTDOWN_PRI_DEFAULT EVENTHANDLER_PRI_ANY 213 #define SHUTDOWN_PRI_LAST EVENTHANDLER_PRI_LAST 214 215 EVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn); /* before fs sync */ 216 EVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn); /* after fs sync */ 217 EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn); 218 219 /* Power state change events */ 220 typedef void (*power_change_fn)(void *); 221 EVENTHANDLER_DECLARE(power_resume, power_change_fn); 222 EVENTHANDLER_DECLARE(power_suspend, power_change_fn); 223 EVENTHANDLER_DECLARE(power_suspend_early, power_change_fn); 224 225 /* Low memory event */ 226 typedef void (*vm_lowmem_handler_t)(void *, int); 227 #define LOWMEM_PRI_DEFAULT EVENTHANDLER_PRI_FIRST 228 EVENTHANDLER_DECLARE(vm_lowmem, vm_lowmem_handler_t); 229 230 /* Root mounted event */ 231 typedef void (*mountroot_handler_t)(void *); 232 EVENTHANDLER_DECLARE(mountroot, mountroot_handler_t); 233 234 /* File system mount events */ 235 struct mount; 236 struct vnode; 237 struct thread; 238 typedef void (*vfs_mounted_notify_fn)(void *, struct mount *, struct vnode *, 239 struct thread *); 240 typedef void (*vfs_unmounted_notify_fn)(void *, struct mount *, 241 struct thread *); 242 EVENTHANDLER_DECLARE(vfs_mounted, vfs_mounted_notify_fn); 243 EVENTHANDLER_DECLARE(vfs_unmounted, vfs_unmounted_notify_fn); 244 245 /* 246 * Process events 247 * process_fork and exit handlers are called without Giant. 248 * exec handlers are called with Giant, but that is by accident. 249 */ 250 struct proc; 251 struct image_params; 252 253 typedef void (*exitlist_fn)(void *, struct proc *); 254 typedef void (*forklist_fn)(void *, struct proc *, struct proc *, int); 255 typedef void (*execlist_fn)(void *, struct proc *, struct image_params *); 256 typedef void (*proc_ctor_fn)(void *, struct proc *); 257 typedef void (*proc_dtor_fn)(void *, struct proc *); 258 typedef void (*proc_init_fn)(void *, struct proc *); 259 typedef void (*proc_fini_fn)(void *, struct proc *); 260 EVENTHANDLER_DECLARE(process_ctor, proc_ctor_fn); 261 EVENTHANDLER_DECLARE(process_dtor, proc_dtor_fn); 262 EVENTHANDLER_DECLARE(process_init, proc_init_fn); 263 EVENTHANDLER_DECLARE(process_fini, proc_fini_fn); 264 EVENTHANDLER_DECLARE(process_exit, exitlist_fn); 265 EVENTHANDLER_DECLARE(process_fork, forklist_fn); 266 EVENTHANDLER_DECLARE(process_exec, execlist_fn); 267 268 /* 269 * application dump event 270 */ 271 typedef void (*app_coredump_start_fn)(void *, struct thread *, char *name); 272 typedef void (*app_coredump_progress_fn)(void *, struct thread *td, int byte_count); 273 typedef void (*app_coredump_finish_fn)(void *, struct thread *td); 274 typedef void (*app_coredump_error_fn)(void *, struct thread *td, char *msg, ...); 275 276 EVENTHANDLER_DECLARE(app_coredump_start, app_coredump_start_fn); 277 EVENTHANDLER_DECLARE(app_coredump_progress, app_coredump_progress_fn); 278 EVENTHANDLER_DECLARE(app_coredump_finish, app_coredump_finish_fn); 279 EVENTHANDLER_DECLARE(app_coredump_error, app_coredump_error_fn); 280 281 typedef void (*thread_ctor_fn)(void *, struct thread *); 282 typedef void (*thread_dtor_fn)(void *, struct thread *); 283 typedef void (*thread_fini_fn)(void *, struct thread *); 284 typedef void (*thread_init_fn)(void *, struct thread *); 285 EVENTHANDLER_DECLARE(thread_ctor, thread_ctor_fn); 286 EVENTHANDLER_DECLARE(thread_dtor, thread_dtor_fn); 287 EVENTHANDLER_DECLARE(thread_init, thread_init_fn); 288 EVENTHANDLER_DECLARE(thread_fini, thread_fini_fn); 289 290 typedef void (*uma_zone_chfn)(void *); 291 EVENTHANDLER_DECLARE(nmbclusters_change, uma_zone_chfn); 292 EVENTHANDLER_DECLARE(nmbufs_change, uma_zone_chfn); 293 EVENTHANDLER_DECLARE(maxsockets_change, uma_zone_chfn); 294 295 /* Kernel linker file load and unload events */ 296 struct linker_file; 297 typedef void (*kld_load_fn)(void *, struct linker_file *); 298 typedef void (*kld_unload_fn)(void *, const char *, caddr_t, size_t); 299 typedef void (*kld_unload_try_fn)(void *, struct linker_file *, int *); 300 EVENTHANDLER_DECLARE(kld_load, kld_load_fn); 301 EVENTHANDLER_DECLARE(kld_unload, kld_unload_fn); 302 EVENTHANDLER_DECLARE(kld_unload_try, kld_unload_try_fn); 303 304 /* Generic graphics framebuffer interface */ 305 struct fb_info; 306 typedef void (*register_framebuffer_fn)(void *, struct fb_info *); 307 typedef void (*unregister_framebuffer_fn)(void *, struct fb_info *); 308 EVENTHANDLER_DECLARE(register_framebuffer, register_framebuffer_fn); 309 EVENTHANDLER_DECLARE(unregister_framebuffer, unregister_framebuffer_fn); 310 311 /* Veto ada attachment */ 312 struct cam_path; 313 struct ata_params; 314 typedef void (*ada_probe_veto_fn)(void *, struct cam_path *, 315 struct ata_params *, int *); 316 EVENTHANDLER_DECLARE(ada_probe_veto, ada_probe_veto_fn); 317 318 /* Swap device events */ 319 struct swdevt; 320 typedef void (*swapon_fn)(void *, struct swdevt *); 321 typedef void (*swapoff_fn)(void *, struct swdevt *); 322 EVENTHANDLER_DECLARE(swapon, swapon_fn); 323 EVENTHANDLER_DECLARE(swapoff, swapoff_fn); 324 325 /* newbus device events */ 326 enum evhdev_detach { 327 EVHDEV_DETACH_BEGIN, /* Before detach() is called */ 328 EVHDEV_DETACH_COMPLETE, /* After detach() returns 0 */ 329 EVHDEV_DETACH_FAILED /* After detach() returns err */ 330 }; 331 typedef void (*device_attach_fn)(void *, device_t); 332 typedef void (*device_detach_fn)(void *, device_t, enum evhdev_detach); 333 EVENTHANDLER_DECLARE(device_attach, device_attach_fn); 334 EVENTHANDLER_DECLARE(device_detach, device_detach_fn); 335 336 #endif /* _SYS_EVENTHANDLER_H_ */ 337