summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdlib/malloc.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1997-06-22 17:54:27 +0000
committerphk <phk@FreeBSD.org>1997-06-22 17:54:27 +0000
commite682320b6b4ec6dadaaa13a6cbeb428242eac686 (patch)
tree15d9e10f5c4d9600616dea47bc017c23b30b8df4 /lib/libc/stdlib/malloc.c
parent711f7235a180f520b0c1eb667d0519ae5792bdfa (diff)
downloadFreeBSD-src-e682320b6b4ec6dadaaa13a6cbeb428242eac686.zip
FreeBSD-src-e682320b6b4ec6dadaaa13a6cbeb428242eac686.tar.gz
Integrate calloc with the rest of the gang.
Various portability and stylistic cleanups. Kill MALLOC_STATS & the 'D' option. Fix the 'V' option. Major overhaul of the man-page. You milage should not vary. Reviewed by: Keith Bostic <bostic@bostic.com> Submitted by: Keith Bostic <bostic@bostic.com>
Diffstat (limited to 'lib/libc/stdlib/malloc.c')
-rw-r--r--lib/libc/stdlib/malloc.c243
1 files changed, 93 insertions, 150 deletions
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index 446f55d..fb770f5 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
- * $Id: malloc.c,v 1.24 1997/06/04 12:55:49 jb Exp $
+ * $Id: malloc.c,v 1.25 1997/06/12 12:45:45 phk Exp $
*
*/
@@ -22,15 +22,6 @@
#endif
/*
- * Defining MALLOC_STATS will enable you to call malloc_dump() and set
- * the [dD] options in the MALLOC_OPTIONS environment variable.
- * It has no run-time performance hit.
- */
-#ifndef MALLOC_STATS
-#undef MALLOC_STATS
-#endif
-
-/*
* What to use for Junk. This is the byte value we use to fill with
* when the 'J' option is enabled.
*/
@@ -41,7 +32,7 @@
*
* malloc_pageshift pagesize = 1 << malloc_pageshift
* It's probably best if this is the native
- * page size, but it shouldn't have to be.
+ * page size, but it doesn't have to be.
*
* malloc_minsize minimum size of an allocation in bytes.
* If this is too small it's too much work
@@ -51,16 +42,31 @@
*
*/
-#if defined(__i386__) && defined(__FreeBSD__)
-# define malloc_pageshift 12U
-# define malloc_minsize 16U
-#endif /* __i386__ && __FreeBSD__ */
-
-#if defined(__sparc__)
+#if defined(__FreeBSD__)
+# if defined(__i386__)
+# define malloc_pageshift 12U
+# define malloc_minsize 16U
+# endif
+# define HAS_UTRACE
+# if defined(_THREAD_SAFE)
+# include <pthread.h>
+# include "pthread_private.h"
+# define THREAD_LOCK() pthread_mutex_lock(&malloc_lock)
+# define THREAD_UNLOCK() pthread_mutex_unlock(&malloc_lock)
+ static struct pthread_mutex _malloc_lock = PTHREAD_MUTEX_INITIALIZER;
+ static pthread_mutex_t malloc_lock = &_malloc_lock;
+# endif
+#endif /* __FreeBSD__ */
+
+#if defined(__sparc__) || defined(sun)
# define malloc_pageshirt 12U
# define malloc_minsize 16U
# define MAP_ANON (0)
-# define USE_DEV_ZERO
+ static int fdzero;
+# define MMAP_FD fdzero
+# define INIT_MMAP() \
+ { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \
+ wrterror("open of /dev/zero"); }
# define MADV_FREE MADV_DONTNEED
#endif /* __sparc__ */
@@ -68,31 +74,20 @@
#if defined(__FOOCPU__) && defined(__BAROS__)
# define malloc_pageshift 12U
# define malloc_minsize 16U
-#endif /* __i386__ && __FreeBSD__ */
-
-#ifdef _THREAD_SAFE
-#include <pthread.h>
-#include "pthread_private.h"
-static struct pthread_mutex _malloc_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t malloc_lock = &_malloc_lock;
-#define THREAD_LOCK() pthread_mutex_lock(&malloc_lock)
-#define THREAD_UNLOCK() pthread_mutex_unlock(&malloc_lock)
-#else
-#define THREAD_LOCK()
-#define THREAD_UNLOCK()
-#endif
+#endif /* __FOORCPU__ && __BAROS__ */
+
/*
* No user serviceable parts behind this point.
*/
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/mman.h>
/*
* This structure describes a page worth of chunks.
@@ -117,7 +112,7 @@ struct pgfree {
struct pgfree *prev; /* prev run of free pages */
void *page; /* pointer to free pages */
void *end; /* pointer to end of free pages */
- u_long size; /* number of bytes free */
+ size_t size; /* number of bytes free */
};
/*
@@ -143,10 +138,6 @@ struct pgfree {
#define malloc_minsize 16U
#endif
-#ifndef malloc_pageshift
-#error "malloc_pageshift undefined"
-#endif
-
#if !defined(malloc_pagesize)
#define malloc_pagesize (1U<<malloc_pageshift)
#endif
@@ -165,21 +156,28 @@ struct pgfree {
#define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask)))
#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo)
-/* fd of /dev/zero */
-#ifdef USE_DEV_ZERO
-static int fdzero;
-#define MMAP_FD fdzero
-#define INIT_MMAP() \
- { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \
- wrterror("open of /dev/zero"); }
-#else
+#ifndef THREAD_LOCK
+#define THREAD_LOCK()
+#endif
+
+#ifndef THREAD_UNLOCK
+#define THREAD_UNLOCK()
+#endif
+
+#ifndef MMAP_FD
#define MMAP_FD (-1)
+#endif
+
+#ifndef INIT_MMAP
#define INIT_MMAP()
#endif
/* Set when initialization has been done */
static unsigned malloc_started;
+/* Recusion flag for public interface. */
+static int malloc_active;
+
/* Number of free pages we cache */
static unsigned malloc_cache = 16;
@@ -204,9 +202,6 @@ static int malloc_abort;
/* Are we trying to die ? */
static int suicide;
-/* dump statistics */
-static int malloc_stats;
-
/* always realloc ? */
static int malloc_realloc;
@@ -228,7 +223,7 @@ static int malloc_junk;
/* utrace ? */
static int malloc_utrace;
-#ifdef __FreeBSD__
+#ifdef HAS_UTRACE
struct ut { void *p; size_t s; void *r; };
void utrace __P((struct ut *, int));
@@ -236,7 +231,7 @@ void utrace __P((struct ut *, int));
#define UTRACE(a, b, c) \
if (malloc_utrace) \
{struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
-#else /* !__FreeBSD__ */
+#else /* !HAS_UTRACE */
#define UTRACE(a,b,c)
#endif
@@ -265,79 +260,17 @@ static void *imalloc(size_t size);
static void ifree(void *ptr);
static void *irealloc(void *ptr, size_t size);
-#ifdef MALLOC_STATS
-void
-malloc_dump(FILE *fd)
-{
- struct pginfo **pd;
- struct pgfree *pf;
- int j;
-
- pd = page_dir;
-
- /* print out all the pages */
- for(j=0;j<=last_index;j++) {
- fprintf(fd, "%08lx %5d ", (j+malloc_origo) << malloc_pageshift, j);
- if (pd[j] == MALLOC_NOT_MINE) {
- for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++)
- ;
- j--;
- fprintf(fd, ".. %5d not mine\n", j);
- } else if (pd[j] == MALLOC_FREE) {
- for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++)
- ;
- j--;
- fprintf(fd, ".. %5d free\n", j);
- } else if (pd[j] == MALLOC_FIRST) {
- for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++)
- ;
- j--;
- fprintf(fd, ".. %5d in use\n", j);
- } else if (pd[j] < MALLOC_MAGIC) {
- fprintf(fd, "(%p)\n", pd[j]);
- } else {
- fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n",
- pd[j], pd[j]->free, pd[j]->total,
- pd[j]->size, pd[j]->page, pd[j]->next);
- }
- }
-
- for(pf=free_list.next; pf; pf=pf->next) {
- fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
- pf, pf->page, pf->end, pf->size, pf->prev, pf->next);
- if (pf == pf->next) {
- fprintf(fd, "Free_list loops.\n");
- break;
- }
- }
-
- /* print out various info */
- fprintf(fd, "Minsize\t%d\n", malloc_minsize);
- fprintf(fd, "Maxsize\t%d\n", malloc_maxsize);
- fprintf(fd, "Pagesize\t%d\n", malloc_pagesize);
- fprintf(fd, "Pageshift\t%d\n", malloc_pageshift);
- fprintf(fd, "FirstPage\t%ld\n", malloc_origo);
- fprintf(fd, "LastPage\t%ld %lx\n", last_index+malloc_pageshift,
- (last_index + malloc_pageshift) << malloc_pageshift);
- fprintf(fd, "Break\t%ld\n", (u_long)sbrk(0) >> malloc_pageshift);
-}
-#endif /* MALLOC_STATS */
-
extern char *__progname;
static void
wrterror(char *p)
{
char *q = " error: ";
- write(2, __progname, strlen(__progname));
- write(2, malloc_func, strlen(malloc_func));
- write(2, q, strlen(q));
- write(2, p, strlen(p));
+ write(STDERR_FILENO, __progname, strlen(__progname));
+ write(STDERR_FILENO, malloc_func, strlen(malloc_func));
+ write(STDERR_FILENO, q, strlen(q));
+ write(STDERR_FILENO, p, strlen(p));
suicide = 1;
-#ifdef MALLOC_STATS
- if (malloc_stats)
- malloc_dump(stderr);
-#endif /* MALLOC_STATS */
abort();
}
@@ -347,26 +280,12 @@ wrtwarning(char *p)
char *q = " warning: ";
if (malloc_abort)
wrterror(p);
- write(2, __progname, strlen(__progname));
- write(2, malloc_func, strlen(malloc_func));
- write(2, q, strlen(q));
- write(2, p, strlen(p));
+ write(STDERR_FILENO, __progname, strlen(__progname));
+ write(STDERR_FILENO, malloc_func, strlen(malloc_func));
+ write(STDERR_FILENO, q, strlen(q));
+ write(STDERR_FILENO, p, strlen(p));
}
-#ifdef MALLOC_STATS
-static void
-malloc_exit()
-{
- FILE *fd = fopen("malloc.out", "a");
- char *q = "malloc() warning: Couldn't dump stats.\n";
- if (fd) {
- malloc_dump(fd);
- fclose(fd);
- } else
- write(2, q, strlen(q));
-}
-#endif /* MALLOC_STATS */
-
/*
* Allocate a number of pages from the OS
@@ -481,8 +400,6 @@ malloc_init ()
case '<': malloc_cache >>= 1; break;
case 'a': malloc_abort = 0; break;
case 'A': malloc_abort = 1; break;
- case 'd': malloc_stats = 0; break;
- case 'D': malloc_stats = 1; break;
case 'h': malloc_hint = 0; break;
case 'H': malloc_hint = 1; break;
case 'r': malloc_realloc = 0; break;
@@ -516,11 +433,6 @@ malloc_init ()
if (malloc_zero)
malloc_junk=1;
-#ifdef MALLOC_STATS
- if (malloc_stats)
- atexit(malloc_exit);
-#endif /* MALLOC_STATS */
-
/* Allocate one page for the page directory */
page_dir = (struct pginfo **) MMAP(malloc_pagesize);
@@ -568,6 +480,7 @@ malloc_pages(size_t size)
size = pageround(size);
p = 0;
+
/* Look for free pages before asking for more */
for(pf = free_list.next; pf; pf = pf->next) {
@@ -779,9 +692,7 @@ imalloc(size_t size)
if (suicide)
abort();
- if (malloc_sysv && !size)
- result = 0;
- else if ((size + malloc_pagesize) < size) /* Check for overflow */
+ if ((size + malloc_pagesize) < size) /* Check for overflow */
result = 0;
else if (size <= malloc_maxsize)
result = malloc_bytes(size);
@@ -883,7 +794,9 @@ irealloc(void *ptr, size_t size)
if (p) {
/* copy the lesser of the two sizes, and free the old one */
- if (osize < size)
+ if (!size || !osize)
+ ;
+ else if (osize < size)
memcpy(p, ptr, osize);
else
memcpy(p, ptr, size);
@@ -1132,13 +1045,14 @@ ifree(void *ptr)
* These are the public exported interface routines.
*/
-static int malloc_active;
void *
malloc(size_t size)
{
register void *r;
+ if (malloc_sysv && !size)
+ return (0);
malloc_func = " in malloc():";
THREAD_LOCK();
if (malloc_active++) {
@@ -1184,7 +1098,10 @@ realloc(void *ptr, size_t size)
malloc_active--;
return (0);
}
- if (!ptr) {
+ if (malloc_sysv && !size) {
+ ifree(ptr);
+ r = 0;
+ } else if (!ptr) {
r = imalloc(size);
} else {
r = irealloc(ptr, size);
@@ -1196,3 +1113,29 @@ realloc(void *ptr, size_t size)
wrterror("out of memory.\n");
return (r);
}
+
+void *
+calloc(size_t num, size_t size)
+{
+ register void *r;
+
+ size *= num;
+ if (malloc_sysv && !size)
+ return (0);
+ malloc_func = " in calloc():";
+ THREAD_LOCK();
+ if (malloc_active++) {
+ wrtwarning("recursive call.\n");
+ malloc_active--;
+ return (0);
+ }
+ r = imalloc(size);
+ UTRACE(0, size, r);
+ malloc_active--;
+ THREAD_UNLOCK();
+ if (malloc_xmalloc && !r)
+ wrterror("out of memory.\n");
+ if (r)
+ memset(r, 0, size);
+ return (r);
+}
OpenPOWER on IntegriCloud