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
39struct 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
46struct 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)					\
101struct eventhandler_list *_eventhandler_list_ ## name ;			\
102static void _ehl_init_ ## name (void * ctx __unused)			\
103{									\
104	_eventhandler_list_ ## name = eventhandler_create_list(#name);	\
105}									\
106SYSINIT(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, ...)					\
132do {									\
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) 				\
143do {									\
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)			\
151do {									\
152	struct eventhandler_list *_el;					\
153									\
154	if ((_el = eventhandler_find_list(#name)) != NULL)		\
155		eventhandler_deregister_nowait(_el, tag);		\
156} while (0)
157
158eventhandler_tag eventhandler_register(struct eventhandler_list *list,
159	    const char *name, void *func, void *arg, int priority);
160void	eventhandler_deregister(struct eventhandler_list *list,
161	    eventhandler_tag tag);
162void	eventhandler_deregister_nowait(struct eventhandler_list *list,
163	    eventhandler_tag tag);
164struct eventhandler_list *eventhandler_find_list(const char *name);
165void	eventhandler_prune_list(struct eventhandler_list *list);
166struct eventhandler_list *eventhandler_create_list(const char *name);
167
168#ifdef VIMAGE
169typedef	void (*vimage_iterator_func_t)(void *, ...);
170
171eventhandler_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 */
193typedef 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
199EVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn);	/* before fs sync */
200EVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn);	/* after fs sync */
201EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn);
202
203/* Power state change events */
204typedef void (*power_change_fn)(void *);
205EVENTHANDLER_DECLARE(power_resume, power_change_fn);
206EVENTHANDLER_DECLARE(power_suspend, power_change_fn);
207EVENTHANDLER_DECLARE(power_suspend_early, power_change_fn);
208
209/* Low memory event */
210typedef void (*vm_lowmem_handler_t)(void *, int);
211#define	LOWMEM_PRI_DEFAULT	EVENTHANDLER_PRI_FIRST
212EVENTHANDLER_DECLARE(vm_lowmem, vm_lowmem_handler_t);
213/* Some of mbuf(9) zones reached maximum */
214EVENTHANDLER_DECLARE(mbuf_lowmem, vm_lowmem_handler_t);
215
216/* Root mounted event */
217typedef void (*mountroot_handler_t)(void *);
218EVENTHANDLER_DECLARE(mountroot, mountroot_handler_t);
219
220/* File system mount events */
221struct mount;
222struct vnode;
223struct thread;
224typedef void (*vfs_mounted_notify_fn)(void *, struct mount *, struct vnode *,
225    struct thread *);
226typedef void (*vfs_unmounted_notify_fn)(void *, struct mount *,
227    struct thread *);
228EVENTHANDLER_DECLARE(vfs_mounted, vfs_mounted_notify_fn);
229EVENTHANDLER_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 */
236struct proc;
237struct image_params;
238
239typedef void (*exitlist_fn)(void *, struct proc *);
240typedef void (*forklist_fn)(void *, struct proc *, struct proc *, int);
241typedef void (*execlist_fn)(void *, struct proc *, struct image_params *);
242typedef void (*proc_ctor_fn)(void *, struct proc *);
243typedef void (*proc_dtor_fn)(void *, struct proc *);
244typedef void (*proc_init_fn)(void *, struct proc *);
245typedef void (*proc_fini_fn)(void *, struct proc *);
246EVENTHANDLER_DECLARE(process_ctor, proc_ctor_fn);
247EVENTHANDLER_DECLARE(process_dtor, proc_dtor_fn);
248EVENTHANDLER_DECLARE(process_init, proc_init_fn);
249EVENTHANDLER_DECLARE(process_fini, proc_fini_fn);
250EVENTHANDLER_DECLARE(process_exit, exitlist_fn);
251EVENTHANDLER_DECLARE(process_fork, forklist_fn);
252EVENTHANDLER_DECLARE(process_exec, execlist_fn);
253
254/*
255 * application dump event
256 */
257typedef void (*app_coredump_start_fn)(void *, struct thread *, char *name);
258typedef void (*app_coredump_progress_fn)(void *, struct thread *td, int byte_count);
259typedef void (*app_coredump_finish_fn)(void *, struct thread *td);
260typedef void (*app_coredump_error_fn)(void *, struct thread *td, char *msg, ...);
261
262EVENTHANDLER_DECLARE(app_coredump_start, app_coredump_start_fn);
263EVENTHANDLER_DECLARE(app_coredump_progress, app_coredump_progress_fn);
264EVENTHANDLER_DECLARE(app_coredump_finish, app_coredump_finish_fn);
265EVENTHANDLER_DECLARE(app_coredump_error, app_coredump_error_fn);
266
267typedef void (*thread_ctor_fn)(void *, struct thread *);
268typedef void (*thread_dtor_fn)(void *, struct thread *);
269typedef void (*thread_fini_fn)(void *, struct thread *);
270typedef void (*thread_init_fn)(void *, struct thread *);
271EVENTHANDLER_DECLARE(thread_ctor, thread_ctor_fn);
272EVENTHANDLER_DECLARE(thread_dtor, thread_dtor_fn);
273EVENTHANDLER_DECLARE(thread_init, thread_init_fn);
274EVENTHANDLER_DECLARE(thread_fini, thread_fini_fn);
275
276typedef void (*uma_zone_chfn)(void *);
277EVENTHANDLER_DECLARE(nmbclusters_change, uma_zone_chfn);
278EVENTHANDLER_DECLARE(nmbufs_change, uma_zone_chfn);
279EVENTHANDLER_DECLARE(maxsockets_change, uma_zone_chfn);
280
281/* Kernel linker file load and unload events */
282struct linker_file;
283typedef void (*kld_load_fn)(void *, struct linker_file *);
284typedef void (*kld_unload_fn)(void *, const char *, caddr_t, size_t);
285typedef void (*kld_unload_try_fn)(void *, struct linker_file *, int *);
286EVENTHANDLER_DECLARE(kld_load, kld_load_fn);
287EVENTHANDLER_DECLARE(kld_unload, kld_unload_fn);
288EVENTHANDLER_DECLARE(kld_unload_try, kld_unload_try_fn);
289
290/* Generic graphics framebuffer interface */
291struct fb_info;
292typedef void (*register_framebuffer_fn)(void *, struct fb_info *);
293typedef void (*unregister_framebuffer_fn)(void *, struct fb_info *);
294EVENTHANDLER_DECLARE(register_framebuffer, register_framebuffer_fn);
295EVENTHANDLER_DECLARE(unregister_framebuffer, unregister_framebuffer_fn);
296
297/* Veto ada attachment */
298struct cam_path;
299struct ata_params;
300typedef void (*ada_probe_veto_fn)(void *, struct cam_path *,
301    struct ata_params *, int *);
302EVENTHANDLER_DECLARE(ada_probe_veto, ada_probe_veto_fn);
303
304/* Swap device events */
305struct swdevt;
306typedef void (*swapon_fn)(void *, struct swdevt *);
307typedef void (*swapoff_fn)(void *, struct swdevt *);
308EVENTHANDLER_DECLARE(swapon, swapon_fn);
309EVENTHANDLER_DECLARE(swapoff, swapoff_fn);
310
311/* newbus device events */
312enum 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};
317typedef void (*device_attach_fn)(void *, device_t);
318typedef void (*device_detach_fn)(void *, device_t, enum evhdev_detach);
319typedef void (*device_nomatch_fn)(void *, device_t);
320EVENTHANDLER_DECLARE(device_attach, device_attach_fn);
321EVENTHANDLER_DECLARE(device_detach, device_detach_fn);
322EVENTHANDLER_DECLARE(device_nomatch, device_nomatch_fn);
323
324/* Interface address addition and removal event */
325struct ifaddr;
326typedef void (*rt_addrmsg_fn)(void *, struct ifaddr *, int);
327EVENTHANDLER_DECLARE(rt_addrmsg, rt_addrmsg_fn);
328
329/* Kernel environment variable change event */
330typedef void (*env_change_fn)(void *, const char *);
331EVENTHANDLER_DECLARE(setenv, env_change_fn);
332EVENTHANDLER_DECLARE(unsetenv, env_change_fn);
333
334#endif /* _SYS_EVENTHANDLER_H_ */
335