Refined mallinfo() implementation (contributed by Eugene Toder).

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7901 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_mallocfree.c b/coregrind/m_mallocfree.c
index c1f01f8..f78b18e 100644
--- a/coregrind/m_mallocfree.c
+++ b/coregrind/m_mallocfree.c
@@ -47,6 +47,10 @@
 // #define DEBUG_MALLOC      // turn on heavyweight debugging machinery
 // #define VERBOSE_MALLOC    // make verbose, esp. in debugging machinery
 
+/* Number and total size of blocks in free queue. Used by mallinfo(). */
+Long VG_(free_queue_volume) = 0;
+Long VG_(free_queue_length) = 0;
+
 /*------------------------------------------------------------*/
 /*--- Main types                                           ---*/
 /*------------------------------------------------------------*/
@@ -1468,9 +1472,34 @@
    return get_pszB(a, b);
 }
 
-// We cannot return the whole struct as the library function does,
-// because this is called by a client request.  So instead we use
-// a pointer to do call by reference.
+
+// Implementation of mallinfo(). There is no recent standard that defines
+// the behavior of mallinfo(). The meaning of the fields in struct mallinfo
+// is as follows:
+//
+//     struct mallinfo  {
+//                int arena;     /* total space in arena            */
+//                int ordblks;   /* number of ordinary blocks       */
+//                int smblks;    /* number of small blocks          */
+//                int hblks;     /* number of holding blocks        */
+//                int hblkhd;    /* space in holding block headers  */
+//                int usmblks;   /* space in small blocks in use    */
+//                int fsmblks;   /* space in free small blocks      */
+//                int uordblks;  /* space in ordinary blocks in use */
+//                int fordblks;  /* space in free ordinary blocks   */
+//                int keepcost;  /* space penalty if keep option    */
+//                               /* is used                         */
+//        };
+//
+// The glibc documentation about mallinfo (which is somewhat outdated) can
+// be found here:
+// http://www.gnu.org/software/libtool/manual/libc/Statistics-of-Malloc.html
+//
+// See also http://bugs.kde.org/show_bug.cgi?id=160956.
+//
+// Regarding the implementation of VG_(mallinfo)(): we cannot return the
+// whole struct as the library function does, because this is called by a
+// client request.  So instead we use a pointer to do call by reference.
 void VG_(mallinfo) ( ThreadId tid, struct vg_mallinfo* mi )
 {
    UInt   i, free_blocks, free_blocks_size;
@@ -1491,17 +1520,16 @@
    }
 
    // We don't have fastbins so smblks & fsmblks are always 0. Also we don't
-   // have a separate mmap allocator so set hblks & hblkhd to 0. See also
-   // http://www.gnu.org/software/libtool/manual/libc/Statistics-of-Malloc.html
+   // have a separate mmap allocator so set hblks & hblkhd to 0.
    mi->arena    = a->bytes_mmaped;
-   mi->ordblks  = free_blocks;
+   mi->ordblks  = free_blocks + VG_(free_queue_length);
    mi->smblks   = 0;
    mi->hblks    = 0;
    mi->hblkhd   = 0;
    mi->usmblks  = 0;
    mi->fsmblks  = 0;
-   mi->uordblks = a->bytes_on_loan;
-   mi->fordblks = free_blocks_size;
+   mi->uordblks = a->bytes_on_loan - VG_(free_queue_volume);
+   mi->fordblks = free_blocks_size + VG_(free_queue_volume);
    mi->keepcost = 0; // may want some value in here
 }