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