Add aligned_alloc to libc.

Bug: 72969374

Test: Bionic unit tests pass.
Test: Malloc debug unit tests pass.
Change-Id: I235985bbc638855d94249c97c98f14ab2924bda0
(cherry picked from commit d69ee59594088c0d92ba9273188ef53ea5e6cd6a)
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 1f201d1..940c418 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -69,6 +69,7 @@
     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 @@
   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 @@
                                                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;
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 944d72b..ef97538 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -79,6 +79,8 @@
 
 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);
 
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 839c406..a7977eb 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1322,6 +1322,7 @@
   global:
     __freading;
     __fwriting;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index a39a233..1cae22b 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1242,6 +1242,7 @@
   global:
     __freading;
     __fwriting;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index b3bfa8a..1188a85 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1347,6 +1347,7 @@
   global:
     __freading;
     __fwriting;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 2a93132..3d95079 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1306,6 +1306,7 @@
   global:
     __freading;
     __fwriting;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index a39a233..1cae22b 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1242,6 +1242,7 @@
   global:
     __freading;
     __fwriting;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index d2e7399..bcb5feb 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1304,6 +1304,7 @@
   global:
     __freading;
     __fwriting;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index a39a233..1cae22b 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1242,6 +1242,7 @@
   global:
     __freading;
     __fwriting;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
diff --git a/libc/malloc_debug/README.md b/libc/malloc_debug/README.md
index b7a12a5..69d0648 100644
--- a/libc/malloc_debug/README.md
+++ b/libc/malloc_debug/README.md
@@ -23,6 +23,7 @@
 * `realloc`
 * `posix_memalign`
 * `memalign`
+* `aligned_alloc`
 * `malloc_usable_size`
 
 On 32 bit systems, these two deprecated functions are also replaced:
@@ -324,6 +325,10 @@
 
 **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
diff --git a/libc/malloc_debug/RecordData.cpp b/libc/malloc_debug/RecordData.cpp
index 55d9943..8e9c671 100644
--- a/libc/malloc_debug/RecordData.cpp
+++ b/libc/malloc_debug/RecordData.cpp
@@ -86,7 +86,7 @@
                                      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) {
 }
diff --git a/libc/malloc_debug/RecordData.h b/libc/malloc_debug/RecordData.h
index ccabac2..97ad813 100644
--- a/libc/malloc_debug/RecordData.h
+++ b/libc/malloc_debug/RecordData.h
@@ -129,7 +129,7 @@
   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);
diff --git a/libc/malloc_debug/exported32.map b/libc/malloc_debug/exported32.map
index e92a7cf..78a6990 100644
--- a/libc/malloc_debug/exported32.map
+++ b/libc/malloc_debug/exported32.map
@@ -1,5 +1,6 @@
 LIBC_MALLOC_DEBUG {
   global:
+    debug_aligned_alloc;
     debug_calloc;
     debug_dump_heap;
     debug_finalize;
diff --git a/libc/malloc_debug/exported64.map b/libc/malloc_debug/exported64.map
index 94104b0..2bfc38b 100644
--- a/libc/malloc_debug/exported64.map
+++ b/libc/malloc_debug/exported64.map
@@ -1,5 +1,6 @@
 LIBC_MALLOC_DEBUG {
   global:
+    debug_aligned_alloc;
     debug_calloc;
     debug_dump_heap;
     debug_finalize;
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index a2ada2f..ecfbd71 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -77,6 +77,7 @@
 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 @@
   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);
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 4e90668..0e4a7d8 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -54,6 +54,7 @@
 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 @@
   nullptr,
   nullptr,
   mallopt,
+  aligned_alloc,
 };
 
 void VerifyAllocCalls(bool backtrace_enabled) {
@@ -308,6 +310,11 @@
   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 @@
   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);
diff --git a/libc/private/bionic_malloc_dispatch.h b/libc/private/bionic_malloc_dispatch.h
index cdae466..0dce03d 100644
--- a/libc/private/bionic_malloc_dispatch.h
+++ b/libc/private/bionic_malloc_dispatch.h
@@ -46,6 +46,7 @@
 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 @@
   MallocMallocDisable malloc_disable;
   MallocMallocEnable malloc_enable;
   MallocMallopt mallopt;
+  MallocAlignedAlloc aligned_alloc;
 } __attribute__((aligned(32)));
 
 #endif