]> git.proxmox.com Git - mirror_frr.git/blob - lib/event.h
*: Convert thread_cancelXXX to event_cancelXXX
[mirror_frr.git] / lib / event.h
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Thread 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) thread_getrusage(X)
39
40 PREDECL_LIST(thread_list);
41 PREDECL_HEAP(thread_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_threadsched {
61 struct xref xref;
62
63 const char *funcname;
64 const char *dest;
65 uint32_t thread_type;
66 };
67
68 /* Master of the theads. */
69 struct thread_master {
70 char *name;
71
72 struct event **read;
73 struct event **write;
74 struct thread_timer_list_head timer;
75 struct thread_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 /* Thread itself. */
95 struct event {
96 uint8_t type; /* thread type */
97 uint8_t add_type; /* thread type */
98 struct thread_list_item threaditem;
99 struct thread_timer_list_item timeritem;
100 struct event **ref; /* external reference (if given) */
101 struct thread_master *master; /* pointer to the struct thread_master */
102 void (*func)(struct event *); /* event function */
103 void *arg; /* event argument */
104 union {
105 int val; /* second argument of the event. */
106 int fd; /* file descriptor in case of r/w */
107 struct timeval sands; /* rest of time sands value. */
108 } u;
109 struct timeval real;
110 struct cpu_thread_history *hist; /* cache pointer to cpu_history */
111 unsigned long yield; /* yield time in microseconds */
112 const struct xref_threadsched *xref; /* origin location */
113 pthread_mutex_t mtx; /* mutex for thread.c functions */
114 bool ignore_timer_late;
115 };
116
117 #ifdef _FRR_ATTRIBUTE_PRINTFRR
118 #pragma FRR printfrr_ext "%pTH"(struct event *)
119 #endif
120
121 struct cpu_thread_history {
122 void (*func)(struct event *);
123 atomic_size_t total_cpu_warn;
124 atomic_size_t total_wall_warn;
125 atomic_size_t total_starv_warn;
126 atomic_size_t total_calls;
127 atomic_size_t total_active;
128 struct time_stats {
129 atomic_size_t total, max;
130 } real;
131 struct time_stats cpu;
132 atomic_uint_fast32_t types;
133 const char *funcname;
134 };
135
136 /* Struct timeval's tv_usec one second value. */
137 #define TIMER_SECOND_MICRO 1000000L
138
139 /* Thread types. */
140 #define THREAD_READ 0
141 #define THREAD_WRITE 1
142 #define THREAD_TIMER 2
143 #define THREAD_EVENT 3
144 #define THREAD_READY 4
145 #define THREAD_UNUSED 5
146 #define THREAD_EXECUTE 6
147
148 /* Thread yield time. */
149 #define THREAD_YIELD_TIME_SLOT 10 * 1000L /* 10ms */
150
151 #define THREAD_TIMER_STRLEN 12
152
153 /* Macros. */
154 #define THREAD_ARG(X) ((X)->arg)
155 #define THREAD_FD(X) ((X)->u.fd)
156 #define THREAD_VAL(X) ((X)->u.val)
157
158 /*
159 * Please consider this macro deprecated, and do not use it in new code.
160 */
161 #define THREAD_OFF(thread) \
162 do { \
163 if ((thread)) \
164 event_cancel(&(thread)); \
165 } while (0)
166
167 /*
168 * Macro wrappers to generate xrefs for all thread add calls. Includes
169 * file/line/function info for debugging/tracing.
170 */
171 #include "lib/xref.h"
172
173 #define _xref_t_a(addfn, type, m, f, a, v, t) \
174 ({ \
175 static const struct xref_threadsched _xref __attribute__( \
176 (used)) = { \
177 .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
178 .funcname = #f, \
179 .dest = #t, \
180 .thread_type = THREAD_##type, \
181 }; \
182 XREF_LINK(_xref.xref); \
183 _event_add_##addfn(&_xref, m, f, a, v, t); \
184 }) /* end */
185
186 #define event_add_read(m, f, a, v, t) _xref_t_a(read_write, READ, m, f, a, v, t)
187 #define event_add_write(m, f, a, v, t) \
188 _xref_t_a(read_write, WRITE, m, f, a, v, t)
189 #define event_add_timer(m, f, a, v, t) _xref_t_a(timer, TIMER, m, f, a, v, t)
190 #define event_add_timer_msec(m, f, a, v, t) \
191 _xref_t_a(timer_msec, TIMER, m, f, a, v, t)
192 #define event_add_timer_tv(m, f, a, v, t) \
193 _xref_t_a(timer_tv, TIMER, m, f, a, v, t)
194 #define event_add_event(m, f, a, v, t) _xref_t_a(event, EVENT, m, f, a, v, t)
195
196 #define thread_execute(m,f,a,v) \
197 ({ \
198 static const struct xref_threadsched _xref \
199 __attribute__((used)) = { \
200 .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
201 .funcname = #f, \
202 .dest = NULL, \
203 .thread_type = THREAD_EXECUTE, \
204 }; \
205 XREF_LINK(_xref.xref); \
206 _thread_execute(&_xref, m, f, a, v); \
207 }) /* end */
208
209 /* Prototypes. */
210 extern struct thread_master *thread_master_create(const char *);
211 void thread_master_set_name(struct thread_master *master, const char *name);
212 extern void thread_master_free(struct thread_master *);
213 extern void thread_master_free_unused(struct thread_master *);
214
215 extern void _event_add_read_write(const struct xref_threadsched *xref,
216 struct thread_master *master,
217 void (*fn)(struct event *), void *arg, int fd,
218 struct event **tref);
219
220 extern void _event_add_timer(const struct xref_threadsched *xref,
221 struct thread_master *master,
222 void (*fn)(struct event *), void *arg, long t,
223 struct event **tref);
224
225 extern void _event_add_timer_msec(const struct xref_threadsched *xref,
226 struct thread_master *master,
227 void (*fn)(struct event *), void *arg, long t,
228 struct event **tref);
229
230 extern void _event_add_timer_tv(const struct xref_threadsched *xref,
231 struct thread_master *master,
232 void (*fn)(struct event *), void *arg,
233 struct timeval *tv, struct event **tref);
234
235 extern void _event_add_event(const struct xref_threadsched *xref,
236 struct thread_master *master,
237 void (*fn)(struct event *), void *arg, int val,
238 struct event **tref);
239
240 extern void _thread_execute(const struct xref_threadsched *xref,
241 struct thread_master *master,
242 void (*fn)(struct event *), void *arg, int val);
243
244 extern void event_cancel(struct event **event);
245 extern void event_cancel_async(struct thread_master *, struct event **, void *);
246 /* Cancel ready tasks with an arg matching 'arg' */
247 extern void event_cancel_event_ready(struct thread_master *m, void *arg);
248 /* Cancel all tasks with an arg matching 'arg', including timers and io */
249 extern void event_cancel_event(struct thread_master *m, void *arg);
250 extern struct event *thread_fetch(struct thread_master *, struct event *event);
251 extern void thread_call(struct event *event);
252 extern unsigned long thread_timer_remain_second(struct event *event);
253 extern struct timeval thread_timer_remain(struct event *event);
254 extern unsigned long thread_timer_remain_msec(struct event *event);
255 extern int thread_should_yield(struct event *event);
256 /* set yield time for thread */
257 extern void thread_set_yield_time(struct event *event, unsigned long);
258
259 /* Internal libfrr exports */
260 extern void thread_getrusage(RUSAGE_T *);
261 extern void thread_cmd_init(void);
262
263 /* Returns elapsed real (wall clock) time. */
264 extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before,
265 unsigned long *cpu_time_elapsed);
266
267 /* only for use in logging functions! */
268 extern pthread_key_t thread_current;
269 extern char *thread_timer_to_hhmmss(char *buf, int buf_size,
270 struct event *t_timer);
271
272 static inline bool thread_is_scheduled(struct event *thread)
273 {
274 if (thread)
275 return true;
276
277 return false;
278 }
279
280 /* Debug signal mask */
281 void debug_signals(const sigset_t *sigs);
282
283 static inline void thread_ignore_late_timer(struct event *event)
284 {
285 event->ignore_timer_late = true;
286 }
287
288 #ifdef __cplusplus
289 }
290 #endif
291
292 #endif /* _ZEBRA_THREAD_H */