diff options
| author | Donald Sharp <sharpd@nvidia.com> | 2023-03-07 14:22:48 -0500 | 
|---|---|---|
| committer | Donald Sharp <sharpd@nvidia.com> | 2023-03-24 08:32:17 -0400 | 
| commit | 24a58196ddcff2215d382d8a677c2dcdc898e03c (patch) | |
| tree | 96e008127cbe222d07aefc8b31d2176f64a1e21a /lib/frrevent.h | |
| parent | cd9d0537411d0a74cd19ae36f6d3716c8ccbb4c1 (diff) | |
*: Convert event.h to frrevent.h
We should probably prevent any type of namespace collision
with something else.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
Diffstat (limited to 'lib/frrevent.h')
| -rw-r--r-- | lib/frrevent.h | 295 | 
1 files changed, 295 insertions, 0 deletions
diff --git a/lib/frrevent.h b/lib/frrevent.h new file mode 100644 index 0000000000..b05885a985 --- /dev/null +++ b/lib/frrevent.h @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Event management routine header. + * Copyright (C) 1998 Kunihiro Ishiguro + */ + +#ifndef _ZEBRA_THREAD_H +#define _ZEBRA_THREAD_H + +#include <zebra.h> +#include <pthread.h> +#include <poll.h> +#include "monotime.h" +#include "frratomic.h" +#include "typesafe.h" +#include "xref.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern bool cputime_enabled; +extern unsigned long cputime_threshold; +/* capturing wallclock time is always enabled since it is fast (reading + * hardware TSC w/o syscalls) + */ +extern unsigned long walltime_threshold; + +struct rusage_t { +#ifdef HAVE_CLOCK_THREAD_CPUTIME_ID +	struct timespec cpu; +#else +	struct rusage cpu; +#endif +	struct timeval real; +}; +#define RUSAGE_T struct rusage_t + +#define GETRUSAGE(X) event_getrusage(X) + +PREDECL_LIST(event_list); +PREDECL_HEAP(event_timer_list); + +struct fd_handler { +	/* number of pfd that fit in the allocated space of pfds. This is a +	 * constant and is the same for both pfds and copy. +	 */ +	nfds_t pfdsize; + +	/* file descriptors to monitor for i/o */ +	struct pollfd *pfds; +	/* number of pollfds stored in pfds */ +	nfds_t pfdcount; + +	/* chunk used for temp copy of pollfds */ +	struct pollfd *copy; +	/* number of pollfds stored in copy */ +	nfds_t copycount; +}; + +struct xref_eventsched { +	struct xref xref; + +	const char *funcname; +	const char *dest; +	uint32_t event_type; +}; + +/* Master of the theads. */ +struct event_loop { +	char *name; + +	struct event **read; +	struct event **write; +	struct event_timer_list_head timer; +	struct event_list_head event, ready, unuse; +	struct list *cancel_req; +	bool canceled; +	pthread_cond_t cancel_cond; +	struct hash *cpu_record; +	int io_pipe[2]; +	int fd_limit; +	struct fd_handler handler; +	unsigned long alloc; +	long selectpoll_timeout; +	bool spin; +	bool handle_signals; +	pthread_mutex_t mtx; +	pthread_t owner; + +	bool ready_run_loop; +	RUSAGE_T last_getrusage; +}; + +/* Event types. */ +enum event_types { +	EVENT_READ, +	EVENT_WRITE, +	EVENT_TIMER, +	EVENT_EVENT, +	EVENT_READY, +	EVENT_UNUSED, +	EVENT_EXECUTE, +}; + +/* Event itself. */ +struct event { +	enum event_types type;	   /* event type */ +	enum event_types add_type; /* event type */ +	struct event_list_item eventitem; +	struct event_timer_list_item timeritem; +	struct event **ref;	      /* external reference (if given) */ +	struct event_loop *master;    /* pointer to the struct event_loop */ +	void (*func)(struct event *); /* event function */ +	void *arg;		      /* event argument */ +	union { +		int val;	      /* second argument of the event. */ +		int fd;		      /* file descriptor in case of r/w */ +		struct timeval sands; /* rest of time sands value. */ +	} u; +	struct timeval real; +	struct cpu_event_history *hist;	    /* cache pointer to cpu_history */ +	unsigned long yield;		    /* yield time in microseconds */ +	const struct xref_eventsched *xref; /* origin location */ +	pthread_mutex_t mtx;		    /* mutex for thread.c functions */ +	bool ignore_timer_late; +}; + +#ifdef _FRR_ATTRIBUTE_PRINTFRR +#pragma FRR printfrr_ext "%pTH"(struct event *) +#endif + +struct cpu_event_history { +	void (*func)(struct event *); +	atomic_size_t total_cpu_warn; +	atomic_size_t total_wall_warn; +	atomic_size_t total_starv_warn; +	atomic_size_t total_calls; +	atomic_size_t total_active; +	struct time_stats { +		atomic_size_t total, max; +	} real; +	struct time_stats cpu; +	atomic_uint_fast32_t types; +	const char *funcname; +}; + +/* Struct timeval's tv_usec one second value.  */ +#define TIMER_SECOND_MICRO 1000000L + +/* Event yield time.  */ +#define EVENT_YIELD_TIME_SLOT 10 * 1000L /* 10ms */ + +#define EVENT_TIMER_STRLEN 12 + +/* Macros. */ +#define EVENT_ARG(X) ((X)->arg) +#define EVENT_FD(X) ((X)->u.fd) +#define EVENT_VAL(X) ((X)->u.val) + +/* + * Please consider this macro deprecated, and do not use it in new code. + */ +#define EVENT_OFF(thread)                                                      \ +	do {                                                                   \ +		if ((thread))                                                  \ +			event_cancel(&(thread));                               \ +	} while (0) + +/* + * Macro wrappers to generate xrefs for all thread add calls.  Includes + * file/line/function info for debugging/tracing. + */ +#include "lib/xref.h" + +#define _xref_t_a(addfn, type, m, f, a, v, t)                                  \ +	({                                                                     \ +		static const struct xref_eventsched _xref __attribute__(       \ +			(used)) = {                                            \ +			.xref = XREF_INIT(XREFT_EVENTSCHED, NULL, __func__),   \ +			.funcname = #f,                                        \ +			.dest = #t,                                            \ +			.event_type = EVENT_##type,                            \ +		};                                                             \ +		XREF_LINK(_xref.xref);                                         \ +		_event_add_##addfn(&_xref, m, f, a, v, t);                     \ +	}) /* end */ + +#define event_add_read(m, f, a, v, t) _xref_t_a(read_write, READ, m, f, a, v, t) +#define event_add_write(m, f, a, v, t)                                         \ +	_xref_t_a(read_write, WRITE, m, f, a, v, t) +#define event_add_timer(m, f, a, v, t) _xref_t_a(timer, TIMER, m, f, a, v, t) +#define event_add_timer_msec(m, f, a, v, t)                                    \ +	_xref_t_a(timer_msec, TIMER, m, f, a, v, t) +#define event_add_timer_tv(m, f, a, v, t)                                      \ +	_xref_t_a(timer_tv, TIMER, m, f, a, v, t) +#define event_add_event(m, f, a, v, t) _xref_t_a(event, EVENT, m, f, a, v, t) + +#define event_execute(m, f, a, v)                                              \ +	({                                                                     \ +		static const struct xref_eventsched _xref __attribute__(       \ +			(used)) = {                                            \ +			.xref = XREF_INIT(XREFT_EVENTSCHED, NULL, __func__),   \ +			.funcname = #f,                                        \ +			.dest = NULL,                                          \ +			.event_type = EVENT_EXECUTE,                           \ +		};                                                             \ +		XREF_LINK(_xref.xref);                                         \ +		_event_execute(&_xref, m, f, a, v);                            \ +	}) /* end */ + +/* Prototypes. */ +extern struct event_loop *event_master_create(const char *name); +void event_master_set_name(struct event_loop *master, const char *name); +extern void event_master_free(struct event_loop *m); +extern void event_master_free_unused(struct event_loop *m); + +extern void _event_add_read_write(const struct xref_eventsched *xref, +				  struct event_loop *master, +				  void (*fn)(struct event *), void *arg, int fd, +				  struct event **tref); + +extern void _event_add_timer(const struct xref_eventsched *xref, +			     struct event_loop *master, +			     void (*fn)(struct event *), void *arg, long t, +			     struct event **tref); + +extern void _event_add_timer_msec(const struct xref_eventsched *xref, +				  struct event_loop *master, +				  void (*fn)(struct event *), void *arg, long t, +				  struct event **tref); + +extern void _event_add_timer_tv(const struct xref_eventsched *xref, +				struct event_loop *master, +				void (*fn)(struct event *), void *arg, +				struct timeval *tv, struct event **tref); + +extern void _event_add_event(const struct xref_eventsched *xref, +			     struct event_loop *master, +			     void (*fn)(struct event *), void *arg, int val, +			     struct event **tref); + +extern void _event_execute(const struct xref_eventsched *xref, +			   struct event_loop *master, +			   void (*fn)(struct event *), void *arg, int val); + +extern void event_cancel(struct event **event); +extern void event_cancel_async(struct event_loop *m, struct event **eptr, +			       void *data); +/* Cancel ready tasks with an arg matching 'arg' */ +extern void event_cancel_event_ready(struct event_loop *m, void *arg); +/* Cancel all tasks with an arg matching 'arg', including timers and io */ +extern void event_cancel_event(struct event_loop *m, void *arg); +extern struct event *event_fetch(struct event_loop *m, struct event *event); +extern void event_call(struct event *event); +extern unsigned long event_timer_remain_second(struct event *event); +extern struct timeval event_timer_remain(struct event *event); +extern unsigned long event_timer_remain_msec(struct event *event); +extern int event_should_yield(struct event *event); +/* set yield time for thread */ +extern void event_set_yield_time(struct event *event, unsigned long ytime); + +/* Internal libfrr exports */ +extern void event_getrusage(RUSAGE_T *r); +extern void event_cmd_init(void); + +/* Returns elapsed real (wall clock) time. */ +extern unsigned long event_consumed_time(RUSAGE_T *after, RUSAGE_T *before, +					 unsigned long *cpu_time_elapsed); + +/* only for use in logging functions! */ +extern pthread_key_t thread_current; +extern char *event_timer_to_hhmmss(char *buf, int buf_size, +				   struct event *t_timer); + +static inline bool event_is_scheduled(struct event *thread) +{ +	if (thread) +		return true; + +	return false; +} + +/* Debug signal mask */ +void debug_signals(const sigset_t *sigs); + +static inline void event_ignore_late_timer(struct event *event) +{ +	event->ignore_timer_late = true; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _ZEBRA_THREAD_H */  | 
