summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdlib
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1996-10-20 13:20:57 +0000
committerphk <phk@FreeBSD.org>1996-10-20 13:20:57 +0000
commitdcce35102d8055528548c41ea88a3be5bc0dc703 (patch)
tree15285d1a59fdc4959729069a095ca3146dccbd3d /lib/libc/stdlib
parent21bccdcd4a4275128017d9f3bc90a98c3fb3302d (diff)
downloadFreeBSD-src-dcce35102d8055528548c41ea88a3be5bc0dc703.zip
FreeBSD-src-dcce35102d8055528548c41ea88a3be5bc0dc703.tar.gz
malloc_pages should be static.
Add progname to warning/error message layout. (joerg) Remove inline assembler, no speed impact, not need for the obfuscation (bde) Remove on the fly calculation of parameters, no longer critical. Make D & U flags valid even if we don't support them. Don't call imalloc until we're done initializing. Zap contents on free() if we have "Junk" set. [*] Various nitpicking. [*] As a sideeffect of this change, if you are worried about sensitive data lingering in memory, you can use the 'Junk' option now to make sure phkmalloc zaps memory when it is returned. add char * malloc_options = "J"; to your source. Obviously there is a performance impact.
Diffstat (limited to 'lib/libc/stdlib')
-rw-r--r--lib/libc/stdlib/malloc.c290
1 files changed, 103 insertions, 187 deletions
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index 4853b1d..720c4d2 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.14 1996/09/25 08:30:46 phk Exp $
+ * $Id: malloc.c,v 1.15 1996/09/25 16:29:15 sos Exp $
*
*/
@@ -17,17 +17,17 @@
* any good unless you fiddle with the internals of malloc or want
* to catch random pointer corruption as early as possible.
*/
-#undef EXTRA_SANITY
+#ifndef MALLOC_EXTRA_SANITY
+#undef MALLOC_EXTRA_SANITY
+#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.
*/
-#define MALLOC_STATS
-
-#if defined(EXTRA_SANITY) && !defined(MALLOC_STATS)
-# define MALLOC_STATS /* required for EXTRA_SANITY */
+#ifndef MALLOC_STATS
+#undef MALLOC_STATS
#endif
/*
@@ -37,20 +37,32 @@
#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
/*
- * If these weren't defined here, they would be calculated on the fly,
- * with a noticeable performance hit.
+ * The basic parameters you can tweak.
+ *
+ * malloc_pageshift pagesize = 1 << malloc_pageshift
+ * It's probably best if this is the native
+ * page size, but it shouldn't have to be.
+ *
+ * malloc_minsize minimum size of an allocation
+ * If this is too small it's too much work
+ * to manage them.
+ *
*/
+
#if defined(__i386__) && defined(__FreeBSD__)
-# define malloc_pagesize 4096U
# define malloc_pageshift 12U
# define malloc_minsize 16U
-# define malloc_maxsize ((malloc_pagesize)>>1)
+#endif /* __i386__ && __FreeBSD__ */
+
+/* Insert your combination here... */
+#if defined(__FOOCPU__) && defined(__BAROS__)
+# define malloc_pageshift 12U
+# define malloc_minsize 16U
#endif /* __i386__ && __FreeBSD__ */
/*
* No user serviceable parts behind this point.
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -100,61 +112,29 @@ struct pgfree {
#define MALLOC_FOLLOW ((struct pginfo*) 3)
#define MALLOC_MAGIC ((struct pginfo*) 4)
-/*
- * The i386 architecture has some very convenient instructions.
- * We might as well use them. There are C-language backups, but
- * they are considerably slower.
- */
-#if defined(__i386__) && defined(__GNUC__)
-#define ffs _ffs
-static __inline__ int
-_ffs(unsigned input)
-{
- int result;
- __asm__("bsfl %1, %0" : "=r" (result) : "r" (input));
- return result+1;
-}
-
-#define fls _fls
-static __inline__ int
-_fls(unsigned input)
-{
- int result;
- __asm__("bsrl %1, %0" : "=r" (result) : "r" (input));
- return result+1;
-}
+#ifndef malloc_pageshift
+#define malloc_pageshift 12U
+#endif
-#define set_bit _set_bit
-static __inline__ void
-_set_bit(struct pginfo *pi, int bit)
-{
- __asm__("btsl %0, (%1)" :
- : "r" (bit & (MALLOC_BITS-1)), "r" (pi->bits+(bit/MALLOC_BITS)));
-}
+#ifndef malloc_minsize
+#define malloc_minsize 16U
+#endif
-#define clr_bit _clr_bit
-static __inline__ void
-_clr_bit(struct pginfo *pi, int bit)
-{
- __asm__("btcl %0, (%1)" :
- : "r" (bit & (MALLOC_BITS-1)), "r" (pi->bits+(bit/MALLOC_BITS)));
-}
+#ifndef malloc_pageshift
+#error "malloc_pageshift undefined"
+#endif
-#endif /* __i386__ && __GNUC__ */
+#if !defined(malloc_pagesize)
+#define malloc_pagesize (1U<<malloc_pageshift)
+#endif
-/*
- * Set to one when malloc_init has been called
- */
-static unsigned initialized;
+#if ((1<<malloc_pageshift) != malloc_pagesize)
+#error "(1<<malloc_pageshift) != malloc_pagesize"
+#endif
-/*
- * The size of a page.
- * Must be a integral multiplum of the granularity of mmap(2).
- * Your toes will curl if it isn't a power of two
- */
-#ifndef malloc_pagesize
-static unsigned malloc_pagesize;
-#endif /* malloc_pagesize */
+#ifndef malloc_maxsize
+#define malloc_maxsize ((malloc_pagesize)>>1)
+#endif
/* A mask for the offset inside a page. */
#define malloc_pagemask ((malloc_pagesize)-1)
@@ -162,45 +142,26 @@ static unsigned malloc_pagesize;
#define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask)))
#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo)
-/* malloc_pagesize == 1 << malloc_pageshift */
-#ifndef malloc_pageshift
-static unsigned malloc_pageshift;
-#endif /* malloc_pageshift */
+/* Set when initialization has been done */
+static unsigned malloc_started;
-/*
- * The smallest allocation we bother about.
- * Must be power of two
- */
-#ifndef malloc_minsize
-static unsigned malloc_minsize;
-#endif /* malloc_minsize */
-
-/*
- * The largest chunk we care about.
- * Must be smaller than pagesize
- * Must be power of two
- */
-#ifndef malloc_maxsize
-static unsigned malloc_maxsize;
-#endif /* malloc_maxsize */
-
-/* The minimum size (in pages) of the free page cache. */
-static unsigned malloc_cache = 16;
+/* Number of free pages we cache */
+static unsigned malloc_cache = 16;
/* The offset from pagenumber to index into the page directory */
-static u_long malloc_origo;
+static u_long malloc_origo;
/* The last index in the page directory we care about */
-static u_long last_index;
+static u_long last_index;
/* Pointer to page directory. Allocated "as if with" malloc */
-static struct pginfo **page_dir;
+static struct pginfo **page_dir;
/* How many slots in the page directory */
-static unsigned malloc_ninfo;
+static unsigned malloc_ninfo;
/* Free pages line up here */
-static struct pgfree free_list;
+static struct pgfree free_list;
/* Abort(), user doesn't handle problems. */
static int malloc_abort;
@@ -208,10 +169,8 @@ static int malloc_abort;
/* Are we trying to die ? */
static int suicide;
-#ifdef MALLOC_STATS
/* dump statistics */
static int malloc_stats;
-#endif /* MALLOC_STATS */
/* always realloc ? */
static int malloc_realloc;
@@ -225,10 +184,10 @@ static int malloc_zero;
/* junk fill ? */
static int malloc_junk;
-#ifdef __FreeBSD__
/* utrace ? */
static int malloc_utrace;
+#ifdef __FreeBSD__
struct ut { void *p; size_t s; void *r; };
#define UTRACE(a, b, c) \
@@ -247,6 +206,9 @@ static struct pgfree *px;
/* compile-time options */
char *malloc_options;
+/* Name of the current public function */
+static char *malloc_func;
+
/*
* Necessary function declarations
*/
@@ -313,15 +275,16 @@ malloc_dump(FILE *fd)
}
#endif /* MALLOC_STATS */
-static char *malloc_func;
+extern char *__progname;
static void
wrterror(char *p)
{
- char *q = "Malloc error: ";
+ char *q = " error: ";
suicide = 1;
- write(2, q, strlen(q));
+ write(2, __progname, strlen(__progname));
write(2, malloc_func, strlen(malloc_func));
+ write(2, q, strlen(q));
write(2, p, strlen(p));
#ifdef MALLOC_STATS
if (malloc_stats)
@@ -333,15 +296,16 @@ wrterror(char *p)
static void
wrtwarning(char *p)
{
- char *q = "Malloc warning: ";
+ char *q = " warning: ";
if (malloc_abort)
wrterror(p);
- write(2, q, strlen(q));
+ write(2, __progname, strlen(__progname));
write(2, malloc_func, strlen(malloc_func));
+ write(2, q, strlen(q));
write(2, p, strlen(p));
}
-#ifdef EXTRA_SANITY
+#ifdef MALLOC_STATS
static void
malloc_exit()
{
@@ -353,7 +317,7 @@ malloc_exit()
} else
write(2, q, strlen(q));
}
-#endif /* EXTRA_SANITY */
+#endif /* MALLOC_STATS */
/*
@@ -383,43 +347,28 @@ map_pages(int pages)
return result;
}
-/*
- * Set a bit in the bitmap
- */
-#ifndef set_bit
+/* Set a bit in the bitmap */
static __inline__ void
set_bit(struct pginfo *pi, int bit)
{
pi->bits[bit/MALLOC_BITS] |= 1<<(bit%MALLOC_BITS);
}
-#endif /* set_bit */
-/*
- * Clear a bit in the bitmap
- */
-#ifndef clr_bit
+/* Clear a bit in the bitmap */
static __inline__ void
clr_bit(struct pginfo *pi, int bit)
{
pi->bits[bit/MALLOC_BITS] &= ~(1<<(bit%MALLOC_BITS));
}
-#endif /* clr_bit */
-#ifndef tst_bit
-/*
- * Test a bit in the bitmap
- */
+/* Test a bit in the bitmap */
static __inline__ int
tst_bit(struct pginfo *pi, int bit)
{
return pi->bits[bit/MALLOC_BITS] & (1<<(bit%MALLOC_BITS));
}
-#endif /* tst_bit */
-/*
- * Find last bit
- */
-#ifndef fls
+/* Find last bit */
static __inline__ int
fls(int size)
{
@@ -428,7 +377,6 @@ fls(int size)
i++;
return i;
}
-#endif /* fls */
/*
* Extend page directory
@@ -516,20 +464,16 @@ malloc_init ()
case '<': malloc_cache >>= 1; break;
case 'a': malloc_abort = 0; break;
case 'A': malloc_abort = 1; break;
-#ifdef MALLOC_STATS
case 'd': malloc_stats = 0; break;
case 'D': malloc_stats = 1; break;
-#endif /* MALLOC_STATS */
case 'h': malloc_hint = 0; break;
case 'H': malloc_hint = 1; break;
case 'r': malloc_realloc = 0; break;
case 'R': malloc_realloc = 1; break;
case 'j': malloc_junk = 0; break;
case 'J': malloc_junk = 1; break;
-#ifdef __FreeBSD__
case 'u': malloc_utrace = 0; break;
case 'U': malloc_utrace = 1; break;
-#endif /* !__FreeBSD__ */
case 'z': malloc_zero = 0; break;
case 'Z': malloc_zero = 1; break;
default:
@@ -551,53 +495,10 @@ malloc_init ()
if (malloc_zero)
malloc_junk=1;
-#ifdef EXTRA_SANITY
+#ifdef MALLOC_STATS
if (malloc_stats)
atexit(malloc_exit);
-#endif /* EXTRA_SANITY */
-
-#ifndef malloc_pagesize
- /* determine our pagesize */
- malloc_pagesize = getpagesize();
-#endif /* malloc_pagesize */
-
-#ifndef malloc_maxsize
- malloc_maxsize = malloc_pagesize >> 1;
-#endif /* malloc_maxsize */
-
-#ifndef malloc_pageshift
- {
- int i;
- /* determine how much we shift by to get there */
- for (i = malloc_pagesize; i > 1; i >>= 1)
- malloc_pageshift++;
- }
-#endif /* malloc_pageshift */
-
-#ifndef malloc_minsize
- {
- int i;
- /*
- * find the smallest size allocation we will bother about.
- * this is determined as the smallest allocation that can hold
- * it's own pginfo;
- */
- i = 2;
- for(;;) {
- int j;
-
- /* Figure out the size of the bits */
- j = malloc_pagesize/i;
- j /= 8;
- if (j < sizeof(u_long))
- j = sizeof (u_long);
- if (sizeof(struct pginfo) + j - sizeof (u_long) <= i)
- break;
- i += i;
- }
- malloc_minsize = i;
- }
-#endif /* malloc_minsize */
+#endif /* MALLOC_STATS */
/* Allocate one page for the page directory */
page_dir = (struct pginfo **) mmap(0, malloc_pagesize, PROT_READ|PROT_WRITE,
@@ -615,7 +516,14 @@ malloc_init ()
malloc_ninfo = malloc_pagesize / sizeof *page_dir;
/* Been here, done that */
- initialized++;
+ malloc_started++;
+
+ /* Recalculate the cache size in bytes, and make sure it's nonzero */
+
+ if (!malloc_cache)
+ malloc_cache++;
+
+ malloc_cache <<= malloc_pageshift;
/*
* This is a nice hack from Kaleb Keithly (kaleb@x.org).
@@ -623,16 +531,12 @@ malloc_init ()
*/
px = (struct pgfree *) imalloc (sizeof *px);
- if (!malloc_cache)
- malloc_cache++;
-
- malloc_cache <<= malloc_pageshift;
}
/*
* Allocate a number of complete pages
*/
-void *
+static void *
malloc_pages(size_t size)
{
void *p, *delay_free = 0;
@@ -739,8 +643,10 @@ malloc_make_chunks(int bits)
bp = (struct pginfo *)pp;
} else {
bp = (struct pginfo *)imalloc(l);
- if (!bp)
+ if (!bp) {
+ ifree(pp);
return 0;
+ }
}
bp->size = (1<<bits);
@@ -748,12 +654,7 @@ malloc_make_chunks(int bits)
bp->total = bp->free = malloc_pagesize >> bits;
bp->page = pp;
- page_dir[ptr2index(pp)] = bp;
-
- bp->next = page_dir[bits];
- page_dir[bits] = bp;
-
- /* set all valid bits in the bits */
+ /* set all valid bits in the bitmap */
k = bp->total;
i = 0;
@@ -774,6 +675,15 @@ malloc_make_chunks(int bits)
}
}
+ /* MALLOC_LOCK */
+
+ page_dir[ptr2index(pp)] = bp;
+
+ bp->next = page_dir[bits];
+ page_dir[bits] = bp;
+
+ /* MALLOC_UNLOCK */
+
return 1;
}
@@ -833,7 +743,7 @@ imalloc(size_t size)
{
void *result;
- if (!initialized)
+ if (!malloc_started)
malloc_init();
if (suicide)
@@ -867,7 +777,7 @@ irealloc(void *ptr, size_t size)
if (suicide)
return 0;
- if (!initialized) {
+ if (!malloc_started) {
wrtwarning("malloc() has never been called.\n");
return 0;
}
@@ -982,6 +892,9 @@ free_pages(void *ptr, int index, struct pginfo *info)
l = i << malloc_pageshift;
+ if (malloc_junk)
+ memset(ptr, SOME_JUNK, l);
+
if (malloc_hint)
madvise(ptr, l, MADV_FREE);
@@ -1099,6 +1012,9 @@ free_bytes(void *ptr, int index, struct pginfo *info)
return;
}
+ if (malloc_junk)
+ memset(ptr, SOME_JUNK, info->size);
+
set_bit(info, i);
info->free++;
@@ -1148,7 +1064,7 @@ ifree(void *ptr)
if (!ptr)
return;
- if (!initialized) {
+ if (!malloc_started) {
wrtwarning("malloc() has never been called.\n");
return;
}
@@ -1200,7 +1116,7 @@ malloc(size_t size)
{
register void *r;
- malloc_func = "malloc():";
+ malloc_func = " in malloc():";
THREAD_LOCK();
if (malloc_active++) {
wrtwarning("recursive call.\n");
@@ -1217,7 +1133,7 @@ malloc(size_t size)
void
free(void *ptr)
{
- malloc_func = "free():";
+ malloc_func = " in free():";
THREAD_LOCK();
if (malloc_active++) {
wrtwarning("recursive call.\n");
@@ -1236,7 +1152,7 @@ realloc(void *ptr, size_t size)
{
register void *r;
- malloc_func = "realloc():";
+ malloc_func = " in realloc():";
THREAD_LOCK();
if (malloc_active++) {
wrtwarning("recursive call.\n");
OpenPOWER on IntegriCloud