xref: /aosp_15_r20/external/jemalloc_new/include/jemalloc/internal/ticker.h (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
1*1208bc7eSAndroid Build Coastguard Worker #ifndef JEMALLOC_INTERNAL_TICKER_H
2*1208bc7eSAndroid Build Coastguard Worker #define JEMALLOC_INTERNAL_TICKER_H
3*1208bc7eSAndroid Build Coastguard Worker 
4*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/util.h"
5*1208bc7eSAndroid Build Coastguard Worker 
6*1208bc7eSAndroid Build Coastguard Worker /**
7*1208bc7eSAndroid Build Coastguard Worker  * A ticker makes it easy to count-down events until some limit.  You
8*1208bc7eSAndroid Build Coastguard Worker  * ticker_init the ticker to trigger every nticks events.  You then notify it
9*1208bc7eSAndroid Build Coastguard Worker  * that an event has occurred with calls to ticker_tick (or that nticks events
10*1208bc7eSAndroid Build Coastguard Worker  * have occurred with a call to ticker_ticks), which will return true (and reset
11*1208bc7eSAndroid Build Coastguard Worker  * the counter) if the countdown hit zero.
12*1208bc7eSAndroid Build Coastguard Worker  */
13*1208bc7eSAndroid Build Coastguard Worker 
14*1208bc7eSAndroid Build Coastguard Worker typedef struct {
15*1208bc7eSAndroid Build Coastguard Worker 	int32_t tick;
16*1208bc7eSAndroid Build Coastguard Worker 	int32_t nticks;
17*1208bc7eSAndroid Build Coastguard Worker } ticker_t;
18*1208bc7eSAndroid Build Coastguard Worker 
19*1208bc7eSAndroid Build Coastguard Worker static inline void
ticker_init(ticker_t * ticker,int32_t nticks)20*1208bc7eSAndroid Build Coastguard Worker ticker_init(ticker_t *ticker, int32_t nticks) {
21*1208bc7eSAndroid Build Coastguard Worker 	ticker->tick = nticks;
22*1208bc7eSAndroid Build Coastguard Worker 	ticker->nticks = nticks;
23*1208bc7eSAndroid Build Coastguard Worker }
24*1208bc7eSAndroid Build Coastguard Worker 
25*1208bc7eSAndroid Build Coastguard Worker static inline void
ticker_copy(ticker_t * ticker,const ticker_t * other)26*1208bc7eSAndroid Build Coastguard Worker ticker_copy(ticker_t *ticker, const ticker_t *other) {
27*1208bc7eSAndroid Build Coastguard Worker 	*ticker = *other;
28*1208bc7eSAndroid Build Coastguard Worker }
29*1208bc7eSAndroid Build Coastguard Worker 
30*1208bc7eSAndroid Build Coastguard Worker static inline int32_t
ticker_read(const ticker_t * ticker)31*1208bc7eSAndroid Build Coastguard Worker ticker_read(const ticker_t *ticker) {
32*1208bc7eSAndroid Build Coastguard Worker 	return ticker->tick;
33*1208bc7eSAndroid Build Coastguard Worker }
34*1208bc7eSAndroid Build Coastguard Worker 
35*1208bc7eSAndroid Build Coastguard Worker /*
36*1208bc7eSAndroid Build Coastguard Worker  * Not intended to be a public API.  Unfortunately, on x86, neither gcc nor
37*1208bc7eSAndroid Build Coastguard Worker  * clang seems smart enough to turn
38*1208bc7eSAndroid Build Coastguard Worker  *   ticker->tick -= nticks;
39*1208bc7eSAndroid Build Coastguard Worker  *   if (unlikely(ticker->tick < 0)) {
40*1208bc7eSAndroid Build Coastguard Worker  *     fixup ticker
41*1208bc7eSAndroid Build Coastguard Worker  *     return true;
42*1208bc7eSAndroid Build Coastguard Worker  *   }
43*1208bc7eSAndroid Build Coastguard Worker  *   return false;
44*1208bc7eSAndroid Build Coastguard Worker  * into
45*1208bc7eSAndroid Build Coastguard Worker  *   subq %nticks_reg, (%ticker_reg)
46*1208bc7eSAndroid Build Coastguard Worker  *   js fixup ticker
47*1208bc7eSAndroid Build Coastguard Worker  *
48*1208bc7eSAndroid Build Coastguard Worker  * unless we force "fixup ticker" out of line.  In that case, gcc gets it right,
49*1208bc7eSAndroid Build Coastguard Worker  * but clang now does worse than before.  So, on x86 with gcc, we force it out
50*1208bc7eSAndroid Build Coastguard Worker  * of line, but otherwise let the inlining occur.  Ordinarily this wouldn't be
51*1208bc7eSAndroid Build Coastguard Worker  * worth the hassle, but this is on the fast path of both malloc and free (via
52*1208bc7eSAndroid Build Coastguard Worker  * tcache_event).
53*1208bc7eSAndroid Build Coastguard Worker  */
54*1208bc7eSAndroid Build Coastguard Worker #if defined(__GNUC__) && !defined(__clang__)				\
55*1208bc7eSAndroid Build Coastguard Worker     && (defined(__x86_64__) || defined(__i386__))
56*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_NOINLINE
57*1208bc7eSAndroid Build Coastguard Worker #endif
58*1208bc7eSAndroid Build Coastguard Worker static bool
ticker_fixup(ticker_t * ticker)59*1208bc7eSAndroid Build Coastguard Worker ticker_fixup(ticker_t *ticker) {
60*1208bc7eSAndroid Build Coastguard Worker 	ticker->tick = ticker->nticks;
61*1208bc7eSAndroid Build Coastguard Worker 	return true;
62*1208bc7eSAndroid Build Coastguard Worker }
63*1208bc7eSAndroid Build Coastguard Worker 
64*1208bc7eSAndroid Build Coastguard Worker static inline bool
ticker_ticks(ticker_t * ticker,int32_t nticks)65*1208bc7eSAndroid Build Coastguard Worker ticker_ticks(ticker_t *ticker, int32_t nticks) {
66*1208bc7eSAndroid Build Coastguard Worker 	ticker->tick -= nticks;
67*1208bc7eSAndroid Build Coastguard Worker 	if (unlikely(ticker->tick < 0)) {
68*1208bc7eSAndroid Build Coastguard Worker 		return ticker_fixup(ticker);
69*1208bc7eSAndroid Build Coastguard Worker 	}
70*1208bc7eSAndroid Build Coastguard Worker 	return false;
71*1208bc7eSAndroid Build Coastguard Worker }
72*1208bc7eSAndroid Build Coastguard Worker 
73*1208bc7eSAndroid Build Coastguard Worker static inline bool
ticker_tick(ticker_t * ticker)74*1208bc7eSAndroid Build Coastguard Worker ticker_tick(ticker_t *ticker) {
75*1208bc7eSAndroid Build Coastguard Worker 	return ticker_ticks(ticker, 1);
76*1208bc7eSAndroid Build Coastguard Worker }
77*1208bc7eSAndroid Build Coastguard Worker 
78*1208bc7eSAndroid Build Coastguard Worker #endif /* JEMALLOC_INTERNAL_TICKER_H */
79