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