Add the posix_memalign(3) function to bionic

The posix_memalign(3) function is very similar to the traditional
memalign(3) function, but with better error reporting and a guarantee
that the memory it allocates can be freed.  In bionic, memalign(3)
allocated memory can be freed, so posix_memalign(3) is just a wrapper
around memalign(3).

Change-Id: I62ee908aa5ba6b887d8446a00d8298d080a6a299
diff --git a/libc/bionic/dlmalloc.c b/libc/bionic/dlmalloc.c
index 8c75e9c..496cd1c 100644
--- a/libc/bionic/dlmalloc.c
+++ b/libc/bionic/dlmalloc.c
@@ -774,6 +774,22 @@
 void* dlmemalign(size_t, size_t);
 
 /*
+  int posix_memalign(void **memptr, size_t alignment, size_t size);
+  Places a pointer to a newly allocated chunk of size bytes, aligned
+  in accord with the alignment argument, in *memptr.
+
+  The return value is 0 on success, and ENOMEM on failure.
+
+  The alignment argument should be a power of two. If the argument is
+  not a power of two, the nearest greater power is used.
+  8-byte alignment is guaranteed by normal malloc calls, so don't
+  bother calling memalign with an argument of 8 or less.
+
+  Overreliance on posix_memalign is a sure way to fragment space.
+*/
+int posix_memalign(void **memptr, size_t alignment, size_t size);
+
+/*
   valloc(size_t n);
   Equivalent to memalign(pagesize, n), where pagesize is the page
   size of the system. If the pagesize is unknown, 4096 is used.
@@ -4507,6 +4523,18 @@
   return internal_memalign(gm, alignment, bytes);
 }
 
+int posix_memalign(void **memptr, size_t alignment, size_t size) {
+  int ret = 0;
+
+  *memptr = dlmemalign(alignment, size);
+
+  if (*memptr == 0) {
+    ret = ENOMEM;
+  }
+
+  return ret;
+}
+
 void** dlindependent_calloc(size_t n_elements, size_t elem_size,
                                  void* chunks[]) {
   size_t sz = elem_size; /* serves as 1-element array */
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 5dc8a87..e5caadd 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -67,6 +67,8 @@
 extern unsigned long long strtoull(const char *, char **, int);
 extern double strtod(const char *nptr, char **endptr);
 
+extern int posix_memalign(void **memptr, size_t alignment, size_t size);
+
 static __inline__ float strtof(const char *nptr, char **endptr)
 {
     return (float)strtod(nptr, endptr);