mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-06-01 17:54:16 +03:00
Merge ca77aca653 into 6b24522545
This commit is contained in:
commit
2512efbe5a
49 changed files with 4171 additions and 4241 deletions
|
|
@ -109,6 +109,15 @@ C_SRCS := $(srcroot)src/jemalloc.c \
|
|||
$(srcroot)src/ckh.c \
|
||||
$(srcroot)src/counter.c \
|
||||
$(srcroot)src/ctl.c \
|
||||
$(srcroot)src/ctl_arena.c \
|
||||
$(srcroot)src/ctl_background_thread.c \
|
||||
$(srcroot)src/ctl_config.c \
|
||||
$(srcroot)src/ctl_opt.c \
|
||||
$(srcroot)src/ctl_prof.c \
|
||||
$(srcroot)src/ctl_stats.c \
|
||||
$(srcroot)src/ctl_thread.c \
|
||||
$(srcroot)src/ctl_tcache.c \
|
||||
$(srcroot)src/ctl_utilization.c \
|
||||
$(srcroot)src/decay.c \
|
||||
$(srcroot)src/div.c \
|
||||
$(srcroot)src/ecache.c \
|
||||
|
|
|
|||
|
|
@ -115,7 +115,11 @@ bool ctl_boot(void);
|
|||
void ctl_prefork(tsdn_t *tsdn);
|
||||
void ctl_postfork_parent(tsdn_t *tsdn);
|
||||
void ctl_postfork_child(tsdn_t *tsdn);
|
||||
void ctl_mtx_lock(tsdn_t *tsdn);
|
||||
void ctl_mtx_unlock(tsdn_t *tsdn);
|
||||
void ctl_mtx_assert_held(tsdn_t *tsdn);
|
||||
void ctl_mtx_prof_read(tsdn_t *tsdn, mutex_prof_data_t *mutex_prof_data);
|
||||
void ctl_mtx_prof_data_reset(tsdn_t *tsdn);
|
||||
|
||||
#define xmallctl(name, oldp, oldlenp, newp, newlen) \
|
||||
do { \
|
||||
|
|
|
|||
54
include/jemalloc/internal/ctl_arena.h
Normal file
54
include/jemalloc/internal/ctl_arena.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef JEMALLOC_INTERNAL_CTL_ARENA_H
|
||||
#define JEMALLOC_INTERNAL_CTL_ARENA_H
|
||||
|
||||
#include "jemalloc/internal/ctl_mallctl.h"
|
||||
|
||||
#define CTL_ARENA_PROTO(n) \
|
||||
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
|
||||
CTL_ARENA_PROTO(arena_i_initialized)
|
||||
CTL_ARENA_PROTO(arena_i_decay)
|
||||
CTL_ARENA_PROTO(arena_i_purge)
|
||||
CTL_ARENA_PROTO(arena_i_reset)
|
||||
CTL_ARENA_PROTO(arena_i_destroy)
|
||||
CTL_ARENA_PROTO(arena_i_dss)
|
||||
CTL_ARENA_PROTO(arena_i_oversize_threshold)
|
||||
CTL_ARENA_PROTO(arena_i_dirty_decay_ms)
|
||||
CTL_ARENA_PROTO(arena_i_muzzy_decay_ms)
|
||||
CTL_ARENA_PROTO(arena_i_extent_hooks)
|
||||
CTL_ARENA_PROTO(arena_i_retain_grow_limit)
|
||||
CTL_ARENA_PROTO(arena_i_name)
|
||||
|
||||
CTL_ARENA_PROTO(arenas_narenas)
|
||||
CTL_ARENA_PROTO(arenas_dirty_decay_ms)
|
||||
CTL_ARENA_PROTO(arenas_muzzy_decay_ms)
|
||||
CTL_ARENA_PROTO(arenas_quantum)
|
||||
CTL_ARENA_PROTO(arenas_page)
|
||||
CTL_ARENA_PROTO(arenas_hugepage)
|
||||
CTL_ARENA_PROTO(arenas_tcache_max)
|
||||
CTL_ARENA_PROTO(arenas_nbins)
|
||||
CTL_ARENA_PROTO(arenas_nhbins)
|
||||
CTL_ARENA_PROTO(arenas_bin_i_size)
|
||||
CTL_ARENA_PROTO(arenas_bin_i_nregs)
|
||||
CTL_ARENA_PROTO(arenas_bin_i_slab_size)
|
||||
CTL_ARENA_PROTO(arenas_bin_i_nshards)
|
||||
CTL_ARENA_PROTO(arenas_nlextents)
|
||||
CTL_ARENA_PROTO(arenas_lextent_i_size)
|
||||
CTL_ARENA_PROTO(arenas_create)
|
||||
CTL_ARENA_PROTO(arenas_lookup)
|
||||
CTL_ARENA_PROTO(experimental_arenas_create_ext)
|
||||
|
||||
#undef CTL_ARENA_PROTO
|
||||
|
||||
bool ctl_arenas_init(tsd_t *tsd);
|
||||
ctl_arena_t *ctl_arenas_refresh(tsdn_t *tsdn);
|
||||
ctl_arena_t *ctl_arenas_i(size_t i);
|
||||
uint64_t ctl_arenas_epoch_get(void);
|
||||
void ctl_arenas_epoch_advance(void);
|
||||
bool ctl_arena_i_indexable(tsdn_t *tsdn, size_t i);
|
||||
bool ctl_arenas_i_verify(size_t i);
|
||||
int ctl_arena_create(tsd_t *tsd, void *oldp, size_t *oldlenp,
|
||||
const arena_config_t *config);
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_CTL_ARENA_H */
|
||||
11
include/jemalloc/internal/ctl_background_thread.h
Normal file
11
include/jemalloc/internal/ctl_background_thread.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef JEMALLOC_INTERNAL_CTL_BACKGROUND_THREAD_H
|
||||
#define JEMALLOC_INTERNAL_CTL_BACKGROUND_THREAD_H
|
||||
|
||||
#include "jemalloc/internal/ctl_mallctl.h"
|
||||
|
||||
int background_thread_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int max_background_threads_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_CTL_BACKGROUND_THREAD_H */
|
||||
33
include/jemalloc/internal/ctl_config.h
Normal file
33
include/jemalloc/internal/ctl_config.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef JEMALLOC_INTERNAL_CTL_CONFIG_H
|
||||
#define JEMALLOC_INTERNAL_CTL_CONFIG_H
|
||||
|
||||
#include "jemalloc/internal/ctl_mallctl.h"
|
||||
|
||||
int config_cache_oblivious_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int config_debug_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen);
|
||||
int config_fill_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen);
|
||||
int config_lazy_lock_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int config_malloc_conf_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int config_opt_safety_checks_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int config_prof_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen);
|
||||
int config_prof_libgcc_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int config_prof_libunwind_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int config_prof_frameptr_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int config_stats_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen);
|
||||
int config_utrace_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen);
|
||||
int config_xmalloc_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen);
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_CTL_CONFIG_H */
|
||||
170
include/jemalloc/internal/ctl_mallctl.h
Normal file
170
include/jemalloc/internal/ctl_mallctl.h
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
#ifndef JEMALLOC_INTERNAL_CTL_MALLCTL_H
|
||||
#define JEMALLOC_INTERNAL_CTL_MALLCTL_H
|
||||
|
||||
#include "jemalloc/internal/ctl.h"
|
||||
|
||||
#define READONLY() \
|
||||
do { \
|
||||
if (newp != NULL || newlen != 0) { \
|
||||
ret = EPERM; \
|
||||
goto label_return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define WRITEONLY() \
|
||||
do { \
|
||||
if (oldp != NULL || oldlenp != NULL) { \
|
||||
ret = EPERM; \
|
||||
goto label_return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Can read or write, but not both. */
|
||||
#define READ_XOR_WRITE() \
|
||||
do { \
|
||||
if ((oldp != NULL && oldlenp != NULL) \
|
||||
&& (newp != NULL || newlen != 0)) { \
|
||||
ret = EPERM; \
|
||||
goto label_return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Can neither read nor write. */
|
||||
#define NEITHER_READ_NOR_WRITE() \
|
||||
do { \
|
||||
if (oldp != NULL || oldlenp != NULL || newp != NULL \
|
||||
|| newlen != 0) { \
|
||||
ret = EPERM; \
|
||||
goto label_return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Verify that the space provided is enough. */
|
||||
#define VERIFY_READ(t) \
|
||||
do { \
|
||||
if (oldp == NULL || oldlenp == NULL \
|
||||
|| *oldlenp != sizeof(t)) { \
|
||||
if (oldlenp != NULL) { \
|
||||
*oldlenp = 0; \
|
||||
} \
|
||||
ret = EINVAL; \
|
||||
goto label_return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define READ(v, t) \
|
||||
do { \
|
||||
if (oldp != NULL && oldlenp != NULL) { \
|
||||
if (*oldlenp != sizeof(t)) { \
|
||||
size_t copylen = (sizeof(t) <= *oldlenp) \
|
||||
? sizeof(t) \
|
||||
: *oldlenp; \
|
||||
memcpy(oldp, (void *)&(v), copylen); \
|
||||
*oldlenp = copylen; \
|
||||
ret = EINVAL; \
|
||||
goto label_return; \
|
||||
} \
|
||||
*(t *)oldp = (v); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define WRITE(v, t) \
|
||||
do { \
|
||||
if (newp != NULL) { \
|
||||
if (newlen != sizeof(t)) { \
|
||||
ret = EINVAL; \
|
||||
goto label_return; \
|
||||
} \
|
||||
(v) = *(t *)newp; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ASSURED_WRITE(v, t) \
|
||||
do { \
|
||||
if (newp == NULL || newlen != sizeof(t)) { \
|
||||
ret = EINVAL; \
|
||||
goto label_return; \
|
||||
} \
|
||||
(v) = *(t *)newp; \
|
||||
} while (0)
|
||||
|
||||
#define MIB_UNSIGNED(v, i) \
|
||||
do { \
|
||||
if (mib[i] > UINT_MAX) { \
|
||||
ret = EFAULT; \
|
||||
goto label_return; \
|
||||
} \
|
||||
v = (unsigned)mib[i]; \
|
||||
} while (0)
|
||||
|
||||
#define CTL_RO_NL_GEN_PUBLIC(n, v, t) \
|
||||
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
|
||||
int ret; \
|
||||
t oldval; \
|
||||
\
|
||||
READONLY(); \
|
||||
oldval = (v); \
|
||||
READ(oldval, t); \
|
||||
\
|
||||
ret = 0; \
|
||||
label_return: \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define CTL_RO_GEN_PUBLIC(n, v, t) \
|
||||
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
|
||||
int ret; \
|
||||
t oldval; \
|
||||
\
|
||||
READONLY(); \
|
||||
ctl_mtx_lock(tsd_tsdn(tsd)); \
|
||||
oldval = (v); \
|
||||
READ(oldval, t); \
|
||||
\
|
||||
ret = 0; \
|
||||
label_return: \
|
||||
ctl_mtx_unlock(tsd_tsdn(tsd)); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define CTL_RO_NL_CGEN_PUBLIC(c, n, v, t) \
|
||||
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
|
||||
int ret; \
|
||||
t oldval; \
|
||||
\
|
||||
if (!(c)) { \
|
||||
return ENOENT; \
|
||||
} \
|
||||
READONLY(); \
|
||||
oldval = (v); \
|
||||
READ(oldval, t); \
|
||||
\
|
||||
ret = 0; \
|
||||
label_return: \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define CTL_RO_CGEN_PUBLIC(c, n, v, t) \
|
||||
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
|
||||
int ret; \
|
||||
t oldval; \
|
||||
\
|
||||
if (!(c)) { \
|
||||
return ENOENT; \
|
||||
} \
|
||||
READONLY(); \
|
||||
ctl_mtx_lock(tsd_tsdn(tsd)); \
|
||||
oldval = (v); \
|
||||
READ(oldval, t); \
|
||||
\
|
||||
ret = 0; \
|
||||
label_return: \
|
||||
ctl_mtx_unlock(tsd_tsdn(tsd)); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_CTL_MALLCTL_H */
|
||||
93
include/jemalloc/internal/ctl_opt.h
Normal file
93
include/jemalloc/internal/ctl_opt.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#ifndef JEMALLOC_INTERNAL_CTL_OPT_H
|
||||
#define JEMALLOC_INTERNAL_CTL_OPT_H
|
||||
|
||||
#include "jemalloc/internal/ctl_mallctl.h"
|
||||
|
||||
#define CTL_OPT_PROTO(n) \
|
||||
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
|
||||
CTL_OPT_PROTO(opt_abort)
|
||||
CTL_OPT_PROTO(opt_abort_conf)
|
||||
CTL_OPT_PROTO(opt_cache_oblivious)
|
||||
CTL_OPT_PROTO(opt_debug_double_free_max_scan)
|
||||
CTL_OPT_PROTO(opt_trust_madvise)
|
||||
CTL_OPT_PROTO(opt_experimental_hpa_start_huge_if_thp_always)
|
||||
CTL_OPT_PROTO(opt_experimental_hpa_enforce_hugify)
|
||||
CTL_OPT_PROTO(opt_confirm_conf)
|
||||
CTL_OPT_PROTO(opt_hpa)
|
||||
CTL_OPT_PROTO(opt_hpa_slab_max_alloc)
|
||||
CTL_OPT_PROTO(opt_hpa_hugification_threshold)
|
||||
CTL_OPT_PROTO(opt_hpa_hugify_delay_ms)
|
||||
CTL_OPT_PROTO(opt_hpa_hugify_sync)
|
||||
CTL_OPT_PROTO(opt_hpa_min_purge_interval_ms)
|
||||
CTL_OPT_PROTO(opt_experimental_hpa_max_purge_nhp)
|
||||
CTL_OPT_PROTO(opt_hpa_purge_threshold)
|
||||
CTL_OPT_PROTO(opt_hpa_min_purge_delay_ms)
|
||||
CTL_OPT_PROTO(opt_hpa_hugify_style)
|
||||
CTL_OPT_PROTO(opt_hpa_dirty_mult)
|
||||
CTL_OPT_PROTO(opt_hpa_sec_nshards)
|
||||
CTL_OPT_PROTO(opt_hpa_sec_max_alloc)
|
||||
CTL_OPT_PROTO(opt_hpa_sec_max_bytes)
|
||||
CTL_OPT_PROTO(opt_huge_arena_pac_thp)
|
||||
CTL_OPT_PROTO(opt_metadata_thp)
|
||||
CTL_OPT_PROTO(opt_retain)
|
||||
CTL_OPT_PROTO(opt_dss)
|
||||
CTL_OPT_PROTO(opt_narenas)
|
||||
CTL_OPT_PROTO(opt_percpu_arena)
|
||||
CTL_OPT_PROTO(opt_oversize_threshold)
|
||||
CTL_OPT_PROTO(opt_background_thread)
|
||||
CTL_OPT_PROTO(opt_mutex_max_spin)
|
||||
CTL_OPT_PROTO(opt_max_background_threads)
|
||||
CTL_OPT_PROTO(opt_dirty_decay_ms)
|
||||
CTL_OPT_PROTO(opt_muzzy_decay_ms)
|
||||
CTL_OPT_PROTO(opt_stats_print)
|
||||
CTL_OPT_PROTO(opt_stats_print_opts)
|
||||
CTL_OPT_PROTO(opt_stats_interval)
|
||||
CTL_OPT_PROTO(opt_stats_interval_opts)
|
||||
CTL_OPT_PROTO(opt_junk)
|
||||
CTL_OPT_PROTO(opt_zero)
|
||||
CTL_OPT_PROTO(opt_utrace)
|
||||
CTL_OPT_PROTO(opt_xmalloc)
|
||||
CTL_OPT_PROTO(opt_experimental_infallible_new)
|
||||
CTL_OPT_PROTO(opt_experimental_tcache_gc)
|
||||
CTL_OPT_PROTO(opt_tcache)
|
||||
CTL_OPT_PROTO(opt_tcache_max)
|
||||
CTL_OPT_PROTO(opt_tcache_nslots_small_min)
|
||||
CTL_OPT_PROTO(opt_tcache_nslots_small_max)
|
||||
CTL_OPT_PROTO(opt_tcache_nslots_large)
|
||||
CTL_OPT_PROTO(opt_lg_tcache_nslots_mul)
|
||||
CTL_OPT_PROTO(opt_tcache_gc_incr_bytes)
|
||||
CTL_OPT_PROTO(opt_tcache_gc_delay_bytes)
|
||||
CTL_OPT_PROTO(opt_lg_tcache_flush_small_div)
|
||||
CTL_OPT_PROTO(opt_lg_tcache_flush_large_div)
|
||||
CTL_OPT_PROTO(opt_thp)
|
||||
CTL_OPT_PROTO(opt_lg_extent_max_active_fit)
|
||||
CTL_OPT_PROTO(opt_prof)
|
||||
CTL_OPT_PROTO(opt_prof_prefix)
|
||||
CTL_OPT_PROTO(opt_prof_active)
|
||||
CTL_OPT_PROTO(opt_prof_thread_active_init)
|
||||
CTL_OPT_PROTO(opt_prof_bt_max)
|
||||
CTL_OPT_PROTO(opt_lg_prof_sample)
|
||||
CTL_OPT_PROTO(opt_lg_prof_interval)
|
||||
CTL_OPT_PROTO(opt_prof_gdump)
|
||||
CTL_OPT_PROTO(opt_prof_final)
|
||||
CTL_OPT_PROTO(opt_prof_leak)
|
||||
CTL_OPT_PROTO(opt_prof_leak_error)
|
||||
CTL_OPT_PROTO(opt_prof_accum)
|
||||
CTL_OPT_PROTO(opt_prof_pid_namespace)
|
||||
CTL_OPT_PROTO(opt_prof_recent_alloc_max)
|
||||
CTL_OPT_PROTO(opt_prof_stats)
|
||||
CTL_OPT_PROTO(opt_prof_sys_thread_name)
|
||||
CTL_OPT_PROTO(opt_prof_time_res)
|
||||
CTL_OPT_PROTO(opt_lg_san_uaf_align)
|
||||
CTL_OPT_PROTO(opt_zero_realloc)
|
||||
CTL_OPT_PROTO(opt_disable_large_size_classes)
|
||||
CTL_OPT_PROTO(opt_process_madvise_max_batch)
|
||||
CTL_OPT_PROTO(opt_malloc_conf_symlink)
|
||||
CTL_OPT_PROTO(opt_malloc_conf_env_var)
|
||||
CTL_OPT_PROTO(opt_malloc_conf_global_var)
|
||||
|
||||
#undef CTL_OPT_PROTO
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_CTL_OPT_H */
|
||||
33
include/jemalloc/internal/ctl_prof.h
Normal file
33
include/jemalloc/internal/ctl_prof.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef JEMALLOC_INTERNAL_CTL_PROF_H
|
||||
#define JEMALLOC_INTERNAL_CTL_PROF_H
|
||||
|
||||
#include "jemalloc/internal/ctl_mallctl.h"
|
||||
|
||||
#define CTL_PROF_PROTO(n) \
|
||||
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
|
||||
CTL_PROF_PROTO(prof_thread_active_init)
|
||||
CTL_PROF_PROTO(prof_active)
|
||||
CTL_PROF_PROTO(prof_dump)
|
||||
CTL_PROF_PROTO(prof_gdump)
|
||||
CTL_PROF_PROTO(prof_prefix)
|
||||
CTL_PROF_PROTO(prof_reset)
|
||||
CTL_PROF_PROTO(prof_interval)
|
||||
CTL_PROF_PROTO(lg_prof_sample)
|
||||
CTL_PROF_PROTO(prof_log_start)
|
||||
CTL_PROF_PROTO(prof_log_stop)
|
||||
CTL_PROF_PROTO(prof_stats_bins_i_live)
|
||||
CTL_PROF_PROTO(prof_stats_bins_i_accum)
|
||||
CTL_PROF_PROTO(prof_stats_lextents_i_live)
|
||||
CTL_PROF_PROTO(prof_stats_lextents_i_accum)
|
||||
CTL_PROF_PROTO(experimental_hooks_prof_backtrace)
|
||||
CTL_PROF_PROTO(experimental_hooks_prof_dump)
|
||||
CTL_PROF_PROTO(experimental_hooks_prof_sample)
|
||||
CTL_PROF_PROTO(experimental_hooks_prof_sample_free)
|
||||
CTL_PROF_PROTO(experimental_prof_recent_alloc_max)
|
||||
CTL_PROF_PROTO(experimental_prof_recent_alloc_dump)
|
||||
|
||||
#undef CTL_PROF_PROTO
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_CTL_PROF_H */
|
||||
179
include/jemalloc/internal/ctl_stats.h
Normal file
179
include/jemalloc/internal/ctl_stats.h
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
#ifndef JEMALLOC_INTERNAL_CTL_STATS_H
|
||||
#define JEMALLOC_INTERNAL_CTL_STATS_H
|
||||
|
||||
#include "jemalloc/internal/ctl_mallctl.h"
|
||||
|
||||
#define CTL_STATS_PROTO(n) \
|
||||
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
|
||||
CTL_STATS_PROTO(stats_arenas_i_small_allocated)
|
||||
CTL_STATS_PROTO(stats_arenas_i_small_nmalloc)
|
||||
CTL_STATS_PROTO(stats_arenas_i_small_ndalloc)
|
||||
CTL_STATS_PROTO(stats_arenas_i_small_nrequests)
|
||||
CTL_STATS_PROTO(stats_arenas_i_small_nfills)
|
||||
CTL_STATS_PROTO(stats_arenas_i_small_nflushes)
|
||||
CTL_STATS_PROTO(stats_arenas_i_large_allocated)
|
||||
CTL_STATS_PROTO(stats_arenas_i_large_nmalloc)
|
||||
CTL_STATS_PROTO(stats_arenas_i_large_ndalloc)
|
||||
CTL_STATS_PROTO(stats_arenas_i_large_nrequests)
|
||||
CTL_STATS_PROTO(stats_arenas_i_large_nfills)
|
||||
CTL_STATS_PROTO(stats_arenas_i_large_nflushes)
|
||||
CTL_STATS_PROTO(stats_arenas_i_bins_j_nmalloc)
|
||||
CTL_STATS_PROTO(stats_arenas_i_bins_j_ndalloc)
|
||||
CTL_STATS_PROTO(stats_arenas_i_bins_j_nrequests)
|
||||
CTL_STATS_PROTO(stats_arenas_i_bins_j_curregs)
|
||||
CTL_STATS_PROTO(stats_arenas_i_bins_j_nfills)
|
||||
CTL_STATS_PROTO(stats_arenas_i_bins_j_nflushes)
|
||||
CTL_STATS_PROTO(stats_arenas_i_bins_j_nslabs)
|
||||
CTL_STATS_PROTO(stats_arenas_i_bins_j_nreslabs)
|
||||
CTL_STATS_PROTO(stats_arenas_i_bins_j_curslabs)
|
||||
CTL_STATS_PROTO(stats_arenas_i_bins_j_nonfull_slabs)
|
||||
CTL_STATS_PROTO(stats_arenas_i_lextents_j_nmalloc)
|
||||
CTL_STATS_PROTO(stats_arenas_i_lextents_j_ndalloc)
|
||||
CTL_STATS_PROTO(stats_arenas_i_lextents_j_nrequests)
|
||||
CTL_STATS_PROTO(stats_arenas_i_lextents_j_curlextents)
|
||||
CTL_STATS_PROTO(stats_arenas_i_extents_j_ndirty)
|
||||
CTL_STATS_PROTO(stats_arenas_i_extents_j_nmuzzy)
|
||||
CTL_STATS_PROTO(stats_arenas_i_extents_j_nretained)
|
||||
CTL_STATS_PROTO(stats_arenas_i_extents_j_npinned)
|
||||
CTL_STATS_PROTO(stats_arenas_i_extents_j_dirty_bytes)
|
||||
CTL_STATS_PROTO(stats_arenas_i_extents_j_muzzy_bytes)
|
||||
CTL_STATS_PROTO(stats_arenas_i_extents_j_retained_bytes)
|
||||
CTL_STATS_PROTO(stats_arenas_i_extents_j_pinned_bytes)
|
||||
|
||||
/* Merged set of stats for HPA shard. */
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_npageslabs)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_nactive)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_ndirty)
|
||||
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_npurge_passes)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_npurges)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_nhugifies)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_nhugify_failures)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_ndehugifies)
|
||||
|
||||
/* Set of stats for non-hugified and hugified slabs. */
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_slabs_npageslabs_nonhuge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_slabs_npageslabs_huge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_slabs_nactive_nonhuge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_slabs_nactive_huge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_slabs_ndirty_nonhuge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_slabs_ndirty_huge)
|
||||
|
||||
/* A parallel set of stats for full slabs. */
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_full_slabs_npageslabs_nonhuge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_full_slabs_npageslabs_huge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_full_slabs_nactive_nonhuge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_full_slabs_nactive_huge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_full_slabs_ndirty_nonhuge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_full_slabs_ndirty_huge)
|
||||
|
||||
/* A parallel set for the empty slabs. */
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_empty_slabs_npageslabs_nonhuge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_empty_slabs_npageslabs_huge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_empty_slabs_nactive_nonhuge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_empty_slabs_nactive_huge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_empty_slabs_ndirty_nonhuge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_empty_slabs_ndirty_huge)
|
||||
|
||||
/*
|
||||
* And one for the slabs that are neither empty nor full, but indexed by how
|
||||
* full they are.
|
||||
*/
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_nonfull_slabs_j_npageslabs_nonhuge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_nonfull_slabs_j_npageslabs_huge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_nonfull_slabs_j_nactive_nonhuge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_nonfull_slabs_j_nactive_huge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_nonfull_slabs_j_ndirty_nonhuge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_nonfull_slabs_j_ndirty_huge)
|
||||
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_alloc_j_min_extents)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_alloc_j_max_extents)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_alloc_j_extents)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_alloc_j_ps)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_alloc_j_pages_per_ps)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_alloc_j_extents_per_ps)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_shard_alloc_j_total_elapsed_ns_per_ps)
|
||||
|
||||
CTL_STATS_PROTO(stats_arenas_i_nthreads)
|
||||
CTL_STATS_PROTO(stats_arenas_i_uptime)
|
||||
CTL_STATS_PROTO(stats_arenas_i_dss)
|
||||
CTL_STATS_PROTO(stats_arenas_i_dirty_decay_ms)
|
||||
CTL_STATS_PROTO(stats_arenas_i_muzzy_decay_ms)
|
||||
CTL_STATS_PROTO(stats_arenas_i_pactive)
|
||||
CTL_STATS_PROTO(stats_arenas_i_pdirty)
|
||||
CTL_STATS_PROTO(stats_arenas_i_pmuzzy)
|
||||
CTL_STATS_PROTO(stats_arenas_i_mapped)
|
||||
CTL_STATS_PROTO(stats_arenas_i_retained)
|
||||
CTL_STATS_PROTO(stats_arenas_i_pinned)
|
||||
CTL_STATS_PROTO(stats_arenas_i_extent_avail)
|
||||
CTL_STATS_PROTO(stats_arenas_i_dirty_npurge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_dirty_nmadvise)
|
||||
CTL_STATS_PROTO(stats_arenas_i_dirty_purged)
|
||||
CTL_STATS_PROTO(stats_arenas_i_muzzy_npurge)
|
||||
CTL_STATS_PROTO(stats_arenas_i_muzzy_nmadvise)
|
||||
CTL_STATS_PROTO(stats_arenas_i_muzzy_purged)
|
||||
CTL_STATS_PROTO(stats_arenas_i_base)
|
||||
CTL_STATS_PROTO(stats_arenas_i_internal)
|
||||
CTL_STATS_PROTO(stats_arenas_i_metadata_edata)
|
||||
CTL_STATS_PROTO(stats_arenas_i_metadata_rtree)
|
||||
CTL_STATS_PROTO(stats_arenas_i_metadata_thp)
|
||||
CTL_STATS_PROTO(stats_arenas_i_tcache_bytes)
|
||||
CTL_STATS_PROTO(stats_arenas_i_tcache_stashed_bytes)
|
||||
CTL_STATS_PROTO(stats_arenas_i_resident)
|
||||
CTL_STATS_PROTO(stats_arenas_i_abandoned_vm)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_sec_bytes)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_sec_hits)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_sec_misses)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_sec_dalloc_flush)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_sec_dalloc_noflush)
|
||||
CTL_STATS_PROTO(stats_arenas_i_hpa_sec_overfills)
|
||||
CTL_STATS_PROTO(stats_allocated)
|
||||
CTL_STATS_PROTO(stats_active)
|
||||
CTL_STATS_PROTO(stats_background_thread_num_threads)
|
||||
CTL_STATS_PROTO(stats_background_thread_num_runs)
|
||||
CTL_STATS_PROTO(stats_background_thread_run_interval)
|
||||
CTL_STATS_PROTO(stats_metadata)
|
||||
CTL_STATS_PROTO(stats_metadata_edata)
|
||||
CTL_STATS_PROTO(stats_metadata_rtree)
|
||||
CTL_STATS_PROTO(stats_metadata_thp)
|
||||
CTL_STATS_PROTO(stats_resident)
|
||||
CTL_STATS_PROTO(stats_mapped)
|
||||
CTL_STATS_PROTO(stats_retained)
|
||||
CTL_STATS_PROTO(stats_pinned)
|
||||
CTL_STATS_PROTO(stats_zero_reallocs)
|
||||
CTL_STATS_PROTO(approximate_stats_active)
|
||||
|
||||
#define MUTEX_STATS_CTL_PROTO_GEN(n) \
|
||||
CTL_STATS_PROTO(stats_##n##_num_ops) \
|
||||
CTL_STATS_PROTO(stats_##n##_num_wait) \
|
||||
CTL_STATS_PROTO(stats_##n##_num_spin_acq) \
|
||||
CTL_STATS_PROTO(stats_##n##_num_owner_switch) \
|
||||
CTL_STATS_PROTO(stats_##n##_total_wait_time) \
|
||||
CTL_STATS_PROTO(stats_##n##_max_wait_time) \
|
||||
CTL_STATS_PROTO(stats_##n##_max_num_thds)
|
||||
|
||||
/* Global mutexes. */
|
||||
#define OP(mtx) MUTEX_STATS_CTL_PROTO_GEN(mutexes_##mtx)
|
||||
MUTEX_PROF_GLOBAL_MUTEXES
|
||||
#undef OP
|
||||
|
||||
/* Per arena mutexes. */
|
||||
#define OP(mtx) MUTEX_STATS_CTL_PROTO_GEN(arenas_i_mutexes_##mtx)
|
||||
MUTEX_PROF_ARENA_MUTEXES
|
||||
#undef OP
|
||||
|
||||
/* Arena bin mutexes. */
|
||||
MUTEX_STATS_CTL_PROTO_GEN(arenas_i_bins_j_mutex)
|
||||
#undef MUTEX_STATS_CTL_PROTO_GEN
|
||||
|
||||
CTL_STATS_PROTO(stats_mutexes_reset)
|
||||
|
||||
|
||||
#undef CTL_STATS_PROTO
|
||||
|
||||
bool ctl_stats_init(tsdn_t *tsdn);
|
||||
void ctl_stats_refresh(tsdn_t *tsdn, ctl_arena_t *ctl_sarena);
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_CTL_STATS_H */
|
||||
13
include/jemalloc/internal/ctl_tcache.h
Normal file
13
include/jemalloc/internal/ctl_tcache.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef JEMALLOC_INTERNAL_CTL_TCACHE_H
|
||||
#define JEMALLOC_INTERNAL_CTL_TCACHE_H
|
||||
|
||||
#include "jemalloc/internal/ctl_mallctl.h"
|
||||
|
||||
int tcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen);
|
||||
int tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen);
|
||||
int tcache_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen);
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_CTL_TCACHE_H */
|
||||
39
include/jemalloc/internal/ctl_thread.h
Normal file
39
include/jemalloc/internal/ctl_thread.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef JEMALLOC_INTERNAL_CTL_THREAD_H
|
||||
#define JEMALLOC_INTERNAL_CTL_THREAD_H
|
||||
|
||||
#include "jemalloc/internal/ctl_mallctl.h"
|
||||
|
||||
int thread_tcache_enabled_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_tcache_max_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_tcache_ncached_max_write_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_tcache_ncached_max_read_sizeclass_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_peak_read_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_peak_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_prof_name_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_arena_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_allocated_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_allocatedp_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_deallocated_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_deallocatedp_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
int thread_idle_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen);
|
||||
int experimental_hooks_thread_event_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_CTL_THREAD_H */
|
||||
9
include/jemalloc/internal/ctl_utilization.h
Normal file
9
include/jemalloc/internal/ctl_utilization.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef JEMALLOC_INTERNAL_CTL_UTILIZATION_H
|
||||
#define JEMALLOC_INTERNAL_CTL_UTILIZATION_H
|
||||
|
||||
#include "jemalloc/internal/ctl_mallctl.h"
|
||||
|
||||
int experimental_utilization_batch_query_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_CTL_UTILIZATION_H */
|
||||
|
|
@ -11,9 +11,8 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* The following two structs are for experimental purposes. See
|
||||
* experimental_utilization_query_ctl and
|
||||
* experimental_utilization_batch_query_ctl in src/ctl.c.
|
||||
* The following struct is for experimental purposes. See
|
||||
* experimental_utilization_batch_query_ctl in src/ctl_utilization.c.
|
||||
*/
|
||||
typedef struct inspect_extent_util_stats_s inspect_extent_util_stats_t;
|
||||
struct inspect_extent_util_stats_s {
|
||||
|
|
@ -22,22 +21,7 @@ struct inspect_extent_util_stats_s {
|
|||
size_t size;
|
||||
};
|
||||
|
||||
typedef struct inspect_extent_util_stats_verbose_s
|
||||
inspect_extent_util_stats_verbose_t;
|
||||
|
||||
struct inspect_extent_util_stats_verbose_s {
|
||||
void *slabcur_addr;
|
||||
size_t nfree;
|
||||
size_t nregs;
|
||||
size_t size;
|
||||
size_t bin_nfree;
|
||||
size_t bin_nregs;
|
||||
};
|
||||
|
||||
void inspect_extent_util_stats_get(
|
||||
tsdn_t *tsdn, const void *ptr, size_t *nfree, size_t *nregs, size_t *size);
|
||||
void inspect_extent_util_stats_verbose_get(tsdn_t *tsdn, const void *ptr,
|
||||
size_t *nfree, size_t *nregs, size_t *size, size_t *bin_nfree,
|
||||
size_t *bin_nregs, void **slabcur_addr);
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_INSPECT_H */
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ extern bool opt_disable_large_size_classes;
|
|||
|
||||
extern const char *opt_malloc_conf_symlink;
|
||||
extern const char *opt_malloc_conf_env_var;
|
||||
extern const char *je_malloc_conf_2_conf_harder;
|
||||
|
||||
/* Escape free-fastpath when ptr & mask == 0 (for sanitization purpose). */
|
||||
extern uintptr_t san_cache_bin_nonfast_mask;
|
||||
|
|
|
|||
|
|
@ -11,11 +11,6 @@ void safety_check_fail_sized_dealloc(
|
|||
bool current_dealloc, const void *ptr, size_t true_size, size_t input_size);
|
||||
void safety_check_fail(const char *format, ...);
|
||||
|
||||
typedef void (*safety_check_abort_hook_t)(const char *message);
|
||||
|
||||
/* Can set to NULL for a default. */
|
||||
void safety_check_set_abort(safety_check_abort_hook_t abort_fn);
|
||||
|
||||
#define REDZONE_SIZE ((size_t)32)
|
||||
#define REDZONE_FILL_VALUE 0xBC
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
extern JEMALLOC_EXPORT void (*test_hooks_arena_new_hook)(void);
|
||||
extern JEMALLOC_EXPORT void (*test_hooks_libc_hook)(void);
|
||||
extern JEMALLOC_EXPORT void (*test_hooks_safety_check_abort)(const char *);
|
||||
|
||||
#if defined(JEMALLOC_JET) || defined(JEMALLOC_UNIT_TEST)
|
||||
# define JEMALLOC_TEST_HOOK(fn, hook) \
|
||||
|
|
|
|||
|
|
@ -48,6 +48,15 @@
|
|||
<ClCompile Include="..\..\..\..\src\conf.c" />
|
||||
<ClCompile Include="..\..\..\..\src\counter.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_arena.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_background_thread.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_config.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_opt.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_prof.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_stats.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_thread.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_tcache.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_utilization.c" />
|
||||
<ClCompile Include="..\..\..\..\src\decay.c" />
|
||||
<ClCompile Include="..\..\..\..\src\div.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ecache.c" />
|
||||
|
|
|
|||
|
|
@ -40,6 +40,33 @@
|
|||
<ClCompile Include="..\..\..\..\src\ctl.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_arena.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_background_thread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_config.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_opt.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_prof.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_stats.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_thread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_tcache.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_utilization.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\decay.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -48,6 +48,15 @@
|
|||
<ClCompile Include="..\..\..\..\src\conf.c" />
|
||||
<ClCompile Include="..\..\..\..\src\counter.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_arena.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_background_thread.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_config.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_opt.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_prof.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_stats.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_thread.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_tcache.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_utilization.c" />
|
||||
<ClCompile Include="..\..\..\..\src\decay.c" />
|
||||
<ClCompile Include="..\..\..\..\src\div.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ecache.c" />
|
||||
|
|
|
|||
|
|
@ -40,6 +40,33 @@
|
|||
<ClCompile Include="..\..\..\..\src\ctl.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_arena.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_background_thread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_config.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_opt.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_prof.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_stats.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_thread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_tcache.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_utilization.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\decay.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -48,6 +48,15 @@
|
|||
<ClCompile Include="..\..\..\..\src\conf.c" />
|
||||
<ClCompile Include="..\..\..\..\src\counter.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_arena.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_background_thread.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_config.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_opt.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_prof.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_stats.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_thread.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_tcache.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_utilization.c" />
|
||||
<ClCompile Include="..\..\..\..\src\decay.c" />
|
||||
<ClCompile Include="..\..\..\..\src\div.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ecache.c" />
|
||||
|
|
|
|||
|
|
@ -40,6 +40,33 @@
|
|||
<ClCompile Include="..\..\..\..\src\ctl.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_arena.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_background_thread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_config.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_opt.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_prof.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_stats.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_thread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_tcache.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_utilization.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\decay.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -48,6 +48,15 @@
|
|||
<ClCompile Include="..\..\..\..\src\conf.c" />
|
||||
<ClCompile Include="..\..\..\..\src\counter.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_arena.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_background_thread.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_config.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_opt.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_prof.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_stats.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_thread.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_tcache.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ctl_utilization.c" />
|
||||
<ClCompile Include="..\..\..\..\src\decay.c" />
|
||||
<ClCompile Include="..\..\..\..\src\div.c" />
|
||||
<ClCompile Include="..\..\..\..\src\ecache.c" />
|
||||
|
|
|
|||
|
|
@ -40,6 +40,33 @@
|
|||
<ClCompile Include="..\..\..\..\src\ctl.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_arena.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_background_thread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_config.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_opt.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_prof.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_stats.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_thread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_tcache.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\ctl_utilization.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\src\decay.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
1143
src/ctl_arena.c
Normal file
1143
src/ctl_arena.c
Normal file
File diff suppressed because it is too large
Load diff
118
src/ctl_background_thread.c
Normal file
118
src/ctl_background_thread.c
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||
#include "jemalloc/internal/jemalloc_internal_includes.h"
|
||||
|
||||
#include "jemalloc/internal/background_thread_externs.h"
|
||||
#include "jemalloc/internal/background_thread_inlines.h"
|
||||
#include "jemalloc/internal/ctl_background_thread.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/* background_thread mallctl handlers. */
|
||||
|
||||
int
|
||||
background_thread_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
bool oldval;
|
||||
|
||||
if (!have_background_thread) {
|
||||
return ENOENT;
|
||||
}
|
||||
background_thread_ctl_init(tsd_tsdn(tsd));
|
||||
|
||||
ctl_mtx_lock(tsd_tsdn(tsd));
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock);
|
||||
if (newp == NULL) {
|
||||
oldval = background_thread_enabled();
|
||||
READ(oldval, bool);
|
||||
} else {
|
||||
if (newlen != sizeof(bool)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
oldval = background_thread_enabled();
|
||||
READ(oldval, bool);
|
||||
|
||||
bool newval = *(bool *)newp;
|
||||
if (newval == oldval) {
|
||||
ret = 0;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
background_thread_enabled_set(tsd_tsdn(tsd), newval);
|
||||
if (newval) {
|
||||
if (background_threads_enable(tsd)) {
|
||||
ret = EFAULT;
|
||||
goto label_return;
|
||||
}
|
||||
} else {
|
||||
if (background_threads_disable(tsd)) {
|
||||
ret = EFAULT;
|
||||
goto label_return;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
label_return:
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock);
|
||||
ctl_mtx_unlock(tsd_tsdn(tsd));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
max_background_threads_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
size_t oldval;
|
||||
|
||||
if (!have_background_thread) {
|
||||
return ENOENT;
|
||||
}
|
||||
background_thread_ctl_init(tsd_tsdn(tsd));
|
||||
|
||||
ctl_mtx_lock(tsd_tsdn(tsd));
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock);
|
||||
if (newp == NULL) {
|
||||
oldval = max_background_threads;
|
||||
READ(oldval, size_t);
|
||||
} else {
|
||||
if (newlen != sizeof(size_t)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
oldval = max_background_threads;
|
||||
READ(oldval, size_t);
|
||||
|
||||
size_t newval = *(size_t *)newp;
|
||||
if (newval == oldval) {
|
||||
ret = 0;
|
||||
goto label_return;
|
||||
}
|
||||
if (newval > opt_max_background_threads || newval == 0) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
if (background_thread_enabled()) {
|
||||
background_thread_enabled_set(tsd_tsdn(tsd), false);
|
||||
if (background_threads_disable(tsd)) {
|
||||
ret = EFAULT;
|
||||
goto label_return;
|
||||
}
|
||||
max_background_threads = newval;
|
||||
background_thread_enabled_set(tsd_tsdn(tsd), true);
|
||||
if (background_threads_enable(tsd)) {
|
||||
ret = EFAULT;
|
||||
goto label_return;
|
||||
}
|
||||
} else {
|
||||
max_background_threads = newval;
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
label_return:
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock);
|
||||
ctl_mtx_unlock(tsd_tsdn(tsd));
|
||||
|
||||
return ret;
|
||||
}
|
||||
38
src/ctl_config.c
Normal file
38
src/ctl_config.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||
#include "jemalloc/internal/jemalloc_internal_includes.h"
|
||||
|
||||
#include "jemalloc/internal/ctl_config.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/* config.* mallctl handlers. */
|
||||
|
||||
#define CTL_RO_CONFIG_GEN(n, t) \
|
||||
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
|
||||
int ret; \
|
||||
t oldval; \
|
||||
\
|
||||
READONLY(); \
|
||||
oldval = n; \
|
||||
READ(oldval, t); \
|
||||
\
|
||||
ret = 0; \
|
||||
label_return: \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
CTL_RO_CONFIG_GEN(config_cache_oblivious, bool)
|
||||
CTL_RO_CONFIG_GEN(config_debug, bool)
|
||||
CTL_RO_CONFIG_GEN(config_fill, bool)
|
||||
CTL_RO_CONFIG_GEN(config_lazy_lock, bool)
|
||||
CTL_RO_CONFIG_GEN(config_malloc_conf, const char *)
|
||||
CTL_RO_CONFIG_GEN(config_opt_safety_checks, bool)
|
||||
CTL_RO_CONFIG_GEN(config_prof, bool)
|
||||
CTL_RO_CONFIG_GEN(config_prof_libgcc, bool)
|
||||
CTL_RO_CONFIG_GEN(config_prof_libunwind, bool)
|
||||
CTL_RO_CONFIG_GEN(config_prof_frameptr, bool)
|
||||
CTL_RO_CONFIG_GEN(config_stats, bool)
|
||||
CTL_RO_CONFIG_GEN(config_utrace, bool)
|
||||
CTL_RO_CONFIG_GEN(config_xmalloc, bool)
|
||||
|
||||
#undef CTL_RO_CONFIG_GEN
|
||||
138
src/ctl_opt.c
Normal file
138
src/ctl_opt.c
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||
#include "jemalloc/internal/jemalloc_internal_includes.h"
|
||||
|
||||
#include "jemalloc/internal/ctl_opt.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/* opt.* mallctl handlers. */
|
||||
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_abort, opt_abort, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_abort_conf, opt_abort_conf, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_cache_oblivious, opt_cache_oblivious, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_debug_double_free_max_scan, opt_debug_double_free_max_scan, unsigned)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_trust_madvise, opt_trust_madvise, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_experimental_hpa_start_huge_if_thp_always,
|
||||
opt_experimental_hpa_start_huge_if_thp_always, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_experimental_hpa_enforce_hugify,
|
||||
opt_experimental_hpa_enforce_hugify, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_confirm_conf, opt_confirm_conf, bool)
|
||||
|
||||
/* HPA options. */
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_hpa, opt_hpa, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_hpa_hugification_threshold, opt_hpa_opts.hugification_threshold, size_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_hpa_hugify_delay_ms, opt_hpa_opts.hugify_delay_ms, uint64_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_hpa_hugify_sync, opt_hpa_opts.hugify_sync, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_hpa_min_purge_interval_ms, opt_hpa_opts.min_purge_interval_ms, uint64_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_experimental_hpa_max_purge_nhp,
|
||||
opt_hpa_opts.experimental_max_purge_nhp, ssize_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_hpa_purge_threshold, opt_hpa_opts.purge_threshold, size_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_hpa_min_purge_delay_ms, opt_hpa_opts.min_purge_delay_ms, uint64_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_hpa_hugify_style,
|
||||
hpa_hugify_style_names[opt_hpa_opts.hugify_style], const char *)
|
||||
/*
|
||||
* This will have to change before we publicly document this option; fxp_t and
|
||||
* its representation are internal implementation details.
|
||||
*/
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_hpa_dirty_mult, opt_hpa_opts.dirty_mult, fxp_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_hpa_slab_max_alloc, opt_hpa_opts.slab_max_alloc, size_t)
|
||||
|
||||
/* HPA SEC options */
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_hpa_sec_nshards, opt_hpa_sec_opts.nshards, size_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_hpa_sec_max_alloc, opt_hpa_sec_opts.max_alloc, size_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_hpa_sec_max_bytes, opt_hpa_sec_opts.max_bytes, size_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_huge_arena_pac_thp, opt_huge_arena_pac_thp, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_metadata_thp, metadata_thp_mode_names[opt_metadata_thp], const char *)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_retain, opt_retain, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_dss, opt_dss, const char *)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_narenas, opt_narenas, unsigned)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_percpu_arena, percpu_arena_mode_names[opt_percpu_arena], const char *)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_mutex_max_spin, opt_mutex_max_spin, int64_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_oversize_threshold, opt_oversize_threshold, size_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_background_thread, opt_background_thread, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_max_background_threads, opt_max_background_threads,
|
||||
size_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_dirty_decay_ms, opt_dirty_decay_ms, ssize_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_muzzy_decay_ms, opt_muzzy_decay_ms, ssize_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_stats_print, opt_stats_print, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_stats_print_opts, opt_stats_print_opts, const char *)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_stats_interval, opt_stats_interval, int64_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_stats_interval_opts, opt_stats_interval_opts, const char *)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_fill, opt_junk, opt_junk, const char *)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_fill, opt_zero, opt_zero, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_utrace, opt_utrace, opt_utrace, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_enable_cxx, opt_experimental_infallible_new,
|
||||
opt_experimental_infallible_new, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_experimental_tcache_gc, opt_experimental_tcache_gc, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_tcache, opt_tcache, bool)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_tcache_max, opt_tcache_max, size_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_tcache_nslots_small_min, opt_tcache_nslots_small_min, unsigned)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_tcache_nslots_small_max, opt_tcache_nslots_small_max, unsigned)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_tcache_nslots_large, opt_tcache_nslots_large, unsigned)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_lg_tcache_nslots_mul, opt_lg_tcache_nslots_mul, ssize_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_tcache_gc_incr_bytes, opt_tcache_gc_incr_bytes, size_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_tcache_gc_delay_bytes, opt_tcache_gc_delay_bytes,
|
||||
size_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_lg_tcache_flush_small_div, opt_lg_tcache_flush_small_div, unsigned)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_lg_tcache_flush_large_div, opt_lg_tcache_flush_large_div, unsigned)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_thp, thp_mode_names[opt_thp], const char *)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_lg_extent_max_active_fit, opt_lg_extent_max_active_fit, size_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_process_madvise_max_batch, opt_process_madvise_max_batch, size_t)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_prof, opt_prof, opt_prof, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_prof, opt_prof_prefix, opt_prof_prefix,
|
||||
const char *)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_prof, opt_prof_active, opt_prof_active, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(
|
||||
config_prof, opt_prof_thread_active_init, opt_prof_thread_active_init, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_prof, opt_prof_bt_max, opt_prof_bt_max, unsigned)
|
||||
CTL_RO_NL_CGEN_PUBLIC(
|
||||
config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_prof, opt_prof_accum, opt_prof_accum, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(
|
||||
config_prof, opt_prof_pid_namespace, opt_prof_pid_namespace, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(
|
||||
config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_prof, opt_prof_final, opt_prof_final, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_prof, opt_prof_leak, opt_prof_leak, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(
|
||||
config_prof, opt_prof_leak_error, opt_prof_leak_error, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(
|
||||
config_prof, opt_prof_recent_alloc_max, opt_prof_recent_alloc_max, ssize_t)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_prof, opt_prof_stats, opt_prof_stats, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(
|
||||
config_prof, opt_prof_sys_thread_name, opt_prof_sys_thread_name, bool)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_prof, opt_prof_time_res,
|
||||
prof_time_res_mode_names[opt_prof_time_res], const char *)
|
||||
CTL_RO_NL_CGEN_PUBLIC(
|
||||
config_uaf_detection, opt_lg_san_uaf_align, opt_lg_san_uaf_align, ssize_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(opt_zero_realloc,
|
||||
zero_realloc_mode_names[opt_zero_realloc_action], const char *)
|
||||
CTL_RO_NL_GEN_PUBLIC(
|
||||
opt_disable_large_size_classes, opt_disable_large_size_classes, bool)
|
||||
|
||||
/* malloc_conf options */
|
||||
CTL_RO_NL_CGEN_PUBLIC(opt_malloc_conf_symlink, opt_malloc_conf_symlink,
|
||||
opt_malloc_conf_symlink, const char *)
|
||||
CTL_RO_NL_CGEN_PUBLIC(opt_malloc_conf_env_var, opt_malloc_conf_env_var,
|
||||
opt_malloc_conf_env_var, const char *)
|
||||
CTL_RO_NL_CGEN_PUBLIC(
|
||||
je_malloc_conf, opt_malloc_conf_global_var, je_malloc_conf, const char *)
|
||||
450
src/ctl_prof.c
Normal file
450
src/ctl_prof.c
Normal file
|
|
@ -0,0 +1,450 @@
|
|||
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||
#include "jemalloc/internal/jemalloc_internal_includes.h"
|
||||
|
||||
#include "jemalloc/internal/ctl_prof.h"
|
||||
#include "jemalloc/internal/prof_data.h"
|
||||
#include "jemalloc/internal/prof_log.h"
|
||||
#include "jemalloc/internal/prof_recent.h"
|
||||
#include "jemalloc/internal/prof_stats.h"
|
||||
#include "jemalloc/internal/prof_sys.h"
|
||||
#include "jemalloc/internal/sc.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/* prof.* mallctl handlers. */
|
||||
|
||||
int
|
||||
prof_thread_active_init_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
bool oldval;
|
||||
|
||||
if (!config_prof) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
if (newp != NULL) {
|
||||
if (!opt_prof) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
if (newlen != sizeof(bool)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
oldval = prof_thread_active_init_set(
|
||||
tsd_tsdn(tsd), *(bool *)newp);
|
||||
} else {
|
||||
oldval = opt_prof ? prof_thread_active_init_get(tsd_tsdn(tsd))
|
||||
: false;
|
||||
}
|
||||
READ(oldval, bool);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
bool oldval;
|
||||
|
||||
if (!config_prof) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
if (newp != NULL) {
|
||||
if (newlen != sizeof(bool)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
bool val = *(bool *)newp;
|
||||
if (!opt_prof) {
|
||||
if (val) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
} else {
|
||||
/* No change needed (already off). */
|
||||
oldval = false;
|
||||
}
|
||||
} else {
|
||||
oldval = prof_active_set(tsd_tsdn(tsd), val);
|
||||
}
|
||||
} else {
|
||||
oldval = opt_prof ? prof_active_get(tsd_tsdn(tsd)) : false;
|
||||
}
|
||||
READ(oldval, bool);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
prof_dump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
const char *filename = NULL;
|
||||
|
||||
if (!config_prof || !opt_prof) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
WRITEONLY();
|
||||
WRITE(filename, const char *);
|
||||
|
||||
if (prof_mdump(tsd, filename)) {
|
||||
ret = EFAULT;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
prof_gdump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
bool oldval;
|
||||
|
||||
if (!config_prof) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
if (newp != NULL) {
|
||||
if (!opt_prof) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
if (newlen != sizeof(bool)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
oldval = prof_gdump_set(tsd_tsdn(tsd), *(bool *)newp);
|
||||
} else {
|
||||
oldval = opt_prof ? prof_gdump_get(tsd_tsdn(tsd)) : false;
|
||||
}
|
||||
READ(oldval, bool);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
prof_prefix_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
const char *prefix = NULL;
|
||||
|
||||
if (!config_prof || !opt_prof) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
ctl_mtx_lock(tsd_tsdn(tsd));
|
||||
WRITEONLY();
|
||||
WRITE(prefix, const char *);
|
||||
|
||||
ret = prof_prefix_set(tsd_tsdn(tsd), prefix) ? EFAULT : 0;
|
||||
label_return:
|
||||
ctl_mtx_unlock(tsd_tsdn(tsd));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
prof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
size_t lg_sample = lg_prof_sample;
|
||||
|
||||
if (!config_prof || !opt_prof) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
WRITEONLY();
|
||||
WRITE(lg_sample, size_t);
|
||||
if (lg_sample >= (sizeof(uint64_t) << 3)) {
|
||||
lg_sample = (sizeof(uint64_t) << 3) - 1;
|
||||
}
|
||||
|
||||
prof_reset(tsd, lg_sample);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_prof, prof_interval, prof_interval, uint64_t)
|
||||
CTL_RO_NL_CGEN_PUBLIC(config_prof, lg_prof_sample, lg_prof_sample, size_t)
|
||||
|
||||
int
|
||||
prof_log_start_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
|
||||
const char *filename = NULL;
|
||||
|
||||
if (!config_prof || !opt_prof) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
WRITEONLY();
|
||||
WRITE(filename, const char *);
|
||||
|
||||
if (prof_log_start(tsd_tsdn(tsd), filename)) {
|
||||
ret = EFAULT;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
prof_log_stop_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
if (!config_prof || !opt_prof) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
if (prof_log_stop(tsd_tsdn(tsd))) {
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
prof_stats_bins_i_live_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
unsigned binind;
|
||||
prof_stats_t stats;
|
||||
|
||||
if (!(config_prof && opt_prof && opt_prof_stats)) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
READONLY();
|
||||
MIB_UNSIGNED(binind, 3);
|
||||
if (binind >= SC_NBINS) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
prof_stats_get_live(tsd, (szind_t)binind, &stats);
|
||||
READ(stats, prof_stats_t);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
prof_stats_bins_i_accum_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
unsigned binind;
|
||||
prof_stats_t stats;
|
||||
|
||||
if (!(config_prof && opt_prof && opt_prof_stats)) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
READONLY();
|
||||
MIB_UNSIGNED(binind, 3);
|
||||
if (binind >= SC_NBINS) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
prof_stats_get_accum(tsd, (szind_t)binind, &stats);
|
||||
READ(stats, prof_stats_t);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
prof_stats_lextents_i_live_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
unsigned lextent_ind;
|
||||
prof_stats_t stats;
|
||||
|
||||
if (!(config_prof && opt_prof && opt_prof_stats)) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
READONLY();
|
||||
MIB_UNSIGNED(lextent_ind, 3);
|
||||
if (lextent_ind >= SC_NSIZES - SC_NBINS) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
prof_stats_get_live(tsd, (szind_t)(lextent_ind + SC_NBINS), &stats);
|
||||
READ(stats, prof_stats_t);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
prof_stats_lextents_i_accum_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
unsigned lextent_ind;
|
||||
prof_stats_t stats;
|
||||
|
||||
if (!(config_prof && opt_prof && opt_prof_stats)) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
READONLY();
|
||||
MIB_UNSIGNED(lextent_ind, 3);
|
||||
if (lextent_ind >= SC_NSIZES - SC_NBINS) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
prof_stats_get_accum(tsd, (szind_t)(lextent_ind + SC_NBINS), &stats);
|
||||
READ(stats, prof_stats_t);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* experimental.prof_recent.* and experimental.hooks.prof_* mallctl handlers. */
|
||||
|
||||
#define PROF_HOOK_CTL_BODY(hook_type, hook_get, hook_set, allow_null) \
|
||||
do { \
|
||||
int ret; \
|
||||
if (oldp == NULL && newp == NULL) { \
|
||||
ret = EINVAL; \
|
||||
goto label_return; \
|
||||
} \
|
||||
if (oldp != NULL) { \
|
||||
hook_type old_hook = hook_get(); \
|
||||
READ(old_hook, hook_type); \
|
||||
} \
|
||||
if (newp != NULL) { \
|
||||
if (!opt_prof) { \
|
||||
ret = ENOENT; \
|
||||
goto label_return; \
|
||||
} \
|
||||
hook_type new_hook JEMALLOC_CC_SILENCE_INIT(NULL); \
|
||||
WRITE(new_hook, hook_type); \
|
||||
if (!(allow_null) && new_hook == NULL) { \
|
||||
ret = EINVAL; \
|
||||
goto label_return; \
|
||||
} \
|
||||
hook_set(new_hook); \
|
||||
} \
|
||||
ret = 0; \
|
||||
label_return: \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
int
|
||||
experimental_hooks_prof_backtrace_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
PROF_HOOK_CTL_BODY(prof_backtrace_hook_t, prof_backtrace_hook_get,
|
||||
prof_backtrace_hook_set, false);
|
||||
}
|
||||
|
||||
int
|
||||
experimental_hooks_prof_dump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
PROF_HOOK_CTL_BODY(prof_dump_hook_t, prof_dump_hook_get,
|
||||
prof_dump_hook_set, true);
|
||||
}
|
||||
|
||||
int
|
||||
experimental_hooks_prof_sample_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
PROF_HOOK_CTL_BODY(prof_sample_hook_t, prof_sample_hook_get,
|
||||
prof_sample_hook_set, true);
|
||||
}
|
||||
|
||||
int
|
||||
experimental_hooks_prof_sample_free_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
PROF_HOOK_CTL_BODY(prof_sample_free_hook_t, prof_sample_free_hook_get,
|
||||
prof_sample_free_hook_set, true);
|
||||
}
|
||||
|
||||
#undef PROF_HOOK_CTL_BODY
|
||||
|
||||
int
|
||||
experimental_prof_recent_alloc_max_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
|
||||
if (!(config_prof && opt_prof)) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
ssize_t old_max;
|
||||
if (newp != NULL) {
|
||||
if (newlen != sizeof(ssize_t)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
ssize_t max = *(ssize_t *)newp;
|
||||
if (max < -1) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
old_max = prof_recent_alloc_max_ctl_write(tsd, max);
|
||||
} else {
|
||||
old_max = prof_recent_alloc_max_ctl_read();
|
||||
}
|
||||
READ(old_max, ssize_t);
|
||||
|
||||
ret = 0;
|
||||
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct write_cb_packet_s write_cb_packet_t;
|
||||
struct write_cb_packet_s {
|
||||
write_cb_t *write_cb;
|
||||
void *cbopaque;
|
||||
};
|
||||
|
||||
int
|
||||
experimental_prof_recent_alloc_dump_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
|
||||
if (!(config_prof && opt_prof)) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
assert(sizeof(write_cb_packet_t) == sizeof(void *) * 2);
|
||||
|
||||
WRITEONLY();
|
||||
write_cb_packet_t write_cb_packet;
|
||||
ASSURED_WRITE(write_cb_packet, write_cb_packet_t);
|
||||
|
||||
prof_recent_alloc_dump(
|
||||
tsd, write_cb_packet.write_cb, write_cb_packet.cbopaque);
|
||||
|
||||
ret = 0;
|
||||
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
577
src/ctl_stats.c
Normal file
577
src/ctl_stats.c
Normal file
|
|
@ -0,0 +1,577 @@
|
|||
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||
#include "jemalloc/internal/jemalloc_internal_includes.h"
|
||||
|
||||
#include "jemalloc/internal/assert.h"
|
||||
#include "jemalloc/internal/ctl_arena.h"
|
||||
#include "jemalloc/internal/ctl_mallctl.h"
|
||||
#include "jemalloc/internal/ctl_stats.h"
|
||||
#include "jemalloc/internal/mutex.h"
|
||||
#include "jemalloc/internal/nstime.h"
|
||||
#include "jemalloc/internal/prof_data.h"
|
||||
#include "jemalloc/internal/prof_recent.h"
|
||||
#include "jemalloc/internal/prof_stats.h"
|
||||
#include "jemalloc/internal/sc.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/* stats.* ctl state. */
|
||||
|
||||
static ctl_stats_t *ctl_stats;
|
||||
|
||||
bool
|
||||
ctl_stats_init(tsdn_t *tsdn) {
|
||||
if (!config_stats || ctl_stats != NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctl_stats = (ctl_stats_t *)base_alloc(
|
||||
tsdn, b0get(), sizeof(ctl_stats_t), QUANTUM);
|
||||
return ctl_stats == NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_background_thread_stats_read(tsdn_t *tsdn) {
|
||||
background_thread_stats_t *stats = &ctl_stats->background_thread;
|
||||
if (!have_background_thread
|
||||
|| background_thread_stats_read(tsdn, stats)) {
|
||||
memset(stats, 0, sizeof(background_thread_stats_t));
|
||||
nstime_init_zero(&stats->run_interval);
|
||||
}
|
||||
malloc_mutex_prof_copy(
|
||||
&ctl_stats->mutex_prof_data[global_prof_mutex_max_per_bg_thd],
|
||||
&stats->max_counter_per_bg_thd);
|
||||
}
|
||||
|
||||
void
|
||||
ctl_stats_refresh(tsdn_t *tsdn, ctl_arena_t *ctl_sarena) {
|
||||
if (!config_stats) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctl_stats->allocated = ctl_sarena->astats->allocated_small
|
||||
+ ctl_sarena->astats->astats.allocated_large;
|
||||
ctl_stats->active = (ctl_sarena->pactive << LG_PAGE);
|
||||
ctl_stats->metadata = ctl_sarena->astats->astats.base
|
||||
+ atomic_load_zu(
|
||||
&ctl_sarena->astats->astats.internal, ATOMIC_RELAXED);
|
||||
ctl_stats->metadata_edata = ctl_sarena->astats->astats.metadata_edata;
|
||||
ctl_stats->metadata_rtree = ctl_sarena->astats->astats.metadata_rtree;
|
||||
ctl_stats->resident = ctl_sarena->astats->astats.resident;
|
||||
ctl_stats->metadata_thp = ctl_sarena->astats->astats.metadata_thp;
|
||||
ctl_stats->mapped = ctl_sarena->astats->astats.mapped;
|
||||
ctl_stats->retained = ctl_sarena->astats->astats.pa_shard_stats
|
||||
.pac_stats.retained;
|
||||
ctl_stats->pinned = ctl_sarena->astats->astats.pa_shard_stats
|
||||
.pac_stats.pinned;
|
||||
|
||||
ctl_background_thread_stats_read(tsdn);
|
||||
|
||||
#define READ_GLOBAL_MUTEX_PROF_DATA(i, mtx) \
|
||||
malloc_mutex_lock(tsdn, &mtx); \
|
||||
malloc_mutex_prof_read(tsdn, &ctl_stats->mutex_prof_data[i], &mtx); \
|
||||
malloc_mutex_unlock(tsdn, &mtx);
|
||||
|
||||
if (config_prof && opt_prof) {
|
||||
READ_GLOBAL_MUTEX_PROF_DATA(
|
||||
global_prof_mutex_prof, bt2gctx_mtx);
|
||||
READ_GLOBAL_MUTEX_PROF_DATA(
|
||||
global_prof_mutex_prof_thds_data, tdatas_mtx);
|
||||
READ_GLOBAL_MUTEX_PROF_DATA(
|
||||
global_prof_mutex_prof_dump, prof_dump_mtx);
|
||||
READ_GLOBAL_MUTEX_PROF_DATA(
|
||||
global_prof_mutex_prof_recent_alloc,
|
||||
prof_recent_alloc_mtx);
|
||||
READ_GLOBAL_MUTEX_PROF_DATA(
|
||||
global_prof_mutex_prof_recent_dump,
|
||||
prof_recent_dump_mtx);
|
||||
READ_GLOBAL_MUTEX_PROF_DATA(
|
||||
global_prof_mutex_prof_stats, prof_stats_mtx);
|
||||
}
|
||||
if (have_background_thread) {
|
||||
READ_GLOBAL_MUTEX_PROF_DATA(
|
||||
global_prof_mutex_background_thread, background_thread_lock);
|
||||
} else {
|
||||
memset(&ctl_stats->mutex_prof_data
|
||||
[global_prof_mutex_background_thread],
|
||||
0, sizeof(mutex_prof_data_t));
|
||||
}
|
||||
ctl_mtx_prof_read(
|
||||
tsdn, &ctl_stats->mutex_prof_data[global_prof_mutex_ctl]);
|
||||
#undef READ_GLOBAL_MUTEX_PROF_DATA
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* stats.* mallctl handlers. */
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_allocated, ctl_stats->allocated, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_active, ctl_stats->active, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_metadata, ctl_stats->metadata, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(
|
||||
config_stats, stats_metadata_edata, ctl_stats->metadata_edata, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(
|
||||
config_stats, stats_metadata_rtree, ctl_stats->metadata_rtree, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_metadata_thp, ctl_stats->metadata_thp, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_resident, ctl_stats->resident, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_mapped, ctl_stats->mapped, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_retained, ctl_stats->retained, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_pinned, ctl_stats->pinned, size_t)
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_background_thread_num_threads,
|
||||
ctl_stats->background_thread.num_threads, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_background_thread_num_runs,
|
||||
ctl_stats->background_thread.num_runs, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_background_thread_run_interval,
|
||||
nstime_ns(&ctl_stats->background_thread.run_interval), uint64_t)
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_zero_reallocs,
|
||||
atomic_load_zu(&zero_realloc_count, ATOMIC_RELAXED), size_t)
|
||||
|
||||
/*
|
||||
* approximate_stats.active returns a result that is informative itself,
|
||||
* but the returned value SHOULD NOT be compared against other stats retrieved.
|
||||
* For instance, approximate_stats.active should not be compared against
|
||||
* any stats, e.g., stats.active or stats.resident, because there is no
|
||||
* guarantee in the comparison results. Results returned by stats.*, on the
|
||||
* other hand, provides such guarantees, i.e., stats.active <= stats.resident,
|
||||
* as long as epoch is called right before the queries.
|
||||
*/
|
||||
|
||||
int
|
||||
approximate_stats_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
size_t approximate_nactive = 0;
|
||||
size_t approximate_active_bytes = 0;
|
||||
|
||||
READONLY();
|
||||
|
||||
tsdn_t *tsdn = tsd_tsdn(tsd);
|
||||
unsigned n = narenas_total_get();
|
||||
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
arena_t *arena = arena_get(tsdn, i, false);
|
||||
if (!arena) {
|
||||
continue;
|
||||
}
|
||||
/* Accumulate nactive pages from each arena's pa_shard */
|
||||
approximate_nactive += pa_shard_nactive(&arena->pa_shard);
|
||||
}
|
||||
|
||||
approximate_active_bytes = approximate_nactive << LG_PAGE;
|
||||
READ(approximate_active_bytes, size_t);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
CTL_RO_GEN_PUBLIC(stats_arenas_i_dss, ctl_arenas_i(mib[2])->dss, const char *)
|
||||
CTL_RO_GEN_PUBLIC(
|
||||
stats_arenas_i_dirty_decay_ms, ctl_arenas_i(mib[2])->dirty_decay_ms, ssize_t)
|
||||
CTL_RO_GEN_PUBLIC(
|
||||
stats_arenas_i_muzzy_decay_ms, ctl_arenas_i(mib[2])->muzzy_decay_ms, ssize_t)
|
||||
CTL_RO_GEN_PUBLIC(stats_arenas_i_nthreads, ctl_arenas_i(mib[2])->nthreads, unsigned)
|
||||
CTL_RO_GEN_PUBLIC(stats_arenas_i_uptime,
|
||||
nstime_ns(&ctl_arenas_i(mib[2])->astats->astats.uptime), uint64_t)
|
||||
CTL_RO_GEN_PUBLIC(stats_arenas_i_pactive, ctl_arenas_i(mib[2])->pactive, size_t)
|
||||
CTL_RO_GEN_PUBLIC(stats_arenas_i_pdirty, ctl_arenas_i(mib[2])->pdirty, size_t)
|
||||
CTL_RO_GEN_PUBLIC(stats_arenas_i_pmuzzy, ctl_arenas_i(mib[2])->pmuzzy, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_mapped,
|
||||
ctl_arenas_i(mib[2])->astats->astats.mapped, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_retained,
|
||||
ctl_arenas_i(mib[2])->astats->astats.pa_shard_stats.pac_stats.retained, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_pinned,
|
||||
ctl_arenas_i(mib[2])->astats->astats.pa_shard_stats.pac_stats.pinned, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_extent_avail,
|
||||
ctl_arenas_i(mib[2])->astats->astats.pa_shard_stats.edata_avail, size_t)
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_dirty_npurge,
|
||||
locked_read_u64_unsynchronized(&ctl_arenas_i(mib[2])
|
||||
->astats->astats.pa_shard_stats.pac_stats.decay_dirty.npurge),
|
||||
uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_dirty_nmadvise,
|
||||
locked_read_u64_unsynchronized(&ctl_arenas_i(mib[2])
|
||||
->astats->astats.pa_shard_stats.pac_stats.decay_dirty.nmadvise),
|
||||
uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_dirty_purged,
|
||||
locked_read_u64_unsynchronized(&ctl_arenas_i(mib[2])
|
||||
->astats->astats.pa_shard_stats.pac_stats.decay_dirty.purged),
|
||||
uint64_t)
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_muzzy_npurge,
|
||||
locked_read_u64_unsynchronized(&ctl_arenas_i(mib[2])
|
||||
->astats->astats.pa_shard_stats.pac_stats.decay_muzzy.npurge),
|
||||
uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_muzzy_nmadvise,
|
||||
locked_read_u64_unsynchronized(&ctl_arenas_i(mib[2])
|
||||
->astats->astats.pa_shard_stats.pac_stats.decay_muzzy.nmadvise),
|
||||
uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_muzzy_purged,
|
||||
locked_read_u64_unsynchronized(&ctl_arenas_i(mib[2])
|
||||
->astats->astats.pa_shard_stats.pac_stats.decay_muzzy.purged),
|
||||
uint64_t)
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_base,
|
||||
ctl_arenas_i(mib[2])->astats->astats.base, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_internal,
|
||||
atomic_load_zu(&ctl_arenas_i(mib[2])->astats->astats.internal, ATOMIC_RELAXED),
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_metadata_edata,
|
||||
ctl_arenas_i(mib[2])->astats->astats.metadata_edata, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_metadata_rtree,
|
||||
ctl_arenas_i(mib[2])->astats->astats.metadata_rtree, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_metadata_thp,
|
||||
ctl_arenas_i(mib[2])->astats->astats.metadata_thp, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_tcache_bytes,
|
||||
ctl_arenas_i(mib[2])->astats->astats.tcache_bytes, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_tcache_stashed_bytes,
|
||||
ctl_arenas_i(mib[2])->astats->astats.tcache_stashed_bytes, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_resident,
|
||||
ctl_arenas_i(mib[2])->astats->astats.resident, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_abandoned_vm,
|
||||
atomic_load_zu(
|
||||
&ctl_arenas_i(mib[2])->astats->astats.pa_shard_stats.pac_stats.abandoned_vm,
|
||||
ATOMIC_RELAXED),
|
||||
size_t)
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_sec_bytes,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.secstats.bytes, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_sec_hits,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.secstats.total.nhits, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_sec_misses,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.secstats.total.nmisses, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_sec_dalloc_flush,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.secstats.total.ndalloc_flush, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_sec_dalloc_noflush,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.secstats.total.ndalloc_noflush, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_sec_overfills,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.secstats.total.noverfills, size_t)
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_small_allocated,
|
||||
ctl_arenas_i(mib[2])->astats->allocated_small, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_small_nmalloc,
|
||||
ctl_arenas_i(mib[2])->astats->nmalloc_small, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_small_ndalloc,
|
||||
ctl_arenas_i(mib[2])->astats->ndalloc_small, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_small_nrequests,
|
||||
ctl_arenas_i(mib[2])->astats->nrequests_small, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_small_nfills,
|
||||
ctl_arenas_i(mib[2])->astats->nfills_small, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_small_nflushes,
|
||||
ctl_arenas_i(mib[2])->astats->nflushes_small, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_large_allocated,
|
||||
ctl_arenas_i(mib[2])->astats->astats.allocated_large, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_large_nmalloc,
|
||||
ctl_arenas_i(mib[2])->astats->astats.nmalloc_large, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_large_ndalloc,
|
||||
ctl_arenas_i(mib[2])->astats->astats.ndalloc_large, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_large_nrequests,
|
||||
ctl_arenas_i(mib[2])->astats->astats.nrequests_large, uint64_t)
|
||||
/*
|
||||
* Note: "nmalloc_large" here instead of "nfills" in the read. This is
|
||||
* intentional (large has no batch fill).
|
||||
*/
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_large_nfills,
|
||||
ctl_arenas_i(mib[2])->astats->astats.nmalloc_large, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_large_nflushes,
|
||||
ctl_arenas_i(mib[2])->astats->astats.nflushes_large, uint64_t)
|
||||
|
||||
/* Lock profiling related APIs below. */
|
||||
#define RO_MUTEX_CTL_GEN(n, l) \
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_##n##_num_ops, l.n_lock_ops, uint64_t) \
|
||||
CTL_RO_CGEN_PUBLIC( \
|
||||
config_stats, stats_##n##_num_wait, l.n_wait_times, uint64_t) \
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_##n##_num_spin_acq, l.n_spin_acquired, \
|
||||
uint64_t) \
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_##n##_num_owner_switch, \
|
||||
l.n_owner_switches, uint64_t) \
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_##n##_total_wait_time, \
|
||||
nstime_ns(&l.tot_wait_time), uint64_t) \
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_##n##_max_wait_time, \
|
||||
nstime_ns(&l.max_wait_time), uint64_t) \
|
||||
CTL_RO_CGEN_PUBLIC( \
|
||||
config_stats, stats_##n##_max_num_thds, l.max_n_thds, uint32_t)
|
||||
|
||||
/* Global mutexes. */
|
||||
#define OP(mtx) \
|
||||
RO_MUTEX_CTL_GEN(mutexes_##mtx, \
|
||||
ctl_stats->mutex_prof_data[global_prof_mutex_##mtx])
|
||||
MUTEX_PROF_GLOBAL_MUTEXES
|
||||
#undef OP
|
||||
|
||||
/* Per arena mutexes */
|
||||
#define OP(mtx) \
|
||||
RO_MUTEX_CTL_GEN(arenas_i_mutexes_##mtx, \
|
||||
ctl_arenas_i(mib[2]) \
|
||||
->astats->astats.mutex_prof_data[arena_prof_mutex_##mtx])
|
||||
MUTEX_PROF_ARENA_MUTEXES
|
||||
#undef OP
|
||||
|
||||
/* tcache bin mutex */
|
||||
RO_MUTEX_CTL_GEN(
|
||||
arenas_i_bins_j_mutex, ctl_arenas_i(mib[2])->astats->bstats[mib[4]].mutex_data)
|
||||
#undef RO_MUTEX_CTL_GEN
|
||||
|
||||
/* Resets all mutex stats, including global, arena and bin mutexes. */
|
||||
int
|
||||
stats_mutexes_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
if (!config_stats) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
tsdn_t *tsdn = tsd_tsdn(tsd);
|
||||
|
||||
#define MUTEX_PROF_RESET(mtx) \
|
||||
malloc_mutex_lock(tsdn, &mtx); \
|
||||
malloc_mutex_prof_data_reset(tsdn, &mtx); \
|
||||
malloc_mutex_unlock(tsdn, &mtx);
|
||||
|
||||
/* Global mutexes: ctl and prof. */
|
||||
ctl_mtx_prof_data_reset(tsdn);
|
||||
if (have_background_thread) {
|
||||
MUTEX_PROF_RESET(background_thread_lock);
|
||||
}
|
||||
if (config_prof && opt_prof) {
|
||||
MUTEX_PROF_RESET(bt2gctx_mtx);
|
||||
MUTEX_PROF_RESET(tdatas_mtx);
|
||||
MUTEX_PROF_RESET(prof_dump_mtx);
|
||||
MUTEX_PROF_RESET(prof_recent_alloc_mtx);
|
||||
MUTEX_PROF_RESET(prof_recent_dump_mtx);
|
||||
MUTEX_PROF_RESET(prof_stats_mtx);
|
||||
}
|
||||
|
||||
/* Per arena mutexes. */
|
||||
unsigned n = narenas_total_get();
|
||||
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
arena_t *arena = arena_get(tsdn, i, false);
|
||||
if (!arena) {
|
||||
continue;
|
||||
}
|
||||
MUTEX_PROF_RESET(arena->large_mtx);
|
||||
MUTEX_PROF_RESET(arena->pa_shard.edata_cache.mtx);
|
||||
MUTEX_PROF_RESET(arena->pa_shard.pac.ecache_dirty.mtx);
|
||||
MUTEX_PROF_RESET(arena->pa_shard.pac.ecache_muzzy.mtx);
|
||||
MUTEX_PROF_RESET(arena->pa_shard.pac.ecache_retained.mtx);
|
||||
MUTEX_PROF_RESET(arena->pa_shard.pac.ecache_pinned.mtx);
|
||||
MUTEX_PROF_RESET(arena->pa_shard.pac.decay_dirty.mtx);
|
||||
MUTEX_PROF_RESET(arena->pa_shard.pac.decay_muzzy.mtx);
|
||||
MUTEX_PROF_RESET(arena->cache_bin_array_descriptor_ql_mtx);
|
||||
MUTEX_PROF_RESET(arena->base->mtx);
|
||||
|
||||
for (szind_t j = 0; j < SC_NBINS; j++) {
|
||||
for (unsigned k = 0; k < bin_infos[j].n_shards; k++) {
|
||||
bin_t *bin = arena_get_bin(arena, j, k);
|
||||
MUTEX_PROF_RESET(bin->lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef MUTEX_PROF_RESET
|
||||
return 0;
|
||||
}
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_bins_j_nmalloc,
|
||||
ctl_arenas_i(mib[2])->astats->bstats[mib[4]].stats_data.nmalloc, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_bins_j_ndalloc,
|
||||
ctl_arenas_i(mib[2])->astats->bstats[mib[4]].stats_data.ndalloc, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_bins_j_nrequests,
|
||||
ctl_arenas_i(mib[2])->astats->bstats[mib[4]].stats_data.nrequests, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_bins_j_curregs,
|
||||
ctl_arenas_i(mib[2])->astats->bstats[mib[4]].stats_data.curregs, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_bins_j_nfills,
|
||||
ctl_arenas_i(mib[2])->astats->bstats[mib[4]].stats_data.nfills, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_bins_j_nflushes,
|
||||
ctl_arenas_i(mib[2])->astats->bstats[mib[4]].stats_data.nflushes, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_bins_j_nslabs,
|
||||
ctl_arenas_i(mib[2])->astats->bstats[mib[4]].stats_data.nslabs, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_bins_j_nreslabs,
|
||||
ctl_arenas_i(mib[2])->astats->bstats[mib[4]].stats_data.reslabs, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_bins_j_curslabs,
|
||||
ctl_arenas_i(mib[2])->astats->bstats[mib[4]].stats_data.curslabs, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_bins_j_nonfull_slabs,
|
||||
ctl_arenas_i(mib[2])->astats->bstats[mib[4]].stats_data.nonfull_slabs, size_t)
|
||||
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_lextents_j_nmalloc,
|
||||
locked_read_u64_unsynchronized(
|
||||
&ctl_arenas_i(mib[2])->astats->lstats[mib[4]].nmalloc),
|
||||
uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_lextents_j_ndalloc,
|
||||
locked_read_u64_unsynchronized(
|
||||
&ctl_arenas_i(mib[2])->astats->lstats[mib[4]].ndalloc),
|
||||
uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_lextents_j_nrequests,
|
||||
locked_read_u64_unsynchronized(
|
||||
&ctl_arenas_i(mib[2])->astats->lstats[mib[4]].nrequests),
|
||||
uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_lextents_j_curlextents,
|
||||
ctl_arenas_i(mib[2])->astats->lstats[mib[4]].curlextents, size_t)
|
||||
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_extents_j_ndirty,
|
||||
ctl_arenas_i(mib[2])->astats->estats[mib[4]].ndirty, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_extents_j_nmuzzy,
|
||||
ctl_arenas_i(mib[2])->astats->estats[mib[4]].nmuzzy, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_extents_j_nretained,
|
||||
ctl_arenas_i(mib[2])->astats->estats[mib[4]].nretained, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_extents_j_npinned,
|
||||
ctl_arenas_i(mib[2])->astats->estats[mib[4]].npinned, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_extents_j_dirty_bytes,
|
||||
ctl_arenas_i(mib[2])->astats->estats[mib[4]].dirty_bytes, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_extents_j_muzzy_bytes,
|
||||
ctl_arenas_i(mib[2])->astats->estats[mib[4]].muzzy_bytes, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_extents_j_retained_bytes,
|
||||
ctl_arenas_i(mib[2])->astats->estats[mib[4]].retained_bytes, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_extents_j_pinned_bytes,
|
||||
ctl_arenas_i(mib[2])->astats->estats[mib[4]].pinned_bytes, size_t)
|
||||
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_npageslabs,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.merged.npageslabs, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_nactive,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.merged.nactive, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_ndirty,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.merged.ndirty, size_t)
|
||||
|
||||
/* Nonhuge slabs */
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_slabs_npageslabs_nonhuge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.slabs[0].npageslabs, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_slabs_nactive_nonhuge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.slabs[0].nactive, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_slabs_ndirty_nonhuge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.slabs[0].ndirty, size_t)
|
||||
|
||||
/* Huge slabs */
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_slabs_npageslabs_huge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.slabs[1].npageslabs, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_slabs_nactive_huge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.slabs[1].nactive, size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_slabs_ndirty_huge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.slabs[1].ndirty, size_t)
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_npurge_passes,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.nonderived_stats.npurge_passes,
|
||||
uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_npurges,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.nonderived_stats.npurges, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_nhugifies,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.nonderived_stats.nhugifies, uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_nhugify_failures,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.nonderived_stats.nhugify_failures,
|
||||
uint64_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_ndehugifies,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.nonderived_stats.ndehugifies, uint64_t)
|
||||
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_alloc_j_min_extents,
|
||||
ctl_arenas_i(mib[2])
|
||||
->astats->hpastats.nonderived_stats.hpa_alloc_min_extents[mib[5]],
|
||||
uint64_t);
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_alloc_j_max_extents,
|
||||
ctl_arenas_i(mib[2])
|
||||
->astats->hpastats.nonderived_stats.hpa_alloc_max_extents[mib[5]],
|
||||
uint64_t);
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_alloc_j_extents,
|
||||
ctl_arenas_i(mib[2])
|
||||
->astats->hpastats.nonderived_stats.hpa_alloc_extents[mib[5]],
|
||||
uint64_t);
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_alloc_j_ps,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.nonderived_stats.hpa_alloc_ps[mib[5]],
|
||||
uint64_t);
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_alloc_j_pages_per_ps,
|
||||
ctl_arenas_i(mib[2])
|
||||
->astats->hpastats.nonderived_stats.hpa_alloc_pages_per_ps[mib[5]],
|
||||
uint64_t);
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_alloc_j_extents_per_ps,
|
||||
ctl_arenas_i(mib[2])
|
||||
->astats->hpastats.nonderived_stats.hpa_alloc_extents_per_ps[mib[5]],
|
||||
uint64_t);
|
||||
CTL_RO_CGEN_PUBLIC(config_stats,
|
||||
stats_arenas_i_hpa_shard_alloc_j_total_elapsed_ns_per_ps,
|
||||
ctl_arenas_i(mib[2])
|
||||
->astats->hpastats.nonderived_stats
|
||||
.hpa_alloc_total_elapsed_ns_per_ps[mib[5]],
|
||||
uint64_t);
|
||||
|
||||
/* Full, nonhuge */
|
||||
CTL_RO_CGEN_PUBLIC(config_stats,
|
||||
stats_arenas_i_hpa_shard_full_slabs_npageslabs_nonhuge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.full_slabs[0].npageslabs,
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_full_slabs_nactive_nonhuge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.full_slabs[0].nactive,
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_full_slabs_ndirty_nonhuge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.full_slabs[0].ndirty,
|
||||
size_t)
|
||||
|
||||
/* Full, huge */
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_full_slabs_npageslabs_huge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.full_slabs[1].npageslabs,
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_full_slabs_nactive_huge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.full_slabs[1].nactive,
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_full_slabs_ndirty_huge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.full_slabs[1].ndirty,
|
||||
size_t)
|
||||
|
||||
/* Empty, nonhuge */
|
||||
CTL_RO_CGEN_PUBLIC(config_stats,
|
||||
stats_arenas_i_hpa_shard_empty_slabs_npageslabs_nonhuge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.empty_slabs[0].npageslabs,
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_empty_slabs_nactive_nonhuge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.empty_slabs[0].nactive,
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_empty_slabs_ndirty_nonhuge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.empty_slabs[0].ndirty,
|
||||
size_t)
|
||||
|
||||
/* Empty, huge */
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_empty_slabs_npageslabs_huge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.empty_slabs[1].npageslabs,
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_empty_slabs_nactive_huge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.empty_slabs[1].nactive,
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_empty_slabs_ndirty_huge,
|
||||
ctl_arenas_i(mib[2])->astats->hpastats.psset_stats.empty_slabs[1].ndirty,
|
||||
size_t)
|
||||
|
||||
/* Nonfull, nonhuge */
|
||||
CTL_RO_CGEN_PUBLIC(config_stats,
|
||||
stats_arenas_i_hpa_shard_nonfull_slabs_j_npageslabs_nonhuge,
|
||||
ctl_arenas_i(mib[2])
|
||||
->astats->hpastats.psset_stats.nonfull_slabs[mib[5]][0]
|
||||
.npageslabs,
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats,
|
||||
stats_arenas_i_hpa_shard_nonfull_slabs_j_nactive_nonhuge,
|
||||
ctl_arenas_i(mib[2])
|
||||
->astats->hpastats.psset_stats.nonfull_slabs[mib[5]][0]
|
||||
.nactive,
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats,
|
||||
stats_arenas_i_hpa_shard_nonfull_slabs_j_ndirty_nonhuge,
|
||||
ctl_arenas_i(mib[2])
|
||||
->astats->hpastats.psset_stats.nonfull_slabs[mib[5]][0]
|
||||
.ndirty,
|
||||
size_t)
|
||||
|
||||
/* Nonfull, huge */
|
||||
CTL_RO_CGEN_PUBLIC(config_stats,
|
||||
stats_arenas_i_hpa_shard_nonfull_slabs_j_npageslabs_huge,
|
||||
ctl_arenas_i(mib[2])
|
||||
->astats->hpastats.psset_stats.nonfull_slabs[mib[5]][1]
|
||||
.npageslabs,
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_nonfull_slabs_j_nactive_huge,
|
||||
ctl_arenas_i(mib[2])
|
||||
->astats->hpastats.psset_stats.nonfull_slabs[mib[5]][1]
|
||||
.nactive,
|
||||
size_t)
|
||||
CTL_RO_CGEN_PUBLIC(config_stats, stats_arenas_i_hpa_shard_nonfull_slabs_j_ndirty_huge,
|
||||
ctl_arenas_i(mib[2])
|
||||
->astats->hpastats.psset_stats.nonfull_slabs[mib[5]][1]
|
||||
.ndirty,
|
||||
size_t)
|
||||
56
src/ctl_tcache.c
Normal file
56
src/ctl_tcache.c
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||
#include "jemalloc/internal/jemalloc_internal_includes.h"
|
||||
|
||||
#include "jemalloc/internal/ctl_tcache.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/* tcache.* mallctl handlers. */
|
||||
|
||||
int
|
||||
tcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
unsigned tcache_ind;
|
||||
|
||||
READONLY();
|
||||
VERIFY_READ(unsigned);
|
||||
if (tcaches_create(tsd, b0get(), &tcache_ind)) {
|
||||
ret = EFAULT;
|
||||
goto label_return;
|
||||
}
|
||||
READ(tcache_ind, unsigned);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
unsigned tcache_ind;
|
||||
|
||||
WRITEONLY();
|
||||
ASSURED_WRITE(tcache_ind, unsigned);
|
||||
tcaches_flush(tsd, tcache_ind);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
tcache_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
unsigned tcache_ind;
|
||||
|
||||
WRITEONLY();
|
||||
ASSURED_WRITE(tcache_ind, unsigned);
|
||||
tcaches_destroy(tsd, tcache_ind);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
353
src/ctl_thread.c
Normal file
353
src/ctl_thread.c
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||
#include "jemalloc/internal/jemalloc_internal_includes.h"
|
||||
|
||||
#include "jemalloc/internal/assert.h"
|
||||
#include "jemalloc/internal/ctl_thread.h"
|
||||
#include "jemalloc/internal/peak_event.h"
|
||||
#include "jemalloc/internal/prof_data.h"
|
||||
#include "jemalloc/internal/sc.h"
|
||||
#include "jemalloc/internal/thread_event_registry.h"
|
||||
|
||||
/*******************************************************************************/
|
||||
/* thread.* mallctl handlers. */
|
||||
|
||||
int
|
||||
thread_arena_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
arena_t *oldarena;
|
||||
unsigned newind, oldind;
|
||||
|
||||
oldarena = arena_choose(tsd, NULL);
|
||||
if (oldarena == NULL) {
|
||||
return EAGAIN;
|
||||
}
|
||||
newind = oldind = arena_ind_get(oldarena);
|
||||
WRITE(newind, unsigned);
|
||||
READ(oldind, unsigned);
|
||||
|
||||
if (newind != oldind) {
|
||||
arena_t *newarena;
|
||||
|
||||
if (newind >= narenas_total_get()) {
|
||||
/* New arena index is out of range. */
|
||||
ret = EFAULT;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
if (have_percpu_arena
|
||||
&& PERCPU_ARENA_ENABLED(opt_percpu_arena)) {
|
||||
if (newind < percpu_arena_ind_limit(opt_percpu_arena)) {
|
||||
/*
|
||||
* If perCPU arena is enabled, thread_arena
|
||||
* control is not allowed for the auto arena
|
||||
* range.
|
||||
*/
|
||||
ret = EPERM;
|
||||
goto label_return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize arena if necessary. */
|
||||
newarena = arena_get(tsd_tsdn(tsd), newind, true);
|
||||
if (newarena == NULL) {
|
||||
ret = EAGAIN;
|
||||
goto label_return;
|
||||
}
|
||||
thread_migrate_arena(tsd, oldarena, newarena);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
CTL_RO_NL_GEN_PUBLIC(thread_allocated, tsd_thread_allocated_get(tsd), uint64_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(thread_allocatedp, tsd_thread_allocatedp_get(tsd), uint64_t *)
|
||||
|
||||
int
|
||||
thread_tcache_ncached_max_read_sizeclass_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
size_t bin_size = 0;
|
||||
|
||||
/* Read the bin size from newp. */
|
||||
if (newp == NULL) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
WRITE(bin_size, size_t);
|
||||
|
||||
cache_bin_sz_t ncached_max = 0;
|
||||
if (tcache_bin_ncached_max_read(tsd, bin_size, &ncached_max)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
size_t result = (size_t)ncached_max;
|
||||
READ(result, size_t);
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
thread_tcache_ncached_max_write_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
WRITEONLY();
|
||||
if (newp != NULL) {
|
||||
if (!tcache_available(tsd)) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
char *settings = NULL;
|
||||
WRITE(settings, char *);
|
||||
if (settings == NULL) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
/* Get the length of the setting string safely. */
|
||||
char *end = (char *)memchr(
|
||||
settings, '\0', CTL_MULTI_SETTING_MAX_LEN);
|
||||
if (end == NULL) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
/*
|
||||
* Exclude the last '\0' for len since it is not handled by
|
||||
* multi_setting_parse_next.
|
||||
*/
|
||||
size_t len = (uintptr_t)end - (uintptr_t)settings;
|
||||
if (len == 0) {
|
||||
ret = 0;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
if (tcache_bins_ncached_max_write(tsd, settings, len)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
CTL_RO_NL_GEN_PUBLIC(thread_deallocated, tsd_thread_deallocated_get(tsd), uint64_t)
|
||||
CTL_RO_NL_GEN_PUBLIC(thread_deallocatedp, tsd_thread_deallocatedp_get(tsd), uint64_t *)
|
||||
|
||||
int
|
||||
thread_tcache_enabled_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
bool oldval;
|
||||
|
||||
oldval = tcache_enabled_get(tsd);
|
||||
if (newp != NULL) {
|
||||
if (newlen != sizeof(bool)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
tcache_enabled_set(tsd, *(bool *)newp);
|
||||
}
|
||||
READ(oldval, bool);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
thread_tcache_max_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
size_t oldval;
|
||||
|
||||
/* pointer to tcache_t always exists even with tcache disabled. */
|
||||
tcache_t *tcache = tsd_tcachep_get(tsd);
|
||||
assert(tcache != NULL);
|
||||
oldval = tcache_max_get(tcache->tcache_slow);
|
||||
READ(oldval, size_t);
|
||||
|
||||
if (newp != NULL) {
|
||||
if (newlen != sizeof(size_t)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
size_t new_tcache_max = oldval;
|
||||
WRITE(new_tcache_max, size_t);
|
||||
if (new_tcache_max > TCACHE_MAXCLASS_LIMIT) {
|
||||
new_tcache_max = TCACHE_MAXCLASS_LIMIT;
|
||||
}
|
||||
new_tcache_max = sz_s2u(new_tcache_max);
|
||||
if (new_tcache_max != oldval) {
|
||||
thread_tcache_max_set(tsd, new_tcache_max);
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
thread_tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
|
||||
if (!tcache_available(tsd)) {
|
||||
ret = EFAULT;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
NEITHER_READ_NOR_WRITE();
|
||||
|
||||
tcache_flush(tsd);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
thread_peak_read_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
if (!config_stats) {
|
||||
return ENOENT;
|
||||
}
|
||||
READONLY();
|
||||
peak_event_update(tsd);
|
||||
uint64_t result = peak_event_max(tsd);
|
||||
READ(result, uint64_t);
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
thread_peak_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
if (!config_stats) {
|
||||
return ENOENT;
|
||||
}
|
||||
NEITHER_READ_NOR_WRITE();
|
||||
peak_event_zero(tsd);
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
thread_prof_name_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
|
||||
if (!config_prof || !opt_prof) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
READ_XOR_WRITE();
|
||||
|
||||
if (newp != NULL) {
|
||||
const char *newval = *(const char **)newp;
|
||||
if (newlen != sizeof(const char *) || newval == NULL) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
if ((ret = prof_thread_name_set(tsd, newval)) != 0) {
|
||||
goto label_return;
|
||||
}
|
||||
} else {
|
||||
const char *oldname = prof_thread_name_get(tsd);
|
||||
READ(oldname, const char *);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
thread_prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
bool oldval;
|
||||
|
||||
if (!config_prof) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
oldval = opt_prof ? prof_thread_active_get(tsd) : false;
|
||||
if (newp != NULL) {
|
||||
if (!opt_prof) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
if (newlen != sizeof(bool)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
if (prof_thread_active_set(tsd, *(bool *)newp)) {
|
||||
ret = EAGAIN;
|
||||
goto label_return;
|
||||
}
|
||||
}
|
||||
READ(oldval, bool);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
thread_idle_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
|
||||
NEITHER_READ_NOR_WRITE();
|
||||
|
||||
if (tcache_available(tsd)) {
|
||||
tcache_flush(tsd);
|
||||
}
|
||||
/*
|
||||
* This heuristic is perhaps not the most well-considered. But it
|
||||
* matches the only idling policy we have experience with in the status
|
||||
* quo. Over time we should investigate more principled approaches.
|
||||
*/
|
||||
if (opt_narenas > ncpus * 2) {
|
||||
arena_t *arena = arena_choose(tsd, NULL);
|
||||
if (arena != NULL) {
|
||||
arena_decay(tsd_tsdn(tsd), arena, false, true);
|
||||
}
|
||||
/*
|
||||
* The missing arena case is not actually an error; a thread
|
||||
* might be idle before it associates itself to one. This is
|
||||
* unusual, but not wrong.
|
||||
*/
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
experimental_hooks_thread_event_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
|
||||
if (newp == NULL) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
user_hook_object_t t_new = {NULL, 0, false};
|
||||
WRITE(t_new, user_hook_object_t);
|
||||
ret = te_register_user_handler(tsd_tsdn(tsd), &t_new);
|
||||
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
51
src/ctl_utilization.c
Normal file
51
src/ctl_utilization.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||
#include "jemalloc/internal/jemalloc_internal_includes.h"
|
||||
|
||||
#include "jemalloc/internal/assert.h"
|
||||
#include "jemalloc/internal/ctl_utilization.h"
|
||||
#include "jemalloc/internal/inspect.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/* experimental.utilization.* mallctl handlers. */
|
||||
|
||||
/*
|
||||
* Given an input array of pointers, output three memory utilization entries of
|
||||
* type size_t for each input pointer about the extent it resides in:
|
||||
*
|
||||
* (a) number of free regions in the extent,
|
||||
* (b) number of regions in the extent, and
|
||||
* (c) size of the extent in terms of bytes.
|
||||
*
|
||||
* This API is mainly intended for small class allocations, where extents are
|
||||
* used as slab. In case of large class allocations, the outputs are trivial:
|
||||
* "(a)" will be 0, "(b)" will be 1, and "(c)" will be the usable size.
|
||||
*/
|
||||
int
|
||||
experimental_utilization_batch_query_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
|
||||
assert(sizeof(inspect_extent_util_stats_t) == sizeof(size_t) * 3);
|
||||
|
||||
const size_t len = newlen / sizeof(const void *);
|
||||
if (oldp == NULL || oldlenp == NULL || newp == NULL || newlen == 0
|
||||
|| newlen != len * sizeof(const void *)
|
||||
|| *oldlenp != len * sizeof(inspect_extent_util_stats_t)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
void **ptrs = (void **)newp;
|
||||
inspect_extent_util_stats_t *util_stats =
|
||||
(inspect_extent_util_stats_t *)oldp;
|
||||
size_t i;
|
||||
for (i = 0; i < len; ++i) {
|
||||
inspect_extent_util_stats_get(tsd_tsdn(tsd), ptrs[i],
|
||||
&util_stats[i].nfree, &util_stats[i].nregs,
|
||||
&util_stats[i].size);
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -24,54 +24,3 @@ inspect_extent_util_stats_get(
|
|||
assert(*nfree * edata_usize_get(edata) <= *size);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
inspect_extent_util_stats_verbose_get(tsdn_t *tsdn, const void *ptr,
|
||||
size_t *nfree, size_t *nregs, size_t *size, size_t *bin_nfree,
|
||||
size_t *bin_nregs, void **slabcur_addr) {
|
||||
assert(ptr != NULL && nfree != NULL && nregs != NULL && size != NULL
|
||||
&& bin_nfree != NULL && bin_nregs != NULL && slabcur_addr != NULL);
|
||||
|
||||
const edata_t *edata = emap_edata_lookup(tsdn, &arena_emap_global, ptr);
|
||||
if (unlikely(edata == NULL)) {
|
||||
*nfree = *nregs = *size = *bin_nfree = *bin_nregs = 0;
|
||||
*slabcur_addr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*size = edata_size_get(edata);
|
||||
if (!edata_slab_get(edata)) {
|
||||
*nfree = *bin_nfree = *bin_nregs = 0;
|
||||
*nregs = 1;
|
||||
*slabcur_addr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*nfree = edata_nfree_get(edata);
|
||||
const szind_t szind = edata_szind_get(edata);
|
||||
*nregs = bin_infos[szind].nregs;
|
||||
assert(*nfree <= *nregs);
|
||||
assert(*nfree * edata_usize_get(edata) <= *size);
|
||||
|
||||
arena_t *arena = arena_get_from_edata(edata);
|
||||
assert(arena != NULL);
|
||||
const unsigned binshard = edata_binshard_get(edata);
|
||||
bin_t *bin = arena_get_bin(arena, szind, binshard);
|
||||
|
||||
malloc_mutex_lock(tsdn, &bin->lock);
|
||||
if (config_stats) {
|
||||
*bin_nregs = *nregs * bin->stats.curslabs;
|
||||
assert(*bin_nregs >= bin->stats.curregs);
|
||||
*bin_nfree = *bin_nregs - bin->stats.curregs;
|
||||
} else {
|
||||
*bin_nfree = *bin_nregs = 0;
|
||||
}
|
||||
edata_t *slab;
|
||||
if (bin->slabcur != NULL) {
|
||||
slab = bin->slabcur;
|
||||
} else {
|
||||
slab = edata_heap_first(&bin->slabs_nonfull);
|
||||
}
|
||||
*slabcur_addr = slab != NULL ? edata_addr_get(slab) : NULL;
|
||||
malloc_mutex_unlock(tsdn, &bin->lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||
#include "jemalloc/internal/jemalloc_internal_includes.h"
|
||||
|
||||
static safety_check_abort_hook_t safety_check_abort;
|
||||
|
||||
void
|
||||
safety_check_fail_sized_dealloc(bool current_dealloc, const void *ptr,
|
||||
size_t true_size, size_t input_size) {
|
||||
|
|
@ -19,23 +17,18 @@ safety_check_fail_sized_dealloc(bool current_dealloc, const void *ptr,
|
|||
true_size, input_size, ptr, src, suggest_debug_build);
|
||||
}
|
||||
|
||||
void
|
||||
safety_check_set_abort(safety_check_abort_hook_t abort_fn) {
|
||||
safety_check_abort = abort_fn;
|
||||
}
|
||||
|
||||
/*
|
||||
* In addition to malloc_write, also embed hint msg in the abort function name
|
||||
* because there are cases only logging crash stack traces.
|
||||
*/
|
||||
static void
|
||||
safety_check_detected_heap_corruption___run_address_sanitizer_build_to_debug(
|
||||
const char *buf) {
|
||||
if (safety_check_abort == NULL) {
|
||||
const char *buf) {
|
||||
if (test_hooks_safety_check_abort == NULL) {
|
||||
malloc_write(buf);
|
||||
abort();
|
||||
} else {
|
||||
safety_check_abort(buf);
|
||||
test_hooks_safety_check_abort(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1708,10 +1708,9 @@ stats_general_print(emitter_t *emitter) {
|
|||
MALLOC_CONF_WRITE("global_var", "Global variable malloc_conf");
|
||||
MALLOC_CONF_WRITE("symlink", "Symbolic link malloc.conf");
|
||||
MALLOC_CONF_WRITE("env_var", "Environment variable MALLOC_CONF");
|
||||
/* As this config is unofficial, skip the output if it's NULL */
|
||||
if (je_mallctl("opt.malloc_conf.global_var_2_conf_harder", (void *)&cpv,
|
||||
&cpsz, NULL, 0)
|
||||
== 0) {
|
||||
/* As this config is unofficial, skip the output if it's NULL. */
|
||||
if (je_malloc_conf_2_conf_harder != NULL) {
|
||||
cpv = je_malloc_conf_2_conf_harder;
|
||||
emitter_kv(emitter, "global_var_2_conf_harder",
|
||||
"Global "
|
||||
"variable malloc_conf_2_conf_harder",
|
||||
|
|
|
|||
|
|
@ -10,3 +10,6 @@ void (*test_hooks_arena_new_hook)(void) = NULL;
|
|||
|
||||
JEMALLOC_EXPORT
|
||||
void (*test_hooks_libc_hook)(void) = NULL;
|
||||
|
||||
JEMALLOC_EXPORT
|
||||
void (*test_hooks_safety_check_abort)(const char *) = NULL;
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@
|
|||
#include "test/jemalloc_test.h"
|
||||
|
||||
/*
|
||||
* We can't test C++ in unit tests. In order to intercept abort, use a secret
|
||||
* safety check abort hook in integration tests.
|
||||
* We can't test C++ in unit tests. In order to intercept abort, use the
|
||||
* internal test hook in integration tests.
|
||||
*/
|
||||
typedef void (*abort_hook_t)(const char *message);
|
||||
bool fake_abort_called;
|
||||
void
|
||||
fake_abort(const char *message) {
|
||||
|
|
@ -34,10 +33,7 @@ own_operator_new(void) {
|
|||
}
|
||||
|
||||
TEST_BEGIN(test_failing_alloc) {
|
||||
abort_hook_t abort_hook = &fake_abort;
|
||||
expect_d_eq(mallctl("experimental.hooks.safety_check_abort", NULL, NULL,
|
||||
(void *)&abort_hook, sizeof(abort_hook)),
|
||||
0, "Unexpected mallctl failure setting abort hook");
|
||||
test_hooks_safety_check_abort = &fake_abort;
|
||||
|
||||
/*
|
||||
* Not owning operator new is only expected to happen on MinGW which
|
||||
|
|
@ -57,6 +53,7 @@ TEST_BEGIN(test_failing_alloc) {
|
|||
}
|
||||
expect_ptr_null(ptr, "Allocation should have failed");
|
||||
expect_b_eq(fake_abort_called, true, "Abort hook not invoked");
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
}
|
||||
TEST_END
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ p_test_impl(bool do_malloc_init, bool do_reentrant, test_t *t, va_list ap) {
|
|||
/* Non-reentrant run. */
|
||||
reentrancy = non_reentrant;
|
||||
test_hooks_arena_new_hook = test_hooks_libc_hook = NULL;
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
t();
|
||||
if (test_status > ret) {
|
||||
ret = test_status;
|
||||
|
|
@ -158,6 +159,7 @@ p_test_impl(bool do_malloc_init, bool do_reentrant, test_t *t, va_list ap) {
|
|||
if (do_reentrant) {
|
||||
reentrancy = libc_reentrant;
|
||||
test_hooks_arena_new_hook = NULL;
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
test_hooks_libc_hook = &libc_reentrancy_hook;
|
||||
t();
|
||||
if (test_status > ret) {
|
||||
|
|
@ -166,6 +168,7 @@ p_test_impl(bool do_malloc_init, bool do_reentrant, test_t *t, va_list ap) {
|
|||
|
||||
reentrancy = arena_new_reentrant;
|
||||
test_hooks_libc_hook = NULL;
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
test_hooks_arena_new_hook = &arena_new_reentrancy_hook;
|
||||
t();
|
||||
if (test_status > ret) {
|
||||
|
|
|
|||
|
|
@ -2,15 +2,30 @@
|
|||
|
||||
case @abi@ in
|
||||
macho)
|
||||
export DYLD_FALLBACK_LIBRARY_PATH="@objroot@lib"
|
||||
export DYLD_FALLBACK_LIBRARY_PATH="@abs_objroot@lib"
|
||||
;;
|
||||
pecoff)
|
||||
export PATH="${PATH}:@objroot@lib"
|
||||
export PATH="@abs_objroot@lib:${PATH}"
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
prepare_test_exec() {
|
||||
case @abi@ in
|
||||
pecoff)
|
||||
test_dir=`dirname "$1"`
|
||||
for dll in @abs_objroot@lib/*.dll ; do
|
||||
if [ -f "${dll}" ] ; then
|
||||
cp -f "${dll}" "${test_dir}/"
|
||||
fi
|
||||
done
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Make a copy of the @JEMALLOC_CPREFIX@MALLOC_CONF passed in to this script, so
|
||||
# it can be repeatedly concatenated with per test settings.
|
||||
export MALLOC_CONF_ALL=${@JEMALLOC_CPREFIX@MALLOC_CONF}
|
||||
|
|
@ -45,10 +60,12 @@ for t in $@; do
|
|||
enable_prof=@enable_prof@ \
|
||||
disable_large_size_classes=@disable_large_size_classes@ \
|
||||
. @srcroot@${t}.sh && \
|
||||
prepare_test_exec ${t}@exe@ && \
|
||||
export_malloc_conf && \
|
||||
$JEMALLOC_TEST_PREFIX ${t}@exe@ @abs_srcroot@ @abs_objroot@
|
||||
else
|
||||
export MALLOC_CONF= && \
|
||||
prepare_test_exec ${t}@exe@ && \
|
||||
export_malloc_conf && \
|
||||
$JEMALLOC_TEST_PREFIX ${t}@exe@ @abs_srcroot@ @abs_objroot@
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@ fake_abort(const char *message) {
|
|||
|
||||
static void
|
||||
test_double_free_pre(void) {
|
||||
safety_check_set_abort(&fake_abort);
|
||||
test_hooks_safety_check_abort = &fake_abort;
|
||||
fake_abort_called = false;
|
||||
}
|
||||
|
||||
static void
|
||||
test_double_free_post(void) {
|
||||
expect_b_eq(fake_abort_called, true, "Double-free check didn't fire.");
|
||||
safety_check_set_abort(NULL);
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@
|
|||
"Output content touched when given invalid arguments"); \
|
||||
} while (0)
|
||||
|
||||
#define TEST_UTIL_QUERY_EINVAL(a, b, c, d, why_inval) \
|
||||
TEST_UTIL_EINVAL("query", a, b, c, d, why_inval)
|
||||
#define TEST_UTIL_BATCH_EINVAL(a, b, c, d, why_inval) \
|
||||
TEST_UTIL_EINVAL("batch_query", a, b, c, d, why_inval)
|
||||
|
||||
|
|
@ -30,139 +28,6 @@
|
|||
|
||||
#define TEST_MAX_SIZE (1 << 20)
|
||||
|
||||
TEST_BEGIN(test_query) {
|
||||
size_t sz;
|
||||
/*
|
||||
* Select some sizes that can span both small and large sizes, and are
|
||||
* numerically unrelated to any size boundaries.
|
||||
*/
|
||||
for (sz = 7; sz <= TEST_MAX_SIZE && sz <= SC_LARGE_MAXCLASS;
|
||||
sz += (sz <= SC_SMALL_MAXCLASS ? 1009 : 99989)) {
|
||||
void *p = mallocx(sz, 0);
|
||||
void **in = &p;
|
||||
size_t in_sz = sizeof(const void *);
|
||||
size_t out_sz = sizeof(void *) + sizeof(size_t) * 5;
|
||||
void *out = mallocx(out_sz, 0);
|
||||
void *out_ref = mallocx(out_sz, 0);
|
||||
size_t out_sz_ref = out_sz;
|
||||
|
||||
assert_ptr_not_null(p, "test pointer allocation failed");
|
||||
assert_ptr_not_null(out, "test output allocation failed");
|
||||
assert_ptr_not_null(
|
||||
out_ref, "test reference output allocation failed");
|
||||
|
||||
#define SLABCUR_READ(out) (*(void **)out)
|
||||
#define COUNTS(out) ((size_t *)((void **)out + 1))
|
||||
#define NFREE_READ(out) COUNTS(out)[0]
|
||||
#define NREGS_READ(out) COUNTS(out)[1]
|
||||
#define SIZE_READ(out) COUNTS(out)[2]
|
||||
#define BIN_NFREE_READ(out) COUNTS(out)[3]
|
||||
#define BIN_NREGS_READ(out) COUNTS(out)[4]
|
||||
|
||||
SLABCUR_READ(out) = NULL;
|
||||
NFREE_READ(out) = NREGS_READ(out) = SIZE_READ(out) = -1;
|
||||
BIN_NFREE_READ(out) = BIN_NREGS_READ(out) = -1;
|
||||
memcpy(out_ref, out, out_sz);
|
||||
|
||||
/* Test invalid argument(s) errors */
|
||||
TEST_UTIL_QUERY_EINVAL(NULL, &out_sz, in, in_sz, "old is NULL");
|
||||
TEST_UTIL_QUERY_EINVAL(out, NULL, in, in_sz, "oldlenp is NULL");
|
||||
TEST_UTIL_QUERY_EINVAL(
|
||||
out, &out_sz, NULL, in_sz, "newp is NULL");
|
||||
TEST_UTIL_QUERY_EINVAL(out, &out_sz, in, 0, "newlen is zero");
|
||||
in_sz -= 1;
|
||||
TEST_UTIL_QUERY_EINVAL(
|
||||
out, &out_sz, in, in_sz, "invalid newlen");
|
||||
in_sz += 1;
|
||||
out_sz_ref = out_sz -= 2 * sizeof(size_t);
|
||||
TEST_UTIL_QUERY_EINVAL(
|
||||
out, &out_sz, in, in_sz, "invalid *oldlenp");
|
||||
out_sz_ref = out_sz += 2 * sizeof(size_t);
|
||||
|
||||
/* Examine output for valid call */
|
||||
TEST_UTIL_VALID("query");
|
||||
expect_zu_le(sz, SIZE_READ(out),
|
||||
"Extent size should be at least allocation size");
|
||||
expect_zu_eq(SIZE_READ(out) & (PAGE - 1), 0,
|
||||
"Extent size should be a multiple of page size");
|
||||
|
||||
/*
|
||||
* We don't do much bin checking if prof is on, since profiling
|
||||
* can produce extents that are for small size classes but not
|
||||
* slabs, which interferes with things like region counts.
|
||||
*/
|
||||
if (!opt_prof && sz <= SC_SMALL_MAXCLASS) {
|
||||
expect_zu_le(NFREE_READ(out), NREGS_READ(out),
|
||||
"Extent free count exceeded region count");
|
||||
expect_zu_le(NREGS_READ(out), SIZE_READ(out),
|
||||
"Extent region count exceeded size");
|
||||
expect_zu_ne(NREGS_READ(out), 0,
|
||||
"Extent region count must be positive");
|
||||
expect_true(NFREE_READ(out) == 0
|
||||
|| (SLABCUR_READ(out) != NULL
|
||||
&& SLABCUR_READ(out) <= p),
|
||||
"Allocation should follow first fit principle");
|
||||
|
||||
if (config_stats) {
|
||||
expect_zu_le(BIN_NFREE_READ(out),
|
||||
BIN_NREGS_READ(out),
|
||||
"Bin free count exceeded region count");
|
||||
expect_zu_ne(BIN_NREGS_READ(out), 0,
|
||||
"Bin region count must be positive");
|
||||
expect_zu_le(NFREE_READ(out),
|
||||
BIN_NFREE_READ(out),
|
||||
"Extent free count exceeded bin free count");
|
||||
expect_zu_le(NREGS_READ(out),
|
||||
BIN_NREGS_READ(out),
|
||||
"Extent region count exceeded "
|
||||
"bin region count");
|
||||
expect_zu_eq(
|
||||
BIN_NREGS_READ(out) % NREGS_READ(out), 0,
|
||||
"Bin region count isn't a multiple of "
|
||||
"extent region count");
|
||||
expect_zu_le(
|
||||
BIN_NFREE_READ(out) - NFREE_READ(out),
|
||||
BIN_NREGS_READ(out) - NREGS_READ(out),
|
||||
"Free count in other extents in the bin "
|
||||
"exceeded region count in other extents "
|
||||
"in the bin");
|
||||
expect_zu_le(NREGS_READ(out) - NFREE_READ(out),
|
||||
BIN_NREGS_READ(out) - BIN_NFREE_READ(out),
|
||||
"Extent utilized count exceeded "
|
||||
"bin utilized count");
|
||||
}
|
||||
} else if (sz > SC_SMALL_MAXCLASS) {
|
||||
expect_zu_eq(NFREE_READ(out), 0,
|
||||
"Extent free count should be zero");
|
||||
expect_zu_eq(NREGS_READ(out), 1,
|
||||
"Extent region count should be one");
|
||||
expect_ptr_null(SLABCUR_READ(out),
|
||||
"Current slab must be null for large size classes");
|
||||
if (config_stats) {
|
||||
expect_zu_eq(BIN_NFREE_READ(out), 0,
|
||||
"Bin free count must be zero for "
|
||||
"large sizes");
|
||||
expect_zu_eq(BIN_NREGS_READ(out), 0,
|
||||
"Bin region count must be zero for "
|
||||
"large sizes");
|
||||
}
|
||||
}
|
||||
|
||||
#undef BIN_NREGS_READ
|
||||
#undef BIN_NFREE_READ
|
||||
#undef SIZE_READ
|
||||
#undef NREGS_READ
|
||||
#undef NFREE_READ
|
||||
#undef COUNTS
|
||||
#undef SLABCUR_READ
|
||||
|
||||
free(out_ref);
|
||||
free(out);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_batch) {
|
||||
size_t sz;
|
||||
/*
|
||||
|
|
@ -217,10 +82,7 @@ TEST_BEGIN(test_batch) {
|
|||
"Extent size should be at least allocation size");
|
||||
expect_zu_eq(SIZE_READ(out, 0) & (PAGE - 1), 0,
|
||||
"Extent size should be a multiple of page size");
|
||||
/*
|
||||
* See the corresponding comment in test_query; profiling breaks
|
||||
* our slab count expectations.
|
||||
*/
|
||||
/* Profiling breaks our slab count expectations. */
|
||||
if (sz <= SC_SMALL_MAXCLASS && !opt_prof) {
|
||||
expect_zu_le(NFREE_READ(out, 0), NREGS_READ(out, 0),
|
||||
"Extent free count exceeded region count");
|
||||
|
|
@ -270,5 +132,5 @@ int
|
|||
main(void) {
|
||||
assert_zu_lt(SC_SMALL_MAXCLASS + 100000, TEST_MAX_SIZE,
|
||||
"Test case cannot cover large classes");
|
||||
return test(test_query, test_batch);
|
||||
return test(test_batch);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,13 +39,6 @@ TEST_BEGIN(test_mallctl_global_var) {
|
|||
expect_str_eq(mc, malloc_conf,
|
||||
"Unexpected value for the global variable "
|
||||
"malloc_conf");
|
||||
|
||||
expect_d_eq(mallctl("opt.malloc_conf.global_var_2_conf_harder",
|
||||
(void *)&mc, &sz, NULL, 0),
|
||||
0, "Unexpected mallctl() failure");
|
||||
expect_str_eq(mc, malloc_conf_2_conf_harder,
|
||||
"Unexpected value for the "
|
||||
"global variable malloc_conf_2_conf_harder");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
|
|
|
|||
|
|
@ -334,9 +334,23 @@ TEST_BEGIN(test_prof_sample_hooks) {
|
|||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_prof_hook_noop) {
|
||||
test_skip_if(!config_prof);
|
||||
|
||||
const char *hooks[] = {"experimental.hooks.prof_backtrace",
|
||||
"experimental.hooks.prof_dump", "experimental.hooks.prof_sample",
|
||||
"experimental.hooks.prof_sample_free"};
|
||||
|
||||
for (unsigned i = 0; i < sizeof(hooks) / sizeof(hooks[0]); i++) {
|
||||
expect_d_eq(mallctl(hooks[i], NULL, NULL, NULL, 0), EINVAL,
|
||||
"Unexpected noop hook mallctl result");
|
||||
}
|
||||
}
|
||||
TEST_END
|
||||
|
||||
int
|
||||
main(void) {
|
||||
return test(test_prof_backtrace_hook_replace,
|
||||
test_prof_backtrace_hook_augment, test_prof_dump_hook,
|
||||
test_prof_sample_hooks);
|
||||
test_prof_sample_hooks, test_prof_hook_noop);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ TEST_BEGIN(test_malloc_free_overflow) {
|
|||
test_skip_if(!config_prof);
|
||||
test_skip_if(!config_opt_safety_checks);
|
||||
|
||||
safety_check_set_abort(&fake_abort);
|
||||
test_hooks_safety_check_abort = &fake_abort;
|
||||
/* Buffer overflow! */
|
||||
char *ptr = malloc(128);
|
||||
buffer_overflow_write(ptr, 128);
|
||||
free(ptr);
|
||||
safety_check_set_abort(NULL);
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
|
||||
expect_b_eq(fake_abort_called, true, "Redzone check didn't fire.");
|
||||
fake_abort_called = false;
|
||||
|
|
@ -41,12 +41,12 @@ TEST_BEGIN(test_mallocx_dallocx_overflow) {
|
|||
test_skip_if(!config_prof);
|
||||
test_skip_if(!config_opt_safety_checks);
|
||||
|
||||
safety_check_set_abort(&fake_abort);
|
||||
test_hooks_safety_check_abort = &fake_abort;
|
||||
/* Buffer overflow! */
|
||||
char *ptr = mallocx(128, 0);
|
||||
buffer_overflow_write(ptr, 128);
|
||||
dallocx(ptr, 0);
|
||||
safety_check_set_abort(NULL);
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
|
||||
expect_b_eq(fake_abort_called, true, "Redzone check didn't fire.");
|
||||
fake_abort_called = false;
|
||||
|
|
@ -57,12 +57,12 @@ TEST_BEGIN(test_malloc_sdallocx_overflow) {
|
|||
test_skip_if(!config_prof);
|
||||
test_skip_if(!config_opt_safety_checks);
|
||||
|
||||
safety_check_set_abort(&fake_abort);
|
||||
test_hooks_safety_check_abort = &fake_abort;
|
||||
/* Buffer overflow! */
|
||||
char *ptr = malloc(128);
|
||||
buffer_overflow_write(ptr, 128);
|
||||
sdallocx(ptr, 128, 0);
|
||||
safety_check_set_abort(NULL);
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
|
||||
expect_b_eq(fake_abort_called, true, "Redzone check didn't fire.");
|
||||
fake_abort_called = false;
|
||||
|
|
@ -73,12 +73,12 @@ TEST_BEGIN(test_realloc_overflow) {
|
|||
test_skip_if(!config_prof);
|
||||
test_skip_if(!config_opt_safety_checks);
|
||||
|
||||
safety_check_set_abort(&fake_abort);
|
||||
test_hooks_safety_check_abort = &fake_abort;
|
||||
/* Buffer overflow! */
|
||||
char *ptr = malloc(128);
|
||||
buffer_overflow_write(ptr, 128);
|
||||
ptr = realloc(ptr, 129);
|
||||
safety_check_set_abort(NULL);
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
free(ptr);
|
||||
|
||||
expect_b_eq(fake_abort_called, true, "Redzone check didn't fire.");
|
||||
|
|
@ -90,12 +90,12 @@ TEST_BEGIN(test_rallocx_overflow) {
|
|||
test_skip_if(!config_prof);
|
||||
test_skip_if(!config_opt_safety_checks);
|
||||
|
||||
safety_check_set_abort(&fake_abort);
|
||||
test_hooks_safety_check_abort = &fake_abort;
|
||||
/* Buffer overflow! */
|
||||
char *ptr = malloc(128);
|
||||
buffer_overflow_write(ptr, 128);
|
||||
ptr = rallocx(ptr, 129, 0);
|
||||
safety_check_set_abort(NULL);
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
free(ptr);
|
||||
|
||||
expect_b_eq(fake_abort_called, true, "Redzone check didn't fire.");
|
||||
|
|
@ -107,7 +107,7 @@ TEST_BEGIN(test_xallocx_overflow) {
|
|||
test_skip_if(!config_prof);
|
||||
test_skip_if(!config_opt_safety_checks);
|
||||
|
||||
safety_check_set_abort(&fake_abort);
|
||||
test_hooks_safety_check_abort = &fake_abort;
|
||||
/* Buffer overflow! */
|
||||
char *ptr = malloc(128);
|
||||
buffer_overflow_write(ptr, 128);
|
||||
|
|
@ -116,7 +116,7 @@ TEST_BEGIN(test_xallocx_overflow) {
|
|||
free(ptr);
|
||||
expect_b_eq(fake_abort_called, true, "Redzone check didn't fire.");
|
||||
fake_abort_called = false;
|
||||
safety_check_set_abort(NULL);
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
}
|
||||
TEST_END
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ fake_abort(const char *message) {
|
|||
|
||||
static void *
|
||||
test_invalid_size_pre(size_t sz) {
|
||||
safety_check_set_abort(&fake_abort);
|
||||
test_hooks_safety_check_abort = &fake_abort;
|
||||
|
||||
fake_abort_called = false;
|
||||
void *ptr = malloc(sz);
|
||||
|
|
@ -29,7 +29,7 @@ test_invalid_size_pre(size_t sz) {
|
|||
static void
|
||||
test_invalid_size_post(void) {
|
||||
expect_true(fake_abort_called, "Safety check didn't fire");
|
||||
safety_check_set_abort(NULL);
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
}
|
||||
|
||||
TEST_BEGIN(test_invalid_size_sdallocx) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ fake_abort(const char *message) {
|
|||
|
||||
static void
|
||||
test_write_after_free_pre(void) {
|
||||
safety_check_set_abort(&fake_abort);
|
||||
test_hooks_safety_check_abort = &fake_abort;
|
||||
fake_abort_called = false;
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ test_write_after_free_post(void) {
|
|||
assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0), 0,
|
||||
"Unexpected tcache flush failure");
|
||||
expect_true(fake_abort_called, "Use-after-free check didn't fire.");
|
||||
safety_check_set_abort(NULL);
|
||||
test_hooks_safety_check_abort = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ set_abort_called(const char *message) {
|
|||
|
||||
TEST_BEGIN(test_realloc_abort) {
|
||||
abort_called = false;
|
||||
safety_check_set_abort(&set_abort_called);
|
||||
test_hooks_safety_check_abort = &set_abort_called;
|
||||
void *ptr = mallocx(42, 0);
|
||||
expect_ptr_not_null(ptr, "Unexpected mallocx error");
|
||||
ptr = realloc(ptr, 0);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue