ソースを参照

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 19 年 前
コミット
3e0a1f3882
3 ファイル変更22 行追加6 行削除
  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)  \