diff options
Diffstat (limited to 'lib/libc/stdlib/malloc.c')
-rw-r--r-- | lib/libc/stdlib/malloc.c | 243 |
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); +} |