1 #ifndef JEMALLOC_INTERNAL_MUTEX_PROF_H 2 #define JEMALLOC_INTERNAL_MUTEX_PROF_H 3 4 #include "jemalloc/internal/atomic.h" 5 #include "jemalloc/internal/nstime.h" 6 #include "jemalloc/internal/tsd_types.h" 7 8 #define MUTEX_PROF_GLOBAL_MUTEXES \ 9 OP(background_thread) \ 10 OP(max_per_bg_thd) \ 11 OP(ctl) \ 12 OP(prof) \ 13 OP(prof_thds_data) \ 14 OP(prof_dump) \ 15 OP(prof_recent_alloc) \ 16 OP(prof_recent_dump) \ 17 OP(prof_stats) 18 19 typedef enum { 20 #define OP(mtx) global_prof_mutex_##mtx, 21 MUTEX_PROF_GLOBAL_MUTEXES 22 #undef OP 23 mutex_prof_num_global_mutexes 24 } mutex_prof_global_ind_t; 25 26 #define MUTEX_PROF_ARENA_MUTEXES \ 27 OP(large) \ 28 OP(extent_avail) \ 29 OP(extents_dirty) \ 30 OP(extents_muzzy) \ 31 OP(extents_retained) \ 32 OP(decay_dirty) \ 33 OP(decay_muzzy) \ 34 OP(base) \ 35 OP(tcache_list) \ 36 OP(hpa_shard) \ 37 OP(hpa_shard_grow) \ 38 OP(hpa_sec) 39 40 typedef enum { 41 #define OP(mtx) arena_prof_mutex_##mtx, 42 MUTEX_PROF_ARENA_MUTEXES 43 #undef OP 44 mutex_prof_num_arena_mutexes 45 } mutex_prof_arena_ind_t; 46 47 /* 48 * The forth parameter is a boolean value that is true for derived rate counters 49 * and false for real ones. 50 */ 51 #define MUTEX_PROF_UINT64_COUNTERS \ 52 OP(num_ops, uint64_t, "n_lock_ops", false, num_ops) \ 53 OP(num_ops_ps, uint64_t, "(#/sec)", true, num_ops) \ 54 OP(num_wait, uint64_t, "n_waiting", false, num_wait) \ 55 OP(num_wait_ps, uint64_t, "(#/sec)", true, num_wait) \ 56 OP(num_spin_acq, uint64_t, "n_spin_acq", false, num_spin_acq) \ 57 OP(num_spin_acq_ps, uint64_t, "(#/sec)", true, num_spin_acq) \ 58 OP(num_owner_switch, uint64_t, "n_owner_switch", false, num_owner_switch) \ 59 OP(num_owner_switch_ps, uint64_t, "(#/sec)", true, num_owner_switch) \ 60 OP(total_wait_time, uint64_t, "total_wait_ns", false, total_wait_time) \ 61 OP(total_wait_time_ps, uint64_t, "(#/sec)", true, total_wait_time) \ 62 OP(max_wait_time, uint64_t, "max_wait_ns", false, max_wait_time) 63 64 #define MUTEX_PROF_UINT32_COUNTERS \ 65 OP(max_num_thds, uint32_t, "max_n_thds", false, max_num_thds) 66 67 #define MUTEX_PROF_COUNTERS \ 68 MUTEX_PROF_UINT64_COUNTERS \ 69 MUTEX_PROF_UINT32_COUNTERS 70 71 #define OP(counter, type, human, derived, base_counter) mutex_counter_##counter, 72 73 #define COUNTER_ENUM(counter_list, t) \ 74 typedef enum { \ 75 counter_list \ 76 mutex_prof_num_##t##_counters \ 77 } mutex_prof_##t##_counter_ind_t; 78 79 COUNTER_ENUM(MUTEX_PROF_UINT64_COUNTERS, uint64_t) 80 COUNTER_ENUM(MUTEX_PROF_UINT32_COUNTERS, uint32_t) 81 82 #undef COUNTER_ENUM 83 #undef OP 84 85 typedef struct { 86 /* 87 * Counters touched on the slow path, i.e. when there is lock 88 * contention. We update them once we have the lock. 89 */ 90 /* Total time (in nano seconds) spent waiting on this mutex. */ 91 nstime_t tot_wait_time; 92 /* Max time (in nano seconds) spent on a single lock operation. */ 93 nstime_t max_wait_time; 94 /* # of times have to wait for this mutex (after spinning). */ 95 uint64_t n_wait_times; 96 /* # of times acquired the mutex through local spinning. */ 97 uint64_t n_spin_acquired; 98 /* Max # of threads waiting for the mutex at the same time. */ 99 uint32_t max_n_thds; 100 /* Current # of threads waiting on the lock. Atomic synced. */ 101 atomic_u32_t n_waiting_thds; 102 103 /* 104 * Data touched on the fast path. These are modified right after we 105 * grab the lock, so it's placed closest to the end (i.e. right before 106 * the lock) so that we have a higher chance of them being on the same 107 * cacheline. 108 */ 109 /* # of times the mutex holder is different than the previous one. */ 110 uint64_t n_owner_switches; 111 /* Previous mutex holder, to facilitate n_owner_switches. */ 112 tsdn_t *prev_owner; 113 /* # of lock() operations in total. */ 114 uint64_t n_lock_ops; 115 } mutex_prof_data_t; 116 117 #endif /* JEMALLOC_INTERNAL_MUTEX_PROF_H */ 118