diff options
author | jasone <jasone@FreeBSD.org> | 2006-01-12 07:28:21 +0000 |
---|---|---|
committer | jasone <jasone@FreeBSD.org> | 2006-01-12 07:28:21 +0000 |
commit | 3668a2e4940ebe0e7c33729ad375a9a7b0c6ceb1 (patch) | |
tree | 25770955017440672d2cba68e6d8c382b53d9f75 | |
parent | 40e5b400fdbcc7db744cb07d18d2c5dcfdb6fd18 (diff) | |
download | FreeBSD-src-3668a2e4940ebe0e7c33729ad375a9a7b0c6ceb1.zip FreeBSD-src-3668a2e4940ebe0e7c33729ad375a9a7b0c6ceb1.tar.gz |
In preparation for a new malloc implementation:
* Add posix_memalign().
* Move calloc() from calloc.c to malloc.c. Add a calloc() implementation in
rtld-elf in order to make the loader happy (even though calloc() isn't
used in rtld-elf).
* Add _malloc_prefork() and _malloc_postfork(), and use them instead of
directly manipulating __malloc_lock.
Approved by: phk, markm (mentor)
-rw-r--r-- | lib/libc/include/libc_private.h | 7 | ||||
-rw-r--r-- | lib/libc/stdlib/Makefile.inc | 5 | ||||
-rw-r--r-- | lib/libc/stdlib/calloc.c | 61 | ||||
-rw-r--r-- | lib/libc/stdlib/malloc.c | 64 | ||||
-rw-r--r-- | lib/libc/stdlib/posix_memalign.3 | 89 | ||||
-rw-r--r-- | lib/libkse/thread/thr_fork.c | 6 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_fork.c | 6 | ||||
-rw-r--r-- | lib/libthr/thread/thr_fork.c | 14 | ||||
-rw-r--r-- | libexec/rtld-elf/malloc.c | 16 |
9 files changed, 186 insertions, 82 deletions
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h index 8dca7a0..0959c6c 100644 --- a/lib/libc/include/libc_private.h +++ b/lib/libc/include/libc_private.h @@ -130,10 +130,11 @@ void _set_tp(void *tp); extern const char *__progname; /* - * This is the lock to make malloc() thread-safe. It is externalized - * so that thread libraries can protect malloc across fork(). + * These functions are used by the threading libraries in order to protect + * malloc across fork(). */ -extern struct _spinlock *__malloc_lock; +void _malloc_prefork(void); +void _malloc_postfork(void); /* * Function to clean up streams, called from abort() and exit(). diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc index 7883e96..4516637 100644 --- a/lib/libc/stdlib/Makefile.inc +++ b/lib/libc/stdlib/Makefile.inc @@ -5,7 +5,7 @@ .PATH: ${.CURDIR}/${MACHINE_ARCH}/stdlib ${.CURDIR}/stdlib MISRCS+=_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \ - bsearch.c calloc.c div.c exit.c getenv.c getopt.c getopt_long.c \ + bsearch.c div.c exit.c getenv.c getopt.c getopt_long.c \ getsubopt.c grantpt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c \ insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c malloc.c \ merge.c putenv.c qsort.c qsort_r.c radixsort.c rand.c random.c \ @@ -21,7 +21,8 @@ MISRCS+=_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \ MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \ div.3 exit.3 getenv.3 getopt.3 getopt_long.3 getsubopt.3 grantpt.3 \ hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 llabs.3 lldiv.3 \ - lsearch.3 malloc.3 memory.3 qsort.3 radixsort.3 rand.3 random.3 \ + lsearch.3 malloc.3 memory.3 posix_memalign.3 qsort.3 radixsort.3 \ + rand.3 random.3 \ realpath.3 strfmon.3 strtod.3 strtol.3 strtoul.3 system.3 tsearch.3 MLINKS+=a64l.3 l64a.3 a64l.3 l64a_r.3 diff --git a/lib/libc/stdlib/calloc.c b/lib/libc/stdlib/calloc.c deleted file mode 100644 index 9e7850c..0000000 --- a/lib/libc/stdlib/calloc.c +++ /dev/null @@ -1,61 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)calloc.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <errno.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> - -void * -calloc(num, size) - size_t num; - size_t size; -{ - void *p; - - if (size != 0 && SIZE_T_MAX / size < num) { - errno = ENOMEM; - return (NULL); - } - - size *= num; - if ( (p = malloc(size)) ) - bzero(p, size); - return(p); -} diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c index 5fbbe08..65374ea 100644 --- a/lib/libc/stdlib/malloc.c +++ b/lib/libc/stdlib/malloc.c @@ -1150,6 +1150,50 @@ malloc(size_t size) return (pubrealloc(NULL, size, " in malloc():")); } +int +posix_memalign(void **memptr, size_t alignment, size_t size) +{ + int err; + void *result; + + /* Make sure that alignment is a large enough power of 2. */ + if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *)) + return (EINVAL); + + /* + * (size & alignment) is enough to assure the requested alignment, since + * the allocator always allocates power-of-two blocks. + */ + err = errno; /* Protect errno against changes in pubrealloc(). */ + result = pubrealloc(NULL, (size & alignment), " in posix_memalign()"); + errno = err; + + if (result == NULL) + return (ENOMEM); + + *memptr = result; + return (0); +} + +void * +calloc(size_t num, size_t size) +{ + void *ret; + + if (size != 0 && (num * size) / size != num) { + /* size_t overflow. */ + errno = ENOMEM; + return (NULL); + } + + ret = pubrealloc(NULL, num * size, " in calloc():"); + + if (ret != NULL) + memset(ret, 0, num * size); + + return (ret); +} + void free(void *ptr) { @@ -1164,3 +1208,23 @@ realloc(void *ptr, size_t size) return (pubrealloc(ptr, size, " in realloc():")); } +/* + * Begin library-private functions, used by threading libraries for protection + * of malloc during fork(). These functions are only called if the program is + * running in threaded mode, so there is no need to check whether the program + * is threaded here. + */ + +void +_malloc_prefork(void) +{ + + _spinlock(__malloc_lock); +} + +void +_malloc_postfork(void) +{ + + _spinunlock(__malloc_lock); +} diff --git a/lib/libc/stdlib/posix_memalign.3 b/lib/libc/stdlib/posix_memalign.3 new file mode 100644 index 0000000..6de2c4a --- /dev/null +++ b/lib/libc/stdlib/posix_memalign.3 @@ -0,0 +1,89 @@ +.\" Copyright (C) 2006 Jason Evans <jasone@FreeBSD.org>. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice(s), this list of conditions and the following disclaimer as +.\" the first lines of this file unmodified other than the possible +.\" addition of one or more copyright notices. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice(s), this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY +.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +.\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd January 11, 2006 +.Dt POSIX_MEMALIGN 3 +.Os +.Sh NAME +.Nm posix_memalign +.Nd aligned memory allocation +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In stdlib.h +.Ft int +.Fn posix_memalign "void **ptr" "size_t alignment" "size_t size" +.Sh DESCRIPTION +The +.Fn posix_memalign +function allocates +.Fa size +bytes of memory such that the allocation's base address is an even multiple of +.Fa alignment , +and returns the allocation in the value pointed to by +.Fa ptr . +.Pp +The requested +.Fa alignment +must be a power of 2 at least as large as sizeof(void *). +.Pp +Memory that is allocated via +.Fn posix_memalign +can be used as an argument in subsequent calls to +.Xr realloc 3 , +.Xr reallocf 3 , +and +.Xr free 3 . +.Sh RETURN VALUES +The +.Fn posix_memalign +function returns the value 0 if successful; otherwise it returns an error value. +.Sh ERRORS +The +.Fn posix_memalign +function will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The +.Fa alignment +parameter is not a power of 2 at least as large as sizeof(void *). +.It Bq Er ENOMEM +Memory allocation error. +.El +.Sh SEE ALSO +.Xr malloc 3 , +.Xr valloc 3 , +.Xr realloc 3 , +.Xr reallocf 3 , +.Xr free 3 +.Sh STANDARDS +The +.Fn posix_memalign +function conforms to +.St -p1003.1-2001 . diff --git a/lib/libkse/thread/thr_fork.c b/lib/libkse/thread/thr_fork.c index fdbfd86..5445483 100644 --- a/lib/libkse/thread/thr_fork.c +++ b/lib/libkse/thread/thr_fork.c @@ -91,7 +91,7 @@ _fork(void) /* Fork a new process: */ if (_kse_isthreaded() != 0) { - _spinlock(__malloc_lock); + _malloc_prefork(); } if ((ret = __sys_fork()) == 0) { /* Child process */ @@ -107,8 +107,8 @@ _fork(void) } _thr_mutex_reinit(&_thr_atfork_mutex); } else { - if ((_kse_isthreaded() != 0) && (__malloc_lock != NULL)) { - _spinunlock(__malloc_lock); + if (_kse_isthreaded() != 0) { + _malloc_postfork(); } errsave = errno; if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { diff --git a/lib/libpthread/thread/thr_fork.c b/lib/libpthread/thread/thr_fork.c index fdbfd86..5445483 100644 --- a/lib/libpthread/thread/thr_fork.c +++ b/lib/libpthread/thread/thr_fork.c @@ -91,7 +91,7 @@ _fork(void) /* Fork a new process: */ if (_kse_isthreaded() != 0) { - _spinlock(__malloc_lock); + _malloc_prefork(); } if ((ret = __sys_fork()) == 0) { /* Child process */ @@ -107,8 +107,8 @@ _fork(void) } _thr_mutex_reinit(&_thr_atfork_mutex); } else { - if ((_kse_isthreaded() != 0) && (__malloc_lock != NULL)) { - _spinunlock(__malloc_lock); + if (_kse_isthreaded() != 0) { + _malloc_postfork(); } errsave = errno; if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c index 4c222d9..3a6ba51 100644 --- a/lib/libthr/thread/thr_fork.c +++ b/lib/libthr/thread/thr_fork.c @@ -94,12 +94,6 @@ _pthread_atfork(void (*prepare)(void), void (*parent)(void), return (0); } -/* - * For a while, allow libpthread to work with a libc that doesn't - * export the malloc lock. - */ -#pragma weak __malloc_lock - __weak_reference(_fork, fork); pid_t @@ -129,9 +123,9 @@ _fork(void) * child process because another thread in malloc code will * simply be kill by fork(). */ - if ((_thr_isthreaded() != 0) && (__malloc_lock != NULL)) { + if (_thr_isthreaded() != 0) { unlock_malloc = 1; - _spinlock(__malloc_lock); + _malloc_prefork(); } else { unlock_malloc = 0; } @@ -160,7 +154,7 @@ _fork(void) _thr_umtx_init(&_thr_atfork_lock); _thr_setthreaded(0); - /* reinitialize libc spinlocks, this includes __malloc_lock. */ + /* reinitialize libc spinlocks. */ _thr_spinlock_init(); _mutex_fork(curthread); @@ -183,7 +177,7 @@ _fork(void) _thr_signal_unblock(curthread); if (unlock_malloc) - _spinunlock(__malloc_lock); + _malloc_postfork(); /* Run down atfork parent handlers. */ TAILQ_FOREACH(af, &_thr_atfork_list, qe) { diff --git a/libexec/rtld-elf/malloc.c b/libexec/rtld-elf/malloc.c index 2fe69a7..3da5bee 100644 --- a/libexec/rtld-elf/malloc.c +++ b/libexec/rtld-elf/malloc.c @@ -236,6 +236,22 @@ malloc(nbytes) return ((char *)(op + 1)); } +void * +calloc(size_t num, size_t size) +{ + void *ret; + + if (size != 0 && (num * size) / size != num) { + /* size_t overflow. */ + return (NULL); + } + + if ((ret = malloc(num * size)) != NULL) + memset(ret, 0, num * size); + + return (ret); +} + /* * Allocate more memory to the indicated bucket. */ |