|
#ifndef FFSW_SPEW_THROTTLED_H
|
|
#define FFSW_SPEW_THROTTLED_H
|
|
|
|
#include <stddef.h> // for size_t
|
|
#include <pthread.h> // for pthread_mutex_lock, pthread_mute...
|
|
#include "common/tick.h" // for tickns
|
|
|
|
struct spew_throttle {
|
|
pthread_mutex_t mx;
|
|
const tickns_t period;
|
|
tickns_t last_suppressed;
|
|
size_t n_suppressed;
|
|
};
|
|
|
|
// To avoid the "static variable defined locally" warning
|
|
#ifndef __CHECKER__
|
|
#define init_throttle(__spew_throttle,wait_time) \
|
|
static struct spew_throttle __spew_throttle = { \
|
|
.mx = PTHREAD_MUTEX_INITIALIZER, \
|
|
.period = (wait_time), \
|
|
.last_suppressed = 0, \
|
|
.n_suppressed = 0, \
|
|
};
|
|
#else
|
|
#define init_throttle(obj,wait_time) \
|
|
struct spew_throttle obj = { \
|
|
.mx = PTHREAD_MUTEX_INITIALIZER, \
|
|
.period = (wait_time), \
|
|
.last_suppressed = 0, \
|
|
.n_suppressed = 0, \
|
|
};
|
|
#endif // __CHECKER__
|
|
|
|
#define spew_throttled(wait_time, level, format, ...) \
|
|
({ \
|
|
init_throttle(__spew_throttle, wait_time); \
|
|
CHECK0(pthread_mutex_lock(&__spew_throttle.mx)); \
|
|
tickns_t __now = tickns(); \
|
|
if (__now >= (__spew_throttle.last_suppressed) + ( __spew_throttle.period)) { \
|
|
__spew_throttle.last_suppressed = __now; \
|
|
spew(level,format " (suppressed:%zu)", ##__VA_ARGS__, __spew_throttle.n_suppressed); \
|
|
__spew_throttle.n_suppressed = 0; \
|
|
} \
|
|
else { \
|
|
__spew_throttle.n_suppressed += 1; \
|
|
} \
|
|
CHECK0(pthread_mutex_unlock(&__spew_throttle.mx)); \
|
|
})
|
|
|
|
#endif // FFSW_SPEW_THROTTLED_H
|