]> git.proxmox.com Git - mirror_frr.git/blame - lib/frrevent.h
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / lib / frrevent.h
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
5163a1c5 2/* Event management routine header.
718e3744 3 * Copyright (C) 1998 Kunihiro Ishiguro
718e3744 4 */
5
6#ifndef _ZEBRA_THREAD_H
7#define _ZEBRA_THREAD_H
8
5734509c 9#include <zebra.h>
1189d95f 10#include <pthread.h>
75bcb355
QY
11#include <poll.h>
12#include "monotime.h"
fbcac826 13#include "frratomic.h"
c284542b 14#include "typesafe.h"
60a3efec 15#include "xref.h"
5734509c 16
5e244469
RW
17#ifdef __cplusplus
18extern "C" {
19#endif
20
45f01188
DL
21extern bool cputime_enabled;
22extern unsigned long cputime_threshold;
23/* capturing wallclock time is always enabled since it is fast (reading
24 * hardware TSC w/o syscalls)
25 */
26extern unsigned long walltime_threshold;
27
d62a17ae 28struct rusage_t {
6418e2d3
DL
29#ifdef HAVE_CLOCK_THREAD_CPUTIME_ID
30 struct timespec cpu;
31#else
d62a17ae 32 struct rusage cpu;
6418e2d3 33#endif
d62a17ae 34 struct timeval real;
8b70d0b0 35};
24a58196 36#define RUSAGE_T struct rusage_t
8b70d0b0 37
5f6eaa9b 38#define GETRUSAGE(X) event_getrusage(X)
718e3744 39
3905fb73
DS
40PREDECL_LIST(event_list);
41PREDECL_HEAP(event_timer_list);
4becea72 42
d62a17ae 43struct fd_handler {
44 /* number of pfd that fit in the allocated space of pfds. This is a
a9318a32
MS
45 * constant and is the same for both pfds and copy.
46 */
d62a17ae 47 nfds_t pfdsize;
48
49 /* file descriptors to monitor for i/o */
50 struct pollfd *pfds;
51 /* number of pollfds stored in pfds */
52 nfds_t pfdcount;
53
54 /* chunk used for temp copy of pollfds */
55 struct pollfd *copy;
56 /* number of pollfds stored in copy */
57 nfds_t copycount;
0a95a0d0 58};
0a95a0d0 59
5163a1c5 60struct xref_eventsched {
60a3efec
DL
61 struct xref xref;
62
63 const char *funcname;
64 const char *dest;
2ccccdf5 65 uint32_t event_type;
60a3efec
DL
66};
67
718e3744 68/* Master of the theads. */
cd9d0537 69struct event_loop {
d62a17ae 70 char *name;
71
e6685141
DS
72 struct event **read;
73 struct event **write;
3905fb73
DS
74 struct event_timer_list_head timer;
75 struct event_list_head event, ready, unuse;
d62a17ae 76 struct list *cancel_req;
77 bool canceled;
78 pthread_cond_t cancel_cond;
79 struct hash *cpu_record;
80 int io_pipe[2];
81 int fd_limit;
82 struct fd_handler handler;
83 unsigned long alloc;
84 long selectpoll_timeout;
85 bool spin;
86 bool handle_signals;
87 pthread_mutex_t mtx;
88 pthread_t owner;
5e822957
DS
89
90 bool ready_run_loop;
91 RUSAGE_T last_getrusage;
718e3744 92};
93
2ccccdf5
DS
94/* Event types. */
95enum event_types {
96 EVENT_READ,
97 EVENT_WRITE,
98 EVENT_TIMER,
99 EVENT_EVENT,
100 EVENT_READY,
101 EVENT_UNUSED,
102 EVENT_EXECUTE,
103};
104
04ec6679 105/* Event itself. */
e6685141 106struct event {
04ec6679
DS
107 enum event_types type; /* event type */
108 enum event_types add_type; /* event type */
3905fb73
DS
109 struct event_list_item eventitem;
110 struct event_timer_list_item timeritem;
e6685141 111 struct event **ref; /* external reference (if given) */
cd9d0537 112 struct event_loop *master; /* pointer to the struct event_loop */
02e701e4 113 void (*func)(struct event *e); /* event function */
d62a17ae 114 void *arg; /* event argument */
115 union {
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. */
119 } u;
d62a17ae 120 struct timeval real;
24a58196
DS
121 struct cpu_event_history *hist; /* cache pointer to cpu_history */
122 unsigned long yield; /* yield time in microseconds */
5163a1c5 123 const struct xref_eventsched *xref; /* origin location */
24a58196 124 pthread_mutex_t mtx; /* mutex for thread.c functions */
e8b3a2f7 125 bool ignore_timer_late;
e04ab74d 126};
127
f59e6882 128#ifdef _FRR_ATTRIBUTE_PRINTFRR
e6685141 129#pragma FRR printfrr_ext "%pTH"(struct event *)
f59e6882
DL
130#endif
131
04ec6679 132struct cpu_event_history {
02e701e4 133 void (*func)(struct event *e);
9b8e01ca
DS
134 atomic_size_t total_cpu_warn;
135 atomic_size_t total_wall_warn;
1dd08c22 136 atomic_size_t total_starv_warn;
72327cf3
MS
137 atomic_size_t total_calls;
138 atomic_size_t total_active;
d62a17ae 139 struct time_stats {
c8a65463 140 atomic_size_t total, max;
d62a17ae 141 } real;
142 struct time_stats cpu;
c8a65463 143 atomic_uint_fast32_t types;
d62a17ae 144 const char *funcname;
718e3744 145};
146
ca1f4309
DS
147/* Struct timeval's tv_usec one second value. */
148#define TIMER_SECOND_MICRO 1000000L
149
70d4d90c 150/* Event yield time. */
ba7d2705 151#define EVENT_YIELD_TIME_SLOT 10 * 1000L /* 10ms */
718e3744 152
70d4d90c 153#define EVENT_TIMER_STRLEN 12
0447957e 154
718e3744 155/* Macros. */
e16d030c
DS
156#define EVENT_ARG(X) ((X)->arg)
157#define EVENT_FD(X) ((X)->u.fd)
158#define EVENT_VAL(X) ((X)->u.val)
718e3744 159
50478845
MS
160/*
161 * Please consider this macro deprecated, and do not use it in new code.
162 */
e16d030c 163#define EVENT_OFF(thread) \
332beb64
DS
164 do { \
165 if ((thread)) \
166 event_cancel(&(thread)); \
50478845 167 } while (0)
718e3744 168
60a3efec
DL
169/*
170 * Macro wrappers to generate xrefs for all thread add calls. Includes
171 * file/line/function info for debugging/tracing.
172 */
173#include "lib/xref.h"
174
175#define _xref_t_a(addfn, type, m, f, a, v, t) \
176 ({ \
5163a1c5 177 static const struct xref_eventsched _xref __attribute__( \
907a2395 178 (used)) = { \
5163a1c5 179 .xref = XREF_INIT(XREFT_EVENTSCHED, NULL, __func__), \
60a3efec
DL
180 .funcname = #f, \
181 .dest = #t, \
2ccccdf5 182 .event_type = EVENT_##type, \
60a3efec
DL
183 }; \
184 XREF_LINK(_xref.xref); \
907a2395
DS
185 _event_add_##addfn(&_xref, m, f, a, v, t); \
186 }) /* end */
60a3efec 187
907a2395
DS
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)
60a3efec 197
8c1186d3 198#define event_execute(m, f, a, v) \
60a3efec 199 ({ \
5163a1c5 200 static const struct xref_eventsched _xref __attribute__( \
2ccccdf5 201 (used)) = { \
5163a1c5 202 .xref = XREF_INIT(XREFT_EVENTSCHED, NULL, __func__), \
60a3efec
DL
203 .funcname = #f, \
204 .dest = NULL, \
2ccccdf5 205 .event_type = EVENT_EXECUTE, \
60a3efec
DL
206 }; \
207 XREF_LINK(_xref.xref); \
8c1186d3 208 _event_execute(&_xref, m, f, a, v); \
60a3efec 209 }) /* end */
fb9e46bb 210
718e3744 211/* Prototypes. */
cd9d0537
DS
212extern struct event_loop *event_master_create(const char *name);
213void event_master_set_name(struct event_loop *master, const char *name);
214extern void event_master_free(struct event_loop *m);
215extern void event_master_free_unused(struct event_loop *m);
8cc4198f 216
5163a1c5 217extern void _event_add_read_write(const struct xref_eventsched *xref,
cd9d0537 218 struct event_loop *master,
907a2395
DS
219 void (*fn)(struct event *), void *arg, int fd,
220 struct event **tref);
221
5163a1c5 222extern void _event_add_timer(const struct xref_eventsched *xref,
cd9d0537 223 struct event_loop *master,
907a2395
DS
224 void (*fn)(struct event *), void *arg, long t,
225 struct event **tref);
226
5163a1c5 227extern void _event_add_timer_msec(const struct xref_eventsched *xref,
cd9d0537 228 struct event_loop *master,
907a2395
DS
229 void (*fn)(struct event *), void *arg, long t,
230 struct event **tref);
231
5163a1c5 232extern void _event_add_timer_tv(const struct xref_eventsched *xref,
cd9d0537 233 struct event_loop *master,
907a2395
DS
234 void (*fn)(struct event *), void *arg,
235 struct timeval *tv, struct event **tref);
236
5163a1c5 237extern void _event_add_event(const struct xref_eventsched *xref,
cd9d0537 238 struct event_loop *master,
907a2395
DS
239 void (*fn)(struct event *), void *arg, int val,
240 struct event **tref);
60a3efec 241
5163a1c5 242extern void _event_execute(const struct xref_eventsched *xref,
cd9d0537 243 struct event_loop *master,
8c1186d3 244 void (*fn)(struct event *), void *arg, int val);
9c7753e4 245
332beb64 246extern void event_cancel(struct event **event);
cd9d0537 247extern void event_cancel_async(struct event_loop *m, struct event **eptr,
2453d15d 248 void *data);
a9318a32 249/* Cancel ready tasks with an arg matching 'arg' */
cd9d0537 250extern void event_cancel_event_ready(struct event_loop *m, void *arg);
a9318a32 251/* Cancel all tasks with an arg matching 'arg', including timers and io */
cd9d0537
DS
252extern void event_cancel_event(struct event_loop *m, void *arg);
253extern struct event *event_fetch(struct event_loop *m, struct event *event);
de2754be 254extern void event_call(struct event *event);
4f830a07
DS
255extern unsigned long event_timer_remain_second(struct event *event);
256extern struct timeval event_timer_remain(struct event *event);
257extern unsigned long event_timer_remain_msec(struct event *event);
70c35c11 258extern int event_should_yield(struct event *event);
50596be0 259/* set yield time for thread */
2453d15d 260extern void event_set_yield_time(struct event *event, unsigned long ytime);
718e3744 261
55c72803 262/* Internal libfrr exports */
2453d15d 263extern void event_getrusage(RUSAGE_T *r);
5f6eaa9b 264extern void event_cmd_init(void);
e04ab74d 265
8b70d0b0 266/* Returns elapsed real (wall clock) time. */
5f6eaa9b
DS
267extern unsigned long event_consumed_time(RUSAGE_T *after, RUSAGE_T *before,
268 unsigned long *cpu_time_elapsed);
8b70d0b0 269
d1265948 270/* only for use in logging functions! */
e0bebc7c 271extern pthread_key_t thread_current;
5f6eaa9b
DS
272extern char *event_timer_to_hhmmss(char *buf, int buf_size,
273 struct event *t_timer);
d1265948 274
5f6eaa9b 275static inline bool event_is_scheduled(struct event *thread)
cfb9e0ee
DS
276{
277 if (thread)
278 return true;
279
280 return false;
281}
282
1543c387
MS
283/* Debug signal mask */
284void debug_signals(const sigset_t *sigs);
285
5f6eaa9b 286static inline void event_ignore_late_timer(struct event *event)
e8b3a2f7 287{
e6685141 288 event->ignore_timer_late = true;
e8b3a2f7
DS
289}
290
5e244469
RW
291#ifdef __cplusplus
292}
293#endif
294
718e3744 295#endif /* _ZEBRA_THREAD_H */