]> git.proxmox.com Git - mirror_frr.git/blob - lib/event.h
*: Convert `struct event_master` to `struct event_loop`
[mirror_frr.git] / lib / event.h
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Event management routine header.
3 * Copyright (C) 1998 Kunihiro Ishiguro
4 */
5
6 #ifndef _ZEBRA_THREAD_H
7 #define _ZEBRA_THREAD_H
8
9 #include <zebra.h>
10 #include <pthread.h>
11 #include <poll.h>
12 #include "monotime.h"
13 #include "frratomic.h"
14 #include "typesafe.h"
15 #include "xref.h"
16
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20
21 extern bool cputime_enabled;
22 extern unsigned long cputime_threshold;
23 /* capturing wallclock time is always enabled since it is fast (reading
24 * hardware TSC w/o syscalls)
25 */
26 extern unsigned long walltime_threshold;
27
28 struct rusage_t {
29 #ifdef HAVE_CLOCK_THREAD_CPUTIME_ID
30 struct timespec cpu;
31 #else
32 struct rusage cpu;
33 #endif
34 struct timeval real;
35 };
36 #define RUSAGE_T struct rusage_t
37
38 #define GETRUSAGE(X) event_getrusage(X)
39
40 PREDECL_LIST(event_list);
41 PREDECL_HEAP(event_timer_list);
42
43 struct fd_handler {
44 /* number of pfd that fit in the allocated space of pfds. This is a
45 * constant and is the same for both pfds and copy.
46 */
47 nfds_t pfdsize;
48
49 /* file descriptors to monitor for i/o */
50 struct pollfd *pfds;
51 /* number of pollfds stored in pfds */
52 nfds_t pfdcount;
53
54 /* chunk used for temp copy of pollfds */
55 struct pollfd *copy;
56 /* number of pollfds stored in copy */
57 nfds_t copycount;
58 };
59
60 struct xref_eventsched {
61 struct xref xref;
62
63 const char *funcname;
64 const char *dest;
65 uint32_t event_type;
66 };
67
68 /* Master of the theads. */
69 struct event_loop {
70 char *name;
71
72 struct event **read;
73 struct event **write;
74 struct event_timer_list_head timer;
75 struct event_list_head event, ready, unuse;
76 struct list *cancel_req;
77 bool canceled;
78 pthread_cond_t cancel_cond;
79 struct hash *cpu_record;
80 int io_pipe[2];
81 int fd_limit;
82 struct fd_handler handler;
83 unsigned long alloc;
84 long selectpoll_timeout;
85 bool spin;
86 bool handle_signals;
87 pthread_mutex_t mtx;
88 pthread_t owner;
89
90 bool ready_run_loop;
91 RUSAGE_T last_getrusage;
92 };
93
94 /* Event types. */
95 enum event_types {
96 EVENT_READ,
97 EVENT_WRITE,
98 EVENT_TIMER,
99 EVENT_EVENT,
100 EVENT_READY,
101 EVENT_UNUSED,
102 EVENT_EXECUTE,
103 };
104
105 /* Event itself. */
106 struct event {
107 enum event_types type; /* event type */
108 enum event_types add_type; /* event type */
109 struct event_list_item eventitem;
110 struct event_timer_list_item timeritem;
111 struct event **ref; /* external reference (if given) */
112 struct event_loop *master; /* pointer to the struct event_loop */
113 void (*func)(struct event *); /* event function */
114 void *arg; /* event argument */
115 union {
116 int val; /* second argument of the event. */
117 int fd; /* file descriptor in case of r/w */
118 struct timeval sands; /* rest of time sands value. */
119 } u;
120 struct timeval real;
121 struct cpu_event_history *hist; /* cache pointer to cpu_history */
122 unsigned long yield; /* yield time in microseconds */
123 const struct xref_eventsched *xref; /* origin location */
124 pthread_mutex_t mtx; /* mutex for thread.c functions */
125 bool ignore_timer_late;
126 };
127
128 #ifdef _FRR_ATTRIBUTE_PRINTFRR
129 #pragma FRR printfrr_ext "%pTH"(struct event *)
130 #endif
131
132 struct cpu_event_history {
133 void (*func)(struct event *);
134 atomic_size_t total_cpu_warn;
135 atomic_size_t total_wall_warn;
136 atomic_size_t total_starv_warn;
137 atomic_size_t total_calls;
138 atomic_size_t total_active;
139 struct time_stats {
140 atomic_size_t total, max;
141 } real;
142 struct time_stats cpu;
143 atomic_uint_fast32_t types;
144 const char *funcname;
145 };
146
147 /* Struct timeval's tv_usec one second value. */
148 #define TIMER_SECOND_MICRO 1000000L
149
150 /* Event yield time. */
151 #define EVENT_YIELD_TIME_SLOT 10 * 1000L /* 10ms */
152
153 #define EVENT_TIMER_STRLEN 12
154
155 /* Macros. */
156 #define EVENT_ARG(X) ((X)->arg)
157 #define EVENT_FD(X) ((X)->u.fd)
158 #define EVENT_VAL(X) ((X)->u.val)
159
160 /*
161 * Please consider this macro deprecated, and do not use it in new code.
162 */
163 #define EVENT_OFF(thread) \
164 do { \
165 if ((thread)) \
166 event_cancel(&(thread)); \
167 } while (0)
168
169 /*
170 * Macro wrappers to generate xrefs for all thread add calls. Includes
171 * file/line/function info for debugging/tracing.
172 */
173 #include "lib/xref.h"
174
175 #define _xref_t_a(addfn, type, m, f, a, v, t) \
176 ({ \
177 static const struct xref_eventsched _xref __attribute__( \
178 (used)) = { \
179 .xref = XREF_INIT(XREFT_EVENTSCHED, NULL, __func__), \
180 .funcname = #f, \
181 .dest = #t, \
182 .event_type = EVENT_##type, \
183 }; \
184 XREF_LINK(_xref.xref); \
185 _event_add_##addfn(&_xref, m, f, a, v, t); \
186 }) /* end */
187
188 #define event_add_read(m, f, a, v, t) _xref_t_a(read_write, READ, m, f, a, v, t)
189 #define event_add_write(m, f, a, v, t) \
190 _xref_t_a(read_write, WRITE, m, f, a, v, t)
191 #define event_add_timer(m, f, a, v, t) _xref_t_a(timer, TIMER, m, f, a, v, t)
192 #define event_add_timer_msec(m, f, a, v, t) \
193 _xref_t_a(timer_msec, TIMER, m, f, a, v, t)
194 #define event_add_timer_tv(m, f, a, v, t) \
195 _xref_t_a(timer_tv, TIMER, m, f, a, v, t)
196 #define event_add_event(m, f, a, v, t) _xref_t_a(event, EVENT, m, f, a, v, t)
197
198 #define event_execute(m, f, a, v) \
199 ({ \
200 static const struct xref_eventsched _xref __attribute__( \
201 (used)) = { \
202 .xref = XREF_INIT(XREFT_EVENTSCHED, NULL, __func__), \
203 .funcname = #f, \
204 .dest = NULL, \
205 .event_type = EVENT_EXECUTE, \
206 }; \
207 XREF_LINK(_xref.xref); \
208 _event_execute(&_xref, m, f, a, v); \
209 }) /* end */
210
211 /* Prototypes. */
212 extern struct event_loop *event_master_create(const char *name);
213 void event_master_set_name(struct event_loop *master, const char *name);
214 extern void event_master_free(struct event_loop *m);
215 extern void event_master_free_unused(struct event_loop *m);
216
217 extern void _event_add_read_write(const struct xref_eventsched *xref,
218 struct event_loop *master,
219 void (*fn)(struct event *), void *arg, int fd,
220 struct event **tref);
221
222 extern void _event_add_timer(const struct xref_eventsched *xref,
223 struct event_loop *master,
224 void (*fn)(struct event *), void *arg, long t,
225 struct event **tref);
226
227 extern void _event_add_timer_msec(const struct xref_eventsched *xref,
228 struct event_loop *master,
229 void (*fn)(struct event *), void *arg, long t,
230 struct event **tref);
231
232 extern void _event_add_timer_tv(const struct xref_eventsched *xref,
233 struct event_loop *master,
234 void (*fn)(struct event *), void *arg,
235 struct timeval *tv, struct event **tref);
236
237 extern void _event_add_event(const struct xref_eventsched *xref,
238 struct event_loop *master,
239 void (*fn)(struct event *), void *arg, int val,
240 struct event **tref);
241
242 extern void _event_execute(const struct xref_eventsched *xref,
243 struct event_loop *master,
244 void (*fn)(struct event *), void *arg, int val);
245
246 extern void event_cancel(struct event **event);
247 extern void event_cancel_async(struct event_loop *m, struct event **eptr,
248 void *data);
249 /* Cancel ready tasks with an arg matching 'arg' */
250 extern void event_cancel_event_ready(struct event_loop *m, void *arg);
251 /* Cancel all tasks with an arg matching 'arg', including timers and io */
252 extern void event_cancel_event(struct event_loop *m, void *arg);
253 extern struct event *event_fetch(struct event_loop *m, struct event *event);
254 extern void event_call(struct event *event);
255 extern unsigned long event_timer_remain_second(struct event *event);
256 extern struct timeval event_timer_remain(struct event *event);
257 extern unsigned long event_timer_remain_msec(struct event *event);
258 extern int event_should_yield(struct event *event);
259 /* set yield time for thread */
260 extern void event_set_yield_time(struct event *event, unsigned long ytime);
261
262 /* Internal libfrr exports */
263 extern void event_getrusage(RUSAGE_T *r);
264 extern void event_cmd_init(void);
265
266 /* Returns elapsed real (wall clock) time. */
267 extern unsigned long event_consumed_time(RUSAGE_T *after, RUSAGE_T *before,
268 unsigned long *cpu_time_elapsed);
269
270 /* only for use in logging functions! */
271 extern pthread_key_t thread_current;
272 extern char *event_timer_to_hhmmss(char *buf, int buf_size,
273 struct event *t_timer);
274
275 static inline bool event_is_scheduled(struct event *thread)
276 {
277 if (thread)
278 return true;
279
280 return false;
281 }
282
283 /* Debug signal mask */
284 void debug_signals(const sigset_t *sigs);
285
286 static inline void event_ignore_late_timer(struct event *event)
287 {
288 event->ignore_timer_late = true;
289 }
290
291 #ifdef __cplusplus
292 }
293 #endif
294
295 #endif /* _ZEBRA_THREAD_H */