diff --git a/src/builtin_functions.c b/src/builtin_functions.c index c0b8f6c6bc3f25fc687fbd55f9cb65f69e00e065..65a843b2e367e106695bd8b415126798af256249 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -7442,6 +7442,7 @@ PMOD_EXPORT void f__memory_usage(INT32 args) #elif HAVE_MALLINFO struct mallinfo mi = mallinfo(); #endif + pop_n_elems(args); ss=Pike_sp; @@ -7454,6 +7455,16 @@ PMOD_EXPORT void f__memory_usage(INT32 args) push_text("num_malloc_blocks"); push_ulongest(1 + mi.hblks); /* 1 for the arena. */ push_text("malloc_block_bytes"); + if (mi.arena < 0) { + /* Kludge for broken Linux libc, where the fields are ints. + * + * 31-bit overflow, so perform an unsigned read. + */ + size = (unsigned int)mi.arena; + } else { + /* On Solaris the fields are unsigned long (and may thus be 64-bit). */ + size = mi.arena; + } /* NB: Kludge for glibc: hblkhd is intended for malloc overhead * according to the Solaris manpages, but glibc keeps the * amount of mmapped memory there, and uses the arena only @@ -7463,22 +7474,45 @@ PMOD_EXPORT void f__memory_usage(INT32 args) * small enough not to affect the total much, so no need * for a special case. */ - push_ulongest(mi.arena + mi.hblkhd); + if (mi.hblkhd < 0) { + size += (unsigned int)mi.hblkhd; + } else { + size += mi.hblkhd; + } + push_ulongest(size); push_text("num_malloc"); push_ulongest(mi.ordblks + mi.smblks); push_text("malloc_bytes"); - if (!mi.smblks) { - /* NB: Kludge for dlmalloc: usmblks contains the max uordblks value. */ - push_ulongest(mi.uordblks); + if (mi.uordblks < 0) { + size = (unsigned int)mi.uordblks; } else { - push_ulongest(mi.usmblks + mi.uordblks); + size = mi.uordblks; } + if (mi.smblks) { + /* NB: Not dlmalloc where usmblks contains the max uordblks value. */ + if (mi.usmblks < 0) { + size += (unsigned int)mi.usmblks; + } else { + size += mi.usmblks; + } + } + push_ulongest(size); push_text("num_free_blocks"); push_int(1); push_text("free_block_bytes"); - push_ulongest(mi.fsmblks + mi.fordblks); + if (mi.fsmblks < 0) { + size = (unsigned int)mi.fsmblks; + } else { + size = mi.fsmblks; + } + if (mi.fordblks < 0) { + size += (unsigned int)mi.fordblks; + } else { + size += mi.fordblks; + } + push_ulongest(size); #endif