]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/sys/eventhandler.h
Make m_length() and m_fixhdr() return unsigned.
[FreeBSD/FreeBSD.git] / sys / sys / eventhandler.h
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/sx.h>
34 #include <sys/queue.h>
35
36 struct eventhandler_entry {
37         TAILQ_ENTRY(eventhandler_entry) ee_link;
38         int                             ee_priority;
39         void                            *ee_arg;
40 };
41
42 struct eventhandler_list {
43         char                            *el_name;
44         int                             el_flags;
45 #define EHE_INITTED     (1<<0)
46         struct sx                       el_lock;
47         TAILQ_ENTRY(eventhandler_list)  el_link;
48         TAILQ_HEAD(,eventhandler_entry) el_entries;
49 };
50
51 typedef struct eventhandler_entry       *eventhandler_tag;
52
53 #define EHE_LOCK(p)     sx_xlock(&(p)->el_lock)
54 #define EHE_UNLOCK(p)   sx_xunlock(&(p)->el_lock)
55
56 /* 
57  * Fast handler lists require the eventhandler list be present
58  * at link time.  They don't allow addition of entries to
59  * unknown eventhandler lists, ie. each list must have an 
60  * "owner".
61  *
62  * Fast handler lists must be defined once by the owner 
63  * of the eventhandler list, and the declaration must be in 
64  * scope at any point the list is manipulated.
65  */
66 #define EVENTHANDLER_FAST_DECLARE(name, type)                           \
67 extern struct eventhandler_list Xeventhandler_list_ ## name ;           \
68 struct eventhandler_entry_ ## name {                                    \
69         struct eventhandler_entry       ee;                             \
70         type            eh_func;                                        \
71 };                                                                      \
72 struct __hack
73
74 #define EVENTHANDLER_FAST_DEFINE(name, type)                            \
75 struct eventhandler_list Xeventhandler_list_ ## name = { #name };       \
76 struct __hack
77
78 #define EVENTHANDLER_FAST_INVOKE(name, ...)                             \
79 do {                                                                    \
80         struct eventhandler_list *_el = &Xeventhandler_list_ ## name ;  \
81         struct eventhandler_entry *_ep, *_en;                           \
82         struct eventhandler_entry_ ## name *_t;                         \
83                                                                         \
84         if (_el->el_flags & EHE_INITTED) {                              \
85                 EHE_LOCK(_el);                                          \
86                 _ep = TAILQ_FIRST(&(_el->el_entries));                  \
87                 while (_ep != NULL) {                                   \
88                         _en = TAILQ_NEXT(_ep, ee_link);                 \
89                         _t = (struct eventhandler_entry_ ## name *)_ep; \
90                         _t->eh_func(_ep->ee_arg , __VA_ARGS__);         \
91                         _ep = _en;                                      \
92                 }                                                       \
93                 EHE_UNLOCK(_el);                                        \
94         }                                                               \
95 } while (0)
96
97 #define EVENTHANDLER_FAST_REGISTER(name, func, arg, priority)           \
98         eventhandler_register(&Xeventhandler_list_ ## name,             \
99         #name, func, arg, priority)
100
101 #define EVENTHANDLER_FAST_DEREGISTER(name, tag)                         \
102         eventhandler_deregister(&Xeventhandler_list_ ## name, tag)
103
104 /*
105  * Slow handlers are entirely dynamic; lists are created
106  * when entries are added to them, and thus have no concept of "owner",
107  *
108  * Slow handlers need to be declared, but do not need to be defined. The
109  * declaration must be in scope wherever the handler is to be invoked.
110  */
111 #define EVENTHANDLER_DECLARE(name, type)                                \
112 struct eventhandler_entry_ ## name                                      \
113 {                                                                       \
114         struct eventhandler_entry       ee;                             \
115         type                            eh_func;                        \
116 };                                                                      \
117 struct __hack
118
119 #define EVENTHANDLER_INVOKE(name, ...)                                  \
120 do {                                                                    \
121         struct eventhandler_list *_el;                                  \
122         struct eventhandler_entry *_ep, *_en;                           \
123         struct eventhandler_entry_ ## name *_t;                         \
124                                                                         \
125         if (((_el = eventhandler_find_list(#name)) != NULL) &&          \
126                 (_el->el_flags & EHE_INITTED)) {                        \
127                 EHE_LOCK(_el);                                          \
128                 _ep = TAILQ_FIRST(&(_el->el_entries));                  \
129                 while (_ep != NULL) {                                   \
130                         _en = TAILQ_NEXT(_ep, ee_link);                 \
131                         _t = (struct eventhandler_entry_ ## name *)_ep; \
132                         _t->eh_func(_ep->ee_arg , __VA_ARGS__);         \
133                         _ep = _en;                                      \
134                 }                                                       \
135                 EHE_UNLOCK(_el);                                        \
136         }                                                               \
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
151 extern eventhandler_tag eventhandler_register(struct eventhandler_list *list, 
152                                               char *name,
153                                               void *func, 
154                                               void *arg, 
155                                               int priority);
156 extern void             eventhandler_deregister(struct eventhandler_list *list,
157                                                 eventhandler_tag tag);
158 extern struct eventhandler_list *eventhandler_find_list(char *name);
159
160 /*
161  * Standard system event queues.
162  */
163
164 /* Shutdown events */
165 typedef void (*shutdown_fn)(void *, int);
166
167 #define SHUTDOWN_PRI_FIRST      0
168 #define SHUTDOWN_PRI_DEFAULT    10000
169 #define SHUTDOWN_PRI_LAST       20000
170
171 EVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn);   /* before fs sync */
172 EVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn);  /* after fs sync */
173 EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn);
174
175 /* Idle process event */
176 typedef void (*idle_eventhandler_t)(void *, int);
177
178 #define IDLE_PRI_FIRST          10000
179 #define IDLE_PRI_LAST           20000
180 EVENTHANDLER_FAST_DECLARE(idle_event, idle_eventhandler_t);
181
182
183 #endif /* SYS_EVENTHANDLER_H */