summaryrefslogtreecommitdiff
path: root/libc/stdlib/malloc-standard
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2006-12-07 23:24:02 +0000
committerEric Andersen <andersen@codepoet.org>2006-12-07 23:24:02 +0000
commit1478c2de052374c6356db5513749a144c13791b1 (patch)
tree3b22a3f8361f94c99508c497e240ecb71acf8641 /libc/stdlib/malloc-standard
parent99d6c367c4820a072dc4ada51561df17e2093778 (diff)
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.
Diffstat (limited to 'libc/stdlib/malloc-standard')
-rw-r--r--libc/stdlib/malloc-standard/calloc.c4
-rw-r--r--libc/stdlib/malloc-standard/free.c4
-rw-r--r--libc/stdlib/malloc-standard/mallinfo.c45
-rw-r--r--libc/stdlib/malloc-standard/malloc.c51
-rw-r--r--libc/stdlib/malloc-standard/malloc.h11
-rw-r--r--libc/stdlib/malloc-standard/mallopt.c4
-rw-r--r--libc/stdlib/malloc-standard/memalign.c18
-rw-r--r--libc/stdlib/malloc-standard/realloc.c34
8 files changed, 98 insertions, 73 deletions
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 <malloc.h>
#include <stdlib.h>
#include <sys/mman.h>
+#include <bits/uClibc_mutex.h>
libc_hidden_proto(mmap)
libc_hidden_proto(sysconf)
libc_hidden_proto(sbrk)
libc_hidden_proto(abort)
-#ifdef __UCLIBC_HAS_THREADS__
-# include <pthread.h>
-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;
}