summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2007-09-03 14:37:03 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2007-09-03 14:37:03 +0000
commit166c3541d324a24a53c683fea45c202fa80e9a06 (patch)
tree4c818d106319c9d0b7cf9f86df2f457104e623b9
parentce1239c9976aa8f3748a2143bb12a543a27293e4 (diff)
add recaloc(3)
-rw-r--r--include/stdlib.h3
-rw-r--r--lib/libc/stdlib/Makefile.inc4
-rw-r--r--lib/libc/stdlib/malloc.328
-rw-r--r--lib/libc/stdlib/malloc.c50
4 files changed, 64 insertions, 21 deletions
diff --git a/include/stdlib.h b/include/stdlib.h
index 9124a884d0e..bf3a88e05da 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: stdlib.h,v 1.39 2006/09/17 16:48:04 djm Exp $ */
+/* $OpenBSD: stdlib.h,v 1.40 2007/09/03 14:37:02 millert Exp $ */
/* $NetBSD: stdlib.h,v 1.25 1995/12/27 21:19:08 jtc Exp $ */
/*-
@@ -128,6 +128,7 @@ void *malloc(size_t);
void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
int rand(void);
void *realloc(void *, size_t);
+void *recalloc(void *, size_t, size_t);
void srand(unsigned);
double strtod(const char *, char **);
long strtol(const char *, char **, int);
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc
index c7ee0a80ec9..04e84fe9412 100644
--- a/lib/libc/stdlib/Makefile.inc
+++ b/lib/libc/stdlib/Makefile.inc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.inc,v 1.35 2006/01/13 17:58:09 millert Exp $
+# $OpenBSD: Makefile.inc,v 1.36 2007/09/03 14:37:02 millert Exp $
# stdlib sources
.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib
@@ -55,7 +55,7 @@ MLINKS+=insque.3 remque.3
MLINKS+=labs.3 llabs.3
MLINKS+=lsearch.3 lfind.3
MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3
-MLINKS+=malloc.3 cfree.3 malloc.3 malloc.conf.5
+MLINKS+=malloc.3 recalloc.3 malloc.3 cfree.3 malloc.3 malloc.conf.5
MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
MLINKS+=radixsort.3 sradixsort.3
MLINKS+=rand.3 srand.3 rand.3 rand_r.3
diff --git a/lib/libc/stdlib/malloc.3 b/lib/libc/stdlib/malloc.3
index 35f83a0c24c..4c5ea84c08c 100644
--- a/lib/libc/stdlib/malloc.3
+++ b/lib/libc/stdlib/malloc.3
@@ -30,15 +30,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $OpenBSD: malloc.3,v 1.47 2007/08/08 21:24:29 millert Exp $
+.\" $OpenBSD: malloc.3,v 1.48 2007/09/03 14:37:02 millert Exp $
.\"
-.Dd $Mdocdate: August 8 2007 $
+.Dd $Mdocdate: September 3 2007 $
.Dt MALLOC 3
.Os
.Sh NAME
.Nm malloc ,
.Nm calloc ,
.Nm realloc ,
+.Nm recalloc ,
.Nm free ,
.Nm cfree
.Nd memory allocation and deallocation
@@ -50,6 +51,8 @@
.Fn calloc "size_t nmemb" "size_t size"
.Ft void *
.Fn realloc "void *ptr" "size_t size"
+.Ft void *
+.Fn recalloc "void *ptr" "size_t nmemb" "size_t size"
.Ft void
.Fn free "void *ptr"
.Ft void
@@ -203,7 +206,18 @@ if ((newp = realloc(p, num * size)) == NULL) {
...
.Ed
.Pp
-Malloc will first look for a symbolic link called
+The
+.Fn recalloc
+function is similar to
+.Fn realloc
+except that it shares semantics with
+.Fn calloc
+rather than
+.Fn malloc .
+Newly allocated space is initialized to zero and the resulting size is
+checked for integer overflow.
+.Pp
+These functions will first look for a symbolic link called
.Pa /etc/malloc.conf
and next check the environment for a variable called
.Ev MALLOC_OPTIONS
@@ -258,6 +272,8 @@ sizeof(ptr) errors where sizeof(*ptr) is meant.
.Dq realloc .
Always reallocate when
.Fn realloc
+or
+.Fn recalloc
is called, even if the initial allocation was big enough.
This can substantially aid in compacting memory.
.\".Pp
@@ -440,6 +456,12 @@ The
.Fn malloc
function conforms to
.St -ansiC .
+.Pp
+The
+.Fn recalloc
+function is an
+.Ox
+extension.
.Sh HISTORY
The present implementation of
.Fn malloc
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index 67f5de512ef..08b8a088d0d 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: malloc.c,v 1.86 2007/02/12 20:00:14 otto Exp $ */
+/* $OpenBSD: malloc.c,v 1.87 2007/09/03 14:37:02 millert Exp $ */
/*
* ----------------------------------------------------------------------------
@@ -250,9 +250,9 @@ static char *malloc_func;
/*
* Necessary function declarations.
*/
-static void *imalloc(size_t size);
+static void *imalloc(size_t size, int zero_fill);
static void ifree(void *ptr);
-static void *irealloc(void *ptr, size_t size);
+static void *irealloc(void *ptr, size_t size, int zero_fill);
static void *malloc_bytes(size_t size);
static struct pginfo *pginfo_list;
@@ -1188,7 +1188,7 @@ malloc_bytes(size_t size)
* Allocate a piece of memory
*/
static void *
-imalloc(size_t size)
+imalloc(size_t size, int zero_fill)
{
void *result;
int ptralloc = 0;
@@ -1218,7 +1218,7 @@ imalloc(size_t size)
if (malloc_abort == 1 && result == NULL)
wrterror("allocation failed");
- if (malloc_zero && result != NULL)
+ if ((malloc_zero || zero_fill) && result != NULL)
memset(result, 0, size);
if (result && ptralloc)
@@ -1230,7 +1230,7 @@ imalloc(size_t size)
* Change the size of an allocation.
*/
static void *
-irealloc(void *ptr, size_t size)
+irealloc(void *ptr, size_t size, int zero_fill)
{
void *p;
size_t osize;
@@ -1253,7 +1253,7 @@ irealloc(void *ptr, size_t size)
if (size <= PTR_SIZE)
return (ptr);
- p = imalloc(size);
+ p = imalloc(size, zero_fill);
if (p)
memcpy(p, ptr, PTR_SIZE);
ifree(ptr);
@@ -1315,7 +1315,9 @@ irealloc(void *ptr, size_t size)
if (!malloc_realloc && size <= osize &&
size > osize - malloc_pagesize) {
- if (malloc_junk)
+ if (zero_fill)
+ memset((char *)ptr + size, 0, osize - size);
+ else if (malloc_junk)
memset((char *)ptr + size, SOME_JUNK, osize - size);
return (ptr); /* ..don't do anything else. */
}
@@ -1338,7 +1340,9 @@ irealloc(void *ptr, size_t size)
if (!malloc_realloc && size <= osize &&
(size > osize / 2 || osize == malloc_minsize)) {
- if (malloc_junk)
+ if (zero_fill)
+ memset((char *) ptr + size, 0, osize - size);
+ else if (malloc_junk)
memset((char *) ptr + size, SOME_JUNK, osize - size);
return (ptr); /* ..don't do anything else. */
}
@@ -1347,7 +1351,7 @@ irealloc(void *ptr, size_t size)
return (NULL);
}
- p = imalloc(size);
+ p = imalloc(size, zero_fill);
if (p != NULL) {
/* copy the lesser of the two sizes, and free the old one */
@@ -1876,7 +1880,7 @@ malloc(size_t size)
malloc_recurse();
return (NULL);
}
- r = imalloc(size);
+ r = imalloc(size, 0);
UTRACE(0, size, r);
malloc_active--;
_MALLOC_UNLOCK();
@@ -1907,8 +1911,8 @@ free(void *ptr)
return;
}
-void *
-realloc(void *ptr, size_t size)
+static void *
+_realloc(void *ptr, size_t size, int zero_fill)
{
void *r;
@@ -1920,9 +1924,9 @@ realloc(void *ptr, size_t size)
}
if (ptr == NULL)
- r = imalloc(size);
+ r = imalloc(size, zero_fill);
else
- r = irealloc(ptr, size);
+ r = irealloc(ptr, size, zero_fill);
UTRACE(ptr, size, r);
malloc_active--;
@@ -1933,3 +1937,19 @@ realloc(void *ptr, size_t size)
}
return (r);
}
+
+void *
+realloc(void *ptr, size_t size)
+{
+ return (_realloc(ptr, size, 0));
+}
+
+void *
+recalloc(void *ptr, size_t nmemb, size_t size)
+{
+ if (nmemb && SIZE_MAX / nmemb < size) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ return (_realloc(ptr, nmemb * size, 1));
+}