prof.h revision 0b25fe79aaf8840a5acda7e3160a053d42349872
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************/ 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef JEMALLOC_H_TYPES 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct prof_bt_s prof_bt_t; 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct prof_cnt_s prof_cnt_t; 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct prof_thr_cnt_s prof_thr_cnt_t; 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct prof_ctx_s prof_ctx_t; 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct prof_tdata_s prof_tdata_t; 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Option defaults. */ 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROF_PREFIX_DEFAULT "jeprof" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LG_PROF_SAMPLE_DEFAULT 19 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LG_PROF_INTERVAL_DEFAULT -1 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)/* 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Hard limit on stack backtrace depth. The version of prof_backtrace() that 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * is based on __builtin_return_address() necessarily has a hard-coded number 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * of backtrace frame handlers, and should be kept in sync with this setting. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROF_BT_MAX 128 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Maximum number of backtraces to store in each per thread LRU cache. */ 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROF_TCMAX 1024 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Initial hash table size. */ 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROF_CKH_MINITEMS 64 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Size of memory buffer to use when writing dump files. */ 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROF_DUMP_BUFSIZE 65536 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Size of stack-allocated buffer used by prof_printf(). */ 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROF_PRINTF_BUFSIZE 128 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Number of mutexes shared among all ctx's. No space is allocated for these 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * unless profiling is enabled, so it's okay to over-provision. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROF_NCTX_LOCKS 1024 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* JEMALLOC_H_TYPES */ 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************/ 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef JEMALLOC_H_STRUCTS 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct prof_bt_s { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Backtrace, stored as len program counters. */ 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void **vec; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned len; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef JEMALLOC_PROF_LIBGCC 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Data structure passed to libgcc _Unwind_Backtrace() callback functions. */ 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_bt_t *bt; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned nignore; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned max; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} prof_unwind_data_t; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct prof_cnt_s { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Profiling counters. An allocation/deallocation pair can operate on 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * different prof_thr_cnt_t objects that are linked into the same 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * prof_ctx_t cnts_ql, so it is possible for the cur* counters to go 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * negative. In principle it is possible for the *bytes counters to 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * overflow/underflow, but a general solution would require something 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * like 128-bit counters; this implementation doesn't bother to solve 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that problem. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64_t curobjs; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64_t curbytes; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t accumobjs; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t accumbytes; 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}; 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)struct prof_thr_cnt_s { 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /* Linkage into prof_ctx_t's cnts_ql. */ 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ql_elm(prof_thr_cnt_t) cnts_link; 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /* Linkage into thread's LRU. */ 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ql_elm(prof_thr_cnt_t) lru_link; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Associated context. If a thread frees an object that it did not 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * allocate, it is possible that the context is not cached in the 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * thread's hash table, in which case it must be able to look up the 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * context, insert a new prof_thr_cnt_t into the thread's hash table, 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * and link it into the prof_ctx_t's cnts_ql. 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_ctx_t *ctx; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 92a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) * Threads use memory barriers to update the counters. Since there is 93a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) * only ever one writer, the only challenge is for the reader to get a 94a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) * consistent read of the counters. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The writer uses this series of operations: 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1) Increment epoch to an odd number. 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * 2) Update counters. 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * 3) Increment epoch to an even number. 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * The reader must assure 1) that the epoch is even while it reads the 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * counters, and 2) that the epoch doesn't change between the time it 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * starts and finishes reading the counters. 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned epoch; 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* Profiling counters. */ 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prof_cnt_t cnts; 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct prof_ctx_s { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Associated backtrace. */ 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prof_bt_t *bt; 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* Protects cnt_merged and cnts_ql. */ 117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch malloc_mutex_t *lock; 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* Temporary storage for summation during dump. */ 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_cnt_t cnt_summed; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* When threads exit, they merge their stats into cnt_merged. */ 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_cnt_t cnt_merged; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * List of profile counters, one for each thread that has allocated in 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this context. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ql_head(prof_thr_cnt_t) cnts_ql; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct prof_tdata_s { 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /* 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Hash of (prof_bt_t *)-->(prof_thr_cnt_t *). Each thread keeps a 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * cache of backtraces, with associated thread-specific prof_thr_cnt_t 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * objects. Other threads may read the prof_thr_cnt_t contents, but no 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * others will ever write them. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Upon thread exit, the thread must merge all the prof_thr_cnt_t 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * counter data into the associated prof_ctx_t objects, and unlink/free 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the prof_thr_cnt_t objects. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ckh_t bt2cnt; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* LRU for contents of bt2cnt. */ 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ql_head(prof_thr_cnt_t) lru_ql; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Backtrace vector, used for calls to prof_backtrace(). */ 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void **vec; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Sampling state. */ 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t prng_state; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t threshold; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t accum; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* JEMALLOC_H_STRUCTS */ 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************/ 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef JEMALLOC_H_EXTERNS 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern bool opt_prof; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Even if opt_prof is true, sampling can be temporarily disabled by setting 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * opt_prof_active to false. No locking is used when updating opt_prof_active, 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * so there are no guarantees regarding how long it will take for all threads 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to notice state changes. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern bool opt_prof_active; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern size_t opt_lg_prof_sample; /* Mean bytes between samples. */ 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern ssize_t opt_lg_prof_interval; /* lg(prof_interval). */ 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern bool opt_prof_gdump; /* High-water memory dumping. */ 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern bool opt_prof_final; /* Final profile dumping. */ 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern bool opt_prof_leak; /* Dump leak summary at exit. */ 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern bool opt_prof_accum; /* Report cumulative bytes. */ 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern char opt_prof_prefix[PATH_MAX + 1]; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Profile dump interval, measured in bytes allocated. Each arena triggers a 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * profile dump when it reaches this threshold. The effect is that the 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * interval between profile dumps averages prof_interval, though the actual 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * interval between dumps will tend to be sporadic, and the interval will be a 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * maximum of approximately (prof_interval * narenas). 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern uint64_t prof_interval; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/* 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If true, promote small sampled objects to large objects, since small run 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * headers do not have embedded profile context pointers. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern bool prof_promote; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void bt_init(prof_bt_t *bt, void **vec); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void prof_backtrace(prof_bt_t *bt, unsigned nignore); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)prof_thr_cnt_t *prof_lookup(prof_bt_t *bt); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void prof_idump(void); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool prof_mdump(const char *filename); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void prof_gdump(void); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)prof_tdata_t *prof_tdata_init(void); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void prof_tdata_cleanup(void *arg); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void prof_boot0(void); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void prof_boot1(void); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool prof_boot2(void); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* JEMALLOC_H_EXTERNS */ 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************/ 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef JEMALLOC_H_INLINES 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROF_ALLOC_PREP(nignore, size, ret) do { \ 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_tdata_t *prof_tdata; \ 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_bt_t bt; \ 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) \ 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(size == s2u(size)); \ 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) \ 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_tdata = *prof_tdata_tsd_get(); \ 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prof_tdata == NULL) { \ 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_tdata = prof_tdata_init(); \ 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prof_tdata == NULL) { \ 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = NULL; \ 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; \ 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) \ 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opt_prof_active == false) { \ 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Sampling is currently inactive, so avoid sampling. */\ 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = (prof_thr_cnt_t *)(uintptr_t)1U; \ 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (opt_lg_prof_sample == 0) { \ 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Don't bother with sampling logic, since sampling */\ 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* interval is 1. */\ 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bt_init(&bt, prof_tdata->vec); \ 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_backtrace(&bt, nignore); \ 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = prof_lookup(&bt); \ 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { \ 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prof_tdata->threshold == 0) { \ 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Initialize. Seed the prng differently for */\ 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* each thread. */\ 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_tdata->prng_state = \ 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (uint64_t)(uintptr_t)&size; \ 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_sample_threshold_update(prof_tdata); \ 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) \ 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* Determine whether to capture a backtrace based on */\ 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* whether size is enough for prof_accum to reach */\ 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* prof_tdata->threshold. However, delay updating */\ 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* these variables until prof_{m,re}alloc(), because */\ 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* we don't know for sure that the allocation will */\ 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* succeed. */\ 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* */\ 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Use subtraction rather than addition to avoid */\ 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* potential integer overflow. */\ 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size >= prof_tdata->threshold - \ 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_tdata->accum) { \ 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bt_init(&bt, prof_tdata->vec); \ 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_backtrace(&bt, nignore); \ 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = prof_lookup(&bt); \ 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else \ 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = (prof_thr_cnt_t *)(uintptr_t)1U; \ 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef JEMALLOC_ENABLE_INLINE 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)malloc_tsd_protos(JEMALLOC_ATTR(unused), prof_tdata, prof_tdata_t *) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void prof_sample_threshold_update(prof_tdata_t *prof_tdata); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)prof_ctx_t *prof_ctx_get(const void *ptr); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void prof_ctx_set(const void *ptr, prof_ctx_t *ctx); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool prof_sample_accum_update(size_t size); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void prof_malloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t old_size, prof_ctx_t *old_ctx); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void prof_free(const void *ptr, size_t size); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_PROF_C_)) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Thread-specific backtrace cache, used to reduce bt2ctx contention. */ 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)malloc_tsd_externs(prof_tdata, prof_tdata_t *) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)malloc_tsd_funcs(JEMALLOC_INLINE, prof_tdata, prof_tdata_t *, NULL, 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_tdata_cleanup) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JEMALLOC_INLINE void 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)prof_sample_threshold_update(prof_tdata_t *prof_tdata) 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t r; 2837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) double u; 2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) cassert(config_prof); 2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) /* 2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * Compute sample threshold as a geometrically distributed random 2897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * variable with mean (2^opt_lg_prof_sample). 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * __ __ 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * | log(u) | 1 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * prof_tdata->threshold = | -------- |, where p = ------------------- 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * | log(1-p) | opt_lg_prof_sample 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * For more information on the math, see: 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Non-Uniform Random Variate Generation 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Luc Devroye 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Springer-Verlag, New York, 1986 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * pp 500 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (http://cg.scs.carleton.ca/~luc/rnbookindex.html) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prng64(r, 53, prof_tdata->prng_state, 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT64_C(6364136223846793005), UINT64_C(1442695040888963407)); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u = (double)r * (1.0/9007199254740992.0L); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_tdata->threshold = (uint64_t)(log(u) / 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(1.0 - (1.0 / (double)((uint64_t)1U << opt_lg_prof_sample)))) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) + (uint64_t)1U; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JEMALLOC_INLINE prof_ctx_t * 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)prof_ctx_get(const void *ptr) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_ctx_t *ret; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arena_chunk_t *chunk; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cassert(config_prof); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(ptr != NULL); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chunk != ptr) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Region. */ 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = arena_prof_ctx_get(ptr); 326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else 327effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ret = huge_prof_ctx_get(ptr); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (ret); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)JEMALLOC_INLINE void 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)prof_ctx_set(const void *ptr, prof_ctx_t *ctx) 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) arena_chunk_t *chunk; 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cassert(config_prof); 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(ptr != NULL); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chunk != ptr) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Region. */ 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arena_prof_ctx_set(ptr, ctx); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) huge_prof_ctx_set(ptr, ctx); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JEMALLOC_INLINE bool 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)prof_sample_accum_update(size_t size) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_tdata_t *prof_tdata; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cassert(config_prof); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Sampling logic is unnecessary if the interval is 1. */ 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(opt_lg_prof_sample != 0); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 357 prof_tdata = *prof_tdata_tsd_get(); 358 assert(prof_tdata != NULL); 359 360 /* Take care to avoid integer overflow. */ 361 if (size >= prof_tdata->threshold - prof_tdata->accum) { 362 prof_tdata->accum -= (prof_tdata->threshold - size); 363 /* Compute new sample threshold. */ 364 prof_sample_threshold_update(prof_tdata); 365 while (prof_tdata->accum >= prof_tdata->threshold) { 366 prof_tdata->accum -= prof_tdata->threshold; 367 prof_sample_threshold_update(prof_tdata); 368 } 369 return (false); 370 } else { 371 prof_tdata->accum += size; 372 return (true); 373 } 374} 375 376JEMALLOC_INLINE void 377prof_malloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt) 378{ 379 380 cassert(config_prof); 381 assert(ptr != NULL); 382 assert(size == isalloc(ptr, true)); 383 384 if (opt_lg_prof_sample != 0) { 385 if (prof_sample_accum_update(size)) { 386 /* 387 * Don't sample. For malloc()-like allocation, it is 388 * always possible to tell in advance how large an 389 * object's usable size will be, so there should never 390 * be a difference between the size passed to 391 * PROF_ALLOC_PREP() and prof_malloc(). 392 */ 393 assert((uintptr_t)cnt == (uintptr_t)1U); 394 } 395 } 396 397 if ((uintptr_t)cnt > (uintptr_t)1U) { 398 prof_ctx_set(ptr, cnt->ctx); 399 400 cnt->epoch++; 401 /*********/ 402 mb_write(); 403 /*********/ 404 cnt->cnts.curobjs++; 405 cnt->cnts.curbytes += size; 406 if (opt_prof_accum) { 407 cnt->cnts.accumobjs++; 408 cnt->cnts.accumbytes += size; 409 } 410 /*********/ 411 mb_write(); 412 /*********/ 413 cnt->epoch++; 414 /*********/ 415 mb_write(); 416 /*********/ 417 } else 418 prof_ctx_set(ptr, (prof_ctx_t *)(uintptr_t)1U); 419} 420 421JEMALLOC_INLINE void 422prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt, 423 size_t old_size, prof_ctx_t *old_ctx) 424{ 425 prof_thr_cnt_t *told_cnt; 426 427 cassert(config_prof); 428 assert(ptr != NULL || (uintptr_t)cnt <= (uintptr_t)1U); 429 430 if (ptr != NULL) { 431 assert(size == isalloc(ptr, true)); 432 if (opt_lg_prof_sample != 0) { 433 if (prof_sample_accum_update(size)) { 434 /* 435 * Don't sample. The size passed to 436 * PROF_ALLOC_PREP() was larger than what 437 * actually got allocated, so a backtrace was 438 * captured for this allocation, even though 439 * its actual size was insufficient to cross 440 * the sample threshold. 441 */ 442 cnt = (prof_thr_cnt_t *)(uintptr_t)1U; 443 } 444 } 445 } 446 447 if ((uintptr_t)old_ctx > (uintptr_t)1U) { 448 told_cnt = prof_lookup(old_ctx->bt); 449 if (told_cnt == NULL) { 450 /* 451 * It's too late to propagate OOM for this realloc(), 452 * so operate directly on old_cnt->ctx->cnt_merged. 453 */ 454 malloc_mutex_lock(old_ctx->lock); 455 old_ctx->cnt_merged.curobjs--; 456 old_ctx->cnt_merged.curbytes -= old_size; 457 malloc_mutex_unlock(old_ctx->lock); 458 told_cnt = (prof_thr_cnt_t *)(uintptr_t)1U; 459 } 460 } else 461 told_cnt = (prof_thr_cnt_t *)(uintptr_t)1U; 462 463 if ((uintptr_t)told_cnt > (uintptr_t)1U) 464 told_cnt->epoch++; 465 if ((uintptr_t)cnt > (uintptr_t)1U) { 466 prof_ctx_set(ptr, cnt->ctx); 467 cnt->epoch++; 468 } else 469 prof_ctx_set(ptr, (prof_ctx_t *)(uintptr_t)1U); 470 /*********/ 471 mb_write(); 472 /*********/ 473 if ((uintptr_t)told_cnt > (uintptr_t)1U) { 474 told_cnt->cnts.curobjs--; 475 told_cnt->cnts.curbytes -= old_size; 476 } 477 if ((uintptr_t)cnt > (uintptr_t)1U) { 478 cnt->cnts.curobjs++; 479 cnt->cnts.curbytes += size; 480 if (opt_prof_accum) { 481 cnt->cnts.accumobjs++; 482 cnt->cnts.accumbytes += size; 483 } 484 } 485 /*********/ 486 mb_write(); 487 /*********/ 488 if ((uintptr_t)told_cnt > (uintptr_t)1U) 489 told_cnt->epoch++; 490 if ((uintptr_t)cnt > (uintptr_t)1U) 491 cnt->epoch++; 492 /*********/ 493 mb_write(); /* Not strictly necessary. */ 494} 495 496JEMALLOC_INLINE void 497prof_free(const void *ptr, size_t size) 498{ 499 prof_ctx_t *ctx = prof_ctx_get(ptr); 500 501 cassert(config_prof); 502 503 if ((uintptr_t)ctx > (uintptr_t)1) { 504 assert(size == isalloc(ptr, true)); 505 prof_thr_cnt_t *tcnt = prof_lookup(ctx->bt); 506 507 if (tcnt != NULL) { 508 tcnt->epoch++; 509 /*********/ 510 mb_write(); 511 /*********/ 512 tcnt->cnts.curobjs--; 513 tcnt->cnts.curbytes -= size; 514 /*********/ 515 mb_write(); 516 /*********/ 517 tcnt->epoch++; 518 /*********/ 519 mb_write(); 520 /*********/ 521 } else { 522 /* 523 * OOM during free() cannot be propagated, so operate 524 * directly on cnt->ctx->cnt_merged. 525 */ 526 malloc_mutex_lock(ctx->lock); 527 ctx->cnt_merged.curobjs--; 528 ctx->cnt_merged.curbytes -= size; 529 malloc_mutex_unlock(ctx->lock); 530 } 531 } 532} 533#endif 534 535#endif /* JEMALLOC_H_INLINES */ 536/******************************************************************************/ 537