On Mon, Mar 28, 2016 at 03:40:21AM -0600, Abel Abraham Camarillo Ojeda wrote:
> On Mon, Mar 28, 2016 at 3:27 AM, Otto Moerbeek <[email protected]> wrote: > > On Wed, Mar 23, 2016 at 08:00:19AM +0100, Otto Moerbeek wrote: > > > >> Hi, > >> > >> first diff that seems to work. Tested on amd64 and compile tested on > >> sparc64. > >> > >> It is alo available at http://www.drijf.net/openbsd/malloc > >> > >> Form the README: > >> > >> The diff should be applied while in /usr/src/lib, it will patch > >> both librthreads as as well as libc. > >> > >> THIS IS WORK IN PROGRESS. It contains multiple things that should > >> be improved. To name a few things: > >> > >> - Curently fixed at 4 pools with a fixed thread -> pool mapping. > >> - All pools are always initialized, even for single threaded programs, > >> where > >> only one pool is used. > >> - Especially realloc gets quite a bit uglier. > >> - I'm pondering storing the thread -> pool mapping in the thread > >> struct instead of computing it each time from the tcb address. > >> > >> -Otto > >> > > > > Second diff. Only one person (Stefan Kempf, thanks!) gave feedback... > > > > A race condition was fixed in the init code. But there remain race > > problems in the init code. I will be working on that the coming time. > > > > Please be aware that to make this code ready for commit, I need > > feedback/tests/reviews. There's no way this code will end up in the tree > > without those. > > > > Hi Otto, > > anything specific to test or general desktop-browser-use testing is enough? > > thanks No specifics, just watch out for malloc related bugs. It's both important that non-threaded programs and non-threaded programs show no new bugs. -Otto > > > > -Otto > > > > > > Index: libc/include/thread_private.h > > =================================================================== > > RCS file: /cvs/src/lib/libc/include/thread_private.h,v > > retrieving revision 1.26 > > diff -u -p -r1.26 thread_private.h > > --- libc/include/thread_private.h 7 Apr 2015 01:27:07 -0000 1.26 > > +++ libc/include/thread_private.h 28 Mar 2016 08:22:31 -0000 > > @@ -17,6 +17,8 @@ > > */ > > extern int __isthreaded; > > > > +#define _MALLOC_MUTEXES 4 > > + > > /* > > * Weak symbols are used in libc so that the thread library can > > * efficiently wrap libc functions. > > @@ -136,16 +138,16 @@ extern void *__THREAD_NAME(serv_mutex); > > /* > > * malloc lock/unlock prototypes and definitions > > */ > > -void _thread_malloc_lock(void); > > -void _thread_malloc_unlock(void); > > +void _thread_malloc_lock(int); > > +void _thread_malloc_unlock(int); > > > > -#define _MALLOC_LOCK() do { \ > > +#define _MALLOC_LOCK(n) do { > > \ > > if (__isthreaded) \ > > - _thread_malloc_lock(); \ > > + _thread_malloc_lock(n); \ > > } while (0) > > -#define _MALLOC_UNLOCK() do { \ > > +#define _MALLOC_UNLOCK(n) do { \ > > if (__isthreaded) \ > > - _thread_malloc_unlock();\ > > + _thread_malloc_unlock(n);\ > > } while (0) > > > > void _thread_atexit_lock(void); > > Index: libc/stdlib/malloc.c > > =================================================================== > > RCS file: /cvs/src/lib/libc/stdlib/malloc.c,v > > retrieving revision 1.185 > > diff -u -p -r1.185 malloc.c > > --- libc/stdlib/malloc.c 17 Mar 2016 17:55:33 -0000 1.185 > > +++ libc/stdlib/malloc.c 28 Mar 2016 08:22:31 -0000 > > @@ -1,6 +1,6 @@ > > /* $OpenBSD: malloc.c,v 1.185 2016/03/17 17:55:33 mmcc Exp $ */ > > /* > > - * Copyright (c) 2008, 2010, 2011 Otto Moerbeek <[email protected]> > > + * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <[email protected]> > > * Copyright (c) 2012 Matthew Dempsky <[email protected]> > > * Copyright (c) 2008 Damien Miller <[email protected]> > > * Copyright (c) 2000 Poul-Henning Kamp <[email protected]> > > @@ -43,6 +43,7 @@ > > #endif > > > > #include "thread_private.h" > > +#include <machine/tcb.h> > > > > #if defined(__sparc__) && !defined(__sparcv9__) > > #define MALLOC_PAGESHIFT (13U) > > @@ -95,10 +96,10 @@ > > > > #define _MALLOC_LEAVE(d) do { if (__isthreaded) { \ > > (d)->active--; \ > > - _MALLOC_UNLOCK(); } \ > > + _MALLOC_UNLOCK(d->mutex); } \ > > } while (0) > > #define _MALLOC_ENTER(d) do { if (__isthreaded) { \ > > - _MALLOC_LOCK(); \ > > + _MALLOC_LOCK(d->mutex); \ > > (d)->active++; } \ > > } while (0) > > > > @@ -129,6 +130,7 @@ struct dir_info { > > void *delayed_chunks[MALLOC_DELAYED_CHUNK_MASK + 1]; > > size_t rbytesused; /* random bytes used */ > > char *func; /* current function */ > > + int mutex; > > u_char rbytes[32]; /* random bytes */ > > u_short chunk_start; > > #ifdef MALLOC_STATS > > @@ -178,7 +180,7 @@ struct chunk_info { > > }; > > > > struct malloc_readonly { > > - struct dir_info *malloc_pool; /* Main bookkeeping information */ > > + struct dir_info *malloc_pool[_MALLOC_MUTEXES]; /* Main bookkeeping > > information */ > > int malloc_freenow; /* Free quickly - disable chunk rnd > > */ > > int malloc_freeunmap; /* mprotect free pages PROT_NONE? */ > > int malloc_hint; /* call madvice on free pages? */ > > @@ -202,14 +204,13 @@ static union { > > u_char _pad[MALLOC_PAGESIZE]; > > } malloc_readonly __attribute__((aligned(MALLOC_PAGESIZE))); > > #define mopts malloc_readonly.mopts > > -#define getpool() mopts.malloc_pool > > > > char *malloc_options; /* compile-time options */ > > > > static u_char getrbyte(struct dir_info *d); > > > > #ifdef MALLOC_STATS > > -void malloc_dump(int); > > +void malloc_dump(int, struct dir_info *); > > PROTO_NORMAL(malloc_dump); > > static void malloc_exit(void); > > #define CALLER __builtin_return_address(0) > > @@ -240,6 +241,18 @@ hash(void *p) > > return sum; > > } > > > > +static inline > > +struct dir_info *getpool(void) > > +{ > > + //return mopts.malloc_pool[0]; > > + if (!__isthreaded) > > + return mopts.malloc_pool[0]; > > + else > > + return mopts.malloc_pool[hash(TCB_GET()) & > > + (_MALLOC_MUTEXES - 1)]; > > +} > > + > > + > > static void > > wrterror(struct dir_info *d, char *msg, void *p) > > { > > @@ -247,7 +260,7 @@ wrterror(struct dir_info *d, char *msg, > > struct iovec iov[7]; > > char pidbuf[20]; > > char buf[20]; > > - int saved_errno = errno; > > + int saved_errno = errno, i; > > > > iov[0].iov_base = __progname; > > iov[0].iov_len = strlen(__progname); > > @@ -278,7 +291,8 @@ wrterror(struct dir_info *d, char *msg, > > > > #ifdef MALLOC_STATS > > if (mopts.malloc_stats) > > - malloc_dump(STDERR_FILENO); > > + for (i = 0; i < _MALLOC_MUTEXES; i++) > > + malloc_dump(STDERR_FILENO, mopts.malloc_pool[i]); > > #endif /* MALLOC_STATS */ > > > > errno = saved_errno; > > @@ -565,16 +579,11 @@ omalloc_parseopt(char opt) > > } > > } > > > > -/* > > - * Initialize a dir_info, which should have been cleared by caller > > - */ > > -static int > > -omalloc_init(struct dir_info **dp) > > +static void > > +omalloc_init(void) > > { > > char *p, *q, b[64]; > > int i, j; > > - size_t d_avail, regioninfo_size; > > - struct dir_info *d; > > > > /* > > * Default options > > @@ -637,6 +646,18 @@ omalloc_init(struct dir_info **dp) > > > > arc4random_buf(&mopts.malloc_chunk_canary, > > sizeof(mopts.malloc_chunk_canary)); > > +} > > + > > +/* > > + * Initialize a dir_info, which should have been cleared by caller > > + */ > > +static int > > +omalloc_poolinit(struct dir_info **dp) > > +{ > > + void *p; > > + size_t d_avail, regioninfo_size; > > + struct dir_info *d; > > + int i, j; > > > > /* > > * Allocate dir_info with a guard page on either side. Also > > @@ -644,7 +665,7 @@ omalloc_init(struct dir_info **dp) > > * lies (subject to alignment by 1 << MALLOC_MINSHIFT) > > */ > > if ((p = MMAP(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED) > > - return -1; > > + return 1; > > mprotect(p, MALLOC_PAGESIZE, PROT_NONE); > > mprotect(p + MALLOC_PAGESIZE + DIR_INFO_RSZ, > > MALLOC_PAGESIZE, PROT_NONE); > > @@ -672,13 +693,6 @@ omalloc_init(struct dir_info **dp) > > > > *dp = d; > > > > - /* > > - * Options have been set and will never be reset. > > - * Prevent further tampering with them. > > - */ > > - if (((uintptr_t)&malloc_readonly & MALLOC_PAGEMASK) == 0) > > - mprotect(&malloc_readonly, sizeof(malloc_readonly), > > PROT_READ); > > - > > return 0; > > } > > > > @@ -1174,20 +1188,41 @@ malloc_recurse(struct dir_info *d) > > wrterror(d, "recursive call", NULL); > > } > > d->active--; > > - _MALLOC_UNLOCK(); > > + _MALLOC_UNLOCK(d->mutex); > > errno = EDEADLK; > > } > > > > static int > > malloc_init(void) > > { > > - if (omalloc_init(&mopts.malloc_pool)) { > > - _MALLOC_UNLOCK(); > > - if (mopts.malloc_xmalloc) > > - wrterror(NULL, "out of memory", NULL); > > - errno = ENOMEM; > > - return -1; > > + int i; > > + struct dir_info *d; > > + > > + _MALLOC_LOCK(0); > > + if (mopts.malloc_pool[0]) { > > + _MALLOC_UNLOCK(0); > > + return 0; > > + } > > + omalloc_init(); > > + for (i = 0; i < _MALLOC_MUTEXES; i++) { > > + if (omalloc_poolinit(&d)) { > > + _MALLOC_UNLOCK(0); > > + if (mopts.malloc_xmalloc) > > + wrterror(NULL, "out of memory", NULL); > > + errno = ENOMEM; > > + return -1; > > + } > > + d->mutex = i; > > + mopts.malloc_pool[i] = d; > > } > > + > > + /* > > + * Options have been set and will never be reset. > > + * Prevent further tampering with them. > > + */ > > + if (((uintptr_t)&malloc_readonly & MALLOC_PAGEMASK) == 0) > > + mprotect(&malloc_readonly, sizeof(malloc_readonly), > > PROT_READ); > > + _MALLOC_UNLOCK(0); > > return 0; > > } > > > > @@ -1198,13 +1233,13 @@ malloc(size_t size) > > struct dir_info *d; > > int saved_errno = errno; > > > > - _MALLOC_LOCK(); > > d = getpool(); > > if (d == NULL) { > > if (malloc_init() != 0) > > return NULL; > > d = getpool(); > > } > > + _MALLOC_LOCK(d->mutex); > > d->func = "malloc():"; > > > > if (d->active++) { > > @@ -1215,7 +1250,7 @@ malloc(size_t size) > > size += mopts.malloc_canaries; > > r = omalloc(d, size, 0, CALLER); > > d->active--; > > - _MALLOC_UNLOCK(); > > + _MALLOC_UNLOCK(d->mutex); > > if (r == NULL && mopts.malloc_xmalloc) { > > wrterror(d, "out of memory", NULL); > > errno = ENOMEM; > > @@ -1252,23 +1287,41 @@ validate_junk(struct dir_info *pool, voi > > } > > > > static void > > -ofree(struct dir_info *pool, void *p) > > +ofree(struct dir_info *argpool, void *p) > > { > > + struct dir_info *pool; > > struct region_info *r; > > size_t sz; > > + int i; > > > > + pool = argpool; > > r = find(pool, p); > > if (r == NULL) { > > - wrterror(pool, "bogus pointer (double free?)", p); > > - return; > > + for (i = 0; i < _MALLOC_MUTEXES; i++) { > > + if (i == pool->mutex) > > + continue; > > + pool->active--; > > + _MALLOC_UNLOCK(pool->mutex); > > + pool = mopts.malloc_pool[i]; > > + _MALLOC_LOCK(pool->mutex); > > + pool->active++; > > + r = find(pool, p); > > + if (r != NULL) > > + break; > > + } > > + if (r == NULL) { > > + wrterror(pool, "bogus pointer (double free?)", p); > > + goto done; > > + } > > } > > + > > REALSIZE(sz, r); > > if (sz > MALLOC_MAXCHUNK) { > > if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE - > > MALLOC_LEEWAY) { > > if (r->p != p) { > > wrterror(pool, "bogus pointer", p); > > - return; > > + goto done; > > } > > } else { > > #if notyetbecause_of_realloc > > @@ -1306,13 +1359,13 @@ ofree(struct dir_info *pool, void *p) > > memset(p, SOME_FREEJUNK, sz - > > mopts.malloc_canaries); > > if (!mopts.malloc_freenow) { > > if (find_chunknum(pool, r, p) == -1) > > - return; > > + goto done; > > i = getrbyte(pool) & MALLOC_DELAYED_CHUNK_MASK; > > tmp = p; > > p = pool->delayed_chunks[i]; > > if (tmp == p) { > > wrterror(pool, "double free", p); > > - return; > > + goto done; > > } > > if (mopts.malloc_junk) > > validate_junk(pool, p); > > @@ -1322,11 +1375,18 @@ ofree(struct dir_info *pool, void *p) > > r = find(pool, p); > > if (r == NULL) { > > wrterror(pool, "bogus pointer (double > > free?)", p); > > - return; > > + goto done; > > } > > free_bytes(pool, r, p); > > } > > } > > +done: > > + if (argpool != pool) { > > + pool->active--; > > + _MALLOC_UNLOCK(pool->mutex); > > + _MALLOC_LOCK(argpool->mutex); > > + argpool->active++; > > + } > > } > > > > void > > @@ -1339,13 +1399,12 @@ free(void *ptr) > > if (ptr == NULL) > > return; > > > > - _MALLOC_LOCK(); > > d = getpool(); > > if (d == NULL) { > > - _MALLOC_UNLOCK(); > > wrterror(d, "free() called before allocation", NULL); > > return; > > } > > + _MALLOC_LOCK(d->mutex); > > d->func = "free():"; > > if (d->active++) { > > malloc_recurse(d); > > @@ -1353,30 +1412,50 @@ free(void *ptr) > > } > > ofree(d, ptr); > > d->active--; > > - _MALLOC_UNLOCK(); > > + _MALLOC_UNLOCK(d->mutex); > > errno = saved_errno; > > } > > /*DEF_STRONG(free);*/ > > > > > > static void * > > -orealloc(struct dir_info *pool, void *p, size_t newsz, void *f) > > +orealloc(struct dir_info *argpool, void *p, size_t newsz, void *f) > > { > > + struct dir_info *pool; > > struct region_info *r; > > size_t oldsz, goldsz, gnewsz; > > - void *q; > > + void *q, *ret; > > + int i; > > + > > + pool = argpool; > > > > if (p == NULL) > > return omalloc(pool, newsz, 0, f); > > > > r = find(pool, p); > > if (r == NULL) { > > - wrterror(pool, "bogus pointer (double free?)", p); > > - return NULL; > > + for (i = 0; i < _MALLOC_MUTEXES; i++) { > > + if (i == pool->mutex) > > + continue; > > + pool->active--; > > + _MALLOC_UNLOCK(pool->mutex); > > + pool = mopts.malloc_pool[i]; > > + _MALLOC_LOCK(pool->mutex); > > + pool->active++; > > + r = find(pool, p); > > + if (r != NULL) > > + break; > > + } > > + if (r == NULL) { > > + wrterror(pool, "bogus pointer (double free?)", p); > > + ret = NULL; > > + goto done; > > + } > > } > > if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) { > > errno = ENOMEM; > > - return NULL; > > + ret = NULL; > > + goto done; > > } > > > > REALSIZE(oldsz, r); > > @@ -1419,7 +1498,8 @@ gotit: > > r->size = newsz; > > STATS_SETF(r, f); > > STATS_INC(pool->cheap_reallocs); > > - return p; > > + ret = p; > > + goto done; > > } else if (q != MAP_FAILED) { > > if (munmap(q, needed)) > > wrterror(pool, "munmap", q); > > @@ -1439,14 +1519,16 @@ gotit: > > unmap(pool, (char *)p + rnewsz, roldsz - rnewsz); > > r->size = gnewsz; > > STATS_SETF(r, f); > > - return p; > > + ret = p; > > + goto done; > > } else { > > if (newsz > oldsz && mopts.malloc_junk == 2) > > memset((char *)p + newsz, SOME_JUNK, > > rnewsz - mopts.malloc_guard - newsz); > > r->size = gnewsz; > > STATS_SETF(r, f); > > - return p; > > + ret = p; > > + goto done; > > } > > } > > if (newsz <= oldsz && newsz > oldsz / 2 && !mopts.malloc_realloc) { > > @@ -1458,11 +1540,13 @@ gotit: > > memset((char *)p + newsz, SOME_JUNK, > > usable_oldsz - newsz); > > } > > STATS_SETF(r, f); > > - return p; > > + ret = p; > > } else if (newsz != oldsz || mopts.malloc_realloc) { > > q = omalloc(pool, newsz, 0, f); > > - if (q == NULL) > > - return NULL; > > + if (q == NULL) { > > + ret = NULL; > > + goto done; > > + } > > if (newsz != 0 && oldsz != 0) { > > size_t copysz = oldsz < newsz ? oldsz : newsz; > > if (copysz <= MALLOC_MAXCHUNK) > > @@ -1470,11 +1554,19 @@ gotit: > > memcpy(q, p, copysz); > > } > > ofree(pool, p); > > - return q; > > + ret = q; > > } else { > > STATS_SETF(r, f); > > - return p; > > + ret = p; > > + } > > +done: > > + if (argpool != pool) { > > + pool->active--; > > + _MALLOC_UNLOCK(pool->mutex); > > + _MALLOC_LOCK(argpool->mutex); > > + argpool->active++; > > } > > + return ret; > > } > > > > void * > > @@ -1484,13 +1576,13 @@ realloc(void *ptr, size_t size) > > void *r; > > int saved_errno = errno; > > > > - _MALLOC_LOCK(); > > d = getpool(); > > if (d == NULL) { > > if (malloc_init() != 0) > > return NULL; > > d = getpool(); > > } > > + _MALLOC_LOCK(d->mutex); > > d->func = "realloc():"; > > if (d->active++) { > > malloc_recurse(d); > > @@ -1501,7 +1593,7 @@ realloc(void *ptr, size_t size) > > r = orealloc(d, ptr, size, CALLER); > > > > d->active--; > > - _MALLOC_UNLOCK(); > > + _MALLOC_UNLOCK(d->mutex); > > if (r == NULL && mopts.malloc_xmalloc) { > > wrterror(d, "out of memory", NULL); > > errno = ENOMEM; > > @@ -1526,17 +1618,17 @@ calloc(size_t nmemb, size_t size) > > void *r; > > int saved_errno = errno; > > > > - _MALLOC_LOCK(); > > d = getpool(); > > if (d == NULL) { > > if (malloc_init() != 0) > > return NULL; > > d = getpool(); > > } > > + _MALLOC_LOCK(d->mutex); > > d->func = "calloc():"; > > if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && > > nmemb > 0 && SIZE_MAX / nmemb < size) { > > - _MALLOC_UNLOCK(); > > + _MALLOC_UNLOCK(d->mutex); > > if (mopts.malloc_xmalloc) > > wrterror(d, "out of memory", NULL); > > errno = ENOMEM; > > @@ -1554,7 +1646,7 @@ calloc(size_t nmemb, size_t size) > > r = omalloc(d, size, 1, CALLER); > > > > d->active--; > > - _MALLOC_UNLOCK(); > > + _MALLOC_UNLOCK(d->mutex); > > if (r == NULL && mopts.malloc_xmalloc) { > > wrterror(d, "out of memory", NULL); > > errno = ENOMEM; > > @@ -1668,13 +1760,13 @@ posix_memalign(void **memptr, size_t ali > > if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void > > *)) > > return EINVAL; > > > > - _MALLOC_LOCK(); > > d = getpool(); > > if (d == NULL) { > > if (malloc_init() != 0) > > goto err; > > d = getpool(); > > } > > + _MALLOC_LOCK(d->mutex); > > d->func = "posix_memalign():"; > > if (d->active++) { > > malloc_recurse(d); > > @@ -1684,7 +1776,7 @@ posix_memalign(void **memptr, size_t ali > > size += mopts.malloc_canaries; > > r = omemalign(d, alignment, size, 0, CALLER); > > d->active--; > > - _MALLOC_UNLOCK(); > > + _MALLOC_UNLOCK(d->mutex); > > if (r == NULL) { > > if (mopts.malloc_xmalloc) { > > wrterror(d, "out of memory", NULL); > > @@ -1923,9 +2015,8 @@ malloc_dump1(int fd, struct dir_info *d) > > } > > > > void > > -malloc_dump(int fd) > > +malloc_dump(int fd, struct dir_info *pool) > > { > > - struct dir_info *pool = getpool(); > > int i; > > void *p; > > struct region_info *r; > > @@ -1956,11 +2047,12 @@ static void > > malloc_exit(void) > > { > > static const char q[] = "malloc() warning: Couldn't dump stats\n"; > > - int save_errno = errno, fd; > > + int save_errno = errno, fd, i; > > > > fd = open("malloc.out", O_RDWR|O_APPEND); > > if (fd != -1) { > > - malloc_dump(fd); > > + for (i = 0; i < _MALLOC_MUTEXES; i++) > > + malloc_dump(fd, mopts.malloc_pool[i]); > > close(fd); > > } else > > write(STDERR_FILENO, q, sizeof(q) - 1); > > Index: libc/thread/unithread_malloc_lock.c > > =================================================================== > > RCS file: /cvs/src/lib/libc/thread/unithread_malloc_lock.c,v > > retrieving revision 1.9 > > diff -u -p -r1.9 unithread_malloc_lock.c > > --- libc/thread/unithread_malloc_lock.c 7 Apr 2015 01:27:07 -0000 1.9 > > +++ libc/thread/unithread_malloc_lock.c 28 Mar 2016 08:22:31 -0000 > > @@ -28,13 +28,13 @@ WEAK_ALIAS(_thread_arc4_lock); > > WEAK_ALIAS(_thread_arc4_unlock); > > > > void > > -WEAK_NAME(_thread_malloc_lock)(void) > > +WEAK_NAME(_thread_malloc_lock)(int n) > > { > > return; > > } > > > > void > > -WEAK_NAME(_thread_malloc_unlock)(void) > > +WEAK_NAME(_thread_malloc_unlock)(int n) > > { > > return; > > } > > Index: librthread/rthread_fork.c > > =================================================================== > > RCS file: /cvs/src/lib/librthread/rthread_fork.c,v > > retrieving revision 1.15 > > diff -u -p -r1.15 rthread_fork.c > > --- librthread/rthread_fork.c 27 Jan 2016 08:40:05 -0000 1.15 > > +++ librthread/rthread_fork.c 28 Mar 2016 08:22:31 -0000 > > @@ -55,6 +55,7 @@ _dofork(int is_vfork) > > pthread_t me; > > pid_t (*sys_fork)(void); > > pid_t newid; > > + int i; > > > > sys_fork = is_vfork ? &_thread_sys_vfork : &_thread_sys_fork; > > > > @@ -76,7 +77,8 @@ _dofork(int is_vfork) > > #endif > > > > _thread_atexit_lock(); > > - _thread_malloc_lock(); > > + for (i = 0; i < _MALLOC_MUTEXES; i++) > > + _thread_malloc_lock(i); > > _thread_arc4_lock(); > > > > newid = sys_fork(); > > @@ -85,7 +87,8 @@ _dofork(int is_vfork) > > if (newid == 0) > > _thread_malloc_reinit(); > > else > > - _thread_malloc_unlock(); > > + for (i = 0; i < _MALLOC_MUTEXES; i++) > > + _thread_malloc_unlock(i); > > _thread_atexit_unlock(); > > > > if (newid == 0) { > > Index: librthread/rthread_libc.c > > =================================================================== > > RCS file: /cvs/src/lib/librthread/rthread_libc.c,v > > retrieving revision 1.13 > > diff -u -p -r1.13 rthread_libc.c > > --- librthread/rthread_libc.c 27 Jan 2016 08:40:05 -0000 1.13 > > +++ librthread/rthread_libc.c 28 Mar 2016 08:22:31 -0000 > > @@ -152,35 +152,50 @@ _thread_mutex_destroy(void **mutex) > > /* > > * the malloc lock > > */ > > -static struct pthread_mutex malloc_lock = { > > - _SPINLOCK_UNLOCKED, > > - TAILQ_HEAD_INITIALIZER(malloc_lock.lockers), > > - PTHREAD_MUTEX_DEFAULT, > > - NULL, > > - 0, > > - -1 > > +#define MALLOC_LOCK_INITIALZER(n) { \ > > + _SPINLOCK_UNLOCKED, \ > > + TAILQ_HEAD_INITIALIZER(malloc_lock[n].lockers), \ > > + PTHREAD_MUTEX_DEFAULT, \ > > + NULL, \ > > + 0, \ > > + -1 } \ > > + > > +static struct pthread_mutex malloc_lock[_MALLOC_MUTEXES] = { > > + MALLOC_LOCK_INITIALZER(0), > > + MALLOC_LOCK_INITIALZER(1), > > + MALLOC_LOCK_INITIALZER(2), > > + MALLOC_LOCK_INITIALZER(3) > > +}; > > +static pthread_mutex_t malloc_mutex[_MALLOC_MUTEXES] = { > > + &malloc_lock[0], > > + &malloc_lock[1], > > + &malloc_lock[2], > > + &malloc_lock[3] > > }; > > -static pthread_mutex_t malloc_mutex = &malloc_lock; > > > > void > > -_thread_malloc_lock(void) > > +_thread_malloc_lock(int i) > > { > > - pthread_mutex_lock(&malloc_mutex); > > + pthread_mutex_lock(&malloc_mutex[i]); > > } > > > > void > > -_thread_malloc_unlock(void) > > +_thread_malloc_unlock(int i) > > { > > - pthread_mutex_unlock(&malloc_mutex); > > + pthread_mutex_unlock(&malloc_mutex[i]); > > } > > > > void > > _thread_malloc_reinit(void) > > { > > - malloc_lock.lock = _SPINLOCK_UNLOCKED_ASSIGN; > > - TAILQ_INIT(&malloc_lock.lockers); > > - malloc_lock.owner = NULL; > > - malloc_lock.count = 0; > > + int i; > > + > > + for (i = 0; i < _MALLOC_MUTEXES; i++) { > > + malloc_lock[i].lock = _SPINLOCK_UNLOCKED_ASSIGN; > > + TAILQ_INIT(&malloc_lock[i].lockers); > > + malloc_lock[i].owner = NULL; > > + malloc_lock[i].count = 0; > > + } > > } > > > > /* > >
