Prevent the madvise(MADV_MERGEABLE) mmap hack from affecting errno.
Bug: 9889616
Change-Id: I4a7323e0ae5aeb5cbe0da1b2bc7501d83b3a2aa4
diff --git a/libc/Android.mk b/libc/Android.mk
index 0e93acd..38678f5 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -106,7 +106,6 @@
bionic/md5.c \
bionic/memmem.c \
bionic/memswap.c \
- bionic/mmap.c \
bionic/openat.c \
bionic/open.c \
bionic/pathconf.c \
@@ -200,6 +199,7 @@
bionic/__memcpy_chk.cpp \
bionic/__memmove_chk.cpp \
bionic/__memset_chk.cpp \
+ bionic/mmap.cpp \
bionic/pthread_attr.cpp \
bionic/pthread_detach.cpp \
bionic/pthread_equal.cpp \
diff --git a/libc/bionic/mmap.c b/libc/bionic/mmap.cpp
similarity index 69%
rename from libc/bionic/mmap.c
rename to libc/bionic/mmap.cpp
index e097086..864dea2 100644
--- a/libc/bionic/mmap.c
+++ b/libc/bionic/mmap.cpp
@@ -25,26 +25,30 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#include <unistd.h>
+
#include <errno.h>
#include <sys/mman.h>
+#include <unistd.h>
-extern void* __mmap2(void*, size_t, int, int, int, size_t);
+#include "private/ErrnoRestorer.h"
-#define MMAP2_SHIFT 12
-void* mmap(void *addr, size_t size, int prot, int flags, int fd, long offset)
-{
- void *ret;
+// mmap2(2) is like mmap(2), but the offset is in 4096-byte blocks, not bytes.
+extern "C" void* __mmap2(void*, size_t, int, int, int, size_t);
- if (offset & ((1UL << MMAP2_SHIFT)-1)) {
- errno = EINVAL;
- return MAP_FAILED;
- }
+#define MMAP2_SHIFT 12 // 2**12 == 4096
- ret = __mmap2(addr, size, prot, flags, fd, (size_t)offset >> MMAP2_SHIFT);
+void* mmap(void* addr, size_t size, int prot, int flags, int fd, long offset) {
+ if (offset & ((1UL << MMAP2_SHIFT)-1)) {
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
- if (ret && (flags & (MAP_PRIVATE | MAP_ANONYMOUS)))
- madvise(ret, size, MADV_MERGEABLE);
+ void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
- return ret;
+ if (result != MAP_FAILED && (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) != 0) {
+ ErrnoRestorer errno_restorer;
+ madvise(result, size, MADV_MERGEABLE);
+ }
+
+ return result;
}