blob: 365bc5570330e5b7a56c9e45e081be2f85c30182 [file] [log] [blame] [edit]
#include <limits.h>
#include <malloc.h>
#include <stddef.h>
#include "glue.h"
#include "meta.h"
static void accumulate_meta(struct mallinfo2 *mi, struct meta *g)
{
int sc = g->sizeclass;
if (sc >= 48) {
// Large mmap allocation
mi->hblks++;
mi->uordblks += g->maplen*4096;
mi->hblkhd += g->maplen*4096;
} else {
if (g->freeable && !g->maplen) {
// Small size slots are embedded in a larger slot, avoid
// double counting by subtracting the size of the larger
// slot from the total used memory.
struct meta* outer_g = get_meta((void*)g->mem);
int outer_sc = outer_g->sizeclass;
int outer_sz = size_classes[outer_sc]*UNIT;
mi->uordblks -= outer_sz;
mi->arena -= outer_sz;
}
int sz = size_classes[sc]*UNIT;
int mask = g->avail_mask | g->freed_mask;
int nr_unused = a_popcount_32(mask);
if (!g->last_idx) {
// Allocation groups with a single allocation may use a
// smaller maplen than normally used for the size class.
if (sz > g->maplen-IB-UNIT) {
sz = g->maplen-IB-UNIT;
}
}
mi->arena += sz*(g->last_idx+1);
mi->ordblks += nr_unused;
mi->uordblks += sz*(g->last_idx+1-nr_unused);
mi->fordblks += sz*nr_unused;
}
}
static void accumulate_meta_area(struct mallinfo2 *mi, struct meta_area *ma)
{
for (int i=0; i<ma->nslots; i++) {
if (ma->slots[i].mem) {
accumulate_meta(mi, &ma->slots[i]);
}
}
}
struct mallinfo2 mallinfo2(void)
{
struct mallinfo2 mi = {0};
rdlock();
struct meta_area *ma = ctx.meta_area_head;
while (ma) {
accumulate_meta_area(&mi, ma);
ma = ma->next;
}
unlock();
return mi;
}
#define cap(x) ((x > INT_MAX) ? INT_MAX : x)
struct mallinfo mallinfo(void) {
struct mallinfo mi = {0};
struct mallinfo2 mi2 = mallinfo2();
mi.arena = cap(mi2.arena);
mi.ordblks = cap(mi2.ordblks);
mi.smblks = cap(mi2.smblks);
mi.hblks = cap(mi2.hblks);
mi.hblkhd = cap(mi2.hblkhd);
mi.usmblks = cap(mi2.usmblks);
mi.fsmblks = cap(mi2.fsmblks);
mi.uordblks = cap(mi2.uordblks);
mi.fordblks = cap(mi2.fordblks);
mi.keepcost = cap(mi2.keepcost);
return mi;
}