]> git.proxmox.com Git - mirror_frr.git/blob - lib/thread.h
Merge pull request #10464 from pguibert6WIND/negogiate
[mirror_frr.git] / lib / thread.h
1 /* Thread management routine header.
2 * Copyright (C) 1998 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #ifndef _ZEBRA_THREAD_H
22 #define _ZEBRA_THREAD_H
23
24 #include <zebra.h>
25 #include <pthread.h>
26 #include <poll.h>
27 #include "monotime.h"
28 #include "frratomic.h"
29 #include "typesafe.h"
30 #include "xref.h"
31
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35
36 extern bool cputime_enabled;
37 extern unsigned long cputime_threshold;
38 /* capturing wallclock time is always enabled since it is fast (reading
39 * hardware TSC w/o syscalls)
40 */
41 extern unsigned long walltime_threshold;
42
43 struct rusage_t {
44 #ifdef HAVE_CLOCK_THREAD_CPUTIME_ID
45 struct timespec cpu;
46 #else
47 struct rusage cpu;
48 #endif
49 struct timeval real;
50 };
51 #define RUSAGE_T struct rusage_t
52
53 #define GETRUSAGE(X) thread_getrusage(X)
54
55 PREDECL_LIST(thread_list);
56 PREDECL_HEAP(thread_timer_list);
57
58 struct fd_handler {
59 /* number of pfd that fit in the allocated space of pfds. This is a
60 * constant and is the same for both pfds and copy.
61 */
62 nfds_t pfdsize;
63
64 /* file descriptors to monitor for i/o */
65 struct pollfd *pfds;
66 /* number of pollfds stored in pfds */
67 nfds_t pfdcount;
68
69 /* chunk used for temp copy of pollfds */
70 struct pollfd *copy;
71 /* number of pollfds stored in copy */
72 nfds_t copycount;
73 };
74
75 struct xref_threadsched {
76 struct xref xref;
77
78 const char *funcname;
79 const char *dest;
80 uint32_t thread_type;
81 };
82
83 /* Master of the theads. */
84 struct thread_master {
85 char *name;
86
87 struct thread **read;
88 struct thread **write;
89 struct thread_timer_list_head timer;
90 struct thread_list_head event, ready, unuse;
91 struct list *cancel_req;
92 bool canceled;
93 pthread_cond_t cancel_cond;
94 struct hash *cpu_record;
95 int io_pipe[2];
96 int fd_limit;
97 struct fd_handler handler;
98 unsigned long alloc;
99 long selectpoll_timeout;
100 bool spin;
101 bool handle_signals;
102 pthread_mutex_t mtx;
103 pthread_t owner;
104
105 bool ready_run_loop;
106 RUSAGE_T last_getrusage;
107 };
108
109 /* Thread itself. */
110 struct thread {
111 uint8_t type; /* thread type */
112 uint8_t add_type; /* thread type */
113 struct thread_list_item threaditem;
114 struct thread_timer_list_item timeritem;
115 struct thread **ref; /* external reference (if given) */
116 struct thread_master *master; /* pointer to the struct thread_master */
117 int (*func)(struct thread *); /* event function */
118 void *arg; /* event argument */
119 union {
120 int val; /* second argument of the event. */
121 int fd; /* file descriptor in case of r/w */
122 struct timeval sands; /* rest of time sands value. */
123 } u;
124 struct timeval real;
125 struct cpu_thread_history *hist; /* cache pointer to cpu_history */
126 unsigned long yield; /* yield time in microseconds */
127 const struct xref_threadsched *xref; /* origin location */
128 pthread_mutex_t mtx; /* mutex for thread.c functions */
129 bool ignore_timer_late;
130 };
131
132 #ifdef _FRR_ATTRIBUTE_PRINTFRR
133 #pragma FRR printfrr_ext "%pTH" (struct thread *)
134 #endif
135
136 struct cpu_thread_history {
137 int (*func)(struct thread *);
138 atomic_size_t total_cpu_warn;
139 atomic_size_t total_wall_warn;
140 atomic_size_t total_calls;
141 atomic_size_t total_active;
142 struct time_stats {
143 atomic_size_t total, max;
144 } real;
145 struct time_stats cpu;
146 atomic_uint_fast32_t types;
147 const char *funcname;
148 };
149
150 /* Struct timeval's tv_usec one second value. */
151 #define TIMER_SECOND_MICRO 1000000L
152
153 /* Thread types. */
154 #define THREAD_READ 0
155 #define THREAD_WRITE 1
156 #define THREAD_TIMER 2
157 #define THREAD_EVENT 3
158 #define THREAD_READY 4
159 #define THREAD_UNUSED 5
160 #define THREAD_EXECUTE 6
161
162 /* Thread yield time. */
163 #define THREAD_YIELD_TIME_SLOT 10 * 1000L /* 10ms */
164
165 #define THREAD_TIMER_STRLEN 12
166
167 /* Macros. */
168 #define THREAD_ARG(X) ((X)->arg)
169 #define THREAD_FD(X) ((X)->u.fd)
170 #define THREAD_VAL(X) ((X)->u.val)
171
172 /*
173 * Please consider this macro deprecated, and do not use it in new code.
174 */
175 #define THREAD_OFF(thread) \
176 do { \
177 if ((thread)) \
178 thread_cancel(&(thread)); \
179 } while (0)
180
181 /*
182 * Macro wrappers to generate xrefs for all thread add calls. Includes
183 * file/line/function info for debugging/tracing.
184 */
185 #include "lib/xref.h"
186
187 #define _xref_t_a(addfn, type, m, f, a, v, t) \
188 ({ \
189 static const struct xref_threadsched _xref \
190 __attribute__((used)) = { \
191 .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
192 .funcname = #f, \
193 .dest = #t, \
194 .thread_type = THREAD_ ## type, \
195 }; \
196 XREF_LINK(_xref.xref); \
197 _thread_add_ ## addfn(&_xref, m, f, a, v, t); \
198 }) \
199 /* end */
200
201 #define thread_add_read(m,f,a,v,t) _xref_t_a(read_write, READ, m,f,a,v,t)
202 #define thread_add_write(m,f,a,v,t) _xref_t_a(read_write, WRITE, m,f,a,v,t)
203 #define thread_add_timer(m,f,a,v,t) _xref_t_a(timer, TIMER, m,f,a,v,t)
204 #define thread_add_timer_msec(m,f,a,v,t) _xref_t_a(timer_msec, TIMER, m,f,a,v,t)
205 #define thread_add_timer_tv(m,f,a,v,t) _xref_t_a(timer_tv, TIMER, m,f,a,v,t)
206 #define thread_add_event(m,f,a,v,t) _xref_t_a(event, EVENT, m,f,a,v,t)
207
208 #define thread_execute(m,f,a,v) \
209 ({ \
210 static const struct xref_threadsched _xref \
211 __attribute__((used)) = { \
212 .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
213 .funcname = #f, \
214 .dest = NULL, \
215 .thread_type = THREAD_EXECUTE, \
216 }; \
217 XREF_LINK(_xref.xref); \
218 _thread_execute(&_xref, m, f, a, v); \
219 }) /* end */
220
221 /* Prototypes. */
222 extern struct thread_master *thread_master_create(const char *);
223 void thread_master_set_name(struct thread_master *master, const char *name);
224 extern void thread_master_free(struct thread_master *);
225 extern void thread_master_free_unused(struct thread_master *);
226
227 extern void _thread_add_read_write(const struct xref_threadsched *xref,
228 struct thread_master *master,
229 int (*fn)(struct thread *), void *arg,
230 int fd, struct thread **tref);
231
232 extern void _thread_add_timer(const struct xref_threadsched *xref,
233 struct thread_master *master,
234 int (*fn)(struct thread *), void *arg, long t,
235 struct thread **tref);
236
237 extern void _thread_add_timer_msec(const struct xref_threadsched *xref,
238 struct thread_master *master,
239 int (*fn)(struct thread *), void *arg,
240 long t, struct thread **tref);
241
242 extern void _thread_add_timer_tv(const struct xref_threadsched *xref,
243 struct thread_master *master,
244 int (*fn)(struct thread *), void *arg,
245 struct timeval *tv, struct thread **tref);
246
247 extern void _thread_add_event(const struct xref_threadsched *xref,
248 struct thread_master *master,
249 int (*fn)(struct thread *), void *arg, int val,
250 struct thread **tref);
251
252 extern void _thread_execute(const struct xref_threadsched *xref,
253 struct thread_master *master,
254 int (*fn)(struct thread *), void *arg, int val);
255
256 extern void thread_cancel(struct thread **event);
257 extern void thread_cancel_async(struct thread_master *, struct thread **,
258 void *);
259 /* Cancel ready tasks with an arg matching 'arg' */
260 extern void thread_cancel_event_ready(struct thread_master *m, void *arg);
261 /* Cancel all tasks with an arg matching 'arg', including timers and io */
262 extern void thread_cancel_event(struct thread_master *m, void *arg);
263 extern struct thread *thread_fetch(struct thread_master *, struct thread *);
264 extern void thread_call(struct thread *);
265 extern unsigned long thread_timer_remain_second(struct thread *);
266 extern struct timeval thread_timer_remain(struct thread *);
267 extern unsigned long thread_timer_remain_msec(struct thread *);
268 extern int thread_should_yield(struct thread *);
269 /* set yield time for thread */
270 extern void thread_set_yield_time(struct thread *, unsigned long);
271
272 /* Internal libfrr exports */
273 extern void thread_getrusage(RUSAGE_T *);
274 extern void thread_cmd_init(void);
275
276 /* Returns elapsed real (wall clock) time. */
277 extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before,
278 unsigned long *cpu_time_elapsed);
279
280 /* only for use in logging functions! */
281 extern pthread_key_t thread_current;
282 extern char *thread_timer_to_hhmmss(char *buf, int buf_size,
283 struct thread *t_timer);
284
285 extern bool thread_is_scheduled(struct thread *thread);
286 /* Debug signal mask */
287 void debug_signals(const sigset_t *sigs);
288
289 static inline void thread_ignore_late_timer(struct thread *thread)
290 {
291 thread->ignore_timer_late = true;
292 }
293
294 #ifdef __cplusplus
295 }
296 #endif
297
298 #endif /* _ZEBRA_THREAD_H */