1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Thread management routine header.
3 * Copyright (C) 1998 Kunihiro Ishiguro
6 #ifndef _ZEBRA_THREAD_H
7 #define _ZEBRA_THREAD_H
13 #include "frratomic.h"
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)
26 extern unsigned long walltime_threshold
;
29 #ifdef HAVE_CLOCK_THREAD_CPUTIME_ID
36 #define RUSAGE_T struct rusage_t
38 #define GETRUSAGE(X) thread_getrusage(X)
40 PREDECL_LIST(thread_list
);
41 PREDECL_HEAP(thread_timer_list
);
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.
49 /* file descriptors to monitor for i/o */
51 /* number of pollfds stored in pfds */
54 /* chunk used for temp copy of pollfds */
56 /* number of pollfds stored in copy */
60 struct xref_threadsched
{
68 /* Master of the theads. */
69 struct thread_master
{
74 struct thread_timer_list_head timer
;
75 struct thread_list_head event
, ready
, unuse
;
76 struct list
*cancel_req
;
78 pthread_cond_t cancel_cond
;
79 struct hash
*cpu_record
;
82 struct fd_handler handler
;
84 long selectpoll_timeout
;
91 RUSAGE_T last_getrusage
;
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 */
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. */
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
;
117 #ifdef _FRR_ATTRIBUTE_PRINTFRR
118 #pragma FRR printfrr_ext "%pTH"(struct event *)
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
;
129 atomic_size_t total
, max
;
131 struct time_stats cpu
;
132 atomic_uint_fast32_t types
;
133 const char *funcname
;
136 /* Struct timeval's tv_usec one second value. */
137 #define TIMER_SECOND_MICRO 1000000L
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
148 /* Thread yield time. */
149 #define THREAD_YIELD_TIME_SLOT 10 * 1000L /* 10ms */
151 #define THREAD_TIMER_STRLEN 12
154 #define THREAD_ARG(X) ((X)->arg)
155 #define THREAD_FD(X) ((X)->u.fd)
156 #define THREAD_VAL(X) ((X)->u.val)
159 * Please consider this macro deprecated, and do not use it in new code.
161 #define THREAD_OFF(thread) \
164 event_cancel(&(thread)); \
168 * Macro wrappers to generate xrefs for all thread add calls. Includes
169 * file/line/function info for debugging/tracing.
171 #include "lib/xref.h"
173 #define _xref_t_a(addfn, type, m, f, a, v, t) \
175 static const struct xref_threadsched _xref __attribute__( \
177 .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
180 .thread_type = THREAD_##type, \
182 XREF_LINK(_xref.xref); \
183 _event_add_##addfn(&_xref, m, f, a, v, t); \
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)
196 #define thread_execute(m,f,a,v) \
198 static const struct xref_threadsched _xref \
199 __attribute__((used)) = { \
200 .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
203 .thread_type = THREAD_EXECUTE, \
205 XREF_LINK(_xref.xref); \
206 _thread_execute(&_xref, m, f, a, v); \
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
*);
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
);
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
);
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
);
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
);
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
);
240 extern void _thread_execute(const struct xref_threadsched
*xref
,
241 struct thread_master
*master
,
242 void (*fn
)(struct event
*), void *arg
, int val
);
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);
259 /* Internal libfrr exports */
260 extern void thread_getrusage(RUSAGE_T
*);
261 extern void thread_cmd_init(void);
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
);
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
);
272 static inline bool thread_is_scheduled(struct event
*thread
)
280 /* Debug signal mask */
281 void debug_signals(const sigset_t
*sigs
);
283 static inline void thread_ignore_late_timer(struct event
*event
)
285 event
->ignore_timer_late
= true;
292 #endif /* _ZEBRA_THREAD_H */