1 /* Thread management routine header.
2 * Copyright (C) 1998 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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
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.
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
21 #ifndef _ZEBRA_THREAD_H
22 #define _ZEBRA_THREAD_H
28 #include "frratomic.h"
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)
41 extern unsigned long walltime_threshold
;
44 #ifdef HAVE_CLOCK_THREAD_CPUTIME_ID
51 #define RUSAGE_T struct rusage_t
53 #define GETRUSAGE(X) thread_getrusage(X)
55 PREDECL_LIST(thread_list
);
56 PREDECL_HEAP(thread_timer_list
);
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.
64 /* file descriptors to monitor for i/o */
66 /* number of pollfds stored in pfds */
69 /* chunk used for temp copy of pollfds */
71 /* number of pollfds stored in copy */
75 struct xref_threadsched
{
83 /* Master of the theads. */
84 struct thread_master
{
88 struct thread
**write
;
89 struct thread_timer_list_head timer
;
90 struct thread_list_head event
, ready
, unuse
;
91 struct list
*cancel_req
;
93 pthread_cond_t cancel_cond
;
94 struct hash
*cpu_record
;
97 struct fd_handler handler
;
99 long selectpoll_timeout
;
106 RUSAGE_T last_getrusage
;
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 void (*func
)(struct thread
*); /* event function */
118 void *arg
; /* event argument */
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. */
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
;
132 #ifdef _FRR_ATTRIBUTE_PRINTFRR
133 #pragma FRR printfrr_ext "%pTH" (struct thread *)
136 struct cpu_thread_history
{
137 void (*func
)(struct thread
*);
138 atomic_size_t total_cpu_warn
;
139 atomic_size_t total_wall_warn
;
140 atomic_size_t total_starv_warn
;
141 atomic_size_t total_calls
;
142 atomic_size_t total_active
;
144 atomic_size_t total
, max
;
146 struct time_stats cpu
;
147 atomic_uint_fast32_t types
;
148 const char *funcname
;
151 /* Struct timeval's tv_usec one second value. */
152 #define TIMER_SECOND_MICRO 1000000L
155 #define THREAD_READ 0
156 #define THREAD_WRITE 1
157 #define THREAD_TIMER 2
158 #define THREAD_EVENT 3
159 #define THREAD_READY 4
160 #define THREAD_UNUSED 5
161 #define THREAD_EXECUTE 6
163 /* Thread yield time. */
164 #define THREAD_YIELD_TIME_SLOT 10 * 1000L /* 10ms */
166 #define THREAD_TIMER_STRLEN 12
169 #define THREAD_ARG(X) ((X)->arg)
170 #define THREAD_FD(X) ((X)->u.fd)
171 #define THREAD_VAL(X) ((X)->u.val)
174 * Please consider this macro deprecated, and do not use it in new code.
176 #define THREAD_OFF(thread) \
179 thread_cancel(&(thread)); \
183 * Macro wrappers to generate xrefs for all thread add calls. Includes
184 * file/line/function info for debugging/tracing.
186 #include "lib/xref.h"
188 #define _xref_t_a(addfn, type, m, f, a, v, t) \
190 static const struct xref_threadsched _xref \
191 __attribute__((used)) = { \
192 .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
195 .thread_type = THREAD_ ## type, \
197 XREF_LINK(_xref.xref); \
198 _thread_add_ ## addfn(&_xref, m, f, a, v, t); \
202 #define thread_add_read(m,f,a,v,t) _xref_t_a(read_write, READ, m,f,a,v,t)
203 #define thread_add_write(m,f,a,v,t) _xref_t_a(read_write, WRITE, m,f,a,v,t)
204 #define thread_add_timer(m,f,a,v,t) _xref_t_a(timer, TIMER, m,f,a,v,t)
205 #define thread_add_timer_msec(m,f,a,v,t) _xref_t_a(timer_msec, TIMER, m,f,a,v,t)
206 #define thread_add_timer_tv(m,f,a,v,t) _xref_t_a(timer_tv, TIMER, m,f,a,v,t)
207 #define thread_add_event(m,f,a,v,t) _xref_t_a(event, EVENT, m,f,a,v,t)
209 #define thread_execute(m,f,a,v) \
211 static const struct xref_threadsched _xref \
212 __attribute__((used)) = { \
213 .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
216 .thread_type = THREAD_EXECUTE, \
218 XREF_LINK(_xref.xref); \
219 _thread_execute(&_xref, m, f, a, v); \
223 extern struct thread_master
*thread_master_create(const char *);
224 void thread_master_set_name(struct thread_master
*master
, const char *name
);
225 extern void thread_master_free(struct thread_master
*);
226 extern void thread_master_free_unused(struct thread_master
*);
228 extern void _thread_add_read_write(const struct xref_threadsched
*xref
,
229 struct thread_master
*master
,
230 void (*fn
)(struct thread
*), void *arg
,
231 int fd
, struct thread
**tref
);
233 extern void _thread_add_timer(const struct xref_threadsched
*xref
,
234 struct thread_master
*master
,
235 void (*fn
)(struct thread
*), void *arg
, long t
,
236 struct thread
**tref
);
238 extern void _thread_add_timer_msec(const struct xref_threadsched
*xref
,
239 struct thread_master
*master
,
240 void (*fn
)(struct thread
*), void *arg
,
241 long t
, struct thread
**tref
);
243 extern void _thread_add_timer_tv(const struct xref_threadsched
*xref
,
244 struct thread_master
*master
,
245 void (*fn
)(struct thread
*), void *arg
,
246 struct timeval
*tv
, struct thread
**tref
);
248 extern void _thread_add_event(const struct xref_threadsched
*xref
,
249 struct thread_master
*master
,
250 void (*fn
)(struct thread
*), void *arg
, int val
,
251 struct thread
**tref
);
253 extern void _thread_execute(const struct xref_threadsched
*xref
,
254 struct thread_master
*master
,
255 void (*fn
)(struct thread
*), void *arg
, int val
);
257 extern void thread_cancel(struct thread
**event
);
258 extern void thread_cancel_async(struct thread_master
*, struct thread
**,
260 /* Cancel ready tasks with an arg matching 'arg' */
261 extern void thread_cancel_event_ready(struct thread_master
*m
, void *arg
);
262 /* Cancel all tasks with an arg matching 'arg', including timers and io */
263 extern void thread_cancel_event(struct thread_master
*m
, void *arg
);
264 extern struct thread
*thread_fetch(struct thread_master
*, struct thread
*);
265 extern void thread_call(struct thread
*);
266 extern unsigned long thread_timer_remain_second(struct thread
*);
267 extern struct timeval
thread_timer_remain(struct thread
*);
268 extern unsigned long thread_timer_remain_msec(struct thread
*);
269 extern int thread_should_yield(struct thread
*);
270 /* set yield time for thread */
271 extern void thread_set_yield_time(struct thread
*, unsigned long);
273 /* Internal libfrr exports */
274 extern void thread_getrusage(RUSAGE_T
*);
275 extern void thread_cmd_init(void);
277 /* Returns elapsed real (wall clock) time. */
278 extern unsigned long thread_consumed_time(RUSAGE_T
*after
, RUSAGE_T
*before
,
279 unsigned long *cpu_time_elapsed
);
281 /* only for use in logging functions! */
282 extern pthread_key_t thread_current
;
283 extern char *thread_timer_to_hhmmss(char *buf
, int buf_size
,
284 struct thread
*t_timer
);
286 extern bool thread_is_scheduled(struct thread
*thread
);
287 /* Debug signal mask */
288 void debug_signals(const sigset_t
*sigs
);
290 static inline void thread_ignore_late_timer(struct thread
*thread
)
292 thread
->ignore_timer_late
= true;
299 #endif /* _ZEBRA_THREAD_H */