This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: The direction of malloc?


On Tue, 10 Dec 2013, Jeff Law wrote:

> The other thing that I've been asked about a few times would be to fix the
> thread safety issues around the hooks, which IIRC requires some redesign.

 A starting point could be an implementation I made a while ago, presented 
below.  This was based on 2.8 and intended to make its way into 2.10, but 
regrettably that has never happened.  The change looks extensive, but this 
is due to code shuffling resulting from adding wrappers that separate 
calls to hooks (both the preexisting and the new ones) from actual 
allocation implementation, that may call into itself too.

 This also changes the semantics of the preexisting hooks a bit, in 
particular internal calls into itself do not call any of the hooks anymore 
such as in the case of _do_realloc (nee public_rEALLOc) calling into 
_do_malloc (nee public_mALLOc).  This may require further consideration.

 Formatting follows that of current malloc code and would require updating 
as being discussed here too.

 The original description I made for an internal review follows.

--------------------------------------------------------------------------

 Here is an implementation of the revised malloc hook API.  I have 
designed it with thread safety in mind.  Under such an assumption 
recursive calls via the existing hooks by substituting the value of the 
appropriate variable are infeasible and the hooks are called too early for 
the return value of the respective call (if applicable) to be supplied 
under a revised API.

 Therefore I have introduced a set of new hooks.  They all are called at 
the conclusion of the respective function, when all the data to be 
gathered has already been obtained.  For this to happen the structure of 
malloc.c code had to be modified slightly, introducing an intermediate 
function level with all the hooks moved to the new outermost one.  This 
has made source code a little bit clearer and as a side-effect fixed a bug 
in public_vALLOc() and public_pVALLOc() aka valloc() and pvalloc() where 
the arena would get initialised before calling the __memalign_hook() hook.  
The drawback is there is some performance impact.

2008-12-13  Maciej W. Rozycki  <macro@codesourcery.com>

	* malloc/malloc.c (realloc_hook_ini): Rename ptr to oldptr.
	(__realloc_hook): Likewise.
	(__free_hook): Likewise.
	(__malloc_trace): New hook variable.
	(__free_trace): Likewise.
	(__realloc_trace): Likewise.
	(__memalign_trace): Likewise.
	(public_mALLOc): Add the new hook.  Move all the body but the old 
	hook over to...
	(_do_malloc): ... here.
	(public_fREe): Likewise to...
	(_do_free): ... here.
	(public_mEMALIGn): Likewise to...
	(_do_memalign): ... here.
	(public_vALLOc): Likewise to...
	(_do_valloc): ... here.
	(public_pVALLOc): Likewise to...
	(_do_pvalloc): ... here.
	(public_cALLOc): Likewise to...
	(_do_calloc): ... here.
	(public_rEALLOc): Restructure to call the realloc(), malloc() or 
	free() hooks as appropriate.  Add the new hooks.  Move all the 
	genuine realloc() processing over to...
	(_do_realloc): ... here.
	(__posix_memalign): Add the new hook.  Call _do_memalign() rather 
	than public_mEMALIGn().
	* malloc/malloc.h (__realloc_hook): Rename ptr to oldptr.
	(__free_hook): Likewise.
	(__malloc_trace): New declaration.
	(__free_trace): Likewise.
	(__realloc_trace): Likewise.
	(__memalign_trace): Likewise.
	* Versions.def [libc] (GLIBC_2.10): New version.
	* malloc/Versions [libc] (GLIBC_2.10): Add __malloc_trace, 
	__free_trace, __realloc_trace and __memalign_trace.
	* manual/memory.texi (Hooks for Malloc): Document __malloc_trace,
	__free_trace, __realloc_trace and __memalign_trace.

  Maciej

glibc-2.8-malloc-hooks-13.patch
Index: malloc/malloc.c
===================================================================
--- malloc/malloc.c	(revision 226481)
+++ malloc/malloc.c	(working copy)
@@ -1592,6 +1592,13 @@ static Void_t*  _int_pvalloc(mstate, siz
 static Void_t** _int_icalloc(mstate, size_t, size_t, Void_t**);
 static Void_t** _int_icomalloc(mstate, size_t, size_t*, Void_t**);
 #endif
+static Void_t*  _do_malloc(size_t);
+static void     _do_free(Void_t*);
+static Void_t*  _do_realloc(Void_t*, size_t);
+static Void_t*  _do_memalign(size_t, size_t);
+static Void_t*  _do_valloc(size_t);
+static Void_t*  _do_pvalloc(size_t);
+static Void_t*  _do_calloc(INTERNAL_SIZE_T);
 static int      mTRIm(mstate, size_t);
 static size_t   mUSABLe(Void_t*);
 static void     mSTATs(void);
@@ -1641,6 +1648,13 @@ Void_t*         _int_pvalloc();
 /*static Void_t*  cALLOc();*/
 static Void_t** _int_icalloc();
 static Void_t** _int_icomalloc();
+static Void_t*  _do_malloc();
+static void     _do_free();
+static Void_t*  _do_realloc();
+static Void_t*  _do_memalign();
+static Void_t*  _do_valloc();
+static Void_t*  _do_pvalloc();
+static Void_t*  _do_calloc();
 static int      mTRIm();
 static size_t   mUSABLe();
 static void     mSTATs();
@@ -2466,24 +2480,34 @@ static Void_t** iALLOc();
 /* Forward declarations.  */
 static Void_t* malloc_hook_ini __MALLOC_P ((size_t sz,
 					    const __malloc_ptr_t caller));
-static Void_t* realloc_hook_ini __MALLOC_P ((Void_t* ptr, size_t sz,
+static Void_t* realloc_hook_ini __MALLOC_P ((Void_t* oldptr, size_t sz,
 					     const __malloc_ptr_t caller));
 static Void_t* memalign_hook_ini __MALLOC_P ((size_t alignment, size_t sz,
 					      const __malloc_ptr_t caller));
 
 void weak_variable (*__malloc_initialize_hook) (void) = NULL;
-void weak_variable (*__free_hook) (__malloc_ptr_t __ptr,
+void weak_variable (*__free_hook) (__malloc_ptr_t __oldptr,
 				   const __malloc_ptr_t) = NULL;
 __malloc_ptr_t weak_variable (*__malloc_hook)
      (size_t __size, const __malloc_ptr_t) = malloc_hook_ini;
 __malloc_ptr_t weak_variable (*__realloc_hook)
-     (__malloc_ptr_t __ptr, size_t __size, const __malloc_ptr_t)
+     (__malloc_ptr_t __oldptr, size_t __size, const __malloc_ptr_t)
      = realloc_hook_ini;
 __malloc_ptr_t weak_variable (*__memalign_hook)
      (size_t __alignment, size_t __size, const __malloc_ptr_t)
      = memalign_hook_ini;
 void weak_variable (*__after_morecore_hook) (void) = NULL;
 
+void weak_variable (*__free_trace) (__malloc_ptr_t __oldptr,
+				    const __malloc_ptr_t) = NULL;
+void weak_variable (*__malloc_trace) (size_t __size, const __malloc_ptr_t,
+				      __malloc_ptr_t __ptr) = NULL;
+void weak_variable (*__realloc_trace) (__malloc_ptr_t __oldptr, size_t __size,
+				       const __malloc_ptr_t,
+				       __malloc_ptr_t __ptr) = NULL;
+void weak_variable (*__memalign_trace) (size_t __alignment, size_t __size,
+					const __malloc_ptr_t,
+					__malloc_ptr_t __ptr) = NULL;
 
 /* ---------------- Error behavior ------------------------------------ */
 
@@ -3538,13 +3562,333 @@ mremap_chunk(p, new_size) mchunkptr p; s
 Void_t*
 public_mALLOc(size_t bytes)
 {
-  mstate ar_ptr;
-  Void_t *victim;
+  __malloc_ptr_t (*hook) (size_t, __const __malloc_ptr_t);
+  void (*trace) (size_t, __const __malloc_ptr_t, __malloc_ptr_t);
+  Void_t *mem;
 
-  __malloc_ptr_t (*hook) (size_t, __const __malloc_ptr_t) = __malloc_hook;
+  hook = __malloc_hook;
   if (hook != NULL)
     return (*hook)(bytes, RETURN_ADDRESS (0));
 
+  mem = _do_malloc(bytes);
+
+  trace = __malloc_trace;
+  if (trace != NULL)
+    (*trace)(bytes, RETURN_ADDRESS (0), mem);
+
+  return mem;
+}
+#ifdef libc_hidden_def
+libc_hidden_def(public_mALLOc)
+#endif
+
+void
+public_fREe(Void_t* mem)
+{
+  void (*hook) (__malloc_ptr_t, __const __malloc_ptr_t);
+  void (*trace) (__malloc_ptr_t, __const __malloc_ptr_t);
+
+  hook = __free_hook;
+  if (hook != NULL) {
+    (*hook)(mem, RETURN_ADDRESS (0));
+    return;
+  }
+
+  _do_free(mem);
+
+  trace = __free_trace;
+  if (trace != NULL)
+    (*trace)(mem, RETURN_ADDRESS (0));
+}
+#ifdef libc_hidden_def
+libc_hidden_def (public_fREe)
+#endif
+
+Void_t*
+public_rEALLOc(Void_t* oldmem, size_t bytes)
+{
+  __malloc_ptr_t (*hook) (__malloc_ptr_t, size_t, __const __malloc_ptr_t);
+  void (*trace) (__malloc_ptr_t, size_t, const __malloc_ptr_t, __malloc_ptr_t);
+  Void_t *mem;
+
+  hook = __realloc_hook;
+  if (hook != NULL)
+    return (*hook)(oldmem, bytes, RETURN_ADDRESS (0));
+
+#if REALLOC_ZERO_BYTES_FREES
+  if (bytes == 0 && oldmem != NULL) {
+    void (*free_hook) (__malloc_ptr_t, __const __malloc_ptr_t);
+    void (*free_trace) (__malloc_ptr_t, __const __malloc_ptr_t);
+
+    free_hook = __free_hook;
+    if (free_hook != NULL) {
+      (*free_hook)(oldmem, RETURN_ADDRESS (0));
+      return 0;
+    }
+
+    _do_free(oldmem);
+
+    free_trace = __free_trace;
+    if (free_trace != NULL)
+      (*free_trace)(oldmem, RETURN_ADDRESS (0));
+
+    return 0;
+  }
+#endif
+
+  /* realloc of null is supposed to be same as malloc */
+  if (oldmem == 0) {
+    __malloc_ptr_t (*malloc_hook) (size_t, __const __malloc_ptr_t);
+    void (*malloc_trace) (size_t, __const __malloc_ptr_t, __malloc_ptr_t);
+
+    malloc_hook = __malloc_hook;
+    if (malloc_hook != NULL)
+      return (*malloc_hook)(bytes, RETURN_ADDRESS (0));
+
+    mem = _do_malloc(bytes);
+
+    malloc_trace = __malloc_trace;
+    if (malloc_trace != NULL)
+      (*malloc_trace)(bytes, RETURN_ADDRESS (0), mem);
+
+    return mem;
+  }
+
+  mem = _do_realloc(oldmem, bytes);
+
+  trace = __realloc_trace;
+  if (trace != NULL)
+    (*trace)(oldmem, bytes, RETURN_ADDRESS (0), mem);
+
+  return mem;
+}
+#ifdef libc_hidden_def
+libc_hidden_def (public_rEALLOc)
+#endif
+
+Void_t*
+public_mEMALIGn(size_t alignment, size_t bytes)
+{
+  __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, size_t,
+					__const __malloc_ptr_t));
+  void (*trace) __MALLOC_PMT ((size_t, size_t,
+			       __const __malloc_ptr_t, __malloc_ptr_t));
+  Void_t *mem;
+
+  hook = __memalign_hook;
+  if (hook != NULL)
+    return (*hook)(alignment, bytes, RETURN_ADDRESS (0));
+
+  mem = _do_memalign(alignment, bytes);
+
+  trace = __memalign_trace;
+  if (trace != NULL)
+    (*trace)(alignment, bytes, RETURN_ADDRESS (0), mem);
+
+  return mem;
+}
+#ifdef libc_hidden_def
+libc_hidden_def (public_mEMALIGn)
+#endif
+
+Void_t*
+public_vALLOc(size_t bytes)
+{
+  __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, size_t,
+					__const __malloc_ptr_t));
+  void (*trace) __MALLOC_PMT ((size_t, size_t,
+			       __const __malloc_ptr_t, __malloc_ptr_t));
+  Void_t *mem;
+
+  hook = __memalign_hook;
+  if (hook != NULL)
+    return (*hook)(mp_.pagesize, bytes, RETURN_ADDRESS (0));
+
+  mem = _do_valloc(bytes);
+
+  trace = __memalign_trace;
+  if (trace != NULL)
+    (*trace)(mp_.pagesize, bytes, RETURN_ADDRESS (0), mem);
+
+  return mem;
+}
+
+Void_t*
+public_pVALLOc(size_t bytes)
+{
+  __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, size_t,
+					__const __malloc_ptr_t));
+  void (*trace) __MALLOC_PMT ((size_t, size_t,
+			       __const __malloc_ptr_t, __malloc_ptr_t));
+  Void_t *mem;
+
+  hook = __memalign_hook;
+  if (hook != NULL)
+    return (*hook)(mp_.pagesize,
+		   (bytes + mp_.pagesize - 1) & ~(mp_.pagesize - 1),
+		   RETURN_ADDRESS (0));
+
+  mem = _do_pvalloc(bytes);
+
+  trace = __memalign_trace;
+  if (trace != NULL)
+    (*trace)(mp_.pagesize, (bytes + mp_.pagesize - 1) & ~(mp_.pagesize - 1),
+	     RETURN_ADDRESS (0), mem);
+
+  return mem;
+}
+
+Void_t*
+public_cALLOc(size_t n, size_t elem_size)
+{
+  __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, __const __malloc_ptr_t));
+  void (*trace) (size_t, __const __malloc_ptr_t, __malloc_ptr_t);
+  INTERNAL_SIZE_T bytes;
+  Void_t* mem;
+
+  /* size_t is unsigned so the behavior on overflow is defined.  */
+  bytes = n * elem_size;
+#define HALF_INTERNAL_SIZE_T \
+  (((INTERNAL_SIZE_T) 1) << (8 * sizeof (INTERNAL_SIZE_T) / 2))
+  if (__builtin_expect ((n | elem_size) >= HALF_INTERNAL_SIZE_T, 0)) {
+    if (elem_size != 0 && bytes / elem_size != n) {
+      MALLOC_FAILURE_ACTION;
+      return 0;
+    }
+  }
+
+  hook = __malloc_hook;
+  if (hook != NULL) {
+    mem = (*hook)(bytes, RETURN_ADDRESS (0));
+    if(mem == 0)
+      return 0;
+#ifdef HAVE_MEMCPY
+    return memset(mem, 0, bytes);
+#else
+    while(bytes > 0) ((char*)mem)[--bytes] = 0; /* rather inefficient */
+    return mem;
+#endif
+  }
+
+  mem = _do_calloc(bytes);
+
+  trace = __malloc_trace;
+  if (trace != NULL)
+    (*trace)(bytes, RETURN_ADDRESS (0), mem);
+
+  return mem;
+}
+
+#ifndef _LIBC
+
+Void_t**
+public_iCALLOc(size_t n, size_t elem_size, Void_t** chunks)
+{
+  mstate ar_ptr;
+  Void_t** m;
+
+  arena_get(ar_ptr, n*elem_size);
+  if(!ar_ptr)
+    return 0;
+
+  m = _int_icalloc(ar_ptr, n, elem_size, chunks);
+  (void)mutex_unlock(&ar_ptr->mutex);
+  return m;
+}
+
+Void_t**
+public_iCOMALLOc(size_t n, size_t sizes[], Void_t** chunks)
+{
+  mstate ar_ptr;
+  Void_t** m;
+
+  arena_get(ar_ptr, 0);
+  if(!ar_ptr)
+    return 0;
+
+  m = _int_icomalloc(ar_ptr, n, sizes, chunks);
+  (void)mutex_unlock(&ar_ptr->mutex);
+  return m;
+}
+
+void
+public_cFREe(Void_t* m)
+{
+  public_fREe(m);
+}
+
+#endif /* _LIBC */
+
+int
+public_mTRIm(size_t s)
+{
+  int result = 0;
+
+  if(__malloc_initialized < 0)
+    ptmalloc_init ();
+
+  mstate ar_ptr = &main_arena;
+  do
+    {
+      (void) mutex_lock (&ar_ptr->mutex);
+      result |= mTRIm (ar_ptr, s);
+      (void) mutex_unlock (&ar_ptr->mutex);
+
+      ar_ptr = ar_ptr->next;
+    }
+  while (ar_ptr != &main_arena);
+
+  return result;
+}
+
+size_t
+public_mUSABLe(Void_t* m)
+{
+  size_t result;
+
+  result = mUSABLe(m);
+  return result;
+}
+
+void
+public_mSTATs()
+{
+  mSTATs();
+}
+
+struct mallinfo public_mALLINFo()
+{
+  struct mallinfo m;
+
+  if(__malloc_initialized < 0)
+    ptmalloc_init ();
+  (void)mutex_lock(&main_arena.mutex);
+  m = mALLINFo(&main_arena);
+  (void)mutex_unlock(&main_arena.mutex);
+  return m;
+}
+
+int
+public_mALLOPt(int p, int v)
+{
+  int result;
+  result = mALLOPt(p, v);
+  return result;
+}
+
+/*------------------------ Intermediate helpers. ---------------------------*/
+
+static Void_t*
+#if __STD_C
+_do_malloc(size_t bytes)
+#else
+_do_malloc(bytes)
+size_t bytes;
+#endif
+{
+  mstate ar_ptr;
+  Void_t *victim;
+
   arena_get(ar_ptr, bytes);
   if(!ar_ptr)
     return 0;
@@ -3574,22 +3918,18 @@ public_mALLOc(size_t bytes)
 	 ar_ptr == arena_for_chunk(mem2chunk(victim)));
   return victim;
 }
-#ifdef libc_hidden_def
-libc_hidden_def(public_mALLOc)
-#endif
 
-void
-public_fREe(Void_t* mem)
+static void
+#if __STD_C
+_do_free(Void_t* mem)
+#else
+_do_free(mem)
+Void_t* mem;
+#endif
 {
   mstate ar_ptr;
   mchunkptr p;                          /* chunk corresponding to mem */
 
-  void (*hook) (__malloc_ptr_t, __const __malloc_ptr_t) = __free_hook;
-  if (hook != NULL) {
-    (*hook)(mem, RETURN_ADDRESS (0));
-    return;
-  }
-
   if (mem == 0)                              /* free(0) has no effect */
     return;
 
@@ -3625,12 +3965,14 @@ public_fREe(Void_t* mem)
   _int_free(ar_ptr, mem);
   (void)mutex_unlock(&ar_ptr->mutex);
 }
-#ifdef libc_hidden_def
-libc_hidden_def (public_fREe)
-#endif
 
-Void_t*
-public_rEALLOc(Void_t* oldmem, size_t bytes)
+static Void_t*
+#if __STD_C
+_do_realloc(Void_t* oldmem, size_t bytes)
+#else
+_do_realloc(oldmem, bytes)
+Void_t* oldmem; size_t bytes;
+#endif
 {
   mstate ar_ptr;
   INTERNAL_SIZE_T    nb;      /* padded request size */
@@ -3640,18 +3982,6 @@ public_rEALLOc(Void_t* oldmem, size_t by
 
   Void_t* newp;             /* chunk to return */
 
-  __malloc_ptr_t (*hook) (__malloc_ptr_t, size_t, __const __malloc_ptr_t) =
-    __realloc_hook;
-  if (hook != NULL)
-    return (*hook)(oldmem, bytes, RETURN_ADDRESS (0));
-
-#if REALLOC_ZERO_BYTES_FREES
-  if (bytes == 0 && oldmem != NULL) { public_fREe(oldmem); return 0; }
-#endif
-
-  /* realloc of null is supposed to be same as malloc */
-  if (oldmem == 0) return public_mALLOc(bytes);
-
   oldp    = mem2chunk(oldmem);
   oldsize = chunksize(oldp);
 
@@ -3680,7 +4010,7 @@ public_rEALLOc(Void_t* oldmem, size_t by
     /* Note the extra SIZE_SZ overhead. */
     if(oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */
     /* Must alloc, copy, free. */
-    newmem = public_mALLOc(bytes);
+    newmem = _do_malloc(bytes);
     if (newmem == 0) return 0; /* propagate failure */
     MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ);
     munmap_chunk(oldp);
@@ -3714,7 +4044,7 @@ public_rEALLOc(Void_t* oldmem, size_t by
   if (newp == NULL)
     {
       /* Try harder to allocate memory in other arenas.  */
-      newp = public_mALLOc(bytes);
+      newp = _do_malloc(bytes);
       if (newp != NULL)
 	{
 	  MALLOC_COPY (newp, oldmem, oldsize - 2 * SIZE_SZ);
@@ -3735,24 +4065,20 @@ public_rEALLOc(Void_t* oldmem, size_t by
 
   return newp;
 }
-#ifdef libc_hidden_def
-libc_hidden_def (public_rEALLOc)
-#endif
 
-Void_t*
-public_mEMALIGn(size_t alignment, size_t bytes)
+static Void_t*
+#if __STD_C
+_do_memalign(size_t alignment, size_t bytes)
+#else
+_do_memalign(alignment, bytes)
+size_t alignment; size_t bytes;
+#endif
 {
   mstate ar_ptr;
   Void_t *p;
 
-  __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, size_t,
-					__const __malloc_ptr_t)) =
-    __memalign_hook;
-  if (hook != NULL)
-    return (*hook)(alignment, bytes, RETURN_ADDRESS (0));
-
   /* If need less alignment than we give anyway, just relay to malloc */
-  if (alignment <= MALLOC_ALIGNMENT) return public_mALLOc(bytes);
+  if (alignment <= MALLOC_ALIGNMENT) return _do_malloc(bytes);
 
   /* Otherwise, ensure that it is at least a minimum chunk size */
   if (alignment <  MINSIZE) alignment = MINSIZE;
@@ -3787,12 +4113,14 @@ public_mEMALIGn(size_t alignment, size_t
 	 ar_ptr == arena_for_chunk(mem2chunk(p)));
   return p;
 }
-#ifdef libc_hidden_def
-libc_hidden_def (public_mEMALIGn)
-#endif
 
-Void_t*
-public_vALLOc(size_t bytes)
+static Void_t*
+#if __STD_C
+_do_valloc(size_t bytes)
+#else
+_do_valloc(bytes)
+size_t bytes;
+#endif
 {
   mstate ar_ptr;
   Void_t *p;
@@ -3800,12 +4128,6 @@ public_vALLOc(size_t bytes)
   if(__malloc_initialized < 0)
     ptmalloc_init ();
 
-  __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, size_t,
-					__const __malloc_ptr_t)) =
-    __memalign_hook;
-  if (hook != NULL)
-    return (*hook)(mp_.pagesize, bytes, RETURN_ADDRESS (0));
-
   arena_get(ar_ptr, bytes + mp_.pagesize + MINSIZE);
   if(!ar_ptr)
     return 0;
@@ -3814,8 +4136,13 @@ public_vALLOc(size_t bytes)
   return p;
 }
 
-Void_t*
-public_pVALLOc(size_t bytes)
+static Void_t*
+#if __STD_C
+_do_pvalloc(size_t bytes)
+#else
+_do_pvalloc(bytes)
+size_t bytes;
+#endif
 {
   mstate ar_ptr;
   Void_t *p;
@@ -3823,56 +4150,27 @@ public_pVALLOc(size_t bytes)
   if(__malloc_initialized < 0)
     ptmalloc_init ();
 
-  __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, size_t,
-					__const __malloc_ptr_t)) =
-    __memalign_hook;
-  if (hook != NULL)
-    return (*hook)(mp_.pagesize,
-		   (bytes + mp_.pagesize - 1) & ~(mp_.pagesize - 1),
-		   RETURN_ADDRESS (0));
-
   arena_get(ar_ptr, bytes + 2*mp_.pagesize + MINSIZE);
   p = _int_pvalloc(ar_ptr, bytes);
   (void)mutex_unlock(&ar_ptr->mutex);
   return p;
 }
 
-Void_t*
-public_cALLOc(size_t n, size_t elem_size)
+static Void_t*
+#if __STD_C
+_do_calloc(INTERNAL_SIZE_T bytes)
+#else
+_do_calloc(bytes)
+INTERNAL_SIZE_T bytes;
+#endif
 {
   mstate av;
   mchunkptr oldtop, p;
-  INTERNAL_SIZE_T bytes, sz, csz, oldtopsize;
+  INTERNAL_SIZE_T sz, csz, oldtopsize;
   Void_t* mem;
   unsigned long clearsize;
   unsigned long nclears;
   INTERNAL_SIZE_T* d;
-  __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, __const __malloc_ptr_t)) =
-    __malloc_hook;
-
-  /* size_t is unsigned so the behavior on overflow is defined.  */
-  bytes = n * elem_size;
-#define HALF_INTERNAL_SIZE_T \
-  (((INTERNAL_SIZE_T) 1) << (8 * sizeof (INTERNAL_SIZE_T) / 2))
-  if (__builtin_expect ((n | elem_size) >= HALF_INTERNAL_SIZE_T, 0)) {
-    if (elem_size != 0 && bytes / elem_size != n) {
-      MALLOC_FAILURE_ACTION;
-      return 0;
-    }
-  }
-
-  if (hook != NULL) {
-    sz = bytes;
-    mem = (*hook)(sz, RETURN_ADDRESS (0));
-    if(mem == 0)
-      return 0;
-#ifdef HAVE_MEMCPY
-    return memset(mem, 0, sz);
-#else
-    while(sz > 0) ((char*)mem)[--sz] = 0; /* rather inefficient */
-    return mem;
-#endif
-  }
 
   sz = bytes;
 
@@ -3978,104 +4276,6 @@ public_cALLOc(size_t n, size_t elem_size
 
   return mem;
 }
-
-#ifndef _LIBC
-
-Void_t**
-public_iCALLOc(size_t n, size_t elem_size, Void_t** chunks)
-{
-  mstate ar_ptr;
-  Void_t** m;
-
-  arena_get(ar_ptr, n*elem_size);
-  if(!ar_ptr)
-    return 0;
-
-  m = _int_icalloc(ar_ptr, n, elem_size, chunks);
-  (void)mutex_unlock(&ar_ptr->mutex);
-  return m;
-}
-
-Void_t**
-public_iCOMALLOc(size_t n, size_t sizes[], Void_t** chunks)
-{
-  mstate ar_ptr;
-  Void_t** m;
-
-  arena_get(ar_ptr, 0);
-  if(!ar_ptr)
-    return 0;
-
-  m = _int_icomalloc(ar_ptr, n, sizes, chunks);
-  (void)mutex_unlock(&ar_ptr->mutex);
-  return m;
-}
-
-void
-public_cFREe(Void_t* m)
-{
-  public_fREe(m);
-}
-
-#endif /* _LIBC */
-
-int
-public_mTRIm(size_t s)
-{
-  int result = 0;
-
-  if(__malloc_initialized < 0)
-    ptmalloc_init ();
-
-  mstate ar_ptr = &main_arena;
-  do
-    {
-      (void) mutex_lock (&ar_ptr->mutex);
-      result |= mTRIm (ar_ptr, s);
-      (void) mutex_unlock (&ar_ptr->mutex);
-
-      ar_ptr = ar_ptr->next;
-    }
-  while (ar_ptr != &main_arena);
-
-  return result;
-}
-
-size_t
-public_mUSABLe(Void_t* m)
-{
-  size_t result;
-
-  result = mUSABLe(m);
-  return result;
-}
-
-void
-public_mSTATs()
-{
-  mSTATs();
-}
-
-struct mallinfo public_mALLINFo()
-{
-  struct mallinfo m;
-
-  if(__malloc_initialized < 0)
-    ptmalloc_init ();
-  (void)mutex_lock(&main_arena.mutex);
-  m = mALLINFo(&main_arena);
-  (void)mutex_unlock(&main_arena.mutex);
-  return m;
-}
-
-int
-public_mALLOPt(int p, int v)
-{
-  int result;
-  result = mALLOPt(p, v);
-  return result;
-}
-
 /*
   ------------------------------ malloc ------------------------------
 */
@@ -5963,8 +6163,9 @@ __posix_memalign (void **memptr, size_t 
 {
   void *mem;
   __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, size_t,
-					__const __malloc_ptr_t)) =
-    __memalign_hook;
+					__const __malloc_ptr_t));
+  void (*trace) __MALLOC_PMT ((size_t, size_t,
+			       __const __malloc_ptr_t, __malloc_ptr_t));
 
   /* Test whether the SIZE argument is valid.  It must be a power of
      two multiple of sizeof (void *).  */
@@ -5973,12 +6174,16 @@ __posix_memalign (void **memptr, size_t 
       || alignment == 0)
     return EINVAL;
 
-  /* Call the hook here, so that caller is posix_memalign's caller
-     and not posix_memalign itself.  */
+  hook = __memalign_hook;
   if (hook != NULL)
     mem = (*hook)(alignment, size, RETURN_ADDRESS (0));
-  else
-    mem = public_mEMALIGn (alignment, size);
+  else {
+    mem = _do_memalign (alignment, size);
+
+    trace = __memalign_trace;
+    if (trace != NULL)
+      (*trace)(alignment, size, RETURN_ADDRESS (0), mem);
+  }
 
   if (mem != NULL) {
     *memptr = mem;
Index: malloc/malloc.h
===================================================================
--- malloc/malloc.h	(revision 226481)
+++ malloc/malloc.h	(working copy)
@@ -153,18 +153,33 @@ extern int malloc_set_state __MALLOC_P (
    the application provides the preferred way to set up the hook
    pointers. */
 extern void (*__malloc_initialize_hook) __MALLOC_PMT ((void));
+
 /* Hooks for debugging and user-defined versions. */
-extern void (*__free_hook) __MALLOC_PMT ((void *__ptr,
+extern void (*__free_hook) __MALLOC_PMT ((void *__oldptr,
 					__const __malloc_ptr_t));
 extern void *(*__malloc_hook) __MALLOC_PMT ((size_t __size,
 					     __const __malloc_ptr_t));
-extern void *(*__realloc_hook) __MALLOC_PMT ((void *__ptr, size_t __size,
+extern void *(*__realloc_hook) __MALLOC_PMT ((void *__oldptr, size_t __size,
 					      __const __malloc_ptr_t));
 extern void *(*__memalign_hook) __MALLOC_PMT ((size_t __alignment,
 					       size_t __size,
 					       __const __malloc_ptr_t));
 extern void (*__after_morecore_hook) __MALLOC_PMT ((void));
 
+/* Additional post-processing hooks. */
+extern void (*__free_trace) __MALLOC_PMT ((void *__oldptr,
+					   __const __malloc_ptr_t));
+extern void (*__malloc_trace) __MALLOC_PMT ((size_t __size,
+					     __const __malloc_ptr_t,
+					     void *__ptr));
+extern void (*__realloc_trace) __MALLOC_PMT ((void *__oldptr, size_t __size,
+					      __const __malloc_ptr_t,
+					      void *__ptr));
+extern void (*__memalign_trace) __MALLOC_PMT ((size_t __alignment,
+					       size_t __size,
+					       __const __malloc_ptr_t,
+					       void *__ptr));
+
 /* Activate a standard set of debugging hooks. */
 extern void __malloc_check_init __MALLOC_P ((void));
 
Index: malloc/Versions
===================================================================
--- malloc/Versions	(revision 226481)
+++ malloc/Versions	(working copy)
@@ -55,6 +55,10 @@ libc {
     # p*
     posix_memalign;
   }
+  GLIBC_2.10 {
+    # interface of malloc functions
+    __free_trace; __malloc_trace; __realloc_trace; __memalign_trace;
+  }
   GLIBC_PRIVATE {
     # Internal startup hook for libpthread.
     __libc_malloc_pthread_startup;
Index: Versions.def
===================================================================
--- Versions.def	(revision 226481)
+++ Versions.def	(working copy)
@@ -25,6 +25,7 @@ libc {
   GLIBC_2.6
   GLIBC_2.7
   GLIBC_2.8
+  GLIBC_2.10
 %ifdef USE_IN_LIBIO
   HURD_CTHREADS_0.3
 %endif
Index: manual/memory.texi
===================================================================
--- manual/memory.texi	(revision 226481)
+++ manual/memory.texi	(working copy)
@@ -855,6 +855,24 @@ the memory consumption of the program.
 
 @comment malloc.h
 @comment GNU
+@defvar __malloc_trace
+The value of this variable is a pointer to the function that
+@code{malloc} calls at the conclusion whenever it is called.  You should
+define this function to look like @code{malloc} with additional two
+arguments; that is, like:
+
+@smallexample
+void *@var{function} (size_t @var{size}, const void *@var{caller}, void *@var{ptr})
+@end smallexample
+
+The value of @var{caller} is the return address found on the stack when
+the @code{malloc} function was called.  The value of @var{ptr} is one
+@code{malloc} will return.  This hook lets you trace @code{malloc} calls
+in a thread-safe manner.
+@end defvar
+
+@comment malloc.h
+@comment GNU
 @defvar __realloc_hook
 The value of this variable is a pointer to function that @code{realloc}
 uses whenever it is called.  You should define this function to look
@@ -871,6 +889,26 @@ memory consumption of the program.
 
 @comment malloc.h
 @comment GNU
+@defvar __realloc_trace
+The value of this variable is a pointer to function that @code{realloc}
+calls at the conclusion whenever it is called (note however, that if the
+arguments passed to @code{realloc} imply the semantics of @code{malloc}
+or @code{free}, then @code{__malloc_trace} or @code{__free_trace}
+respectively is called instead).  You should define this function to look
+like @code{realloc} with additional two arguments; that is, like:
+
+@smallexample
+void *@var{function} (void *@var{oldptr}, size_t @var{size}, const void *@var{caller}, void *@var{ptr})
+@end smallexample
+
+The value of @var{caller} is the return address found on the stack when
+the @code{realloc} function was called.  The value of @var{ptr} is one
+@code{realloc} will return.  This hook lets you trace @code{malloc} calls
+in a thread-safe manner.
+@end defvar
+
+@comment malloc.h
+@comment GNU
 @defvar __free_hook
 The value of this variable is a pointer to function that @code{free}
 uses whenever it is called.  You should define this function to look
@@ -887,6 +925,23 @@ memory consumption of the program.
 
 @comment malloc.h
 @comment GNU
+@defvar __free_trace
+The value of this variable is a pointer to function that @code{free}
+calls at the conclusion whenever it is called.  You should define this
+function to look like @code{free} with an additional argument; that is,
+like:
+
+@smallexample
+void @var{function} (void *@var{oldptr}, const void *@var{caller})
+@end smallexample
+
+The value of @var{caller} is the return address found on the stack when
+the @code{free} function was called.  This hook lets you trace @code{free}
+calls in a thread-safe manner.
+@end defvar
+
+@comment malloc.h
+@comment GNU
 @defvar __memalign_hook
 The value of this variable is a pointer to function that @code{memalign}
 uses whenever it is called.  You should define this function to look
@@ -901,6 +956,24 @@ the @code{memalign} function was called.
 memory consumption of the program.
 @end defvar
 
+@comment malloc.h
+@comment GNU
+@defvar __memalign_trace
+The value of this variable is a pointer to function that @code{memalign}
+calls at the conclusion whenever it is called.  You should define this
+function to look like @code{memalign} with additional two arguments; that
+is, like:
+
+@smallexample
+void *@var{function} (size_t @var{alignment}, size_t @var{size}, const void *@var{caller}, void *@var{ptr})
+@end smallexample
+
+The value of @var{caller} is the return address found on the stack when
+the @code{memalign} function was called.  The value of @var{ptr} is one
+@code{memalign} will return.  This hook lets you trace @code{memalign}
+calls in a thread-safe manner.
+@end defvar
+
 You must make sure that the function you install as a hook for one of
 these functions does not call that function recursively without restoring
 the old value of the hook first!  Otherwise, your program will get stuck


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]