Prevent the madvise(MADV_MERGEABLE) mmap hack from affecting errno.
Bug: 9889616
Change-Id: I4a7323e0ae5aeb5cbe0da1b2bc7501d83b3a2aa4
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;
}