summaryrefslogtreecommitdiff
path: root/malloc
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2006-01-11 05:43:11 +0000
committerRoland McGrath <roland@gnu.org>2006-01-11 05:43:11 +0000
commit2fd4de4b15a66f821057af90714145d2c034a609 (patch)
tree3b1a0100481b13b2a03458c1561cdb2507ff4d02 /malloc
parent49a0ba2748e48cd188d049678dd9723221192902 (diff)
[BZ #321]
2005-10-14 Paul Eggert <eggert@cs.ucla.edu> * malloc/obstack.c: Fix old comments. Update FSF snail mail address. * malloc/obstack.h: Likewise. [BZ #321] Fix portability bugs encountered when porting to Itanium. * malloc/obstack.h (obstack_empty_p, obstack_finish): Do not assume that the "contents" member is suitably aligned. It is not, for some hosts and alignments: e.g., Itanium, long-double. * malloc/obstack.c (_obstack_begin, _obstack_begin_1, _obstack_newchunk): Likewise. * malloc/obstack.c: Include <stddef.h>, for size_t. Include <inttypes.h>, <stdint.h> if needed and available. (DEFAULT_ALIGNMENT): Now an enum constant, not a macro. Use C89 offsetof rather than K&R trick. Use the maximum alignment of uintmax_t, long double, void * rather than the alignment of double. (union fooround): Use uintmax_t, long double, void * members rather than just long and double. [BZ #321] Fix portability bugs encountered when porting to the IBM iSeries, where pointers are 256 bits wide and no integers are that wide. * malloc/obstack.h (__PTR_TO_INT, __INT_TO_PTR): Remove. All uses changed to: (__BPTR_ALIGN, __PTR_ALIGN): New macros. (struct _obstack_chunk.temp): Change from int to a union of pointer and int. All uses changed. [BZ #321] * malloc/obstack.c (print_and_abort) [!_LIBC]: Call fprintf (stderr, ...), not __fxprintf (NULL, ...). [_LIBC && USE_IN_LIBIO]: Don't include <wchar.h>; no longer needed.
Diffstat (limited to 'malloc')
-rw-r--r--malloc/obstack.c62
-rw-r--r--malloc/obstack.h109
2 files changed, 105 insertions, 66 deletions
diff --git a/malloc/obstack.c b/malloc/obstack.c
index aba21f9aac..75440d9c79 100644
--- a/malloc/obstack.c
+++ b/malloc/obstack.c
@@ -1,8 +1,7 @@
/* obstack.c - subroutines used implicitly by object stack macros
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
- This file is part of the GNU C Library. Its master source is NOT part of
- the C library, however. The master source lives in /gd/gnu/lib.
+ This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,8 +15,9 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
#ifdef HAVE_CONFIG_H
# include <config.h>
@@ -52,22 +52,38 @@
# endif
#endif
-#if defined _LIBC && defined USE_IN_LIBIO
-# include <wchar.h>
-#endif
+#include <stddef.h>
#ifndef ELIDE_CODE
+# if HAVE_INTTYPES_H
+# include <inttypes.h>
+# endif
+# if HAVE_STDINT_H || defined _LIBC
+# include <stdint.h>
+# endif
+
/* Determine default alignment. */
-struct fooalign {char x; double d;};
-# define DEFAULT_ALIGNMENT \
- ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0))
+union fooround
+{
+ uintmax_t i;
+ long double d;
+ void *p;
+};
+struct fooalign
+{
+ char c;
+ union fooround u;
+};
/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
But in fact it might be less smart and round addresses to as much as
DEFAULT_ROUNDING. So we prepare for it to do that. */
-union fooround {long x; double d;};
-# define DEFAULT_ROUNDING (sizeof (union fooround))
+enum
+ {
+ DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
+ DEFAULT_ROUNDING = sizeof (union fooround)
+ };
/* When we copy a long block of data, this is the unit to do it with.
On some machines, copying successive ints does not work;
@@ -143,7 +159,7 @@ _obstack_begin (struct obstack *h,
register struct _obstack_chunk *chunk; /* points to new chunk */
if (alignment == 0)
- alignment = (int) DEFAULT_ALIGNMENT;
+ alignment = DEFAULT_ALIGNMENT;
if (size == 0)
/* Default size is what GNU malloc can fit in a 4096-byte block. */
{
@@ -170,7 +186,8 @@ _obstack_begin (struct obstack *h,
chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
if (!chunk)
(*obstack_alloc_failed_handler) ();
- h->next_free = h->object_base = chunk->contents;
+ h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
+ alignment - 1);
h->chunk_limit = chunk->limit
= (char *) chunk + h->chunk_size;
chunk->prev = 0;
@@ -189,7 +206,7 @@ _obstack_begin_1 (struct obstack *h, int size, int alignment,
register struct _obstack_chunk *chunk; /* points to new chunk */
if (alignment == 0)
- alignment = (int) DEFAULT_ALIGNMENT;
+ alignment = DEFAULT_ALIGNMENT;
if (size == 0)
/* Default size is what GNU malloc can fit in a 4096-byte block. */
{
@@ -217,7 +234,8 @@ _obstack_begin_1 (struct obstack *h, int size, int alignment,
chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
if (!chunk)
(*obstack_alloc_failed_handler) ();
- h->next_free = h->object_base = chunk->contents;
+ h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
+ alignment - 1);
h->chunk_limit = chunk->limit
= (char *) chunk + h->chunk_size;
chunk->prev = 0;
@@ -259,8 +277,7 @@ _obstack_newchunk (struct obstack *h, int length)
/* Compute an aligned object_base in the new chunk */
object_base =
- __INT_TO_PTR ((__PTR_TO_INT (new_chunk->contents) + h->alignment_mask)
- & ~ (h->alignment_mask));
+ __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
/* Move the existing object to the new chunk.
Word at a time is fast and is safe if the object
@@ -285,7 +302,10 @@ _obstack_newchunk (struct obstack *h, int length)
/* If the object just copied was the only data in OLD_CHUNK,
free that chunk and remove it from the chain.
But not if that chunk might contain an empty object. */
- if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
+ if (! h->maybe_empty_object
+ && (h->object_base
+ == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
+ h->alignment_mask)))
{
new_chunk->prev = old_chunk->prev;
CALL_FREEFUN (h, old_chunk);
@@ -410,7 +430,11 @@ print_and_abort (void)
happen because the "memory exhausted" message appears in other places
like this and the translation should be reused instead of creating
a very similar string which requires a separate translation. */
+# ifdef _LIBC
(void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
+# else
+ fprintf (stderr, "%s\n", _("memory exhausted"));
+# endif
exit (obstack_exit_failure);
}
diff --git a/malloc/obstack.h b/malloc/obstack.h
index 03f6ccb2ce..206fe55050 100644
--- a/malloc/obstack.h
+++ b/malloc/obstack.h
@@ -1,8 +1,7 @@
/* obstack.h - object stack macros
Copyright (C) 1988-1994,1996-1999,2003,2004,2005
Free Software Foundation, Inc.
- This file is part of the GNU C Library. Its master source is NOT part of
- the C library, however. The master source lives in /gd/gnu/lib.
+ This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,8 +15,8 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* Summary:
@@ -111,19 +110,7 @@ Summary:
extern "C" {
#endif
-/* We use subtraction of (char *) 0 instead of casting to int
- because on word-addressable machines a simple cast to int
- may ignore the byte-within-word field of the pointer. */
-
-#ifndef __PTR_TO_INT
-# define __PTR_TO_INT(P) ((P) - (char *) 0)
-#endif
-
-#ifndef __INT_TO_PTR
-# define __INT_TO_PTR(P) ((P) + (char *) 0)
-#endif
-
-/* We need the type of the resulting object. If __PTRDIFF_TYPE__ is
+/* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is
defined, as with GNU C, use that; that way we don't pollute the
namespace with <stddef.h>'s symbols. Otherwise, include <stddef.h>
and use ptrdiff_t. */
@@ -135,6 +122,23 @@ extern "C" {
# define PTR_INT_TYPE ptrdiff_t
#endif
+/* If B is the base of an object addressed by P, return the result of
+ aligning P to the next multiple of A + 1. B and P must be of type
+ char *. A + 1 must be a power of 2. */
+
+#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
+
+/* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case
+ where pointers can be converted to integers, aligned as integers,
+ and converted back again. If PTR_INT_TYPE is narrower than a
+ pointer (e.g., the AS/400), play it safe and compute the alignment
+ relative to B. Otherwise, use the faster strategy of computing the
+ alignment relative to 0. */
+
+#define __PTR_ALIGN(B, P, A) \
+ __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
+ P, A)
+
#include <string.h>
struct _obstack_chunk /* Lives at front of each chunk. */
@@ -151,7 +155,11 @@ struct obstack /* control current object in current chunk */
char *object_base; /* address of object we are building */
char *next_free; /* where to add next char to current object */
char *chunk_limit; /* address of char after current chunk */
- PTR_INT_TYPE temp; /* Temporary for some macros. */
+ union
+ {
+ PTR_INT_TYPE tempint;
+ void *tempptr;
+ } temp; /* Temporary for some macros. */
int alignment_mask; /* Mask of alignment for each object. */
/* These prototypes vary based on `use_extra_arg', and we use
casts to the prototypeless function type in all assignments,
@@ -276,7 +284,10 @@ __extension__ \
# define obstack_empty_p(OBSTACK) \
__extension__ \
({ struct obstack const *__o = (OBSTACK); \
- (__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); })
+ (__o->chunk->prev == 0 \
+ && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \
+ __o->chunk->contents, \
+ __o->alignment_mask)); })
# define obstack_grow(OBSTACK,where,length) \
__extension__ \
@@ -375,8 +386,8 @@ __extension__ \
if (__o1->next_free == __value) \
__o1->maybe_empty_object = 1; \
__o1->next_free \
- = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\
- & ~ (__o1->alignment_mask)); \
+ = __PTR_ALIGN (__o1->object_base, __o1->next_free, \
+ __o1->alignment_mask); \
if (__o1->next_free - (char *)__o1->chunk \
> __o1->chunk_limit - (char *)__o1->chunk) \
__o1->next_free = __o1->chunk_limit; \
@@ -400,7 +411,10 @@ __extension__ \
(unsigned) ((h)->chunk_limit - (h)->next_free)
# define obstack_empty_p(h) \
- ((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0)
+ ((h)->chunk->prev == 0 \
+ && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \
+ (h)->chunk->contents, \
+ (h)->alignment_mask))
/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
so that we can avoid having void expressions
@@ -409,23 +423,23 @@ __extension__ \
but some compilers won't accept it. */
# define obstack_make_room(h,length) \
-( (h)->temp = (length), \
- (((h)->next_free + (h)->temp > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp), 0) : 0))
+( (h)->temp.tempint = (length), \
+ (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0))
# define obstack_grow(h,where,length) \
-( (h)->temp = (length), \
- (((h)->next_free + (h)->temp > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
- memcpy ((h)->next_free, where, (h)->temp), \
- (h)->next_free += (h)->temp)
+( (h)->temp.tempint = (length), \
+ (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp.tempint), \
+ (h)->next_free += (h)->temp.tempint)
# define obstack_grow0(h,where,length) \
-( (h)->temp = (length), \
- (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \
- memcpy ((h)->next_free, where, (h)->temp), \
- (h)->next_free += (h)->temp, \
+( (h)->temp.tempint = (length), \
+ (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp.tempint), \
+ (h)->next_free += (h)->temp.tempint, \
*((h)->next_free)++ = 0)
# define obstack_1grow(h,datum) \
@@ -450,10 +464,10 @@ __extension__ \
(((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
# define obstack_blank(h,length) \
-( (h)->temp = (length), \
- (((h)->chunk_limit - (h)->next_free < (h)->temp) \
- ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
- obstack_blank_fast (h, (h)->temp))
+( (h)->temp.tempint = (length), \
+ (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \
+ ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
+ obstack_blank_fast (h, (h)->temp.tempint))
# define obstack_alloc(h,length) \
(obstack_blank ((h), (length)), obstack_finish ((h)))
@@ -468,22 +482,23 @@ __extension__ \
( ((h)->next_free == (h)->object_base \
? (((h)->maybe_empty_object = 1), 0) \
: 0), \
- (h)->temp = __PTR_TO_INT ((h)->object_base), \
+ (h)->temp.tempptr = (h)->object_base, \
(h)->next_free \
- = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
- & ~ ((h)->alignment_mask)), \
+ = __PTR_ALIGN ((h)->object_base, (h)->next_free, \
+ (h)->alignment_mask), \
(((h)->next_free - (char *) (h)->chunk \
> (h)->chunk_limit - (char *) (h)->chunk) \
? ((h)->next_free = (h)->chunk_limit) : 0), \
(h)->object_base = (h)->next_free, \
- (void *) __INT_TO_PTR ((h)->temp))
+ (h)->temp.tempptr)
# define obstack_free(h,obj) \
-( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \
- (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \
+ ((((h)->temp.tempint > 0 \
+ && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \
? (int) ((h)->next_free = (h)->object_base \
- = (h)->temp + (char *) (h)->chunk) \
- : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0)))
+ = (h)->temp.tempint + (char *) (h)->chunk) \
+ : (((obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0), 0)))
#endif /* not __GNUC__ or not __STDC__ */