[Xenomai-git] Philippe Gerum : copperplate/heapobj-malloc: enforce hard limit on pool size

2013-05-11 Thread git repository hosting
Module: xenomai-forge
Branch: master
Commit: 5d3fae825a8b92dca86f4cdc4b6c4ccabe19d1ce
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=5d3fae825a8b92dca86f4cdc4b6c4ccabe19d1ce

Author: Philippe Gerum 
Date:   Thu May  9 12:22:05 2013 +0200

copperplate/heapobj-malloc: enforce hard limit on pool size

Applications may rely on hard limits when creating memory pools, to
detect over-consumption. Since the global malloc heap is virtually
illimited, we do allocation size accounting for each malloc-based
heap and reject over budget requests.

---

 include/copperplate/heapobj.h|   55 -
 lib/copperplate/heapobj-malloc.c |  127 +-
 2 files changed, 139 insertions(+), 43 deletions(-)

diff --git a/include/copperplate/heapobj.h b/include/copperplate/heapobj.h
index 2dad005..39b6b06 100644
--- a/include/copperplate/heapobj.h
+++ b/include/copperplate/heapobj.h
@@ -140,22 +140,10 @@ static inline char *pvstrdup(const char *ptr)
 
 #include 
 
-static inline
-void pvheapobj_destroy(struct heapobj *hobj)
-{
-}
-
-static inline
-int pvheapobj_extend(struct heapobj *hobj, size_t size, void *mem)
-{
-   return 0;
-}
-
-static inline
-void *pvheapobj_alloc(struct heapobj *hobj, size_t size)
+static inline void *pvmalloc(size_t size)
 {
/*
-* XXX: We don't want debug _nrt assertions to trigger when
+* NOTE: We don't want debug _nrt assertions to trigger when
 * running over Cobalt if the user picked this allocator, so
 * we make sure to call the glibc directly, not the Cobalt
 * wrappers.
@@ -163,44 +151,27 @@ void *pvheapobj_alloc(struct heapobj *hobj, size_t size)
return __STD(malloc(size));
 }
 
-static inline
-void pvheapobj_free(struct heapobj *hobj, void *ptr)
+static inline void pvfree(void *ptr)
 {
__STD(free(ptr));
 }
 
-static inline
-size_t pvheapobj_validate(struct heapobj *hobj, void *ptr)
+static inline char *pvstrdup(const char *ptr)
 {
-   /*
-* We will likely get hard validation here, i.e. crash or
-* abort if the pointer is wrong. TLSF is a bit smarter, and
-* pshared definitely does the right thing.
-*/
-   return malloc_usable_size(ptr);
+   return strdup(ptr);
 }
 
-static inline
-size_t pvheapobj_inquire(struct heapobj *hobj)
-{
-   struct mallinfo m = mallinfo();
-   return m.uordblks;
-}
+void pvheapobj_destroy(struct heapobj *hobj);
 
-static inline void *pvmalloc(size_t size)
-{
-   return __STD(malloc(size));
-}
+int pvheapobj_extend(struct heapobj *hobj, size_t size, void *mem);
 
-static inline void pvfree(void *ptr)
-{
-   __STD(free(ptr));
-}
+void *pvheapobj_alloc(struct heapobj *hobj, size_t size);
 
-static inline char *pvstrdup(const char *ptr)
-{
-   return strdup(ptr);
-}
+void pvheapobj_free(struct heapobj *hobj, void *ptr);
+
+size_t pvheapobj_inquire(struct heapobj *hobj);
+
+size_t pvheapobj_validate(struct heapobj *hobj, void *ptr);
 
 #endif /* !CONFIG_XENO_TLSF */
 
diff --git a/lib/copperplate/heapobj-malloc.c b/lib/copperplate/heapobj-malloc.c
index 96814b9..14d624e 100644
--- a/lib/copperplate/heapobj-malloc.c
+++ b/lib/copperplate/heapobj-malloc.c
@@ -20,19 +20,51 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include "copperplate/lock.h"
 #include "copperplate/heapobj.h"
 #include "copperplate/debug.h"
 
+#define MALLOC_MAGIC 0xabbfcddc
+
+struct pool_header {
+   pthread_mutex_t lock;
+   size_t used;
+};
+
+struct block_header {
+   unsigned int magic;
+   size_t size;
+};
+
 int __heapobj_init_private(struct heapobj *hobj, const char *name,
   size_t size, void *mem)
 {
+   pthread_mutexattr_t mattr;
+   struct pool_header *ph;
+
/*
 * There is no local pool when working with malloc, we just
 * use the global process arena. This should not be an issue
 * since this mode is aimed at debugging, particularly to be
 * used along with Valgrind.
+*
+* However, we maintain a control header to track the amount
+* of memory currently consumed in each heap.
 */
-   hobj->pool = mem;   /* Never used. */
+   ph = malloc(sizeof(*ph));
+   if (ph == NULL)
+   return __bt(-ENOMEM);
+
+   __RT(pthread_mutexattr_init(&mattr));
+   __RT(pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT));
+   __RT(pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_PRIVATE));
+   __RT(pthread_mutex_init(&ph->lock, &mattr));
+   __RT(pthread_mutexattr_destroy(&mattr));
+   ph->used = 0;
+
+   hobj->pool = ph;
hobj->size = size;
if (name)
snprintf(hobj->name, sizeof(hobj->name), "%s", name);
@@ -48,6 +80,99 @@ int heapobj_init_array_private(struct heapobj *hobj, const 
char *name,
return __bt(__heapobj_init_private(hobj, name, size * elems, NULL));
 }
 
+void pvheapobj_destroy(

[Xenomai-git] Philippe Gerum : copperplate/heapobj-malloc: enforce hard limit on pool size

2013-05-10 Thread git repository hosting
Module: xenomai-forge
Branch: next
Commit: 5d3fae825a8b92dca86f4cdc4b6c4ccabe19d1ce
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=5d3fae825a8b92dca86f4cdc4b6c4ccabe19d1ce

Author: Philippe Gerum 
Date:   Thu May  9 12:22:05 2013 +0200

copperplate/heapobj-malloc: enforce hard limit on pool size

Applications may rely on hard limits when creating memory pools, to
detect over-consumption. Since the global malloc heap is virtually
illimited, we do allocation size accounting for each malloc-based
heap and reject over budget requests.

---

 include/copperplate/heapobj.h|   55 -
 lib/copperplate/heapobj-malloc.c |  127 +-
 2 files changed, 139 insertions(+), 43 deletions(-)

diff --git a/include/copperplate/heapobj.h b/include/copperplate/heapobj.h
index 2dad005..39b6b06 100644
--- a/include/copperplate/heapobj.h
+++ b/include/copperplate/heapobj.h
@@ -140,22 +140,10 @@ static inline char *pvstrdup(const char *ptr)
 
 #include 
 
-static inline
-void pvheapobj_destroy(struct heapobj *hobj)
-{
-}
-
-static inline
-int pvheapobj_extend(struct heapobj *hobj, size_t size, void *mem)
-{
-   return 0;
-}
-
-static inline
-void *pvheapobj_alloc(struct heapobj *hobj, size_t size)
+static inline void *pvmalloc(size_t size)
 {
/*
-* XXX: We don't want debug _nrt assertions to trigger when
+* NOTE: We don't want debug _nrt assertions to trigger when
 * running over Cobalt if the user picked this allocator, so
 * we make sure to call the glibc directly, not the Cobalt
 * wrappers.
@@ -163,44 +151,27 @@ void *pvheapobj_alloc(struct heapobj *hobj, size_t size)
return __STD(malloc(size));
 }
 
-static inline
-void pvheapobj_free(struct heapobj *hobj, void *ptr)
+static inline void pvfree(void *ptr)
 {
__STD(free(ptr));
 }
 
-static inline
-size_t pvheapobj_validate(struct heapobj *hobj, void *ptr)
+static inline char *pvstrdup(const char *ptr)
 {
-   /*
-* We will likely get hard validation here, i.e. crash or
-* abort if the pointer is wrong. TLSF is a bit smarter, and
-* pshared definitely does the right thing.
-*/
-   return malloc_usable_size(ptr);
+   return strdup(ptr);
 }
 
-static inline
-size_t pvheapobj_inquire(struct heapobj *hobj)
-{
-   struct mallinfo m = mallinfo();
-   return m.uordblks;
-}
+void pvheapobj_destroy(struct heapobj *hobj);
 
-static inline void *pvmalloc(size_t size)
-{
-   return __STD(malloc(size));
-}
+int pvheapobj_extend(struct heapobj *hobj, size_t size, void *mem);
 
-static inline void pvfree(void *ptr)
-{
-   __STD(free(ptr));
-}
+void *pvheapobj_alloc(struct heapobj *hobj, size_t size);
 
-static inline char *pvstrdup(const char *ptr)
-{
-   return strdup(ptr);
-}
+void pvheapobj_free(struct heapobj *hobj, void *ptr);
+
+size_t pvheapobj_inquire(struct heapobj *hobj);
+
+size_t pvheapobj_validate(struct heapobj *hobj, void *ptr);
 
 #endif /* !CONFIG_XENO_TLSF */
 
diff --git a/lib/copperplate/heapobj-malloc.c b/lib/copperplate/heapobj-malloc.c
index 96814b9..14d624e 100644
--- a/lib/copperplate/heapobj-malloc.c
+++ b/lib/copperplate/heapobj-malloc.c
@@ -20,19 +20,51 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include "copperplate/lock.h"
 #include "copperplate/heapobj.h"
 #include "copperplate/debug.h"
 
+#define MALLOC_MAGIC 0xabbfcddc
+
+struct pool_header {
+   pthread_mutex_t lock;
+   size_t used;
+};
+
+struct block_header {
+   unsigned int magic;
+   size_t size;
+};
+
 int __heapobj_init_private(struct heapobj *hobj, const char *name,
   size_t size, void *mem)
 {
+   pthread_mutexattr_t mattr;
+   struct pool_header *ph;
+
/*
 * There is no local pool when working with malloc, we just
 * use the global process arena. This should not be an issue
 * since this mode is aimed at debugging, particularly to be
 * used along with Valgrind.
+*
+* However, we maintain a control header to track the amount
+* of memory currently consumed in each heap.
 */
-   hobj->pool = mem;   /* Never used. */
+   ph = malloc(sizeof(*ph));
+   if (ph == NULL)
+   return __bt(-ENOMEM);
+
+   __RT(pthread_mutexattr_init(&mattr));
+   __RT(pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT));
+   __RT(pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_PRIVATE));
+   __RT(pthread_mutex_init(&ph->lock, &mattr));
+   __RT(pthread_mutexattr_destroy(&mattr));
+   ph->used = 0;
+
+   hobj->pool = ph;
hobj->size = size;
if (name)
snprintf(hobj->name, sizeof(hobj->name), "%s", name);
@@ -48,6 +80,99 @@ int heapobj_init_array_private(struct heapobj *hobj, const 
char *name,
return __bt(__heapobj_init_private(hobj, name, size * elems, NULL));
 }
 
+void pvheapobj_destroy(st

[Xenomai-git] Philippe Gerum : copperplate/heapobj-malloc: enforce hard limit on pool size

2013-05-10 Thread git repository hosting
Module: xenomai-forge
Branch: next
Commit: 900e0c3f84b8e8374e64b2d6932cce9328713d80
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=900e0c3f84b8e8374e64b2d6932cce9328713d80

Author: Philippe Gerum 
Date:   Thu May  9 12:22:05 2013 +0200

copperplate/heapobj-malloc: enforce hard limit on pool size

Applications may rely on hard limits when creating memory pools, to
detect over-consumption. Since the global malloc heap is virtually
illimited, we do allocation size accounting for each malloc-based
heap and reject over budget requests.

---

 include/copperplate/heapobj.h|   55 -
 lib/copperplate/heapobj-malloc.c |  127 +-
 2 files changed, 139 insertions(+), 43 deletions(-)

diff --git a/include/copperplate/heapobj.h b/include/copperplate/heapobj.h
index 2dad005..39b6b06 100644
--- a/include/copperplate/heapobj.h
+++ b/include/copperplate/heapobj.h
@@ -140,22 +140,10 @@ static inline char *pvstrdup(const char *ptr)
 
 #include 
 
-static inline
-void pvheapobj_destroy(struct heapobj *hobj)
-{
-}
-
-static inline
-int pvheapobj_extend(struct heapobj *hobj, size_t size, void *mem)
-{
-   return 0;
-}
-
-static inline
-void *pvheapobj_alloc(struct heapobj *hobj, size_t size)
+static inline void *pvmalloc(size_t size)
 {
/*
-* XXX: We don't want debug _nrt assertions to trigger when
+* NOTE: We don't want debug _nrt assertions to trigger when
 * running over Cobalt if the user picked this allocator, so
 * we make sure to call the glibc directly, not the Cobalt
 * wrappers.
@@ -163,44 +151,27 @@ void *pvheapobj_alloc(struct heapobj *hobj, size_t size)
return __STD(malloc(size));
 }
 
-static inline
-void pvheapobj_free(struct heapobj *hobj, void *ptr)
+static inline void pvfree(void *ptr)
 {
__STD(free(ptr));
 }
 
-static inline
-size_t pvheapobj_validate(struct heapobj *hobj, void *ptr)
+static inline char *pvstrdup(const char *ptr)
 {
-   /*
-* We will likely get hard validation here, i.e. crash or
-* abort if the pointer is wrong. TLSF is a bit smarter, and
-* pshared definitely does the right thing.
-*/
-   return malloc_usable_size(ptr);
+   return strdup(ptr);
 }
 
-static inline
-size_t pvheapobj_inquire(struct heapobj *hobj)
-{
-   struct mallinfo m = mallinfo();
-   return m.uordblks;
-}
+void pvheapobj_destroy(struct heapobj *hobj);
 
-static inline void *pvmalloc(size_t size)
-{
-   return __STD(malloc(size));
-}
+int pvheapobj_extend(struct heapobj *hobj, size_t size, void *mem);
 
-static inline void pvfree(void *ptr)
-{
-   __STD(free(ptr));
-}
+void *pvheapobj_alloc(struct heapobj *hobj, size_t size);
 
-static inline char *pvstrdup(const char *ptr)
-{
-   return strdup(ptr);
-}
+void pvheapobj_free(struct heapobj *hobj, void *ptr);
+
+size_t pvheapobj_inquire(struct heapobj *hobj);
+
+size_t pvheapobj_validate(struct heapobj *hobj, void *ptr);
 
 #endif /* !CONFIG_XENO_TLSF */
 
diff --git a/lib/copperplate/heapobj-malloc.c b/lib/copperplate/heapobj-malloc.c
index 96814b9..14d624e 100644
--- a/lib/copperplate/heapobj-malloc.c
+++ b/lib/copperplate/heapobj-malloc.c
@@ -20,19 +20,51 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include "copperplate/lock.h"
 #include "copperplate/heapobj.h"
 #include "copperplate/debug.h"
 
+#define MALLOC_MAGIC 0xabbfcddc
+
+struct pool_header {
+   pthread_mutex_t lock;
+   size_t used;
+};
+
+struct block_header {
+   unsigned int magic;
+   size_t size;
+};
+
 int __heapobj_init_private(struct heapobj *hobj, const char *name,
   size_t size, void *mem)
 {
+   pthread_mutexattr_t mattr;
+   struct pool_header *ph;
+
/*
 * There is no local pool when working with malloc, we just
 * use the global process arena. This should not be an issue
 * since this mode is aimed at debugging, particularly to be
 * used along with Valgrind.
+*
+* However, we maintain a control header to track the amount
+* of memory currently consumed in each heap.
 */
-   hobj->pool = mem;   /* Never used. */
+   ph = malloc(sizeof(*ph));
+   if (ph == NULL)
+   return __bt(-ENOMEM);
+
+   __RT(pthread_mutexattr_init(&mattr));
+   __RT(pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT));
+   __RT(pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_PRIVATE));
+   __RT(pthread_mutex_init(&ph->lock, &mattr));
+   __RT(pthread_mutexattr_destroy(&mattr));
+   ph->used = 0;
+
+   hobj->pool = ph;
hobj->size = size;
if (name)
snprintf(hobj->name, sizeof(hobj->name), "%s", name);
@@ -48,6 +80,99 @@ int heapobj_init_array_private(struct heapobj *hobj, const 
char *name,
return __bt(__heapobj_init_private(hobj, name, size * elems, NULL));
 }
 
+void pvheapobj_destroy(st

[Xenomai-git] Philippe Gerum : copperplate/heapobj-malloc: enforce hard limit on pool size

2013-05-09 Thread git repository hosting
Module: xenomai-forge
Branch: next
Commit: 7cf44bdf70b963d41d39fa419f16b787267b777d
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=7cf44bdf70b963d41d39fa419f16b787267b777d

Author: Philippe Gerum 
Date:   Thu May  9 12:22:05 2013 +0200

copperplate/heapobj-malloc: enforce hard limit on pool size

Applications may rely on hard limits when creating memory pools, to
detect over-consumption. Since the global malloc heap is virtually
illimited, we do allocation size accounting for each malloc-based
heap and reject over budget requests.

---

 include/copperplate/heapobj.h|   52 ++--
 lib/copperplate/heapobj-malloc.c |   98 +-
 2 files changed, 113 insertions(+), 37 deletions(-)

diff --git a/include/copperplate/heapobj.h b/include/copperplate/heapobj.h
index 2dad005..6eb874f 100644
--- a/include/copperplate/heapobj.h
+++ b/include/copperplate/heapobj.h
@@ -141,35 +141,6 @@ static inline char *pvstrdup(const char *ptr)
 #include 
 
 static inline
-void pvheapobj_destroy(struct heapobj *hobj)
-{
-}
-
-static inline
-int pvheapobj_extend(struct heapobj *hobj, size_t size, void *mem)
-{
-   return 0;
-}
-
-static inline
-void *pvheapobj_alloc(struct heapobj *hobj, size_t size)
-{
-   /*
-* XXX: We don't want debug _nrt assertions to trigger when
-* running over Cobalt if the user picked this allocator, so
-* we make sure to call the glibc directly, not the Cobalt
-* wrappers.
-*/
-   return __STD(malloc(size));
-}
-
-static inline
-void pvheapobj_free(struct heapobj *hobj, void *ptr)
-{
-   __STD(free(ptr));
-}
-
-static inline
 size_t pvheapobj_validate(struct heapobj *hobj, void *ptr)
 {
/*
@@ -180,15 +151,14 @@ size_t pvheapobj_validate(struct heapobj *hobj, void *ptr)
return malloc_usable_size(ptr);
 }
 
-static inline
-size_t pvheapobj_inquire(struct heapobj *hobj)
-{
-   struct mallinfo m = mallinfo();
-   return m.uordblks;
-}
-
 static inline void *pvmalloc(size_t size)
 {
+   /*
+* NOTE: We don't want debug _nrt assertions to trigger when
+* running over Cobalt if the user picked this allocator, so
+* we make sure to call the glibc directly, not the Cobalt
+* wrappers.
+*/
return __STD(malloc(size));
 }
 
@@ -202,6 +172,16 @@ static inline char *pvstrdup(const char *ptr)
return strdup(ptr);
 }
 
+void pvheapobj_destroy(struct heapobj *hobj);
+
+int pvheapobj_extend(struct heapobj *hobj, size_t size, void *mem);
+
+void *pvheapobj_alloc(struct heapobj *hobj, size_t size);
+
+void pvheapobj_free(struct heapobj *hobj, void *ptr);
+
+size_t pvheapobj_inquire(struct heapobj *hobj);
+
 #endif /* !CONFIG_XENO_TLSF */
 
 #ifdef CONFIG_XENO_PSHARED
diff --git a/lib/copperplate/heapobj-malloc.c b/lib/copperplate/heapobj-malloc.c
index 96814b9..2e4e399 100644
--- a/lib/copperplate/heapobj-malloc.c
+++ b/lib/copperplate/heapobj-malloc.c
@@ -20,19 +20,44 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include "copperplate/lock.h"
 #include "copperplate/heapobj.h"
 #include "copperplate/debug.h"
 
+struct malloc_heap {
+   pthread_mutex_t lock;
+   size_t used;
+};
+
 int __heapobj_init_private(struct heapobj *hobj, const char *name,
   size_t size, void *mem)
 {
+   pthread_mutexattr_t mattr;
+   struct malloc_heap *mh;
+
/*
 * There is no local pool when working with malloc, we just
 * use the global process arena. This should not be an issue
 * since this mode is aimed at debugging, particularly to be
 * used along with Valgrind.
+*
+* However, we maintain a control header to track the amount
+* of memory currently consumed in each heap.
 */
-   hobj->pool = mem;   /* Never used. */
+   mh = malloc(sizeof(*mh));
+   if (mh == NULL)
+   return __bt(-ENOMEM);
+
+   __RT(pthread_mutexattr_init(&mattr));
+   __RT(pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT));
+   __RT(pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_PRIVATE));
+   __RT(pthread_mutex_init(&mh->lock, &mattr));
+   __RT(pthread_mutexattr_destroy(&mattr));
+   mh->used = 0;
+
+   hobj->pool = mh;
hobj->size = size;
if (name)
snprintf(hobj->name, sizeof(hobj->name), "%s", name);
@@ -48,6 +73,77 @@ int heapobj_init_array_private(struct heapobj *hobj, const 
char *name,
return __bt(__heapobj_init_private(hobj, name, size * elems, NULL));
 }
 
+void pvheapobj_destroy(struct heapobj *hobj)
+{
+   struct malloc_heap *mh = hobj->pool;
+
+   __RT(pthread_mutex_destroy(&mh->lock));
+   __STD(free(mh));
+}
+
+int pvheapobj_extend(struct heapobj *hobj, size_t size, void *mem)
+{
+   struct malloc_heap *mh = hobj->pool;
+
+   write_lock_nocancel(&mh->lock);
+   hobj->size += size;
+   write_unlock(&

[Xenomai-git] Philippe Gerum : copperplate/heapobj-malloc: enforce hard limit on pool size

2013-05-09 Thread git repository hosting
Module: xenomai-forge
Branch: next
Commit: 4f454cdadfaa6ed4b2e73bd474c3151fd2aef940
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=4f454cdadfaa6ed4b2e73bd474c3151fd2aef940

Author: Philippe Gerum 
Date:   Thu May  9 12:22:05 2013 +0200

copperplate/heapobj-malloc: enforce hard limit on pool size

Applications may rely on hard limits when creating memory pools, to
detect over-consumption. Since the global malloc heap is virtually
illimited, we do allocation size accounting for each malloc-based
heap and reject over budget requests.

---

 include/copperplate/heapobj.h|   52 ++--
 lib/copperplate/heapobj-malloc.c |   99 +-
 2 files changed, 114 insertions(+), 37 deletions(-)

diff --git a/include/copperplate/heapobj.h b/include/copperplate/heapobj.h
index 2dad005..6eb874f 100644
--- a/include/copperplate/heapobj.h
+++ b/include/copperplate/heapobj.h
@@ -141,35 +141,6 @@ static inline char *pvstrdup(const char *ptr)
 #include 
 
 static inline
-void pvheapobj_destroy(struct heapobj *hobj)
-{
-}
-
-static inline
-int pvheapobj_extend(struct heapobj *hobj, size_t size, void *mem)
-{
-   return 0;
-}
-
-static inline
-void *pvheapobj_alloc(struct heapobj *hobj, size_t size)
-{
-   /*
-* XXX: We don't want debug _nrt assertions to trigger when
-* running over Cobalt if the user picked this allocator, so
-* we make sure to call the glibc directly, not the Cobalt
-* wrappers.
-*/
-   return __STD(malloc(size));
-}
-
-static inline
-void pvheapobj_free(struct heapobj *hobj, void *ptr)
-{
-   __STD(free(ptr));
-}
-
-static inline
 size_t pvheapobj_validate(struct heapobj *hobj, void *ptr)
 {
/*
@@ -180,15 +151,14 @@ size_t pvheapobj_validate(struct heapobj *hobj, void *ptr)
return malloc_usable_size(ptr);
 }
 
-static inline
-size_t pvheapobj_inquire(struct heapobj *hobj)
-{
-   struct mallinfo m = mallinfo();
-   return m.uordblks;
-}
-
 static inline void *pvmalloc(size_t size)
 {
+   /*
+* NOTE: We don't want debug _nrt assertions to trigger when
+* running over Cobalt if the user picked this allocator, so
+* we make sure to call the glibc directly, not the Cobalt
+* wrappers.
+*/
return __STD(malloc(size));
 }
 
@@ -202,6 +172,16 @@ static inline char *pvstrdup(const char *ptr)
return strdup(ptr);
 }
 
+void pvheapobj_destroy(struct heapobj *hobj);
+
+int pvheapobj_extend(struct heapobj *hobj, size_t size, void *mem);
+
+void *pvheapobj_alloc(struct heapobj *hobj, size_t size);
+
+void pvheapobj_free(struct heapobj *hobj, void *ptr);
+
+size_t pvheapobj_inquire(struct heapobj *hobj);
+
 #endif /* !CONFIG_XENO_TLSF */
 
 #ifdef CONFIG_XENO_PSHARED
diff --git a/lib/copperplate/heapobj-malloc.c b/lib/copperplate/heapobj-malloc.c
index 96814b9..ec44f89 100644
--- a/lib/copperplate/heapobj-malloc.c
+++ b/lib/copperplate/heapobj-malloc.c
@@ -20,19 +20,44 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include "copperplate/lock.h"
 #include "copperplate/heapobj.h"
 #include "copperplate/debug.h"
 
+struct malloc_heap {
+   pthread_mutex_t lock;
+   size_t used;
+};
+
 int __heapobj_init_private(struct heapobj *hobj, const char *name,
   size_t size, void *mem)
 {
+   pthread_mutexattr_t mattr;
+   struct malloc_heap *mh;
+
/*
 * There is no local pool when working with malloc, we just
 * use the global process arena. This should not be an issue
 * since this mode is aimed at debugging, particularly to be
 * used along with Valgrind.
+*
+* However, we maintain a control header to track the amount
+* of memory currently consumed in each heap.
 */
-   hobj->pool = mem;   /* Never used. */
+   mh = malloc(sizeof(*mh));
+   if (mh == NULL)
+   return __bt(-ENOMEM);
+
+   __RT(pthread_mutexattr_init(&mattr));
+   __RT(pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT));
+   __RT(pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_PRIVATE));
+   __RT(pthread_mutex_init(&mh->lock, &mattr));
+   __RT(pthread_mutexattr_destroy(&mattr));
+   mh->used = 0;
+
+   hobj->pool = mh;
hobj->size = size;
if (name)
snprintf(hobj->name, sizeof(hobj->name), "%s", name);
@@ -48,6 +73,78 @@ int heapobj_init_array_private(struct heapobj *hobj, const 
char *name,
return __bt(__heapobj_init_private(hobj, name, size * elems, NULL));
 }
 
+void pvheapobj_destroy(struct heapobj *hobj)
+{
+   struct malloc_heap *mh = hobj->pool;
+
+   __RT(pthread_mutex_destroy(&mh->lock));
+   __STD(free(mh));
+}
+
+int pvheapobj_extend(struct heapobj *hobj, size_t size, void *mem)
+{
+   struct malloc_heap *mh = hobj->pool;
+
+   write_lock_nocancel(&mh->lock);
+   hobj->size += size;
+   write_unlock(&