1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Event 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) event_getrusage(X)
40 PREDECL_LIST(event_list
);
41 PREDECL_HEAP(event_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_eventsched
{
68 /* Master of the theads. */
74 struct event_timer_list_head timer
;
75 struct event_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
;
107 enum event_types type
; /* event type */
108 enum event_types add_type
; /* event type */
109 struct event_list_item eventitem
;
110 struct event_timer_list_item timeritem
;
111 struct event
**ref
; /* external reference (if given) */
112 struct event_loop
*master
; /* pointer to the struct event_loop */
113 void (*func
)(struct event
*); /* event function */
114 void *arg
; /* event argument */
116 int val
; /* second argument of the event. */
117 int fd
; /* file descriptor in case of r/w */
118 struct timeval sands
; /* rest of time sands value. */
121 struct cpu_event_history
*hist
; /* cache pointer to cpu_history */
122 unsigned long yield
; /* yield time in microseconds */
123 const struct xref_eventsched
*xref
; /* origin location */
124 pthread_mutex_t mtx
; /* mutex for thread.c functions */
125 bool ignore_timer_late
;
128 #ifdef _FRR_ATTRIBUTE_PRINTFRR
129 #pragma FRR printfrr_ext "%pTH"(struct event *)
132 struct cpu_event_history
{
133 void (*func
)(struct event
*);
134 atomic_size_t total_cpu_warn
;
135 atomic_size_t total_wall_warn
;
136 atomic_size_t total_starv_warn
;
137 atomic_size_t total_calls
;
138 atomic_size_t total_active
;
140 atomic_size_t total
, max
;
142 struct time_stats cpu
;
143 atomic_uint_fast32_t types
;
144 const char *funcname
;
147 /* Struct timeval's tv_usec one second value. */
148 #define TIMER_SECOND_MICRO 1000000L
150 /* Event yield time. */
151 #define EVENT_YIELD_TIME_SLOT 10 * 1000L /* 10ms */
153 #define EVENT_TIMER_STRLEN 12
156 #define EVENT_ARG(X) ((X)->arg)
157 #define EVENT_FD(X) ((X)->u.fd)
158 #define EVENT_VAL(X) ((X)->u.val)
161 * Please consider this macro deprecated, and do not use it in new code.
163 #define EVENT_OFF(thread) \
166 event_cancel(&(thread)); \
170 * Macro wrappers to generate xrefs for all thread add calls. Includes
171 * file/line/function info for debugging/tracing.
173 #include "lib/xref.h"
175 #define _xref_t_a(addfn, type, m, f, a, v, t) \
177 static const struct xref_eventsched _xref __attribute__( \
179 .xref = XREF_INIT(XREFT_EVENTSCHED, NULL, __func__), \
182 .event_type = EVENT_##type, \
184 XREF_LINK(_xref.xref); \
185 _event_add_##addfn(&_xref, m, f, a, v, t); \
188 #define event_add_read(m, f, a, v, t) _xref_t_a(read_write, READ, m, f, a, v, t)
189 #define event_add_write(m, f, a, v, t) \
190 _xref_t_a(read_write, WRITE, m, f, a, v, t)
191 #define event_add_timer(m, f, a, v, t) _xref_t_a(timer, TIMER, m, f, a, v, t)
192 #define event_add_timer_msec(m, f, a, v, t) \
193 _xref_t_a(timer_msec, TIMER, m, f, a, v, t)
194 #define event_add_timer_tv(m, f, a, v, t) \
195 _xref_t_a(timer_tv, TIMER, m, f, a, v, t)
196 #define event_add_event(m, f, a, v, t) _xref_t_a(event, EVENT, m, f, a, v, t)
198 #define event_execute(m, f, a, v) \
200 static const struct xref_eventsched _xref __attribute__( \
202 .xref = XREF_INIT(XREFT_EVENTSCHED, NULL, __func__), \
205 .event_type = EVENT_EXECUTE, \
207 XREF_LINK(_xref.xref); \
208 _event_execute(&_xref, m, f, a, v); \
212 extern struct event_loop
*event_master_create(const char *name
);
213 void event_master_set_name(struct event_loop
*master
, const char *name
);
214 extern void event_master_free(struct event_loop
*m
);
215 extern void event_master_free_unused(struct event_loop
*m
);
217 extern void _event_add_read_write(const struct xref_eventsched
*xref
,
218 struct event_loop
*master
,
219 void (*fn
)(struct event
*), void *arg
, int fd
,
220 struct event
**tref
);
222 extern void _event_add_timer(const struct xref_eventsched
*xref
,
223 struct event_loop
*master
,
224 void (*fn
)(struct event
*), void *arg
, long t
,
225 struct event
**tref
);
227 extern void _event_add_timer_msec(const struct xref_eventsched
*xref
,
228 struct event_loop
*master
,
229 void (*fn
)(struct event
*), void *arg
, long t
,
230 struct event
**tref
);
232 extern void _event_add_timer_tv(const struct xref_eventsched
*xref
,
233 struct event_loop
*master
,
234 void (*fn
)(struct event
*), void *arg
,
235 struct timeval
*tv
, struct event
**tref
);
237 extern void _event_add_event(const struct xref_eventsched
*xref
,
238 struct event_loop
*master
,
239 void (*fn
)(struct event
*), void *arg
, int val
,
240 struct event
**tref
);
242 extern void _event_execute(const struct xref_eventsched
*xref
,
243 struct event_loop
*master
,
244 void (*fn
)(struct event
*), void *arg
, int val
);
246 extern void event_cancel(struct event
**event
);
247 extern void event_cancel_async(struct event_loop
*m
, struct event
**eptr
,
249 /* Cancel ready tasks with an arg matching 'arg' */
250 extern void event_cancel_event_ready(struct event_loop
*m
, void *arg
);
251 /* Cancel all tasks with an arg matching 'arg', including timers and io */
252 extern void event_cancel_event(struct event_loop
*m
, void *arg
);
253 extern struct event
*event_fetch(struct event_loop
*m
, struct event
*event
);
254 extern void event_call(struct event
*event
);
255 extern unsigned long event_timer_remain_second(struct event
*event
);
256 extern struct timeval
event_timer_remain(struct event
*event
);
257 extern unsigned long event_timer_remain_msec(struct event
*event
);
258 extern int event_should_yield(struct event
*event
);
259 /* set yield time for thread */
260 extern void event_set_yield_time(struct event
*event
, unsigned long ytime
);
262 /* Internal libfrr exports */
263 extern void event_getrusage(RUSAGE_T
*r
);
264 extern void event_cmd_init(void);
266 /* Returns elapsed real (wall clock) time. */
267 extern unsigned long event_consumed_time(RUSAGE_T
*after
, RUSAGE_T
*before
,
268 unsigned long *cpu_time_elapsed
);
270 /* only for use in logging functions! */
271 extern pthread_key_t thread_current
;
272 extern char *event_timer_to_hhmmss(char *buf
, int buf_size
,
273 struct event
*t_timer
);
275 static inline bool event_is_scheduled(struct event
*thread
)
283 /* Debug signal mask */
284 void debug_signals(const sigset_t
*sigs
);
286 static inline void event_ignore_late_timer(struct event
*event
)
288 event
->ignore_timer_late
= true;
295 #endif /* _ZEBRA_THREAD_H */