Diff
Modified: trunk/uClibc/libc/stdlib/malloc/free.c (1623 => 1624)
--- trunk/uClibc/libc/stdlib/malloc/free.c 2007-05-14 01:16:27 UTC (rev 1623)
+++ trunk/uClibc/libc/stdlib/malloc/free.c 2007-05-14 03:37:29 UTC (rev 1624)
@@ -125,6 +125,9 @@
start, end - start);
prev_mmb = 0;
+
+ __malloc_lock_mmb ();
+
mmb = __malloc_mmapped_blocks;
while (mmb
&& ((mmb_end = (mmb_start = (unsigned long)mmb->mem) + mmb->size)
@@ -169,30 +172,13 @@
/* Start searching again from the end of this block. */
start = mmb_end;
- /* We have to unlock the heap before we recurse to free the mmb
- descriptor, because we might be unmapping from the mmb
- heap. */
- __heap_unlock (heap);
-
/* Release the descriptor block we used. */
free_to_heap (mmb, &__malloc_mmb_heap);
/* Do the actual munmap. */
munmap ((void *)mmb_start, mmb_end - mmb_start);
- __heap_lock (heap);
-
-# ifdef __UCLIBC_HAS_THREADS__
- /* In a multi-threaded program, it's possible that PREV_MMB has
- been invalidated by another thread when we released the
- heap lock to do the munmap system call, so just start over
- from the beginning of the list. It sucks, but oh well;
- it's probably not worth the bother to do better. */
- prev_mmb = 0;
- mmb = __malloc_mmapped_blocks;
-# else
mmb = next_mmb;
-# endif
}
else
{
@@ -203,6 +189,8 @@
MALLOC_MMB_DEBUG_INDENT (-1);
}
+ __malloc_unlock_mmb ();
+
if (start != end)
/* Hmm, well there's something we couldn't unmap, so put it back
into the heap. */
Modified: trunk/uClibc/libc/stdlib/malloc/heap.h (1623 => 1624)
--- trunk/uClibc/libc/stdlib/malloc/heap.h 2007-05-14 01:16:27 UTC (rev 1623)
+++ trunk/uClibc/libc/stdlib/malloc/heap.h 2007-05-14 03:37:29 UTC (rev 1624)
@@ -51,9 +51,12 @@
#ifdef HEAP_USE_LOCKING
# define HEAP_INIT { 0, PTHREAD_MUTEX_INITIALIZER }
# define HEAP_INIT_WITH_FA(fa) { &fa._fa, PTHREAD_MUTEX_INITIALIZER }
+# define HEAP_INIT_RECURSIVE_WITH_FA(fa) \
+ { &fa._fa, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
#else
# define HEAP_INIT { 0 }
# define HEAP_INIT_WITH_FA(fa) { &fa._fa }
+# define HEAP_INIT_RECURSIVE_WITH_FA(fa) { &fa._fa }
#endif
/* A free-list area `header'. These are actually stored at the _ends_ of
Modified: trunk/uClibc/libc/stdlib/malloc/malloc.c (1623 => 1624)
--- trunk/uClibc/libc/stdlib/malloc/malloc.c 2007-05-14 01:16:27 UTC (rev 1623)
+++ trunk/uClibc/libc/stdlib/malloc/malloc.c 2007-05-14 03:37:29 UTC (rev 1624)
@@ -30,7 +30,7 @@
#if defined(MALLOC_USE_LOCKING) && defined(MALLOC_USE_SBRK)
/* A lock protecting our use of sbrk. */
-malloc_mutex_t __malloc_sbrk_lock;
+malloc_mutex_t __malloc_sbrk_lock = MALLOC_MUTEX_INIT;
#endif /* MALLOC_USE_LOCKING && MALLOC_USE_SBRK */
@@ -43,7 +43,11 @@
them from the main heap, but that tends to cause heap fragmentation in
annoying ways. */
HEAP_DECLARE_STATIC_FREE_AREA (initial_mmb_fa, 48); /* enough for 3 mmbs */
-struct heap __malloc_mmb_heap = HEAP_INIT_WITH_FA (initial_mmb_fa);
+struct heap __malloc_mmb_heap = HEAP_INIT_RECURSIVE_WITH_FA (initial_mmb_fa);
+
+#ifdef MALLOC_USE_LOCKING
+malloc_mutex_t __malloc_mmb_lock = MALLOC_RECURSIVE_MUTEX_INIT;
+#endif /* MALLOC_USE_LOCKING */
#endif /* __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */
@@ -139,6 +143,9 @@
__heap_unlock (heap);
#if !defined(MALLOC_USE_SBRK) && defined(__UCLIBC_UCLINUX_BROKEN_MUNMAP__)
+
+ __malloc_lock_mmb ();
+
/* Insert a record of BLOCK in sorted order into the
__malloc_mmapped_blocks list. */
@@ -158,6 +165,8 @@
else
__malloc_mmapped_blocks = new_mmb;
+ __malloc_unlock_mmb ();
+
MALLOC_MMB_DEBUG (0, "new mmb at 0x%x: 0x%x[%d]",
(unsigned)new_mmb,
(unsigned)new_mmb->mem, block_size);
Modified: trunk/uClibc/libc/stdlib/malloc/malloc.h (1623 => 1624)
--- trunk/uClibc/libc/stdlib/malloc/malloc.h 2007-05-14 01:16:27 UTC (rev 1623)
+++ trunk/uClibc/libc/stdlib/malloc/malloc.h 2007-05-14 03:37:29 UTC (rev 1624)
@@ -52,7 +52,20 @@
# define MALLOC_USE_SBRK
#endif
+/* Locking for multithreaded apps. */
+#ifdef __UCLIBC_HAS_THREADS__
+# include <pthread.h>
+# include <bits/uClibc_pthread.h>
+
+# define MALLOC_USE_LOCKING
+
+typedef pthread_mutex_t malloc_mutex_t;
+# define MALLOC_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
+# define MALLOC_RECURSIVE_MUTEX_INIT \
+ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+#endif /* __UCLIBC_HAS_THREADS__ */
+
/* The current implementation of munmap in uClinux doesn't work correctly:
it requires that ever call to munmap exactly match a corresponding call
to mmap (that is, it doesn't allow you to unmap only part of a
@@ -79,6 +92,15 @@
annoying ways. */
extern struct heap __malloc_mmb_heap;
+# ifdef MALLOC_USE_LOCKING
+extern malloc_mutex_t __malloc_mmb_lock;
+# define __malloc_lock_mmb() __pthread_mutex_lock (&__malloc_mmb_lock)
+# define __malloc_unlock_mmb() __pthread_mutex_unlock (&__malloc_mmb_lock)
+# else /* !MALLOC_USE_LOCKING */
+# define __malloc_lock_mmb() (void)0
+# define __malloc_unlock_mmb() (void)0
+# endif /* MALLOC_USE_LOCKING */
+
/* Define MALLOC_MMB_DEBUGGING to cause malloc to emit debugging info about
about mmap block allocation/freeing by the `uclinux broken munmap' code
to stderr, when the variable __malloc_mmb_debug is set to true. */
@@ -130,18 +152,9 @@
#define MALLOC_SIZE(addr) (*(size_t *)MALLOC_BASE(addr))
-/* Locking for multithreaded apps. */
-#ifdef __UCLIBC_HAS_THREADS__
-# include <pthread.h>
-# include <bits/uClibc_pthread.h>
-
-# define MALLOC_USE_LOCKING
-
-typedef pthread_mutex_t malloc_mutex_t;
-# define MALLOC_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
-
-# ifdef MALLOC_USE_SBRK
+#ifdef MALLOC_USE_SBRK
+# ifdef MALLOC_USE_LOCKING
/* This lock is used to serialize uses of the `sbrk' function (in both
malloc and free, sbrk may be used several times in succession, and
things will break if these multiple calls are interleaved with another
@@ -149,17 +162,17 @@
extern malloc_mutex_t __malloc_sbrk_lock;
# define __malloc_lock_sbrk() __pthread_mutex_lock (&__malloc_sbrk_lock)
# define __malloc_unlock_sbrk() __pthread_mutex_unlock (&__malloc_sbrk_lock)
-# endif /* MALLOC_USE_SBRK */
-#else /* !__UCLIBC_HAS_THREADS__ */
+# else /* !MALLOC_USE_LOCKING */
+
/* Without threads, mutex operations are a nop. */
-# define __malloc_lock_sbrk() (void)0
-# define __malloc_unlock_sbrk() (void)0
+# define __malloc_lock_sbrk() (void)0
+# define __malloc_unlock_sbrk() (void)0
-#endif /* __UCLIBC_HAS_THREADS__ */
+# endif /* MALLOC_USE_LOCKING */
+#endif /* MALLOC_USE_SBRK */
-
/* branch-prediction macros; they may already be defined by libc. */
#ifndef likely
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)