From 1478c2de052374c6356db5513749a144c13791b1 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Thu, 7 Dec 2006 23:24:02 +0000 Subject: Major cleanup of internal mutex locking. Be more consistant in how we do things, and avoid potential deadlocks caused when a thread holding a uClibc internal lock get canceled and terminates without releasing the lock. This change also provides a single place, bits/uClibc_mutex.h, for thread libraries to modify to change all instances of internal locking. --- libc/stdlib/malloc-standard/calloc.c | 4 +-- libc/stdlib/malloc-standard/free.c | 4 +-- libc/stdlib/malloc-standard/mallinfo.c | 45 ++++++++++++++++++++---------- libc/stdlib/malloc-standard/malloc.c | 51 +++++++++++++++++----------------- libc/stdlib/malloc-standard/malloc.h | 11 ++++---- libc/stdlib/malloc-standard/mallopt.c | 4 +-- libc/stdlib/malloc-standard/memalign.c | 18 +++++++----- libc/stdlib/malloc-standard/realloc.c | 34 +++++++++++++---------- 8 files changed, 98 insertions(+), 73 deletions(-) (limited to 'libc/stdlib/malloc-standard') diff --git a/libc/stdlib/malloc-standard/calloc.c b/libc/stdlib/malloc-standard/calloc.c index 99e8884ad..b94fb372b 100644 --- a/libc/stdlib/malloc-standard/calloc.c +++ b/libc/stdlib/malloc-standard/calloc.c @@ -36,7 +36,7 @@ void* calloc(size_t n_elements, size_t elem_size) return NULL; } - LOCK; + __MALLOC_LOCK; mem = malloc(size); if (mem != 0) { p = mem2chunk(mem); @@ -88,7 +88,7 @@ void* calloc(size_t n_elements, size_t elem_size) } #endif } - UNLOCK; + __MALLOC_UNLOCK; return mem; } diff --git a/libc/stdlib/malloc-standard/free.c b/libc/stdlib/malloc-standard/free.c index e0c6ef061..4d24697be 100644 --- a/libc/stdlib/malloc-standard/free.c +++ b/libc/stdlib/malloc-standard/free.c @@ -282,7 +282,7 @@ void free(void* mem) if (mem == NULL) return; - LOCK; + __MALLOC_LOCK; av = get_malloc_state(); p = mem2chunk(mem); size = chunksize(p); @@ -406,6 +406,6 @@ void free(void* mem) av->mmapped_mem -= (size + offset); munmap((char*)p - offset, size + offset); } - UNLOCK; + __MALLOC_UNLOCK; } diff --git a/libc/stdlib/malloc-standard/mallinfo.c b/libc/stdlib/malloc-standard/mallinfo.c index 4f274ed32..18331010a 100644 --- a/libc/stdlib/malloc-standard/mallinfo.c +++ b/libc/stdlib/malloc-standard/mallinfo.c @@ -32,7 +32,7 @@ struct mallinfo mallinfo(void) int nblocks; int nfastblocks; - LOCK; + __MALLOC_LOCK; av = get_malloc_state(); /* Ensure initialization */ if (av->top == 0) { @@ -77,7 +77,7 @@ struct mallinfo mallinfo(void) mi.fsmblks = fastavail; mi.keepcost = chunksize(av->top); mi.usmblks = av->max_total_mem; - UNLOCK; + __MALLOC_UNLOCK; return mi; } libc_hidden_def(mallinfo) @@ -91,19 +91,36 @@ void malloc_stats(FILE *file) } mi = mallinfo(); - fprintf(file, "total bytes allocated = %10u\n", (unsigned int)(mi.arena + mi.hblkhd)); - fprintf(file, "total bytes in use bytes = %10u\n", (unsigned int)(mi.uordblks + mi.hblkhd)); - fprintf(file, "total non-mmapped bytes allocated = %10d\n", mi.arena); - fprintf(file, "number of mmapped regions = %10d\n", mi.hblks); - fprintf(file, "total allocated mmap space = %10d\n", mi.hblkhd); - fprintf(file, "total allocated sbrk space = %10d\n", mi.uordblks); + fprintf(file, + "total bytes allocated = %10u\n" + "total bytes in use bytes = %10u\n" + "total non-mmapped bytes allocated = %10d\n" + "number of mmapped regions = %10d\n" + "total allocated mmap space = %10d\n" + "total allocated sbrk space = %10d\n" #if 0 - fprintf(file, "number of free chunks = %10d\n", mi.ordblks); - fprintf(file, "number of fastbin blocks = %10d\n", mi.smblks); - fprintf(file, "space in freed fastbin blocks = %10d\n", mi.fsmblks); + "number of free chunks = %10d\n" + "number of fastbin blocks = %10d\n" + "space in freed fastbin blocks = %10d\n" #endif - fprintf(file, "maximum total allocated space = %10d\n", mi.usmblks); - fprintf(file, "total free space = %10d\n", mi.fordblks); - fprintf(file, "memory releasable via malloc_trim = %10d\n", mi.keepcost); + "maximum total allocated space = %10d\n" + "total free space = %10d\n" + "memory releasable via malloc_trim = %10d\n", + + (unsigned int)(mi.arena + mi.hblkhd), + (unsigned int)(mi.uordblks + mi.hblkhd), + mi.arena, + mi.hblks, + mi.hblkhd, + mi.uordblks, +#if 0 + mi.ordblks, + mi.smblks, + mi.fsmblks, +#endif + mi.usmblks, + mi.fordblks, + mi.keepcost + ); } diff --git a/libc/stdlib/malloc-standard/malloc.c b/libc/stdlib/malloc-standard/malloc.c index 7a87ffd36..8c06fdf1f 100644 --- a/libc/stdlib/malloc-standard/malloc.c +++ b/libc/stdlib/malloc-standard/malloc.c @@ -17,9 +17,7 @@ #include "malloc.h" -#ifdef __UCLIBC_HAS_THREADS__ -pthread_mutex_t __malloc_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; -#endif +__UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); /* There is exactly one instance of this struct in this malloc. @@ -825,12 +823,13 @@ void* malloc(size_t bytes) mchunkptr fwd; /* misc temp for linking */ mchunkptr bck; /* misc temp for linking */ void * sysmem; + void * retval; #if !defined(__MALLOC_GLIBC_COMPAT__) if (!bytes) return NULL; #endif - LOCK; + __MALLOC_LOCK; av = get_malloc_state(); /* Convert request size to internal form by adding (sizeof(size_t)) bytes @@ -861,8 +860,8 @@ void* malloc(size_t bytes) if ( (victim = *fb) != 0) { *fb = victim->fd; check_remalloced_chunk(victim, nb); - UNLOCK; - return chunk2mem(victim); + retval = chunk2mem(victim); + goto DONE; } } @@ -885,8 +884,8 @@ void* malloc(size_t bytes) bck->fd = bin; check_malloced_chunk(victim, nb); - UNLOCK; - return chunk2mem(victim); + retval = chunk2mem(victim); + goto DONE; } } @@ -902,7 +901,7 @@ void* malloc(size_t bytes) else { idx = __malloc_largebin_index(nb); - if (have_fastchunks(av)) + if (have_fastchunks(av)) __malloc_consolidate(av); } @@ -942,8 +941,8 @@ void* malloc(size_t bytes) set_foot(remainder, remainder_size); check_malloced_chunk(victim, nb); - UNLOCK; - return chunk2mem(victim); + retval = chunk2mem(victim); + goto DONE; } /* remove from unsorted list */ @@ -955,8 +954,8 @@ void* malloc(size_t bytes) if (size == nb) { set_inuse_bit_at_offset(victim, size); check_malloced_chunk(victim, nb); - UNLOCK; - return chunk2mem(victim); + retval = chunk2mem(victim); + goto DONE; } /* place chunk in bin */ @@ -1019,8 +1018,8 @@ void* malloc(size_t bytes) if (remainder_size < MINSIZE) { set_inuse_bit_at_offset(victim, size); check_malloced_chunk(victim, nb); - UNLOCK; - return chunk2mem(victim); + retval = chunk2mem(victim); + goto DONE; } /* Split */ else { @@ -1031,8 +1030,8 @@ void* malloc(size_t bytes) set_head(remainder, remainder_size | PREV_INUSE); set_foot(remainder, remainder_size); check_malloced_chunk(victim, nb); - UNLOCK; - return chunk2mem(victim); + retval = chunk2mem(victim); + goto DONE; } } } @@ -1100,8 +1099,8 @@ void* malloc(size_t bytes) if (remainder_size < MINSIZE) { set_inuse_bit_at_offset(victim, size); check_malloced_chunk(victim, nb); - UNLOCK; - return chunk2mem(victim); + retval = chunk2mem(victim); + goto DONE; } /* Split */ @@ -1118,8 +1117,8 @@ void* malloc(size_t bytes) set_head(remainder, remainder_size | PREV_INUSE); set_foot(remainder, remainder_size); check_malloced_chunk(victim, nb); - UNLOCK; - return chunk2mem(victim); + retval = chunk2mem(victim); + goto DONE; } } } @@ -1151,13 +1150,15 @@ use_top: set_head(remainder, remainder_size | PREV_INUSE); check_malloced_chunk(victim, nb); - UNLOCK; - return chunk2mem(victim); + retval = chunk2mem(victim); + goto DONE; } /* If no space in top, relay to handle system-dependent cases */ sysmem = __malloc_alloc(nb, av); - UNLOCK; - return sysmem; + retval = sysmem; +DONE: + __MALLOC_UNLOCK; + return retval; } diff --git a/libc/stdlib/malloc-standard/malloc.h b/libc/stdlib/malloc-standard/malloc.h index 556aef4d7..389f1f7d4 100644 --- a/libc/stdlib/malloc-standard/malloc.h +++ b/libc/stdlib/malloc-standard/malloc.h @@ -22,18 +22,17 @@ #include #include #include +#include libc_hidden_proto(mmap) libc_hidden_proto(sysconf) libc_hidden_proto(sbrk) libc_hidden_proto(abort) -#ifdef __UCLIBC_HAS_THREADS__ -# include -extern pthread_mutex_t __malloc_lock; -#endif -#define LOCK __pthread_mutex_lock(&__malloc_lock) -#define UNLOCK __pthread_mutex_unlock(&__malloc_lock) + +__UCLIBC_MUTEX_EXTERN(__malloc_lock); +#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock) +#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock) diff --git a/libc/stdlib/malloc-standard/mallopt.c b/libc/stdlib/malloc-standard/mallopt.c index e28792099..053242dbe 100644 --- a/libc/stdlib/malloc-standard/mallopt.c +++ b/libc/stdlib/malloc-standard/mallopt.c @@ -25,7 +25,7 @@ int mallopt(int param_number, int value) ret = 0; - LOCK; + __MALLOC_LOCK; av = get_malloc_state(); /* Ensure initialization/consolidation */ __malloc_consolidate(av); @@ -58,7 +58,7 @@ int mallopt(int param_number, int value) ret = 1; break; } - UNLOCK; + __MALLOC_UNLOCK; return ret; } diff --git a/libc/stdlib/malloc-standard/memalign.c b/libc/stdlib/malloc-standard/memalign.c index 27502893d..7e0674be5 100644 --- a/libc/stdlib/malloc-standard/memalign.c +++ b/libc/stdlib/malloc-standard/memalign.c @@ -35,6 +35,7 @@ void* memalign(size_t alignment, size_t bytes) mchunkptr remainder; /* spare room at end to split off */ unsigned long remainder_size; /* its size */ size_t size; + void *retval; /* If need less alignment than we give anyway, just relay to malloc */ @@ -51,7 +52,7 @@ void* memalign(size_t alignment, size_t bytes) alignment = a; } - LOCK; + __MALLOC_LOCK; checked_request2size(bytes, nb); /* Strategy: find a spot within that chunk that meets the alignment @@ -63,8 +64,8 @@ void* memalign(size_t alignment, size_t bytes) m = (char*)(malloc(nb + alignment + MINSIZE)); if (m == 0) { - UNLOCK; - return 0; /* propagate failure */ + retval = 0; /* propagate failure */ + goto DONE; } p = mem2chunk(m); @@ -92,8 +93,8 @@ void* memalign(size_t alignment, size_t bytes) if (chunk_is_mmapped(p)) { newp->prev_size = p->prev_size + leadsize; set_head(newp, newsize|IS_MMAPPED); - UNLOCK; - return chunk2mem(newp); + retval = chunk2mem(newp); + goto DONE; } /* Otherwise, give back leader, use the rest */ @@ -120,7 +121,10 @@ void* memalign(size_t alignment, size_t bytes) } check_inuse_chunk(p); - UNLOCK; - return chunk2mem(p); + retval = chunk2mem(p); + + DONE: + __MALLOC_UNLOCK; + return retval; } diff --git a/libc/stdlib/malloc-standard/realloc.c b/libc/stdlib/malloc-standard/realloc.c index f25d6d989..ef436da0d 100644 --- a/libc/stdlib/malloc-standard/realloc.c +++ b/libc/stdlib/malloc-standard/realloc.c @@ -46,6 +46,7 @@ void* realloc(void* oldmem, size_t bytes) size_t* s; /* copy source */ size_t* d; /* copy destination */ + void *retval; /* Check for special cases. */ if (! oldmem) @@ -55,7 +56,7 @@ void* realloc(void* oldmem, size_t bytes) return NULL; } - LOCK; + __MALLOC_LOCK; av = get_malloc_state(); checked_request2size(bytes, nb); @@ -82,8 +83,8 @@ void* realloc(void* oldmem, size_t bytes) set_head_size(oldp, nb); av->top = chunk_at_offset(oldp, nb); set_head(av->top, (newsize - nb) | PREV_INUSE); - UNLOCK; - return chunk2mem(oldp); + retval = chunk2mem(oldp); + goto DONE; } /* Try to expand forward into next chunk; split off remainder below */ @@ -99,8 +100,8 @@ void* realloc(void* oldmem, size_t bytes) else { newmem = malloc(nb - MALLOC_ALIGN_MASK); if (newmem == 0) { - UNLOCK; - return 0; /* propagate failure */ + retval = 0; /* propagate failure */ + goto DONE; } newp = mem2chunk(newmem); @@ -149,8 +150,8 @@ void* realloc(void* oldmem, size_t bytes) free(oldmem); check_inuse_chunk(newp); - UNLOCK; - return chunk2mem(newp); + retval = chunk2mem(newp); + goto DONE; } } } @@ -175,8 +176,8 @@ void* realloc(void* oldmem, size_t bytes) } check_inuse_chunk(newp); - UNLOCK; - return chunk2mem(newp); + retval = chunk2mem(newp); + goto DONE; } /* @@ -194,8 +195,8 @@ void* realloc(void* oldmem, size_t bytes) /* don't need to remap if still within same page */ if (oldsize == newsize - offset) { - UNLOCK; - return oldmem; + retval = oldmem; + goto DONE; } cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1); @@ -216,8 +217,8 @@ void* realloc(void* oldmem, size_t bytes) if (sum > (unsigned long)(av->max_total_mem)) av->max_total_mem = sum; - UNLOCK; - return chunk2mem(newp); + retval = chunk2mem(newp); + goto DONE; } /* Note the extra (sizeof(size_t)) overhead. */ @@ -231,8 +232,11 @@ void* realloc(void* oldmem, size_t bytes) free(oldmem); } } - UNLOCK; - return newmem; + retval = newmem; } + + DONE: + __MALLOC_UNLOCK; + return retval; } -- cgit v1.2.3