Merge "Add aligned_alloc to libc." am: dd1742aca5
am: 9e0a5075a0
Change-Id: I1e08df3f6f6e812d71fbabd6f5a608171dbf88f6
This commit is contained in:
commit
3be6a96749
18 changed files with 110 additions and 2 deletions
|
@ -69,6 +69,7 @@ static constexpr MallocDispatch __libc_malloc_default_dispatch
|
||||||
Malloc(malloc_disable),
|
Malloc(malloc_disable),
|
||||||
Malloc(malloc_enable),
|
Malloc(malloc_enable),
|
||||||
Malloc(mallopt),
|
Malloc(mallopt),
|
||||||
|
Malloc(aligned_alloc),
|
||||||
};
|
};
|
||||||
|
|
||||||
// In a VM process, this is set to 1 after fork()ing out of zygote.
|
// In a VM process, this is set to 1 after fork()ing out of zygote.
|
||||||
|
@ -142,6 +143,14 @@ extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size) {
|
||||||
return Malloc(posix_memalign)(memptr, alignment, size);
|
return Malloc(posix_memalign)(memptr, alignment, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void* aligned_alloc(size_t alignment, size_t size) {
|
||||||
|
auto _aligned_alloc = __libc_globals->malloc_dispatch.aligned_alloc;
|
||||||
|
if (__predict_false(_aligned_alloc != nullptr)) {
|
||||||
|
return _aligned_alloc(alignment, size);
|
||||||
|
}
|
||||||
|
return Malloc(aligned_alloc)(alignment, size);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void* realloc(void* old_mem, size_t bytes) {
|
extern "C" void* realloc(void* old_mem, size_t bytes) {
|
||||||
auto _realloc = __libc_globals->malloc_dispatch.realloc;
|
auto _realloc = __libc_globals->malloc_dispatch.realloc;
|
||||||
if (__predict_false(_realloc != nullptr)) {
|
if (__predict_false(_realloc != nullptr)) {
|
||||||
|
@ -276,6 +285,10 @@ static bool InitMalloc(void* malloc_impl_handler, MallocDispatch* table, const c
|
||||||
prefix, "posix_memalign")) {
|
prefix, "posix_memalign")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!InitMallocFunction<MallocAlignedAlloc>(malloc_impl_handler, &table->aligned_alloc,
|
||||||
|
prefix, "aligned_alloc")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!InitMallocFunction<MallocRealloc>(malloc_impl_handler, &table->realloc,
|
if (!InitMallocFunction<MallocRealloc>(malloc_impl_handler, &table->realloc,
|
||||||
prefix, "realloc")) {
|
prefix, "realloc")) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -79,6 +79,8 @@ unsigned long long strtoull(const char* __s, char** __end_ptr, int __base);
|
||||||
|
|
||||||
int posix_memalign(void** __memptr, size_t __alignment, size_t __size) __INTRODUCED_IN(16);
|
int posix_memalign(void** __memptr, size_t __alignment, size_t __size) __INTRODUCED_IN(16);
|
||||||
|
|
||||||
|
void* aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28);
|
||||||
|
|
||||||
double strtod(const char* __s, char** __end_ptr);
|
double strtod(const char* __s, char** __end_ptr);
|
||||||
long double strtold(const char* __s, char** __end_ptr) __RENAME_LDBL(strtod, 3, 21);
|
long double strtold(const char* __s, char** __end_ptr) __RENAME_LDBL(strtod, 3, 21);
|
||||||
|
|
||||||
|
|
|
@ -1322,6 +1322,7 @@ LIBC_P { # introduced=P
|
||||||
global:
|
global:
|
||||||
__freading;
|
__freading;
|
||||||
__fwriting;
|
__fwriting;
|
||||||
|
aligned_alloc;
|
||||||
endhostent;
|
endhostent;
|
||||||
endnetent;
|
endnetent;
|
||||||
endprotoent;
|
endprotoent;
|
||||||
|
|
|
@ -1242,6 +1242,7 @@ LIBC_P { # introduced=P
|
||||||
global:
|
global:
|
||||||
__freading;
|
__freading;
|
||||||
__fwriting;
|
__fwriting;
|
||||||
|
aligned_alloc;
|
||||||
endhostent;
|
endhostent;
|
||||||
endnetent;
|
endnetent;
|
||||||
endprotoent;
|
endprotoent;
|
||||||
|
|
|
@ -1347,6 +1347,7 @@ LIBC_P { # introduced=P
|
||||||
global:
|
global:
|
||||||
__freading;
|
__freading;
|
||||||
__fwriting;
|
__fwriting;
|
||||||
|
aligned_alloc;
|
||||||
endhostent;
|
endhostent;
|
||||||
endnetent;
|
endnetent;
|
||||||
endprotoent;
|
endprotoent;
|
||||||
|
|
|
@ -1306,6 +1306,7 @@ LIBC_P { # introduced=P
|
||||||
global:
|
global:
|
||||||
__freading;
|
__freading;
|
||||||
__fwriting;
|
__fwriting;
|
||||||
|
aligned_alloc;
|
||||||
endhostent;
|
endhostent;
|
||||||
endnetent;
|
endnetent;
|
||||||
endprotoent;
|
endprotoent;
|
||||||
|
|
|
@ -1242,6 +1242,7 @@ LIBC_P { # introduced=P
|
||||||
global:
|
global:
|
||||||
__freading;
|
__freading;
|
||||||
__fwriting;
|
__fwriting;
|
||||||
|
aligned_alloc;
|
||||||
endhostent;
|
endhostent;
|
||||||
endnetent;
|
endnetent;
|
||||||
endprotoent;
|
endprotoent;
|
||||||
|
|
|
@ -1304,6 +1304,7 @@ LIBC_P { # introduced=P
|
||||||
global:
|
global:
|
||||||
__freading;
|
__freading;
|
||||||
__fwriting;
|
__fwriting;
|
||||||
|
aligned_alloc;
|
||||||
endhostent;
|
endhostent;
|
||||||
endnetent;
|
endnetent;
|
||||||
endprotoent;
|
endprotoent;
|
||||||
|
|
|
@ -1242,6 +1242,7 @@ LIBC_P { # introduced=P
|
||||||
global:
|
global:
|
||||||
__freading;
|
__freading;
|
||||||
__fwriting;
|
__fwriting;
|
||||||
|
aligned_alloc;
|
||||||
endhostent;
|
endhostent;
|
||||||
endnetent;
|
endnetent;
|
||||||
endprotoent;
|
endprotoent;
|
||||||
|
|
|
@ -23,6 +23,7 @@ the normal allocation calls. The replaced calls are:
|
||||||
* `realloc`
|
* `realloc`
|
||||||
* `posix_memalign`
|
* `posix_memalign`
|
||||||
* `memalign`
|
* `memalign`
|
||||||
|
* `aligned_alloc`
|
||||||
* `malloc_usable_size`
|
* `malloc_usable_size`
|
||||||
|
|
||||||
On 32 bit systems, these two deprecated functions are also replaced:
|
On 32 bit systems, these two deprecated functions are also replaced:
|
||||||
|
@ -324,6 +325,10 @@ pointer = memalign(alignment, size)
|
||||||
|
|
||||||
**THREAD\_ID**: memalign pointer alignment size
|
**THREAD\_ID**: memalign pointer alignment size
|
||||||
|
|
||||||
|
pointer = aligned\_alloc(alignment, size)
|
||||||
|
|
||||||
|
**THREAD\_ID**: memalign pointer alignment size
|
||||||
|
|
||||||
posix\_memalign(&pointer, alignment, size)
|
posix\_memalign(&pointer, alignment, size)
|
||||||
|
|
||||||
**THREAD\_ID**: memalign pointer alignment size
|
**THREAD\_ID**: memalign pointer alignment size
|
||||||
|
|
|
@ -86,7 +86,7 @@ std::string ReallocEntry::GetString() const {
|
||||||
old_pointer_, size_);
|
old_pointer_, size_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// posix_memalign, memalgin, pvalloc, valloc all recorded with this class.
|
// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
|
||||||
MemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment)
|
MemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment)
|
||||||
: MallocEntry(pointer, size), alignment_(alignment) {
|
: MallocEntry(pointer, size), alignment_(alignment) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ class ReallocEntry : public MallocEntry {
|
||||||
DISALLOW_COPY_AND_ASSIGN(ReallocEntry);
|
DISALLOW_COPY_AND_ASSIGN(ReallocEntry);
|
||||||
};
|
};
|
||||||
|
|
||||||
// posix_memalign, memalign, pvalloc, valloc all recorded with this class.
|
// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
|
||||||
class MemalignEntry : public MallocEntry {
|
class MemalignEntry : public MallocEntry {
|
||||||
public:
|
public:
|
||||||
MemalignEntry(void* pointer, size_t size, size_t alignment);
|
MemalignEntry(void* pointer, size_t size, size_t alignment);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
LIBC_MALLOC_DEBUG {
|
LIBC_MALLOC_DEBUG {
|
||||||
global:
|
global:
|
||||||
|
debug_aligned_alloc;
|
||||||
debug_calloc;
|
debug_calloc;
|
||||||
debug_dump_heap;
|
debug_dump_heap;
|
||||||
debug_finalize;
|
debug_finalize;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
LIBC_MALLOC_DEBUG {
|
LIBC_MALLOC_DEBUG {
|
||||||
global:
|
global:
|
||||||
|
debug_aligned_alloc;
|
||||||
debug_calloc;
|
debug_calloc;
|
||||||
debug_dump_heap;
|
debug_dump_heap;
|
||||||
debug_finalize;
|
debug_finalize;
|
||||||
|
|
|
@ -77,6 +77,7 @@ void debug_free_malloc_leak_info(uint8_t* info);
|
||||||
size_t debug_malloc_usable_size(void* pointer);
|
size_t debug_malloc_usable_size(void* pointer);
|
||||||
void* debug_malloc(size_t size);
|
void* debug_malloc(size_t size);
|
||||||
void debug_free(void* pointer);
|
void debug_free(void* pointer);
|
||||||
|
void* debug_aligned_alloc(size_t alignment, size_t size);
|
||||||
void* debug_memalign(size_t alignment, size_t bytes);
|
void* debug_memalign(size_t alignment, size_t bytes);
|
||||||
void* debug_realloc(void* pointer, size_t bytes);
|
void* debug_realloc(void* pointer, size_t bytes);
|
||||||
void* debug_calloc(size_t nmemb, size_t bytes);
|
void* debug_calloc(size_t nmemb, size_t bytes);
|
||||||
|
@ -669,6 +670,17 @@ int debug_mallopt(int param, int value) {
|
||||||
return g_dispatch->mallopt(param, value);
|
return g_dispatch->mallopt(param, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* debug_aligned_alloc(size_t alignment, size_t size) {
|
||||||
|
if (DebugCallsDisabled()) {
|
||||||
|
return g_dispatch->aligned_alloc(alignment, size);
|
||||||
|
}
|
||||||
|
if (!powerof2(alignment)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return debug_memalign(alignment, size);
|
||||||
|
}
|
||||||
|
|
||||||
int debug_posix_memalign(void** memptr, size_t alignment, size_t size) {
|
int debug_posix_memalign(void** memptr, size_t alignment, size_t size) {
|
||||||
if (DebugCallsDisabled()) {
|
if (DebugCallsDisabled()) {
|
||||||
return g_dispatch->posix_memalign(memptr, alignment, size);
|
return g_dispatch->posix_memalign(memptr, alignment, size);
|
||||||
|
|
|
@ -54,6 +54,7 @@ void* debug_calloc(size_t, size_t);
|
||||||
void* debug_realloc(void*, size_t);
|
void* debug_realloc(void*, size_t);
|
||||||
int debug_posix_memalign(void**, size_t, size_t);
|
int debug_posix_memalign(void**, size_t, size_t);
|
||||||
void* debug_memalign(size_t, size_t);
|
void* debug_memalign(size_t, size_t);
|
||||||
|
void* debug_aligned_alloc(size_t, size_t);
|
||||||
size_t debug_malloc_usable_size(void*);
|
size_t debug_malloc_usable_size(void*);
|
||||||
void debug_get_malloc_leak_info(uint8_t**, size_t*, size_t*, size_t*, size_t*);
|
void debug_get_malloc_leak_info(uint8_t**, size_t*, size_t*, size_t*, size_t*);
|
||||||
void debug_free_malloc_leak_info(uint8_t*);
|
void debug_free_malloc_leak_info(uint8_t*);
|
||||||
|
@ -136,6 +137,7 @@ MallocDispatch MallocDebugTest::dispatch = {
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
mallopt,
|
mallopt,
|
||||||
|
aligned_alloc,
|
||||||
};
|
};
|
||||||
|
|
||||||
void VerifyAllocCalls(bool backtrace_enabled) {
|
void VerifyAllocCalls(bool backtrace_enabled) {
|
||||||
|
@ -308,6 +310,11 @@ TEST_F(MallocDebugTest, expand_alloc) {
|
||||||
ASSERT_LE(1039U, debug_malloc_usable_size(pointer));
|
ASSERT_LE(1039U, debug_malloc_usable_size(pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
|
|
||||||
|
pointer = debug_aligned_alloc(128, 15);
|
||||||
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
|
ASSERT_LE(1039U, debug_malloc_usable_size(pointer));
|
||||||
|
debug_free(pointer);
|
||||||
|
|
||||||
pointer = debug_realloc(nullptr, 30);
|
pointer = debug_realloc(nullptr, 30);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
ASSERT_LE(1054U, debug_malloc_usable_size(pointer));
|
ASSERT_LE(1054U, debug_malloc_usable_size(pointer));
|
||||||
|
@ -1772,6 +1779,12 @@ void VerifyRecordAllocs() {
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
||||||
|
|
||||||
|
pointer = debug_aligned_alloc(32, 50);
|
||||||
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
|
expected += android::base::StringPrintf("%d: memalign %p 32 50\n", getpid(), pointer);
|
||||||
|
debug_free(pointer);
|
||||||
|
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
||||||
|
|
||||||
ASSERT_EQ(0, debug_posix_memalign(&pointer, 32, 50));
|
ASSERT_EQ(0, debug_posix_memalign(&pointer, 32, 50));
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: memalign %p 32 50\n", getpid(), pointer);
|
expected += android::base::StringPrintf("%d: memalign %p 32 50\n", getpid(), pointer);
|
||||||
|
|
|
@ -46,6 +46,7 @@ typedef int (*MallocIterate)(uintptr_t, size_t, void (*)(uintptr_t, size_t, void
|
||||||
typedef void (*MallocMallocDisable)();
|
typedef void (*MallocMallocDisable)();
|
||||||
typedef void (*MallocMallocEnable)();
|
typedef void (*MallocMallocEnable)();
|
||||||
typedef int (*MallocMallopt)(int, int);
|
typedef int (*MallocMallopt)(int, int);
|
||||||
|
typedef void* (*MallocAlignedAlloc)(size_t, size_t);
|
||||||
|
|
||||||
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
|
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
|
||||||
typedef void* (*MallocPvalloc)(size_t);
|
typedef void* (*MallocPvalloc)(size_t);
|
||||||
|
@ -71,6 +72,7 @@ struct MallocDispatch {
|
||||||
MallocMallocDisable malloc_disable;
|
MallocMallocDisable malloc_disable;
|
||||||
MallocMallocEnable malloc_enable;
|
MallocMallocEnable malloc_enable;
|
||||||
MallocMallopt mallopt;
|
MallocMallopt mallopt;
|
||||||
|
MallocAlignedAlloc aligned_alloc;
|
||||||
} __attribute__((aligned(32)));
|
} __attribute__((aligned(32)));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,6 +35,14 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#if defined(__BIONIC__)
|
||||||
|
#define ALIGNED_ALLOC_AVAILABLE 1
|
||||||
|
#elif defined(__GLIBC_PREREQ)
|
||||||
|
#if __GLIBC_PREREQ(2, 16)
|
||||||
|
#define ALIGNED_ALLOC_AVAILABLE 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// The random number generator tests all set the seed, get four values, reset the seed and check
|
// The random number generator tests all set the seed, get four values, reset the seed and check
|
||||||
// that they get the first two values repeated, and then reset the seed and check two more values
|
// that they get the first two values repeated, and then reset the seed and check two more values
|
||||||
// to rule out the possibility that we're just going round a cycle of four values.
|
// to rule out the possibility that we're just going round a cycle of four values.
|
||||||
|
@ -226,6 +234,50 @@ TEST(stdlib, posix_memalign_overflow) {
|
||||||
ASSERT_NE(0, posix_memalign(&ptr, 16, SIZE_MAX));
|
ASSERT_NE(0, posix_memalign(&ptr, 16, SIZE_MAX));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(stdlib, aligned_alloc_sweep) {
|
||||||
|
#if defined(ALIGNED_ALLOC_AVAILABLE)
|
||||||
|
// Verify powers of 2 up to 2048 allocate, and verify that all other
|
||||||
|
// alignment values between the powers of 2 fail.
|
||||||
|
size_t last_align = 1;
|
||||||
|
for (size_t align = 1; align <= 2048; align <<= 1) {
|
||||||
|
// Try all of the non power of 2 values from the last until this value.
|
||||||
|
for (size_t fail_align = last_align + 1; fail_align < align; fail_align++) {
|
||||||
|
ASSERT_TRUE(aligned_alloc(fail_align, 256) == nullptr)
|
||||||
|
<< "Unexpected success at align " << fail_align;
|
||||||
|
ASSERT_EQ(EINVAL, errno) << "Unexpected errno at align " << fail_align;
|
||||||
|
}
|
||||||
|
void* ptr = aligned_alloc(align, 256);
|
||||||
|
ASSERT_TRUE(ptr != nullptr) << "Unexpected failure at align " << align;
|
||||||
|
ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
|
||||||
|
<< "Did not return a valid aligned ptr " << ptr << " expected alignment " << align;
|
||||||
|
free(ptr);
|
||||||
|
last_align = align;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
GTEST_LOG_(INFO) << "This test requires a C library that has aligned_alloc.\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(stdlib, aligned_alloc_overflow) {
|
||||||
|
#if defined(ALIGNED_ALLOC_AVAILABLE)
|
||||||
|
ASSERT_TRUE(aligned_alloc(16, SIZE_MAX) == nullptr);
|
||||||
|
#else
|
||||||
|
GTEST_LOG_(INFO) << "This test requires a C library that has aligned_alloc.\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(stdlib, aligned_alloc_size_not_multiple_of_alignment) {
|
||||||
|
#if defined(ALIGNED_ALLOC_AVAILABLE)
|
||||||
|
for (size_t size = 1; size <= 2048; size++) {
|
||||||
|
void* ptr = aligned_alloc(2048, size);
|
||||||
|
ASSERT_TRUE(ptr != nullptr) << "Failed at size " << std::to_string(size);
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
GTEST_LOG_(INFO) << "This test requires a C library that has aligned_alloc.\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
TEST(stdlib, realpath__NULL_filename) {
|
TEST(stdlib, realpath__NULL_filename) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
// Work around the compile-time error generated by FORTIFY here.
|
// Work around the compile-time error generated by FORTIFY here.
|
||||||
|
|
Loading…
Reference in a new issue