mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-05 03:07:56 +00:00
This is the first part of Bug 466104 aligned_alloc problems, part 1 The bulk of this change is try try to get memalign to be more platform aware. Previously the Valgrind implementation only reflected the glibc implementation. That meant non-power of two alignment values would silently get bumped up to the next largest power of two. Most other platforms return NULL and set errno to EINVAL. There are a few other changes. A couple of the other aligned alloc functions like valloc were caling the Valgrind memalign. This meant that there weould be an extra Valgrind memalign in any error callstacks. Now these functions call the allocator directly. The memcheck memalign2 testcase has been redone. The memalign parts moved out to per-platform versions and the tescase itdelf renamed to posix_memalign, since that is all that is left. I also modified the testcase so that it checks that the memalign calls check for non-NULL returns, and on platforms that set errno that it is correctly set. Previously the test only worked on non-glibc because NULL & alignment is zero. The platform versions have been tested on glibc, MUSL, FreeBSD and OpenIndiana and should hopefully run OK both under memcheck and standalone. There is stil quite a lot that is NOT done 1. I'm not certain that implementations allocate more memory and/or use a wider alignment. It doesn't help that almost universally the memalign implementations are badly documented, undocumented or buggy. 2. We don't handle very large alignment requests well. Most implementations will fail and set EINVAL if the alignment is over half the memory space. Valgrind will core panic if an aligmnt of over 16Mbytes is requested. 3. We don't generate any memcheck errors for invalid values of alignment. That's planned in Part 2. 4. The code is static and fixed at compile time. That means that if you are using MUSL with a glibc-built Valgrind you will still get glibc memalign behaviour. I'll wait to see if there are any requests before trying to make the behaviour selectable at runtime.
85 lines
2.0 KiB
C
85 lines
2.0 KiB
C
#include <stdlib.h>
|
|
#if defined(__FreeBSD__)
|
|
#include <malloc_np.h>
|
|
#endif
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
|
|
int main(void)
|
|
{
|
|
char* p = NULL;
|
|
int res;
|
|
|
|
// zero alignment
|
|
res = posix_memalign((void**)&p, 0, 8);
|
|
assert(p == NULL && res == EINVAL);
|
|
// align not multiple of sizeof(void*)
|
|
res = posix_memalign((void**)&p, 2, 32);
|
|
assert(p == NULL && res == EINVAL);
|
|
// align not power of two
|
|
res = posix_memalign((void**)&p, 40, 160);
|
|
assert(p == NULL && res == EINVAL);
|
|
|
|
// digging through the jemalloc code
|
|
// the max alignment allowed is
|
|
// 0x70000000 for i386 and
|
|
// 0x7000000000000000 for amd64
|
|
// but valgrind has a limit of only 16M
|
|
// 0x10000000
|
|
// on both platforms
|
|
// the 64bit limit is around 1e18 bytes
|
|
// a million terabytes
|
|
|
|
// Valgrind handles that badly. it throws a core_panic :-(
|
|
|
|
//res = posix_memalign((void**)&p, (1UL<<63), 4096);
|
|
//assert(p == NULL && res == ENOMEM);
|
|
|
|
// too big
|
|
if (sizeof(size_t) == 8)
|
|
{
|
|
res = posix_memalign((void**)&p, 16, 1UL<<48);
|
|
}
|
|
else
|
|
{
|
|
// on x86 it's hard to actually get ENOMEM
|
|
// if we ask for more than 2Gbytes the fishy
|
|
// detector will kick in and not try to allocate
|
|
// less than 2Gbytes and it's likely to succeed
|
|
// (at least on a machine just running VG regtests)
|
|
// so fake it
|
|
p = NULL;
|
|
res = ENOMEM;
|
|
}
|
|
assert(p == NULL && res == ENOMEM);
|
|
errno = 0;
|
|
|
|
|
|
// if ever we make this multi-platform, Solaris doesn't support this
|
|
// zero size
|
|
p = aligned_alloc(0, 8);
|
|
assert(p == NULL && errno == EINVAL);
|
|
errno = 0;
|
|
// non multiple of alignment passes on FreeBSD
|
|
//p = aligned_alloc(8, 25);
|
|
//assert(p == NULL && errno == EINVAL);
|
|
//errno = 0;
|
|
// align not power of 2
|
|
p = aligned_alloc(40, 160);
|
|
assert(p == NULL && errno == EINVAL);
|
|
errno = 0;
|
|
// too big
|
|
if (sizeof(size_t) == 8)
|
|
{
|
|
p = aligned_alloc(16, 1UL<<48);
|
|
}
|
|
else
|
|
{
|
|
p = NULL;
|
|
errno = ENOMEM;
|
|
}
|
|
assert(p == NULL && errno == ENOMEM);
|
|
}
|
|
|
|
|