Title: [1624] trunk/uClibc/libc/stdlib/malloc: Bug [#3251].
Revision
1624
Author
jiez
Date
2007-05-13 22:37:29 -0500 (Sun, 13 May 2007)

Log Message

Bug [#3251]. Make malloc and free multithread safe.

Modified Paths

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)
_______________________________________________
Toolchain-commits mailing list
Toolchain-commits@blackfin.uclinux.org
http://blackfin.uclinux.org/mailman/listinfo/toolchain-commits

Reply via email to