add real mallinfo implementation for Android
Android Q uses the mallinfo implementation in the ART GC:c220f98180
1575267302
This commit is contained in:
parent
7acebaa837
commit
350d0e5fd2
@ -25,6 +25,7 @@ common_cflags = [
|
|||||||
"-DFREE_SLABS_QUARANTINE_RANDOM_LENGTH=32",
|
"-DFREE_SLABS_QUARANTINE_RANDOM_LENGTH=32",
|
||||||
"-DCONFIG_CLASS_REGION_SIZE=1073741824", // 1GiB
|
"-DCONFIG_CLASS_REGION_SIZE=1073741824", // 1GiB
|
||||||
"-DN_ARENA=1",
|
"-DN_ARENA=1",
|
||||||
|
"-DSTATS=false",
|
||||||
]
|
]
|
||||||
|
|
||||||
cc_defaults {
|
cc_defaults {
|
||||||
|
6
Makefile
6
Makefile
@ -15,7 +15,8 @@ CONFIG_REGION_QUARANTINE_QUEUE_LENGTH := 1024
|
|||||||
CONFIG_REGION_QUARANTINE_SKIP_THRESHOLD := 33554432 # 32MiB
|
CONFIG_REGION_QUARANTINE_SKIP_THRESHOLD := 33554432 # 32MiB
|
||||||
CONFIG_FREE_SLABS_QUARANTINE_RANDOM_LENGTH := 32
|
CONFIG_FREE_SLABS_QUARANTINE_RANDOM_LENGTH := 32
|
||||||
CONFIG_CLASS_REGION_SIZE := 137438953472 # 128GiB
|
CONFIG_CLASS_REGION_SIZE := 137438953472 # 128GiB
|
||||||
CONFIG_N_ARENA = 1
|
CONFIG_N_ARENA := 1
|
||||||
|
CONFIG_STATS := false
|
||||||
|
|
||||||
define safe_flag
|
define safe_flag
|
||||||
$(shell $(CC) -E $1 - </dev/null >/dev/null 2>&1 && echo $1 || echo $2)
|
$(shell $(CC) -E $1 - </dev/null >/dev/null 2>&1 && echo $1 || echo $2)
|
||||||
@ -81,7 +82,8 @@ CPPFLAGS += \
|
|||||||
-DREGION_QUARANTINE_SKIP_THRESHOLD=$(CONFIG_REGION_QUARANTINE_SKIP_THRESHOLD) \
|
-DREGION_QUARANTINE_SKIP_THRESHOLD=$(CONFIG_REGION_QUARANTINE_SKIP_THRESHOLD) \
|
||||||
-DFREE_SLABS_QUARANTINE_RANDOM_LENGTH=$(CONFIG_FREE_SLABS_QUARANTINE_RANDOM_LENGTH) \
|
-DFREE_SLABS_QUARANTINE_RANDOM_LENGTH=$(CONFIG_FREE_SLABS_QUARANTINE_RANDOM_LENGTH) \
|
||||||
-DCONFIG_CLASS_REGION_SIZE=$(CONFIG_CLASS_REGION_SIZE) \
|
-DCONFIG_CLASS_REGION_SIZE=$(CONFIG_CLASS_REGION_SIZE) \
|
||||||
-DN_ARENA=$(CONFIG_N_ARENA)
|
-DN_ARENA=$(CONFIG_N_ARENA) \
|
||||||
|
-DSTATS=$(CONFIG_STATS)
|
||||||
|
|
||||||
libhardened_malloc.so: $(OBJECTS)
|
libhardened_malloc.so: $(OBJECTS)
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -shared $^ $(LDLIBS) -o $@
|
$(CC) $(CFLAGS) $(LDFLAGS) -shared $^ $(LDLIBS) -o $@
|
||||||
|
69
h_malloc.c
69
h_malloc.c
@ -240,6 +240,11 @@ struct __attribute__((aligned(CACHELINE_SIZE))) size_class {
|
|||||||
struct slab_metadata *free_slabs_tail;
|
struct slab_metadata *free_slabs_tail;
|
||||||
struct slab_metadata *free_slabs_quarantine[FREE_SLABS_QUARANTINE_RANDOM_LENGTH];
|
struct slab_metadata *free_slabs_quarantine[FREE_SLABS_QUARANTINE_RANDOM_LENGTH];
|
||||||
|
|
||||||
|
#if STATS
|
||||||
|
size_t allocated;
|
||||||
|
size_t slab_allocated;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct random_state rng;
|
struct random_state rng;
|
||||||
size_t metadata_allocated;
|
size_t metadata_allocated;
|
||||||
size_t metadata_count;
|
size_t metadata_count;
|
||||||
@ -478,6 +483,9 @@ static inline void *allocate_small(size_t requested_size) {
|
|||||||
set_canary(metadata, p, size);
|
set_canary(metadata, p, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if STATS
|
||||||
|
c->allocated += size;
|
||||||
|
#endif
|
||||||
mutex_unlock(&c->lock);
|
mutex_unlock(&c->lock);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -491,6 +499,9 @@ static inline void *allocate_small(size_t requested_size) {
|
|||||||
mutex_unlock(&c->lock);
|
mutex_unlock(&c->lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#if STATS
|
||||||
|
c->slab_allocated += slab_size;
|
||||||
|
#endif
|
||||||
|
|
||||||
c->free_slabs_head = c->free_slabs_head->next;
|
c->free_slabs_head = c->free_slabs_head->next;
|
||||||
if (c->free_slabs_head == NULL) {
|
if (c->free_slabs_head == NULL) {
|
||||||
@ -509,6 +520,9 @@ static inline void *allocate_small(size_t requested_size) {
|
|||||||
set_canary(metadata, p, size);
|
set_canary(metadata, p, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if STATS
|
||||||
|
c->allocated += size;
|
||||||
|
#endif
|
||||||
mutex_unlock(&c->lock);
|
mutex_unlock(&c->lock);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -518,6 +532,9 @@ static inline void *allocate_small(size_t requested_size) {
|
|||||||
mutex_unlock(&c->lock);
|
mutex_unlock(&c->lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#if STATS
|
||||||
|
c->slab_allocated += slab_size;
|
||||||
|
#endif
|
||||||
metadata->canary_value = get_random_canary(&c->rng);
|
metadata->canary_value = get_random_canary(&c->rng);
|
||||||
|
|
||||||
c->partial_slabs = metadata;
|
c->partial_slabs = metadata;
|
||||||
@ -529,6 +546,9 @@ static inline void *allocate_small(size_t requested_size) {
|
|||||||
set_canary(metadata, p, size);
|
set_canary(metadata, p, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if STATS
|
||||||
|
c->allocated += size;
|
||||||
|
#endif
|
||||||
mutex_unlock(&c->lock);
|
mutex_unlock(&c->lock);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -551,6 +571,9 @@ static inline void *allocate_small(size_t requested_size) {
|
|||||||
set_canary(metadata, p, size);
|
set_canary(metadata, p, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if STATS
|
||||||
|
c->allocated += size;
|
||||||
|
#endif
|
||||||
mutex_unlock(&c->lock);
|
mutex_unlock(&c->lock);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -611,6 +634,9 @@ static inline void deallocate_small(void *p, const size_t *expected_size) {
|
|||||||
size_t slab_size = get_slab_size(slots, size);
|
size_t slab_size = get_slab_size(slots, size);
|
||||||
|
|
||||||
mutex_lock(&c->lock);
|
mutex_lock(&c->lock);
|
||||||
|
#if STATS
|
||||||
|
c->allocated -= size;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct slab_metadata *metadata = get_metadata(c, p);
|
struct slab_metadata *metadata = get_metadata(c, p);
|
||||||
void *slab = get_slab(c, slab_size, metadata);
|
void *slab = get_slab(c, slab_size, metadata);
|
||||||
@ -711,6 +737,9 @@ static inline void deallocate_small(void *p, const size_t *expected_size) {
|
|||||||
if (c->empty_slabs_total + slab_size > max_empty_slabs_total) {
|
if (c->empty_slabs_total + slab_size > max_empty_slabs_total) {
|
||||||
if (!memory_map_fixed(slab, slab_size)) {
|
if (!memory_map_fixed(slab, slab_size)) {
|
||||||
memory_set_name(slab, slab_size, size_class_labels[class]);
|
memory_set_name(slab, slab_size, size_class_labels[class]);
|
||||||
|
#if STATS
|
||||||
|
c->slab_allocated -= slab_size;
|
||||||
|
#endif
|
||||||
enqueue_free_slab(c, metadata);
|
enqueue_free_slab(c, metadata);
|
||||||
mutex_unlock(&c->lock);
|
mutex_unlock(&c->lock);
|
||||||
return;
|
return;
|
||||||
@ -745,6 +774,9 @@ struct region_allocator {
|
|||||||
struct region_metadata *regions;
|
struct region_metadata *regions;
|
||||||
size_t total;
|
size_t total;
|
||||||
size_t free;
|
size_t free;
|
||||||
|
#if STATS
|
||||||
|
size_t allocated;
|
||||||
|
#endif
|
||||||
struct quarantine_info quarantine_random[REGION_QUARANTINE_RANDOM_LENGTH];
|
struct quarantine_info quarantine_random[REGION_QUARANTINE_RANDOM_LENGTH];
|
||||||
struct quarantine_info quarantine_queue[REGION_QUARANTINE_QUEUE_LENGTH];
|
struct quarantine_info quarantine_queue[REGION_QUARANTINE_QUEUE_LENGTH];
|
||||||
size_t quarantine_queue_index;
|
size_t quarantine_queue_index;
|
||||||
@ -1110,6 +1142,9 @@ static void *allocate(size_t size) {
|
|||||||
deallocate_pages(p, size, guard_size);
|
deallocate_pages(p, size, guard_size);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#if STATS
|
||||||
|
ra->allocated += size;
|
||||||
|
#endif
|
||||||
mutex_unlock(&ra->lock);
|
mutex_unlock(&ra->lock);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
@ -1132,6 +1167,9 @@ static void deallocate_large(void *p, const size_t *expected_size) {
|
|||||||
}
|
}
|
||||||
size_t guard_size = region->guard_size;
|
size_t guard_size = region->guard_size;
|
||||||
regions_delete(region);
|
regions_delete(region);
|
||||||
|
#if STATS
|
||||||
|
ra->allocated -= size;
|
||||||
|
#endif
|
||||||
mutex_unlock(&ra->lock);
|
mutex_unlock(&ra->lock);
|
||||||
|
|
||||||
regions_quarantine_deallocate_pages(p, size, guard_size);
|
regions_quarantine_deallocate_pages(p, size, guard_size);
|
||||||
@ -1534,6 +1572,9 @@ EXPORT int h_malloc_trim(UNUSED size_t pad) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memory_set_name(slab, slab_size, size_class_labels[class]);
|
memory_set_name(slab, slab_size, size_class_labels[class]);
|
||||||
|
#if STATS
|
||||||
|
c->slab_allocated -= slab_size;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct slab_metadata *trimmed = iterator;
|
struct slab_metadata *trimmed = iterator;
|
||||||
iterator = iterator->next;
|
iterator = iterator->next;
|
||||||
@ -1557,7 +1598,33 @@ EXPORT void h_malloc_stats(void) {}
|
|||||||
|
|
||||||
#if defined(__GLIBC__) || defined(__ANDROID__)
|
#if defined(__GLIBC__) || defined(__ANDROID__)
|
||||||
EXPORT struct mallinfo h_mallinfo(void) {
|
EXPORT struct mallinfo h_mallinfo(void) {
|
||||||
return (struct mallinfo){0};
|
struct mallinfo info = {0};
|
||||||
|
|
||||||
|
// glibc mallinfo type definition and implementation are both broken
|
||||||
|
#if STATS && !defined(__GLIBC__)
|
||||||
|
struct region_allocator *ra = ro.region_allocator;
|
||||||
|
mutex_lock(&ra->lock);
|
||||||
|
info.hblkhd += ra->allocated;
|
||||||
|
info.uordblks += ra->allocated;
|
||||||
|
mutex_unlock(&ra->lock);
|
||||||
|
|
||||||
|
for (unsigned arena = 0; arena < N_ARENA; arena++) {
|
||||||
|
// skip zero byte size class
|
||||||
|
for (unsigned class = 1; class < N_SIZE_CLASSES; class++) {
|
||||||
|
struct size_class *c = &ro.size_class_metadata[arena][class];
|
||||||
|
|
||||||
|
mutex_lock(&c->lock);
|
||||||
|
info.hblkhd += c->slab_allocated;
|
||||||
|
info.uordblks += c->allocated;
|
||||||
|
mutex_unlock(&c->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info.fordblks = info.hblkhd - info.uordblks;
|
||||||
|
info.usmblks = info.hblkhd;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@ CPPFLAGS += \
|
|||||||
-DSLAB_CANARY=$(CONFIG_SLAB_CANARY)
|
-DSLAB_CANARY=$(CONFIG_SLAB_CANARY)
|
||||||
|
|
||||||
EXECUTABLES := \
|
EXECUTABLES := \
|
||||||
offset
|
offset \
|
||||||
|
mallinfo
|
||||||
|
|
||||||
all: $(EXECUTABLES)
|
all: $(EXECUTABLES)
|
||||||
|
|
||||||
|
21
test/mallinfo.c
Normal file
21
test/mallinfo.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
__attribute__((optimize(0)))
|
||||||
|
int main(void) {
|
||||||
|
malloc(1024 * 1024 * 1024);
|
||||||
|
malloc(16);
|
||||||
|
malloc(32);
|
||||||
|
malloc(64);
|
||||||
|
|
||||||
|
struct mallinfo info = mallinfo();
|
||||||
|
printf("arena: %zu\n", info.arena);
|
||||||
|
printf("ordblks: %zu\n", info.ordblks);
|
||||||
|
printf("smblks: %zu\n", info.smblks);
|
||||||
|
printf("hblks: %zu\n", info.hblks);
|
||||||
|
printf("hblkhd: %zu\n", info.hblkhd);
|
||||||
|
printf("usmblks: %zu\n", info.usmblks);
|
||||||
|
printf("fsmblks: %zu\n", info.fsmblks);
|
||||||
|
printf("uordblks: %zu\n", info.uordblks);
|
||||||
|
printf("fordblks: %zu\n", info.fordblks);
|
||||||
|
printf("keepcost: %zu\n", info.keepcost);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user