]> git.proxmox.com Git - mirror_frr.git/blob - lib/thread.h
Merge pull request #8078 from idryzhov/fix-zebra-vni
[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 struct rusage_t {
37 struct rusage cpu;
38 struct timeval real;
39 };
40 #define RUSAGE_T struct rusage_t
41
42 #define GETRUSAGE(X) thread_getrusage(X)
43
44 PREDECL_LIST(thread_list);
45 PREDECL_HEAP(thread_timer_list);
46
47 struct fd_handler {
48 /* number of pfd that fit in the allocated space of pfds. This is a
49 * constant and is the same for both pfds and copy.
50 */
51 nfds_t pfdsize;
52
53 /* file descriptors to monitor for i/o */
54 struct pollfd *pfds;
55 /* number of pollfds stored in pfds */
56 nfds_t pfdcount;
57
58 /* chunk used for temp copy of pollfds */
59 struct pollfd *copy;
60 /* number of pollfds stored in copy */
61 nfds_t copycount;
62 };
63
64 struct xref_threadsched {
65 struct xref xref;
66
67 const char *funcname;
68 const char *dest;
69 uint32_t thread_type;
70 };
71
72 /* Master of the theads. */
73 struct thread_master {
74 char *name;
75
76 struct thread **read;
77 struct thread **write;
78 struct thread_timer_list_head timer;
79 struct thread_list_head event, ready, unuse;
80 struct list *cancel_req;
81 bool canceled;
82 pthread_cond_t cancel_cond;
83 struct hash *cpu_record;
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 bool ready_run_loop;
95 RUSAGE_T last_getrusage;
96 };
97
98 /* Thread itself. */
99 struct thread {
100 uint8_t type; /* thread type */
101 uint8_t add_type; /* thread type */
102 struct thread_list_item threaditem;
103 struct thread_timer_list_item timeritem;
104 struct thread **ref; /* external reference (if given) */
105 struct thread_master *master; /* pointer to the struct thread_master */
106 int (*func)(struct thread *); /* event function */
107 void *arg; /* event argument */
108 union {
109 int val; /* second argument of the event. */
110 int fd; /* file descriptor in case of r/w */
111 struct timeval sands; /* rest of time sands value. */
112 } u;
113 struct timeval real;
114 struct cpu_thread_history *hist; /* cache pointer to cpu_history */
115 unsigned long yield; /* yield time in microseconds */
116 const struct xref_threadsched *xref; /* origin location */
117 pthread_mutex_t mtx; /* mutex for thread.c functions */
118 };
119
120 struct cpu_thread_history {
121 int (*func)(struct thread *);
122 atomic_size_t total_calls;
123 atomic_size_t total_active;
124 struct time_stats {
125 atomic_size_t total, max;
126 } real;
127 struct time_stats cpu;
128 atomic_uint_fast32_t types;
129 const char *funcname;
130 };
131
132 /* Struct timeval's tv_usec one second value. */
133 #define TIMER_SECOND_MICRO 1000000L
134
135 /* Thread types. */
136 #define THREAD_READ 0
137 #define THREAD_WRITE 1
138 #define THREAD_TIMER 2
139 #define THREAD_EVENT 3
140 #define THREAD_READY 4
141 #define THREAD_UNUSED 5
142 #define THREAD_EXECUTE 6
143
144 /* Thread yield time. */
145 #define THREAD_YIELD_TIME_SLOT 10 * 1000L /* 10ms */
146
147 #define THREAD_TIMER_STRLEN 12
148
149 /* Macros. */
150 #define THREAD_ARG(X) ((X)->arg)
151 #define THREAD_FD(X) ((X)->u.fd)
152 #define THREAD_VAL(X) ((X)->u.val)
153
154 /*
155 * Please consider this macro deprecated, and do not use it in new code.
156 */
157 #define THREAD_OFF(thread) \
158 do { \
159 if ((thread)) \
160 thread_cancel(&(thread)); \
161 } while (0)
162
163 /*
164 * Macro wrappers to generate xrefs for all thread add calls. Includes
165 * file/line/function info for debugging/tracing.
166 */
167 #include "lib/xref.h"
168
169 #define _xref_t_a(addfn, type, m, f, a, v, t) \
170 ({ \
171 static const struct xref_threadsched _xref \
172 __attribute__((used)) = { \
173 .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
174 .funcname = #f, \
175 .dest = #t, \
176 .thread_type = THREAD_ ## type, \
177 }; \
178 XREF_LINK(_xref.xref); \
179 _thread_add_ ## addfn(&_xref, m, f, a, v, t); \
180 }) \
181 /* end */
182
183 #define thread_add_read(m,f,a,v,t) _xref_t_a(read_write, READ, m,f,a,v,t)
184 #define thread_add_write(m,f,a,v,t) _xref_t_a(read_write, WRITE, m,f,a,v,t)
185 #define thread_add_timer(m,f,a,v,t) _xref_t_a(timer, TIMER, m,f,a,v,t)
186 #define thread_add_timer_msec(m,f,a,v,t) _xref_t_a(timer_msec, TIMER, m,f,a,v,t)
187 #define thread_add_timer_tv(m,f,a,v,t) _xref_t_a(timer_tv, TIMER, m,f,a,v,t)
188 #define thread_add_event(m,f,a,v,t) _xref_t_a(event, EVENT, m,f,a,v,t)
189
190 #define thread_execute(m,f,a,v) \
191 ({ \
192 static const struct xref_threadsched _xref \
193 __attribute__((used)) = { \
194 .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
195 .funcname = #f, \
196 .dest = NULL, \
197 .thread_type = THREAD_EXECUTE, \
198 }; \
199 XREF_LINK(_xref.xref); \
200 _thread_execute(&_xref, m, f, a, v); \
201 }) /* end */
202
203 /* Prototypes. */
204 extern struct thread_master *thread_master_create(const char *);
205 void thread_master_set_name(struct thread_master *master, const char *name);
206 extern void thread_master_free(struct thread_master *);
207 extern void thread_master_free_unused(struct thread_master *);
208
209 extern struct thread *_thread_add_read_write(
210 const struct xref_threadsched *xref, struct thread_master *master,
211 int (*fn)(struct thread *), void *arg, int fd, struct thread **tref);
212
213 extern struct thread *_thread_add_timer(
214 const struct xref_threadsched *xref, struct thread_master *master,
215 int (*fn)(struct thread *), void *arg, long t, struct thread **tref);
216
217 extern struct thread *_thread_add_timer_msec(
218 const struct xref_threadsched *xref, struct thread_master *master,
219 int (*fn)(struct thread *), void *arg, long t, struct thread **tref);
220
221 extern struct thread *_thread_add_timer_tv(
222 const struct xref_threadsched *xref, struct thread_master *master,
223 int (*fn)(struct thread *), void *arg, struct timeval *tv,
224 struct thread **tref);
225
226 extern struct thread *_thread_add_event(
227 const struct xref_threadsched *xref, struct thread_master *master,
228 int (*fn)(struct thread *), void *arg, int val, struct thread **tref);
229
230 extern void _thread_execute(const struct xref_threadsched *xref,
231 struct thread_master *master,
232 int (*fn)(struct thread *), void *arg, int val);
233
234 extern void thread_cancel(struct thread **event);
235 extern void thread_cancel_async(struct thread_master *, struct thread **,
236 void *);
237 /* Cancel ready tasks with an arg matching 'arg' */
238 extern void thread_cancel_event_ready(struct thread_master *m, void *arg);
239 /* Cancel all tasks with an arg matching 'arg', including timers and io */
240 extern void thread_cancel_event(struct thread_master *m, void *arg);
241 extern struct thread *thread_fetch(struct thread_master *, struct thread *);
242 extern void thread_call(struct thread *);
243 extern unsigned long thread_timer_remain_second(struct thread *);
244 extern struct timeval thread_timer_remain(struct thread *);
245 extern unsigned long thread_timer_remain_msec(struct thread *);
246 extern int thread_should_yield(struct thread *);
247 /* set yield time for thread */
248 extern void thread_set_yield_time(struct thread *, unsigned long);
249
250 /* Internal libfrr exports */
251 extern void thread_getrusage(RUSAGE_T *);
252 extern void thread_cmd_init(void);
253
254 /* Returns elapsed real (wall clock) time. */
255 extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before,
256 unsigned long *cpu_time_elapsed);
257
258 /* only for use in logging functions! */
259 extern pthread_key_t thread_current;
260 extern char *thread_timer_to_hhmmss(char *buf, int buf_size,
261 struct thread *t_timer);
262
263 /* Debug signal mask */
264 void debug_signals(const sigset_t *sigs);
265
266 #ifdef __cplusplus
267 }
268 #endif
269
270 #endif /* _ZEBRA_THREAD_H */