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