Skip to content

Commit f44c72d

Browse files
committed
Make dlmalloc and emmalloc align to max_align_t
Required by C and C++ standards
1 parent 262d18d commit f44c72d

File tree

4 files changed

+47
-4
lines changed

4 files changed

+47
-4
lines changed

system/lib/dlmalloc.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626
#define USE_SPIN_LOCKS 0 // Ensure we use pthread_mutex_t.
2727
#endif
2828

29+
/* `mallloc`ed pointers must be aligned at least as strictly as max_align_t. */
30+
#ifndef MALLOC_ALIGNMENT
31+
#include <stddef.h>
32+
#define MALLOC_ALIGNMENT (__alignof__(max_align_t))
33+
#endif
34+
2935
#endif
3036

3137

system/lib/emmalloc.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ static size_t lowerBoundPowerOf2(size_t x) {
9696
// Constants
9797

9898
// All allocations are aligned to this value.
99-
static const size_t ALIGNMENT = 8;
99+
// FIXME: compile as C++11 and change this to alignof(max_align_t)
100+
static const size_t ALIGNMENT = __alignof__(long double);
100101

101102
// Even allocating 1 byte incurs this much actual payload
102103
// allocation. This is our minimum bin size.
@@ -131,8 +132,13 @@ struct Region;
131132
// the payload is a multiple of MIN_ALLOC).
132133
struct FreeInfo {
133134
// free lists are doubly-linked lists
134-
FreeInfo* _prev;
135-
FreeInfo* _next;
135+
union {
136+
struct {
137+
FreeInfo* _prev;
138+
FreeInfo* _next;
139+
};
140+
char _padding[ALLOC_UNIT];
141+
};
136142

137143
FreeInfo*& prev() { return _prev; }
138144
FreeInfo*& next() { return _next; }
@@ -173,7 +179,7 @@ struct Region {
173179
// the payload, or freelist info.
174180
union {
175181
FreeInfo _freeInfo;
176-
char _payload[];
182+
__attribute__((aligned(ALIGNMENT))) char _payload[];
177183
};
178184

179185
size_t getTotalSize() { return _totalSize; }

tests/malloc_alignment.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright 2019 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#include <assert.h>
9+
#include <stdalign.h>
10+
#include <stddef.h>
11+
#include <stdint.h>
12+
#include <stdlib.h>
13+
14+
int main(int argc, char **argv) {
15+
for(int i = 0; i < 16; ++i) {
16+
void *p = malloc(i);
17+
assert(((uintptr_t)p & (alignof(max_align_t) - 1)) == 0);
18+
}
19+
20+
return 0;
21+
}

tests/test_core.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8493,6 +8493,16 @@ def test():
84938493
self.emcc_args += ['-DPOOL']
84948494
test()
84958495

8496+
@parameterized({
8497+
'dlmalloc': ['dlmalloc'],
8498+
'emmalloc': ['emmalloc'],
8499+
})
8500+
def test_malloc_alignment(self, malloc):
8501+
self.set_setting('MALLOC', malloc)
8502+
self.emcc_args += ['-std=gnu11']
8503+
src = open(path_from_root('tests', 'malloc_alignment.c')).read()
8504+
self.do_run(src, '', basename='src.c')
8505+
84968506

84978507
# Generate tests for everything
84988508
def make_run(name, emcc_args, settings=None, env=None):

0 commit comments

Comments
 (0)