summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjasone <jasone@FreeBSD.org>2006-01-12 07:28:21 +0000
committerjasone <jasone@FreeBSD.org>2006-01-12 07:28:21 +0000
commit3668a2e4940ebe0e7c33729ad375a9a7b0c6ceb1 (patch)
tree25770955017440672d2cba68e6d8c382b53d9f75
parent40e5b400fdbcc7db744cb07d18d2c5dcfdb6fd18 (diff)
downloadFreeBSD-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.h7
-rw-r--r--lib/libc/stdlib/Makefile.inc5
-rw-r--r--lib/libc/stdlib/calloc.c61
-rw-r--r--lib/libc/stdlib/malloc.c64
-rw-r--r--lib/libc/stdlib/posix_memalign.389
-rw-r--r--lib/libkse/thread/thr_fork.c6
-rw-r--r--lib/libpthread/thread/thr_fork.c6
-rw-r--r--lib/libthr/thread/thr_fork.c14
-rw-r--r--libexec/rtld-elf/malloc.c16
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.
*/
OpenPOWER on IntegriCloud