1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 1999 Michael Smith <msmith@freebsd.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #ifndef _SYS_EVENTHANDLER_H_ 30 #define _SYS_EVENTHANDLER_H_ 31 32 #include <sys/_eventhandler.h> 33 #include <sys/lock.h> 34 #include <sys/ktr.h> 35 #include <sys/mutex.h> 36 #include <sys/power.h> 37 #include <sys/queue.h> 38 39 #ifdef VIMAGE 40 struct eventhandler_entry_vimage { 41 void (* func)(void); /* Original function registered. */ 42 void *ee_arg; /* Original argument registered. */ 43 void *sparep[2]; 44 }; 45 #endif 46 47 struct eventhandler_list { 48 char *el_name; 49 u_int el_deadcount; 50 u_int el_runcount; 51 struct mtx el_lock; 52 TAILQ_ENTRY(eventhandler_list) el_link; 53 TAILQ_HEAD(,eventhandler_entry) el_entries; 54 }; 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 EHL_LOCK_ASSERT((list), MA_OWNED); \ 68 (list)->el_runcount++; \ 69 KASSERT((list)->el_runcount > 0, \ 70 ("eventhandler_invoke: runcount overflow")); \ 71 CTR0(KTR_EVH, "eventhandler_invoke(\"" __STRING(name) "\")"); \ 72 TAILQ_FOREACH(_ep, &((list)->el_entries), ee_link) { \ 73 if (_ep->ee_priority != EHE_DEAD_PRIORITY) { \ 74 EHL_UNLOCK((list)); \ 75 _t = (struct eventhandler_entry_ ## name *)_ep; \ 76 CTR1(KTR_EVH, "eventhandler_invoke: executing %p", \ 77 (void *)_t->eh_func); \ 78 _t->eh_func(_ep->ee_arg , ## __VA_ARGS__); \ 79 EHL_LOCK((list)); \ 80 } \ 81 } \ 82 KASSERT((list)->el_runcount > 0, \ 83 ("eventhandler_invoke: runcount underflow")); \ 84 (list)->el_runcount--; \ 85 if ((list)->el_runcount == 0 && (list)->el_deadcount != 0) \ 86 eventhandler_prune_list(list); \ 87 EHL_UNLOCK((list)); \ 88 } while (0) 89 90 /* 91 * You can optionally use the EVENTHANDLER_LIST and EVENTHANDLER_DIRECT macros 92 * to pre-define a symbol for the eventhandler list. This symbol can be used by 93 * EVENTHANDLER_DIRECT_INVOKE, which has the advantage of not needing to do a 94 * locked search of the global list of eventhandler lists. At least 95 * EVENTHANDLER_LIST_DEFINE must be used for EVENTHANDLER_DIRECT_INVOKE to 96 * work. EVENTHANDLER_LIST_DECLARE is only needed if the call to 97 * EVENTHANDLER_DIRECT_INVOKE is in a different compilation unit from 98 * EVENTHANDLER_LIST_DEFINE. If the events are even relatively high frequency 99 * it is suggested that you directly define a list for them. 100 */ 101 #define EVENTHANDLER_LIST_DEFINE(name) \ 102 struct eventhandler_list *_eventhandler_list_ ## name ; \ 103 static void _ehl_init_ ## name (void * ctx __unused) \ 104 { \ 105 _eventhandler_list_ ## name = eventhandler_create_list(#name); \ 106 } \ 107 SYSINIT(name ## _ehl_init, SI_SUB_EVENTHANDLER, SI_ORDER_ANY, \ 108 _ehl_init_ ## name, NULL); \ 109 struct __hack 110 111 #define EVENTHANDLER_DIRECT_INVOKE(name, ...) do { \ 112 struct eventhandler_list *_el; \ 113 \ 114 _el = _eventhandler_list_ ## name ; \ 115 if (!TAILQ_EMPTY(&_el->el_entries)) { \ 116 EHL_LOCK(_el); \ 117 _EVENTHANDLER_INVOKE(name, _el , ## __VA_ARGS__); \ 118 } \ 119 } while (0) 120 121 #define EVENTHANDLER_DEFINE(name, func, arg, priority) \ 122 static eventhandler_tag name ## _tag; \ 123 static void name ## _evh_init(void *ctx) \ 124 { \ 125 name ## _tag = EVENTHANDLER_REGISTER(name, func, ctx, \ 126 priority); \ 127 } \ 128 SYSINIT(name ## _evh_init, SI_SUB_CONFIGURE, SI_ORDER_ANY, \ 129 name ## _evh_init, arg); \ 130 struct __hack 131 132 #define EVENTHANDLER_INVOKE(name, ...) \ 133 do { \ 134 struct eventhandler_list *_el; \ 135 \ 136 if ((_el = eventhandler_find_list(#name)) != NULL) \ 137 _EVENTHANDLER_INVOKE(name, _el , ## __VA_ARGS__); \ 138 } while (0) 139 140 #define EVENTHANDLER_REGISTER(name, func, arg, priority) \ 141 eventhandler_register(NULL, #name, func, arg, priority) 142 143 #define EVENTHANDLER_DEREGISTER(name, tag) \ 144 do { \ 145 struct eventhandler_list *_el; \ 146 \ 147 if ((_el = eventhandler_find_list(#name)) != NULL) \ 148 eventhandler_deregister(_el, tag); \ 149 } while (0) 150 151 #define EVENTHANDLER_DEREGISTER_NOWAIT(name, tag) \ 152 do { \ 153 struct eventhandler_list *_el; \ 154 \ 155 if ((_el = eventhandler_find_list(#name)) != NULL) \ 156 eventhandler_deregister_nowait(_el, tag); \ 157 } while (0) 158 159 eventhandler_tag eventhandler_register(struct eventhandler_list *list, 160 const char *name, void *func, void *arg, int priority); 161 void eventhandler_deregister(struct eventhandler_list *list, 162 eventhandler_tag tag); 163 void eventhandler_deregister_nowait(struct eventhandler_list *list, 164 eventhandler_tag tag); 165 struct eventhandler_list *eventhandler_find_list(const char *name); 166 void eventhandler_prune_list(struct eventhandler_list *list); 167 struct eventhandler_list *eventhandler_create_list(const char *name); 168 169 #ifdef VIMAGE 170 typedef void (*vimage_iterator_func_t)(void *, ...); 171 172 eventhandler_tag vimage_eventhandler_register(struct eventhandler_list *list, 173 const char *name, void *func, void *arg, int priority, 174 vimage_iterator_func_t); 175 #endif 176 177 /* 178 * Standard system event queues. 179 */ 180 181 /* Generic priority levels */ 182 #define EVENTHANDLER_PRI_FIRST 0 183 #define EVENTHANDLER_PRI_ANY 10000 184 #define EVENTHANDLER_PRI_LAST 20000 185 186 /* 187 * Successive shutdown events invoked by kern_reboot(9). 188 * 189 * Handlers will receive the 'howto' value as their second argument. 190 * 191 * All handlers must be prepared to be executed from a panic/debugger context; 192 * see the man page for details. 193 */ 194 typedef void (*shutdown_fn)(void *, int); 195 196 #define SHUTDOWN_PRI_FIRST EVENTHANDLER_PRI_FIRST 197 #define SHUTDOWN_PRI_DEFAULT EVENTHANDLER_PRI_ANY 198 #define SHUTDOWN_PRI_LAST EVENTHANDLER_PRI_LAST 199 200 EVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn); /* before fs sync */ 201 EVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn); /* after fs sync */ 202 EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn); 203 204 /* Low memory event */ 205 typedef void (*vm_lowmem_handler_t)(void *, int); 206 #define LOWMEM_PRI_DEFAULT EVENTHANDLER_PRI_FIRST 207 EVENTHANDLER_DECLARE(vm_lowmem, vm_lowmem_handler_t); 208 /* Some of mbuf(9) zones reached maximum */ 209 EVENTHANDLER_DECLARE(mbuf_lowmem, vm_lowmem_handler_t); 210 211 /* Root mounted event */ 212 typedef void (*mountroot_handler_t)(void *); 213 EVENTHANDLER_DECLARE(mountroot, mountroot_handler_t); 214 215 /* File system mount events */ 216 struct mount; 217 struct vnode; 218 struct thread; 219 typedef void (*vfs_mounted_notify_fn)(void *, struct mount *, struct vnode *, 220 struct thread *); 221 typedef void (*vfs_unmounted_notify_fn)(void *, struct mount *, 222 struct thread *); 223 EVENTHANDLER_DECLARE(vfs_mounted, vfs_mounted_notify_fn); 224 EVENTHANDLER_DECLARE(vfs_unmounted, vfs_unmounted_notify_fn); 225 226 /* 227 * Process events 228 * process_fork and exit handlers are called without Giant. 229 * exec handlers are called with Giant, but that is by accident. 230 */ 231 struct proc; 232 struct image_params; 233 234 typedef void (*exitlist_fn)(void *, struct proc *); 235 typedef void (*forklist_fn)(void *, struct proc *, struct proc *, int); 236 typedef void (*execlist_fn)(void *, struct proc *, struct image_params *); 237 typedef void (*proc_ctor_fn)(void *, struct proc *); 238 typedef void (*proc_dtor_fn)(void *, struct proc *); 239 typedef void (*proc_init_fn)(void *, struct proc *); 240 typedef void (*proc_fini_fn)(void *, struct proc *); 241 EVENTHANDLER_DECLARE(process_ctor, proc_ctor_fn); 242 EVENTHANDLER_DECLARE(process_dtor, proc_dtor_fn); 243 EVENTHANDLER_DECLARE(process_init, proc_init_fn); 244 EVENTHANDLER_DECLARE(process_fini, proc_fini_fn); 245 EVENTHANDLER_DECLARE(process_exit, exitlist_fn); 246 EVENTHANDLER_DECLARE(process_fork, forklist_fn); 247 EVENTHANDLER_DECLARE(process_exec, execlist_fn); 248 249 /* 250 * application dump event 251 */ 252 typedef void (*app_coredump_start_fn)(void *, struct thread *, char *name); 253 typedef void (*app_coredump_progress_fn)(void *, struct thread *td, int byte_count); 254 typedef void (*app_coredump_finish_fn)(void *, struct thread *td); 255 typedef void (*app_coredump_error_fn)(void *, struct thread *td, char *msg, ...); 256 257 EVENTHANDLER_DECLARE(app_coredump_start, app_coredump_start_fn); 258 EVENTHANDLER_DECLARE(app_coredump_progress, app_coredump_progress_fn); 259 EVENTHANDLER_DECLARE(app_coredump_finish, app_coredump_finish_fn); 260 EVENTHANDLER_DECLARE(app_coredump_error, app_coredump_error_fn); 261 262 typedef void (*thread_ctor_fn)(void *, struct thread *); 263 typedef void (*thread_dtor_fn)(void *, struct thread *); 264 typedef void (*thread_fini_fn)(void *, struct thread *); 265 typedef void (*thread_init_fn)(void *, struct thread *); 266 EVENTHANDLER_DECLARE(thread_ctor, thread_ctor_fn); 267 EVENTHANDLER_DECLARE(thread_dtor, thread_dtor_fn); 268 EVENTHANDLER_DECLARE(thread_init, thread_init_fn); 269 EVENTHANDLER_DECLARE(thread_fini, thread_fini_fn); 270 271 typedef void (*uma_zone_chfn)(void *); 272 EVENTHANDLER_DECLARE(nmbclusters_change, uma_zone_chfn); 273 EVENTHANDLER_DECLARE(nmbufs_change, uma_zone_chfn); 274 EVENTHANDLER_DECLARE(maxsockets_change, uma_zone_chfn); 275 276 /* Kernel linker file load and unload events */ 277 struct linker_file; 278 typedef void (*kld_load_fn)(void *, struct linker_file *); 279 typedef void (*kld_unload_fn)(void *, const char *, caddr_t, size_t); 280 typedef void (*kld_unload_try_fn)(void *, struct linker_file *, int *); 281 EVENTHANDLER_DECLARE(kld_load, kld_load_fn); 282 EVENTHANDLER_DECLARE(kld_unload, kld_unload_fn); 283 EVENTHANDLER_DECLARE(kld_unload_try, kld_unload_try_fn); 284 285 /* Generic graphics framebuffer interface */ 286 struct fb_info; 287 typedef void (*register_framebuffer_fn)(void *, struct fb_info *); 288 typedef void (*unregister_framebuffer_fn)(void *, struct fb_info *); 289 EVENTHANDLER_DECLARE(register_framebuffer, register_framebuffer_fn); 290 EVENTHANDLER_DECLARE(unregister_framebuffer, unregister_framebuffer_fn); 291 292 /* Veto ada attachment */ 293 struct cam_path; 294 struct ata_params; 295 typedef void (*ada_probe_veto_fn)(void *, struct cam_path *, 296 struct ata_params *, int *); 297 EVENTHANDLER_DECLARE(ada_probe_veto, ada_probe_veto_fn); 298 299 /* Swap device events */ 300 struct swdevt; 301 typedef void (*swapon_fn)(void *, struct swdevt *); 302 typedef void (*swapoff_fn)(void *, struct swdevt *); 303 EVENTHANDLER_DECLARE(swapon, swapon_fn); 304 EVENTHANDLER_DECLARE(swapoff, swapoff_fn); 305 306 /* newbus device events */ 307 enum evhdev_detach { 308 EVHDEV_DETACH_BEGIN, /* Before detach() is called */ 309 EVHDEV_DETACH_COMPLETE, /* After detach() returns 0 */ 310 EVHDEV_DETACH_FAILED /* After detach() returns err */ 311 }; 312 typedef void (*device_attach_fn)(void *, device_t); 313 typedef void (*device_detach_fn)(void *, device_t, enum evhdev_detach); 314 typedef void (*device_nomatch_fn)(void *, device_t); 315 EVENTHANDLER_DECLARE(device_attach, device_attach_fn); 316 EVENTHANDLER_DECLARE(device_detach, device_detach_fn); 317 EVENTHANDLER_DECLARE(device_nomatch, device_nomatch_fn); 318 319 /* Interface address addition and removal event */ 320 struct ifaddr; 321 typedef void (*rt_addrmsg_fn)(void *, struct ifaddr *, int); 322 EVENTHANDLER_DECLARE(rt_addrmsg, rt_addrmsg_fn); 323 324 /* Kernel environment variable change event */ 325 typedef void (*env_change_fn)(void *, const char *); 326 EVENTHANDLER_DECLARE(setenv, env_change_fn); 327 EVENTHANDLER_DECLARE(unsetenv, env_change_fn); 328 329 #endif /* _SYS_EVENTHANDLER_H_ */ 330