Merge "Add aligned_alloc to libc."

am: dd1742aca5

Change-Id: Ieab65fd46e7688cce132139e3860cb98e23bda64
This commit is contained in:
Christopher Ferris 2018-02-07 17:07:08 +00:00 committed by android-build-merger
commit 9e0a5075a0
18 changed files with 110 additions and 2 deletions

View file

@ -69,6 +69,7 @@ static constexpr MallocDispatch __libc_malloc_default_dispatch
Malloc(malloc_disable),
Malloc(malloc_enable),
Malloc(mallopt),
Malloc(aligned_alloc),
};
// 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);
}
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) {
auto _realloc = __libc_globals->malloc_dispatch.realloc;
if (__predict_false(_realloc != nullptr)) {
@ -276,6 +285,10 @@ static bool InitMalloc(void* malloc_impl_handler, MallocDispatch* table, const c
prefix, "posix_memalign")) {
return false;
}
if (!InitMallocFunction<MallocAlignedAlloc>(malloc_impl_handler, &table->aligned_alloc,
prefix, "aligned_alloc")) {
return false;
}
if (!InitMallocFunction<MallocRealloc>(malloc_impl_handler, &table->realloc,
prefix, "realloc")) {
return false;

View file

@ -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);
void* aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28);
double strtod(const char* __s, char** __end_ptr);
long double strtold(const char* __s, char** __end_ptr) __RENAME_LDBL(strtod, 3, 21);

View file

@ -1322,6 +1322,7 @@ LIBC_P { # introduced=P
global:
__freading;
__fwriting;
aligned_alloc;
endhostent;
endnetent;
endprotoent;

View file

@ -1242,6 +1242,7 @@ LIBC_P { # introduced=P
global:
__freading;
__fwriting;
aligned_alloc;
endhostent;
endnetent;
endprotoent;

View file

@ -1347,6 +1347,7 @@ LIBC_P { # introduced=P
global:
__freading;
__fwriting;
aligned_alloc;
endhostent;
endnetent;
endprotoent;

View file

@ -1306,6 +1306,7 @@ LIBC_P { # introduced=P
global:
__freading;
__fwriting;
aligned_alloc;
endhostent;
endnetent;
endprotoent;

View file

@ -1242,6 +1242,7 @@ LIBC_P { # introduced=P
global:
__freading;
__fwriting;
aligned_alloc;
endhostent;
endnetent;
endprotoent;

View file

@ -1304,6 +1304,7 @@ LIBC_P { # introduced=P
global:
__freading;
__fwriting;
aligned_alloc;
endhostent;
endnetent;
endprotoent;

View file

@ -1242,6 +1242,7 @@ LIBC_P { # introduced=P
global:
__freading;
__fwriting;
aligned_alloc;
endhostent;
endnetent;
endprotoent;

View file

@ -23,6 +23,7 @@ the normal allocation calls. The replaced calls are:
* `realloc`
* `posix_memalign`
* `memalign`
* `aligned_alloc`
* `malloc_usable_size`
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
pointer = aligned\_alloc(alignment, size)
**THREAD\_ID**: memalign pointer alignment size
posix\_memalign(&pointer, alignment, size)
**THREAD\_ID**: memalign pointer alignment size

View file

@ -86,7 +86,7 @@ std::string ReallocEntry::GetString() const {
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)
: MallocEntry(pointer, size), alignment_(alignment) {
}

View file

@ -129,7 +129,7 @@ class ReallocEntry : public MallocEntry {
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 {
public:
MemalignEntry(void* pointer, size_t size, size_t alignment);

View file

@ -1,5 +1,6 @@
LIBC_MALLOC_DEBUG {
global:
debug_aligned_alloc;
debug_calloc;
debug_dump_heap;
debug_finalize;

View file

@ -1,5 +1,6 @@
LIBC_MALLOC_DEBUG {
global:
debug_aligned_alloc;
debug_calloc;
debug_dump_heap;
debug_finalize;

View file

@ -77,6 +77,7 @@ void debug_free_malloc_leak_info(uint8_t* info);
size_t debug_malloc_usable_size(void* pointer);
void* debug_malloc(size_t size);
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_realloc(void* pointer, 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);
}
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) {
if (DebugCallsDisabled()) {
return g_dispatch->posix_memalign(memptr, alignment, size);

View file

@ -54,6 +54,7 @@ void* debug_calloc(size_t, size_t);
void* debug_realloc(void*, size_t);
int debug_posix_memalign(void**, 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*);
void debug_get_malloc_leak_info(uint8_t**, size_t*, size_t*, size_t*, size_t*);
void debug_free_malloc_leak_info(uint8_t*);
@ -136,6 +137,7 @@ MallocDispatch MallocDebugTest::dispatch = {
nullptr,
nullptr,
mallopt,
aligned_alloc,
};
void VerifyAllocCalls(bool backtrace_enabled) {
@ -308,6 +310,11 @@ TEST_F(MallocDebugTest, expand_alloc) {
ASSERT_LE(1039U, debug_malloc_usable_size(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);
ASSERT_TRUE(pointer != nullptr);
ASSERT_LE(1054U, debug_malloc_usable_size(pointer));
@ -1772,6 +1779,12 @@ void VerifyRecordAllocs() {
debug_free(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_TRUE(pointer != nullptr);
expected += android::base::StringPrintf("%d: memalign %p 32 50\n", getpid(), pointer);

View file

@ -46,6 +46,7 @@ typedef int (*MallocIterate)(uintptr_t, size_t, void (*)(uintptr_t, size_t, void
typedef void (*MallocMallocDisable)();
typedef void (*MallocMallocEnable)();
typedef int (*MallocMallopt)(int, int);
typedef void* (*MallocAlignedAlloc)(size_t, size_t);
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
typedef void* (*MallocPvalloc)(size_t);
@ -71,6 +72,7 @@ struct MallocDispatch {
MallocMallocDisable malloc_disable;
MallocMallocEnable malloc_enable;
MallocMallopt mallopt;
MallocAlignedAlloc aligned_alloc;
} __attribute__((aligned(32)));
#endif

View file

@ -35,6 +35,14 @@
#include <limits>
#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
// 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.
@ -226,6 +234,50 @@ TEST(stdlib, posix_memalign_overflow) {
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) {
errno = 0;
// Work around the compile-time error generated by FORTIFY here.