Merge "[MIPS] Rewrite MIPS crtbegin* as C files."
diff --git a/libc/Android.mk b/libc/Android.mk
index 4206020..bfeb391 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 40a6538..864dea2 100644
--- a/libc/bionic/mmap.c
+++ b/libc/bionic/mmap.cpp
@@ -25,19 +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)
-{
-    if (offset & ((1UL << MMAP2_SHIFT)-1)) {
-        errno = EINVAL;
-        return MAP_FAILED;
-    }
+// 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);
 
-    return __mmap2(addr, size, prot, flags, fd, (size_t)offset >> MMAP2_SHIFT);
+#define MMAP2_SHIFT 12 // 2**12 == 4096
+
+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;
+  }
+
+  void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
+
+  if (result != MAP_FAILED && (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) != 0) {
+    ErrnoRestorer errno_restorer;
+    madvise(result, size, MADV_MERGEABLE);
+  }
+
+  return result;
 }
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index d38e20c..63695d3 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -62,7 +62,16 @@
     thread->tls[i] = NULL;
   }
 
+  // Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
+  thread->tls[TLS_SLOT_SELF] = thread->tls;
+  thread->tls[TLS_SLOT_THREAD_ID] = thread;
+  // GCC looks in the TLS for the stack guard on x86, so copy it there from our global.
+  thread->tls[TLS_SLOT_STACK_GUARD] = (void*) __stack_chk_guard;
+
+  __set_tls(thread->tls);
+
   // Create and set an alternate signal stack.
+  // This must happen after __set_tls, in case a system call fails and tries to set errno.
   stack_t ss;
   ss.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
   if (ss.ss_sp != MAP_FAILED) {
@@ -71,14 +80,6 @@
     sigaltstack(&ss, NULL);
     thread->alternate_signal_stack = ss.ss_sp;
   }
-
-  // Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
-  thread->tls[TLS_SLOT_SELF] = thread->tls;
-  thread->tls[TLS_SLOT_THREAD_ID] = thread;
-  // GCC looks in the TLS for the stack guard on x86, so copy it there from our global.
-  thread->tls[TLS_SLOT_STACK_GUARD] = (void*) __stack_chk_guard;
-
-  __set_tls(thread->tls);
 }
 
 // This trampoline is called from the assembly _pthread_clone function.