1 1.1 christos #ifndef JEMALLOC_INTERNAL_PROF_INLINES_A_H 2 1.1 christos #define JEMALLOC_INTERNAL_PROF_INLINES_A_H 3 1.1 christos 4 1.1 christos #include "jemalloc/internal/mutex.h" 5 1.1 christos 6 1.1 christos static inline bool 7 1.1 christos prof_accum_add(tsdn_t *tsdn, prof_accum_t *prof_accum, uint64_t accumbytes) { 8 1.1 christos cassert(config_prof); 9 1.1 christos 10 1.1 christos bool overflow; 11 1.1 christos uint64_t a0, a1; 12 1.1 christos 13 1.1 christos /* 14 1.1 christos * If the application allocates fast enough (and/or if idump is slow 15 1.1 christos * enough), extreme overflow here (a1 >= prof_interval * 2) can cause 16 1.1 christos * idump trigger coalescing. This is an intentional mechanism that 17 1.1 christos * avoids rate-limiting allocation. 18 1.1 christos */ 19 1.1 christos #ifdef JEMALLOC_ATOMIC_U64 20 1.1 christos a0 = atomic_load_u64(&prof_accum->accumbytes, ATOMIC_RELAXED); 21 1.1 christos do { 22 1.1 christos a1 = a0 + accumbytes; 23 1.1 christos assert(a1 >= a0); 24 1.1 christos overflow = (a1 >= prof_interval); 25 1.1 christos if (overflow) { 26 1.1 christos a1 %= prof_interval; 27 1.1 christos } 28 1.1 christos } while (!atomic_compare_exchange_weak_u64(&prof_accum->accumbytes, &a0, 29 1.1 christos a1, ATOMIC_RELAXED, ATOMIC_RELAXED)); 30 1.1 christos #else 31 1.1 christos malloc_mutex_lock(tsdn, &prof_accum->mtx); 32 1.1 christos a0 = prof_accum->accumbytes; 33 1.1 christos a1 = a0 + accumbytes; 34 1.1 christos overflow = (a1 >= prof_interval); 35 1.1 christos if (overflow) { 36 1.1 christos a1 %= prof_interval; 37 1.1 christos } 38 1.1 christos prof_accum->accumbytes = a1; 39 1.1 christos malloc_mutex_unlock(tsdn, &prof_accum->mtx); 40 1.1 christos #endif 41 1.1 christos return overflow; 42 1.1 christos } 43 1.1 christos 44 1.1 christos static JEMALLOC_NORETURN inline void 45 1.1 christos prof_accum_cancel(tsdn_t *tsdn, prof_accum_t *prof_accum, size_t usize) { 46 1.1 christos cassert(config_prof); 47 1.1 christos 48 1.1 christos /* 49 1.1 christos * Cancel out as much of the excessive prof_accumbytes increase as 50 1.1 christos * possible without underflowing. Interval-triggered dumps occur 51 1.1 christos * slightly more often than intended as a result of incomplete 52 1.1 christos * canceling. 53 1.1 christos */ 54 1.1 christos uint64_t a0, a1; 55 1.1 christos #ifdef JEMALLOC_ATOMIC_U64 56 1.1 christos a0 = atomic_load_u64(&prof_accum->accumbytes, ATOMIC_RELAXED); 57 1.1 christos do { 58 1.1 christos a1 = (a0 >= LARGE_MINCLASS - usize) ? a0 - (LARGE_MINCLASS - 59 1.1 christos usize) : 0; 60 1.1 christos } while (!atomic_compare_exchange_weak_u64(&prof_accum->accumbytes, &a0, 61 1.1 christos a1, ATOMIC_RELAXED, ATOMIC_RELAXED)); 62 1.1 christos #else 63 1.1 christos malloc_mutex_lock(tsdn, &prof_accum->mtx); 64 1.1 christos a0 = prof_accum->accumbytes; 65 1.1 christos a1 = (a0 >= LARGE_MINCLASS - usize) ? a0 - (LARGE_MINCLASS - usize) : 66 1.1 christos 0; 67 1.1 christos prof_accum->accumbytes = a1; 68 1.1 christos malloc_mutex_unlock(tsdn, &prof_accum->mtx); 69 1.1 christos #endif 70 1.1 christos } 71 1.1 christos 72 1.1 christos JEMALLOC_ALWAYS_INLINE bool 73 1.1 christos prof_active_get_unlocked(void) { 74 1.1 christos /* 75 1.1 christos * Even if opt_prof is true, sampling can be temporarily disabled by 76 1.1 christos * setting prof_active to false. No locking is used when reading 77 1.1 christos * prof_active in the fast path, so there are no guarantees regarding 78 1.1 christos * how long it will take for all threads to notice state changes. 79 1.1 christos */ 80 1.1 christos return prof_active; 81 1.1 christos } 82 1.1 christos 83 1.1 christos #endif /* JEMALLOC_INTERNAL_PROF_INLINES_A_H */ 84