version 1.1.1.1, 2012/02/21 22:57:48
|
version 1.1.1.2, 2012/05/29 09:29:43
|
Line 1
|
Line 1
|
/* Safe automatic memory allocation. |
/* Safe automatic memory allocation. |
Copyright (C) 2003, 2006-2007 Free Software Foundation, Inc. | Copyright (C) 2003, 2006-2007, 2009-2011 Free Software Foundation, Inc. |
Written by Bruno Haible <bruno@clisp.org>, 2003. |
Written by Bruno Haible <bruno@clisp.org>, 2003. |
|
|
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
Line 16
|
Line 16
|
along with this program; if not, write to the Free Software Foundation, |
along with this program; if not, write to the Free Software Foundation, |
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ |
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ |
|
|
|
#define _GL_USE_STDLIB_ALLOC 1 |
#include <config.h> |
#include <config.h> |
|
|
/* Specification. */ |
/* Specification. */ |
#include "malloca.h" |
#include "malloca.h" |
|
|
|
#include "verify.h" |
|
|
/* The speed critical point in this file is freea() applied to an alloca() |
/* The speed critical point in this file is freea() applied to an alloca() |
result: it must be fast, to match the speed of alloca(). The speed of |
result: it must be fast, to match the speed of alloca(). The speed of |
mmalloca() and freea() in the other case are not critical, because they |
mmalloca() and freea() in the other case are not critical, because they |
Line 50 struct preliminary_header { void *next; char room[MAGI
|
Line 53 struct preliminary_header { void *next; char room[MAGI
|
#define HEADER_SIZE \ |
#define HEADER_SIZE \ |
(((sizeof (struct preliminary_header) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max) |
(((sizeof (struct preliminary_header) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max) |
struct header { void *next; char room[HEADER_SIZE - sizeof (struct preliminary_header) + MAGIC_SIZE]; }; |
struct header { void *next; char room[HEADER_SIZE - sizeof (struct preliminary_header) + MAGIC_SIZE]; }; |
/* Verify that HEADER_SIZE == sizeof (struct header). */ | verify (HEADER_SIZE == sizeof (struct header)); |
typedef int verify1[2 * (HEADER_SIZE == sizeof (struct header)) - 1]; | |
/* We make the hash table quite big, so that during lookups the probability |
/* We make the hash table quite big, so that during lookups the probability |
of empty hash buckets is quite high. There is no need to make the hash |
of empty hash buckets is quite high. There is no need to make the hash |
table resizable, because when the hash table gets filled so much that the |
table resizable, because when the hash table gets filled so much that the |
Line 74 mmalloca (size_t n)
|
Line 76 mmalloca (size_t n)
|
char *p = (char *) malloc (nplus); |
char *p = (char *) malloc (nplus); |
|
|
if (p != NULL) |
if (p != NULL) |
{ | { |
size_t slot; | size_t slot; |
|
|
p += HEADER_SIZE; | p += HEADER_SIZE; |
|
|
/* Put a magic number into the indicator word. */ | /* Put a magic number into the indicator word. */ |
((int *) p)[-1] = MAGIC_NUMBER; | ((int *) p)[-1] = MAGIC_NUMBER; |
|
|
/* Enter p into the hash table. */ | /* Enter p into the hash table. */ |
slot = (unsigned long) p % HASH_TABLE_SIZE; | slot = (unsigned long) p % HASH_TABLE_SIZE; |
((struct header *) (p - HEADER_SIZE))->next = mmalloca_results[slot]; | ((struct header *) (p - HEADER_SIZE))->next = mmalloca_results[slot]; |
mmalloca_results[slot] = p; | mmalloca_results[slot] = p; |
|
|
return p; | return p; |
} | } |
} |
} |
/* Out of memory. */ |
/* Out of memory. */ |
return NULL; |
return NULL; |
Line 109 freea (void *p)
|
Line 111 freea (void *p)
|
if (p != NULL) |
if (p != NULL) |
{ |
{ |
/* Attempt to quickly distinguish the mmalloca() result - which has |
/* Attempt to quickly distinguish the mmalloca() result - which has |
a magic indicator word - and the alloca() result - which has an | a magic indicator word - and the alloca() result - which has an |
uninitialized indicator word. It is for this test that sa_increment | uninitialized indicator word. It is for this test that sa_increment |
additional bytes are allocated in the alloca() case. */ | additional bytes are allocated in the alloca() case. */ |
if (((int *) p)[-1] == MAGIC_NUMBER) |
if (((int *) p)[-1] == MAGIC_NUMBER) |
{ | { |
/* Looks like a mmalloca() result. To see whether it really is one, | /* Looks like a mmalloca() result. To see whether it really is one, |
perform a lookup in the hash table. */ | perform a lookup in the hash table. */ |
size_t slot = (unsigned long) p % HASH_TABLE_SIZE; | size_t slot = (unsigned long) p % HASH_TABLE_SIZE; |
void **chain = &mmalloca_results[slot]; | void **chain = &mmalloca_results[slot]; |
for (; *chain != NULL;) | for (; *chain != NULL;) |
{ | { |
if (*chain == p) | if (*chain == p) |
{ | { |
/* Found it. Remove it from the hash table and free it. */ | /* Found it. Remove it from the hash table and free it. */ |
char *p_begin = (char *) p - HEADER_SIZE; | char *p_begin = (char *) p - HEADER_SIZE; |
*chain = ((struct header *) p_begin)->next; | *chain = ((struct header *) p_begin)->next; |
free (p_begin); | free (p_begin); |
return; | return; |
} | } |
chain = &((struct header *) ((char *) *chain - HEADER_SIZE))->next; | chain = &((struct header *) ((char *) *chain - HEADER_SIZE))->next; |
} | } |
} | } |
/* At this point, we know it was not a mmalloca() result. */ |
/* At this point, we know it was not a mmalloca() result. */ |
} |
} |
} |
} |