eventhandler.h revision 307253
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: stable/10/sys/sys/eventhandler.h 307253 2016-10-14 03:11:31Z sephe $
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
37struct 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
45struct 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
52struct 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
62typedef 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)				\
108struct eventhandler_entry_ ## name 					\
109{									\
110	struct eventhandler_entry	ee;				\
111	type				eh_func;			\
112};									\
113struct __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, ...)					\
127do {									\
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) 				\
138do {									\
139	struct eventhandler_list *_el;					\
140									\
141	if ((_el = eventhandler_find_list(#name)) != NULL)		\
142		eventhandler_deregister(_el, tag);			\
143} while(0)
144
145
146eventhandler_tag eventhandler_register(struct eventhandler_list *list,
147	    const char *name, void *func, void *arg, int priority);
148void	eventhandler_deregister(struct eventhandler_list *list,
149	    eventhandler_tag tag);
150struct eventhandler_list *eventhandler_find_list(const char *name);
151void	eventhandler_prune_list(struct eventhandler_list *list);
152
153#ifdef VIMAGE
154typedef	void (*vimage_iterator_func_t)(void *, ...);
155
156eventhandler_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 */
171typedef 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
177EVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn);	/* before fs sync */
178EVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn);	/* after fs sync */
179EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn);
180
181/* Power state change events */
182typedef void (*power_change_fn)(void *);
183EVENTHANDLER_DECLARE(power_resume, power_change_fn);
184EVENTHANDLER_DECLARE(power_suspend, power_change_fn);
185EVENTHANDLER_DECLARE(power_suspend_early, power_change_fn);
186
187/* Low memory event */
188typedef void (*vm_lowmem_handler_t)(void *, int);
189#define	LOWMEM_PRI_DEFAULT	EVENTHANDLER_PRI_FIRST
190EVENTHANDLER_DECLARE(vm_lowmem, vm_lowmem_handler_t);
191
192/* Root mounted event */
193typedef void (*mountroot_handler_t)(void *);
194EVENTHANDLER_DECLARE(mountroot, mountroot_handler_t);
195
196/* File system mount events */
197struct mount;
198struct vnode;
199struct thread;
200typedef void (*vfs_mounted_notify_fn)(void *, struct mount *, struct vnode *,
201    struct thread *);
202typedef void (*vfs_unmounted_notify_fn)(void *, struct mount *,
203    struct thread *);
204EVENTHANDLER_DECLARE(vfs_mounted, vfs_mounted_notify_fn);
205EVENTHANDLER_DECLARE(vfs_unmounted, vfs_unmounted_notify_fn);
206
207/* VLAN state change events */
208struct ifnet;
209typedef void (*vlan_config_fn)(void *, struct ifnet *, uint16_t);
210typedef void (*vlan_unconfig_fn)(void *, struct ifnet *, uint16_t);
211EVENTHANDLER_DECLARE(vlan_config, vlan_config_fn);
212EVENTHANDLER_DECLARE(vlan_unconfig, vlan_unconfig_fn);
213
214/* BPF attach/detach events */
215struct ifnet;
216typedef void (*bpf_track_fn)(void *, struct ifnet *, int /* dlt */,
217    int /* 1 =>'s attach */);
218EVENTHANDLER_DECLARE(bpf_track, bpf_track_fn);
219
220/*
221 * Process events
222 * process_fork and exit handlers are called without Giant.
223 * exec handlers are called with Giant, but that is by accident.
224 */
225struct proc;
226struct image_params;
227
228typedef void (*exitlist_fn)(void *, struct proc *);
229typedef void (*forklist_fn)(void *, struct proc *, struct proc *, int);
230typedef void (*execlist_fn)(void *, struct proc *, struct image_params *);
231typedef void (*proc_ctor_fn)(void *, struct proc *);
232typedef void (*proc_dtor_fn)(void *, struct proc *);
233typedef void (*proc_init_fn)(void *, struct proc *);
234typedef void (*proc_fini_fn)(void *, struct proc *);
235EVENTHANDLER_DECLARE(process_ctor, proc_ctor_fn);
236EVENTHANDLER_DECLARE(process_dtor, proc_dtor_fn);
237EVENTHANDLER_DECLARE(process_init, proc_init_fn);
238EVENTHANDLER_DECLARE(process_fini, proc_fini_fn);
239EVENTHANDLER_DECLARE(process_exit, exitlist_fn);
240EVENTHANDLER_DECLARE(process_fork, forklist_fn);
241EVENTHANDLER_DECLARE(process_exec, execlist_fn);
242
243/*
244 * application dump event
245 */
246typedef void (*app_coredump_start_fn)(void *, struct thread *, char *name);
247typedef void (*app_coredump_progress_fn)(void *, struct thread *td, int byte_count);
248typedef void (*app_coredump_finish_fn)(void *, struct thread *td);
249typedef void (*app_coredump_error_fn)(void *, struct thread *td, char *msg, ...);
250
251EVENTHANDLER_DECLARE(app_coredump_start, app_coredump_start_fn);
252EVENTHANDLER_DECLARE(app_coredump_progress, app_coredump_progress_fn);
253EVENTHANDLER_DECLARE(app_coredump_finish, app_coredump_finish_fn);
254EVENTHANDLER_DECLARE(app_coredump_error, app_coredump_error_fn);
255
256typedef void (*thread_ctor_fn)(void *, struct thread *);
257typedef void (*thread_dtor_fn)(void *, struct thread *);
258typedef void (*thread_fini_fn)(void *, struct thread *);
259typedef void (*thread_init_fn)(void *, struct thread *);
260EVENTHANDLER_DECLARE(thread_ctor, thread_ctor_fn);
261EVENTHANDLER_DECLARE(thread_dtor, thread_dtor_fn);
262EVENTHANDLER_DECLARE(thread_init, thread_init_fn);
263EVENTHANDLER_DECLARE(thread_fini, thread_fini_fn);
264
265typedef void (*uma_zone_chfn)(void *);
266EVENTHANDLER_DECLARE(nmbclusters_change, uma_zone_chfn);
267EVENTHANDLER_DECLARE(nmbufs_change, uma_zone_chfn);
268EVENTHANDLER_DECLARE(maxsockets_change, uma_zone_chfn);
269
270/* Kernel linker file load and unload events */
271struct linker_file;
272typedef void (*kld_load_fn)(void *, struct linker_file *);
273typedef void (*kld_unload_fn)(void *, const char *, caddr_t, size_t);
274typedef void (*kld_unload_try_fn)(void *, struct linker_file *, int *);
275EVENTHANDLER_DECLARE(kld_load, kld_load_fn);
276EVENTHANDLER_DECLARE(kld_unload, kld_unload_fn);
277EVENTHANDLER_DECLARE(kld_unload_try, kld_unload_try_fn);
278
279/* Generic graphics framebuffer interface */
280struct fb_info;
281typedef void (*register_framebuffer_fn)(void *, struct fb_info *);
282typedef void (*unregister_framebuffer_fn)(void *, struct fb_info *);
283EVENTHANDLER_DECLARE(register_framebuffer, register_framebuffer_fn);
284EVENTHANDLER_DECLARE(unregister_framebuffer, unregister_framebuffer_fn);
285
286/* Veto ada attachment */
287struct cam_path;
288struct ata_params;
289typedef void (*ada_probe_veto_fn)(void *, struct cam_path *,
290    struct ata_params *, int *);
291EVENTHANDLER_DECLARE(ada_probe_veto, ada_probe_veto_fn);
292
293#endif /* SYS_EVENTHANDLER_H */
294