Browse Source

Richard Sandiford writes:
However, retesting on m68k showed up a problem that had appeared in
uClibc since the last time I tried. Specifically, revision 15785 did:

-#define HEAP_GRANULARITY (sizeof (HEAP_GRANULARITY_TYPE))
+#define HEAP_GRANULARITY (__alignof__ (HEAP_GRANULARITY_TYPE))

-#define MALLOC_ALIGNMENT (sizeof (double))
+#define MALLOC_ALIGNMENT (__alignof__ (double))

The problem is that

(a) MALLOC_HEADER_SIZE == MALLOC_ALIGNMENT
(b) the header contains a size value of type size_t
(c) sizeof (size_t) is 4 on m68k, but...
(d) __alignof__ (double) is only 2 (the largest alignment used on m68k)

So we only allocate 2 bytes for the 4-byte header, and the least
significant 2 bytes of the size are in the user's area rather than
the header. The patch below fixes that problem by redefining
MALLOC_HEADER_SIZE to:

MAX (MALLOC_ALIGNMENT, sizeof (size_t))

(but without the help of the MAX macro ;)). However, we really would
like to have word alignment on Coldfire. It makes a big performance
difference, and because we have to allocate a 4-byte header anyway,
what wastage there is will be confined to the end of the allocated block.
Any wastage will also be limited to 2 bytes per allocation compared to
the current alignment.

I've therefore used the __aligned__ type attribute to create a double
type that has at least sizeof (size_t) bytes of alignment. I've
introduced a new __attribute_aligned__ macro for this. It might seem
silly protecting against old or non-GNU compilers here, but the extra
alignment is only an optimisation, and having the macro is more in the
spirit of the other attribute code.

Mike Frysinger 18 years ago
parent
commit
3e0a1f3882
3 changed files with 22 additions and 6 deletions
  1. 8 0
      include/sys/cdefs.h
  2. 1 1
      libc/stdlib/malloc/heap.h
  3. 13 5
      libc/stdlib/malloc/malloc.h

+ 8 - 0
include/sys/cdefs.h

@@ -189,6 +189,14 @@
 # define __attribute__(xyz)	/* Ignore */
 #endif
 
+/* We make this a no-op unless it can be used as both a variable and
+   a type attribute.  gcc 2.8 is known to support both.  */
+#if __GNUC_PREREQ (2,8)
+# define __attribute_aligned__(size) __attribute__ ((__aligned__ (size)))
+#else
+# define __attribute_aligned__(size) /* Ignore */
+#endif
+
 /* At some point during the gcc 2.96 development the `malloc' attribute
    for functions was introduced.  We don't want to use it unconditionally
    (although this would be possible) since it generates warnings.  */

+ 1 - 1
libc/stdlib/malloc/heap.h

@@ -25,7 +25,7 @@
 /* The heap allocates in multiples of, and aligned to, HEAP_GRANULARITY.
    HEAP_GRANULARITY must be a power of 2.  Malloc depends on this being the
    same as MALLOC_ALIGNMENT.  */
-#define HEAP_GRANULARITY_TYPE	double
+#define HEAP_GRANULARITY_TYPE	double __attribute_aligned__ (sizeof (size_t))
 #define HEAP_GRANULARITY	(__alignof__ (HEAP_GRANULARITY_TYPE))
 
 

+ 13 - 5
libc/stdlib/malloc/malloc.h

@@ -11,8 +11,13 @@
  * Written by Miles Bader <miles@gnu.org>
  */
 
-/* The alignment we guarantee for malloc return values.  */
-#define MALLOC_ALIGNMENT	(__alignof__ (double))
+/* The alignment we guarantee for malloc return values.  We prefer this
+   to be at least sizeof (size_t) bytes because (a) we have to allocate
+   that many bytes for the header anyway and (b) guaranteeing word
+   alignment can be a significant win on targets like m68k and Coldfire,
+   where __alignof__(double) == 2.  */
+#define MALLOC_ALIGNMENT \
+  __alignof__ (double __attribute_aligned__ (sizeof (size_t)))
 
 /* The system pagesize... */
 extern size_t __pagesize;
@@ -98,17 +103,20 @@ extern int __malloc_mmb_debug;
 
 
 /* The size of a malloc allocation is stored in a size_t word
-   MALLOC_ALIGNMENT bytes prior to the start address of the allocation:
+   MALLOC_HEADER_SIZE bytes prior to the start address of the allocation:
 
      +--------+---------+-------------------+
      | SIZE   |(unused) | allocation  ...   |
      +--------+---------+-------------------+
      ^ BASE             ^ ADDR
-     ^ ADDR - MALLOC_ALIGN
+     ^ ADDR - MALLOC_HEADER_SIZE
 */
 
 /* The amount of extra space used by the malloc header.  */
-#define MALLOC_HEADER_SIZE	MALLOC_ALIGNMENT
+#define MALLOC_HEADER_SIZE			\
+  (MALLOC_ALIGNMENT < sizeof (size_t)		\
+   ? sizeof (size_t)				\
+   : MALLOC_ALIGNMENT)
 
 /* Set up the malloc header, and return the user address of a malloc block. */
 #define MALLOC_SETUP(base, size)  \