Extents: Split out introspection functionality.
This isn't really part of the core extent allocation facilities. Especially as this module grows, having it in its own place may come in handy.
This commit is contained in:
parent
92a511d385
commit
403f2d1664
@ -112,6 +112,7 @@ C_SRCS := $(srcroot)src/jemalloc.c \
|
||||
$(srcroot)src/extent_mmap.c \
|
||||
$(srcroot)src/hash.c \
|
||||
$(srcroot)src/hook.c \
|
||||
$(srcroot)src/inspect.c \
|
||||
$(srcroot)src/large.c \
|
||||
$(srcroot)src/log.c \
|
||||
$(srcroot)src/malloc_io.c \
|
||||
@ -189,11 +190,11 @@ TESTS_UNIT := \
|
||||
$(srcroot)test/unit/div.c \
|
||||
$(srcroot)test/unit/emitter.c \
|
||||
$(srcroot)test/unit/extent_quantize.c \
|
||||
$(srcroot)test/unit/extent_util.c \
|
||||
$(srcroot)test/unit/fork.c \
|
||||
$(srcroot)test/unit/hash.c \
|
||||
$(srcroot)test/unit/hook.c \
|
||||
$(srcroot)test/unit/huge.c \
|
||||
$(srcroot)test/unit/inspect.c \
|
||||
$(srcroot)test/unit/junk.c \
|
||||
$(srcroot)test/unit/junk_alloc.c \
|
||||
$(srcroot)test/unit/junk_free.c \
|
||||
|
@ -17,28 +17,6 @@
|
||||
* particular reason. This will also be changed, but much more immediately.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following two structs are for experimental purposes. See
|
||||
* experimental_utilization_query_ctl and
|
||||
* experimental_utilization_batch_query_ctl in src/ctl.c.
|
||||
*/
|
||||
typedef struct extent_util_stats_s extent_util_stats_t;
|
||||
struct extent_util_stats_s {
|
||||
size_t nfree;
|
||||
size_t nregs;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
typedef struct extent_util_stats_verbose_s extent_util_stats_verbose_t;
|
||||
struct 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;
|
||||
};
|
||||
|
||||
/*
|
||||
* When reuse (and split) an active extent, (1U << opt_lg_extent_max_active_fit)
|
||||
* is the max ratio between the size of the active extent and the new extent.
|
||||
@ -83,10 +61,4 @@ bool extent_head_no_merge(extent_t *a, extent_t *b);
|
||||
|
||||
bool extent_boot(void);
|
||||
|
||||
void extent_util_stats_get(tsdn_t *tsdn, const void *ptr,
|
||||
size_t *nfree, size_t *nregs, size_t *size);
|
||||
void 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_EXTENT2_H */
|
||||
|
40
include/jemalloc/internal/inspect.h
Normal file
40
include/jemalloc/internal/inspect.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef JEMALLOC_INTERNAL_INSPECT_H
|
||||
#define JEMALLOC_INTERNAL_INSPECT_H
|
||||
|
||||
/*
|
||||
* This module contains the heap introspection capabilities. For now they are
|
||||
* exposed purely through mallctl APIs in the experimental namespace, but this
|
||||
* may change over time.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following two structs are for experimental purposes. See
|
||||
* experimental_utilization_query_ctl and
|
||||
* experimental_utilization_batch_query_ctl in src/ctl.c.
|
||||
*/
|
||||
typedef struct inspect_extent_util_stats_s inspect_extent_util_stats_t;
|
||||
struct inspect_extent_util_stats_s {
|
||||
size_t nfree;
|
||||
size_t nregs;
|
||||
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 */
|
@ -52,6 +52,7 @@
|
||||
<ClCompile Include="..\..\..\..\src\extent_mmap.c" />
|
||||
<ClCompile Include="..\..\..\..\src\hash.c" />
|
||||
<ClCompile Include="..\..\..\..\src\hook.c" />
|
||||
<ClCompile Include="..\..\..\..\src\inspect.c" />
|
||||
<ClCompile Include="..\..\..\..\src\jemalloc.c" />
|
||||
<ClCompile Include="..\..\..\..\src\large.c" />
|
||||
<ClCompile Include="..\..\..\..\src\log.c" />
|
||||
|
@ -52,6 +52,7 @@
|
||||
<ClCompile Include="..\..\..\..\src\extent_mmap.c" />
|
||||
<ClCompile Include="..\..\..\..\src\hash.c" />
|
||||
<ClCompile Include="..\..\..\..\src\hook.c" />
|
||||
<ClCompile Include="..\..\..\..\src\inspect.c" />
|
||||
<ClCompile Include="..\..\..\..\src\jemalloc.c" />
|
||||
<ClCompile Include="..\..\..\..\src\large.c" />
|
||||
<ClCompile Include="..\..\..\..\src\log.c" />
|
||||
|
20
src/ctl.c
20
src/ctl.c
@ -6,6 +6,7 @@
|
||||
#include "jemalloc/internal/ctl.h"
|
||||
#include "jemalloc/internal/extent_dss.h"
|
||||
#include "jemalloc/internal/extent_mmap.h"
|
||||
#include "jemalloc/internal/inspect.h"
|
||||
#include "jemalloc/internal/mutex.h"
|
||||
#include "jemalloc/internal/nstime.h"
|
||||
#include "jemalloc/internal/sc.h"
|
||||
@ -3258,11 +3259,11 @@ experimental_utilization_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(extent_util_stats_verbose_t)
|
||||
assert(sizeof(inspect_extent_util_stats_verbose_t)
|
||||
== sizeof(void *) + sizeof(size_t) * 5);
|
||||
|
||||
if (oldp == NULL || oldlenp == NULL
|
||||
|| *oldlenp != sizeof(extent_util_stats_verbose_t)
|
||||
|| *oldlenp != sizeof(inspect_extent_util_stats_verbose_t)
|
||||
|| newp == NULL) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
@ -3270,9 +3271,9 @@ experimental_utilization_query_ctl(tsd_t *tsd, const size_t *mib,
|
||||
|
||||
void *ptr = NULL;
|
||||
WRITE(ptr, void *);
|
||||
extent_util_stats_verbose_t *util_stats
|
||||
= (extent_util_stats_verbose_t *)oldp;
|
||||
extent_util_stats_verbose_get(tsd_tsdn(tsd), ptr,
|
||||
inspect_extent_util_stats_verbose_t *util_stats
|
||||
= (inspect_extent_util_stats_verbose_t *)oldp;
|
||||
inspect_extent_util_stats_verbose_get(tsd_tsdn(tsd), ptr,
|
||||
&util_stats->nfree, &util_stats->nregs, &util_stats->size,
|
||||
&util_stats->bin_nfree, &util_stats->bin_nregs,
|
||||
&util_stats->slabcur_addr);
|
||||
@ -3383,21 +3384,22 @@ 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(extent_util_stats_t) == sizeof(size_t) * 3);
|
||||
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(extent_util_stats_t)) {
|
||||
|| *oldlenp != len * sizeof(inspect_extent_util_stats_t)) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
|
||||
void **ptrs = (void **)newp;
|
||||
extent_util_stats_t *util_stats = (extent_util_stats_t *)oldp;
|
||||
inspect_extent_util_stats_t *util_stats =
|
||||
(inspect_extent_util_stats_t *)oldp;
|
||||
size_t i;
|
||||
for (i = 0; i < len; ++i) {
|
||||
extent_util_stats_get(tsd_tsdn(tsd), ptrs[i],
|
||||
inspect_extent_util_stats_get(tsd_tsdn(tsd), ptrs[i],
|
||||
&util_stats[i].nfree, &util_stats[i].nregs,
|
||||
&util_stats[i].size);
|
||||
}
|
||||
|
@ -1661,78 +1661,3 @@ extent_boot(void) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
extent_util_stats_get(tsdn_t *tsdn, const void *ptr,
|
||||
size_t *nfree, size_t *nregs, size_t *size) {
|
||||
assert(ptr != NULL && nfree != NULL && nregs != NULL && size != NULL);
|
||||
|
||||
const extent_t *extent = iealloc(tsdn, ptr);
|
||||
if (unlikely(extent == NULL)) {
|
||||
*nfree = *nregs = *size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*size = extent_size_get(extent);
|
||||
if (!extent_slab_get(extent)) {
|
||||
*nfree = 0;
|
||||
*nregs = 1;
|
||||
} else {
|
||||
*nfree = extent_nfree_get(extent);
|
||||
*nregs = bin_infos[extent_szind_get(extent)].nregs;
|
||||
assert(*nfree <= *nregs);
|
||||
assert(*nfree * extent_usize_get(extent) <= *size);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
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 extent_t *extent = iealloc(tsdn, ptr);
|
||||
if (unlikely(extent == NULL)) {
|
||||
*nfree = *nregs = *size = *bin_nfree = *bin_nregs = 0;
|
||||
*slabcur_addr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*size = extent_size_get(extent);
|
||||
if (!extent_slab_get(extent)) {
|
||||
*nfree = *bin_nfree = *bin_nregs = 0;
|
||||
*nregs = 1;
|
||||
*slabcur_addr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*nfree = extent_nfree_get(extent);
|
||||
const szind_t szind = extent_szind_get(extent);
|
||||
*nregs = bin_infos[szind].nregs;
|
||||
assert(*nfree <= *nregs);
|
||||
assert(*nfree * extent_usize_get(extent) <= *size);
|
||||
|
||||
const arena_t *arena = (arena_t *)atomic_load_p(
|
||||
&arenas[extent_arena_ind_get(extent)], ATOMIC_RELAXED);
|
||||
assert(arena != NULL);
|
||||
const unsigned binshard = extent_binshard_get(extent);
|
||||
bin_t *bin = &arena->bins[szind].bin_shards[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;
|
||||
}
|
||||
extent_t *slab;
|
||||
if (bin->slabcur != NULL) {
|
||||
slab = bin->slabcur;
|
||||
} else {
|
||||
slab = extent_heap_first(&bin->slabs_nonfull);
|
||||
}
|
||||
*slabcur_addr = slab != NULL ? extent_addr_get(slab) : NULL;
|
||||
malloc_mutex_unlock(tsdn, &bin->lock);
|
||||
}
|
||||
|
77
src/inspect.c
Normal file
77
src/inspect.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||
#include "jemalloc/internal/jemalloc_internal_includes.h"
|
||||
|
||||
void
|
||||
inspect_extent_util_stats_get(tsdn_t *tsdn, const void *ptr, size_t *nfree,
|
||||
size_t *nregs, size_t *size) {
|
||||
assert(ptr != NULL && nfree != NULL && nregs != NULL && size != NULL);
|
||||
|
||||
const extent_t *extent = iealloc(tsdn, ptr);
|
||||
if (unlikely(extent == NULL)) {
|
||||
*nfree = *nregs = *size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*size = extent_size_get(extent);
|
||||
if (!extent_slab_get(extent)) {
|
||||
*nfree = 0;
|
||||
*nregs = 1;
|
||||
} else {
|
||||
*nfree = extent_nfree_get(extent);
|
||||
*nregs = bin_infos[extent_szind_get(extent)].nregs;
|
||||
assert(*nfree <= *nregs);
|
||||
assert(*nfree * extent_usize_get(extent) <= *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 extent_t *extent = iealloc(tsdn, ptr);
|
||||
if (unlikely(extent == NULL)) {
|
||||
*nfree = *nregs = *size = *bin_nfree = *bin_nregs = 0;
|
||||
*slabcur_addr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*size = extent_size_get(extent);
|
||||
if (!extent_slab_get(extent)) {
|
||||
*nfree = *bin_nfree = *bin_nregs = 0;
|
||||
*nregs = 1;
|
||||
*slabcur_addr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*nfree = extent_nfree_get(extent);
|
||||
const szind_t szind = extent_szind_get(extent);
|
||||
*nregs = bin_infos[szind].nregs;
|
||||
assert(*nfree <= *nregs);
|
||||
assert(*nfree * extent_usize_get(extent) <= *size);
|
||||
|
||||
const arena_t *arena = (arena_t *)atomic_load_p(
|
||||
&arenas[extent_arena_ind_get(extent)], ATOMIC_RELAXED);
|
||||
assert(arena != NULL);
|
||||
const unsigned binshard = extent_binshard_get(extent);
|
||||
bin_t *bin = &arena->bins[szind].bin_shards[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;
|
||||
}
|
||||
extent_t *slab;
|
||||
if (bin->slabcur != NULL) {
|
||||
slab = bin->slabcur;
|
||||
} else {
|
||||
slab = extent_heap_first(&bin->slabs_nonfull);
|
||||
}
|
||||
*slabcur_addr = slab != NULL ? extent_addr_get(slab) : NULL;
|
||||
malloc_mutex_unlock(tsdn, &bin->lock);
|
||||
}
|
Loading…
Reference in New Issue
Block a user