aboutsummaryrefslogtreecommitdiffstats
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/SYSCALLS.TXT4
-rw-r--r--libc/arch-mips64/bionic/stat.cpp103
-rw-r--r--libc/arch-mips64/mips64.mk1
-rw-r--r--libc/arch-mips64/syscalls/fstat64.S28
-rw-r--r--libc/arch-mips64/syscalls/fstatat64.S28
-rw-r--r--libc/bionic/__cxa_guard.cpp105
-rw-r--r--libc/bionic/bionic_systrace.cpp1
-rw-r--r--libc/bionic/debug_stacktrace.cpp1
-rw-r--r--libc/bionic/dirent.cpp2
-rw-r--r--libc/bionic/getcwd.cpp4
-rw-r--r--libc/bionic/malloc_debug_common.cpp1
-rw-r--r--libc/bionic/malloc_debug_qemu.cpp1
-rw-r--r--libc/bionic/posix_timers.cpp1
-rw-r--r--libc/bionic/pthread_create.cpp1
-rw-r--r--libc/bionic/pthread_once.cpp75
-rw-r--r--libc/bionic/pthread_setname_np.cpp1
-rw-r--r--libc/bionic/vdso.cpp1
-rw-r--r--libc/dns/net/getservent.c1
-rw-r--r--libc/include/pthread.h2
-rw-r--r--libc/include/sys/stat.h4
20 files changed, 215 insertions, 150 deletions
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index a648c9fef..0fa2a1e10 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -134,7 +134,7 @@ int faccessat(int, const char*, int, int) all
int fchmodat(int, const char*, mode_t, int) all
int fchownat(int, const char*, uid_t, gid_t, int) all
int fstatat64|fstatat:fstatat64(int, const char*, struct stat*, int) arm,mips,x86
-int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int) arm64,mips64,x86_64
+int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int) arm64,x86_64
int linkat(int, const char*, int, const char*, int) all
int mkdirat(int, const char*, mode_t) all
int mknodat(int, const char*, mode_t, dev_t) all
@@ -179,7 +179,7 @@ int __statfs64:statfs64(const char*, size_t, struct statfs*) arm,mips,x86
int statfs64|statfs:statfs(const char*, struct statfs*) arm64,mips64,x86_64
int fstat64|fstat:fstat64(int, struct stat*) arm,mips,x86
-int fstat64|fstat:fstat(int, struct stat*) arm64,mips64,x86_64
+int fstat64|fstat:fstat(int, struct stat*) arm64,x86_64
# file system
int chdir(const char*) all
diff --git a/libc/arch-mips64/bionic/stat.cpp b/libc/arch-mips64/bionic/stat.cpp
new file mode 100644
index 000000000..df63906cb
--- /dev/null
+++ b/libc/arch-mips64/bionic/stat.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <asm/unistd.h>
+
+struct kernel_stat {
+ unsigned int st_dev;
+ unsigned int st_pad0[3];
+ unsigned long st_ino;
+ mode_t st_mode;
+ __u32 st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ unsigned int st_rdev;
+ unsigned int st_pad1[3];
+ __kernel_off_t st_size;
+ unsigned int _st_atime;
+ unsigned int st_atime_nsec;
+ unsigned int _st_mtime;
+ unsigned int st_mtime_nsec;
+ unsigned int _st_ctime;
+ unsigned int st_ctime_nsec;
+ unsigned int st_blksize;
+ unsigned int st_pad2;
+ unsigned long st_blocks;
+};
+
+void copy_stat(struct stat *st, struct kernel_stat *s)
+{
+ st->st_dev = static_cast<dev_t>(s->st_dev);
+ st->st_ino = static_cast<ino_t>(s->st_ino);
+ st->st_mode = static_cast<mode_t>(s->st_mode);
+ st->st_nlink = static_cast<nlink_t>(s->st_nlink);
+ st->st_uid = static_cast<uid_t>(s->st_uid);
+ st->st_gid = static_cast<gid_t>(s->st_gid);
+ st->st_rdev = static_cast<dev_t>(s->st_rdev);
+ st->st_size = static_cast<off_t>(s->st_size);
+ st->st_blksize = static_cast<int>(s->st_blksize);
+ st->st_blocks = static_cast<long>(s->st_blocks);
+ st->st_atim.tv_sec = static_cast<time_t>(s->_st_atime);
+ st->st_atim.tv_nsec = static_cast<long>(s->st_atime_nsec);
+ st->st_mtim.tv_sec = static_cast<time_t>(s->_st_mtime);
+ st->st_mtim.tv_nsec = static_cast<long>(s->st_mtime_nsec);
+ st->st_ctim.tv_sec = static_cast<time_t>(s->_st_ctime);
+ st->st_ctim.tv_nsec = static_cast<long>(s->st_ctime_nsec);
+}
+
+int fstat(int fp, struct stat *st)
+{
+ kernel_stat s;
+ int ret;
+ ret = syscall (__NR_fstat, fp, &s);
+ copy_stat (st, &s);
+ return ret;
+}
+__strong_alias(fstat64, fstat);
+
+int newfstatat(int dirfd, const char *pathname, struct stat *buf, int flags)
+{
+ kernel_stat s;
+ int ret;
+ ret = syscall(__NR_newfstatat, dirfd, pathname, &s, flags);
+ copy_stat(buf, &s);
+ return ret;
+}
+
+int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags)
+{
+ kernel_stat s;
+ int ret;
+ ret = syscall(__NR_newfstatat, dirfd, pathname, &s, flags);
+ copy_stat(buf, &s);
+ return ret;
+}
+__strong_alias(fstatat64, fstatat);
diff --git a/libc/arch-mips64/mips64.mk b/libc/arch-mips64/mips64.mk
index 7990c6977..137639550 100644
--- a/libc/arch-mips64/mips64.mk
+++ b/libc/arch-mips64/mips64.mk
@@ -52,6 +52,7 @@ libc_bionic_src_files_mips64 += \
arch-mips64/bionic/setjmp.S \
arch-mips64/bionic/syscall.S \
arch-mips64/bionic/vfork.S \
+ arch-mips64/bionic/stat.cpp \
libc_crt_target_cflags_mips64 := \
$($(my_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) \
diff --git a/libc/arch-mips64/syscalls/fstat64.S b/libc/arch-mips64/syscalls/fstat64.S
deleted file mode 100644
index a14d51cb6..000000000
--- a/libc/arch-mips64/syscalls/fstat64.S
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(fstat64)
- .set push
- .set noreorder
- li v0, __NR_fstat
- syscall
- bnez a3, 1f
- move a0, v0
- j ra
- nop
-1:
- move t0, ra
- bal 2f
- nop
-2:
- .cpsetup ra, t1, 2b
- LA t9,__set_errno_internal
- .cpreturn
- j t9
- move ra, t0
- .set pop
-END(fstat64)
-
- .globl fstat
- .equ fstat, fstat64
diff --git a/libc/arch-mips64/syscalls/fstatat64.S b/libc/arch-mips64/syscalls/fstatat64.S
deleted file mode 100644
index 7888a432d..000000000
--- a/libc/arch-mips64/syscalls/fstatat64.S
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(fstatat64)
- .set push
- .set noreorder
- li v0, __NR_newfstatat
- syscall
- bnez a3, 1f
- move a0, v0
- j ra
- nop
-1:
- move t0, ra
- bal 2f
- nop
-2:
- .cpsetup ra, t1, 2b
- LA t9,__set_errno_internal
- .cpreturn
- j t9
- move ra, t0
- .set pop
-END(fstatat64)
-
- .globl fstatat
- .equ fstatat, fstatat64
diff --git a/libc/bionic/__cxa_guard.cpp b/libc/bionic/__cxa_guard.cpp
index 5b0d57d0b..5b34b584b 100644
--- a/libc/bionic/__cxa_guard.cpp
+++ b/libc/bionic/__cxa_guard.cpp
@@ -14,10 +14,13 @@
* limitations under the License.
*/
-#include <stddef.h>
#include <endian.h>
+#include <limits.h>
+#undef _USING_LIBCXX // Prevent using of <atomic>.
+#include <stdatomic.h>
+
+#include <stddef.h>
-#include "private/bionic_atomic_inline.h"
#include "private/bionic_futex.h"
// This file contains C++ ABI support functions for one time
@@ -49,66 +52,82 @@
// values. The LSB is tested by the compiler-generated code before calling
// __cxa_guard_acquire.
union _guard_t {
- int volatile state;
- int32_t aligner;
+ atomic_int state;
+ int32_t aligner;
};
-const static int ready = 0x1;
-const static int pending = 0x2;
-const static int waiting = 0x6;
-
#else
// The Itanium/x86 C++ ABI (used by all other architectures) mandates that
// guard variables are 64-bit aligned, 64-bit values. The LSB is tested by
// the compiler-generated code before calling __cxa_guard_acquire.
union _guard_t {
- int volatile state;
- int64_t aligner;
+ atomic_int state;
+ int64_t aligner;
};
-const static int ready = letoh32(0x1);
-const static int pending = letoh32(0x100);
-const static int waiting = letoh32(0x10000);
#endif
-extern "C" int __cxa_guard_acquire(_guard_t* gv) {
- // 0 -> pending, return 1
- // pending -> waiting, wait and return 0
- // waiting: untouched, wait and return 0
- // ready: untouched, return 0
+// Set construction state values according to reference documentation.
+// 0 is the initialization value.
+// Arm requires ((*gv & 1) == 1) after __cxa_guard_release, ((*gv & 3) == 0) after __cxa_guard_abort.
+// X86 requires first byte not modified by __cxa_guard_acquire, first byte is non-zero after
+// __cxa_guard_release.
-retry:
- if (__bionic_cmpxchg(0, pending, &gv->state) == 0) {
- ANDROID_MEMBAR_FULL();
- return 1;
- }
- __bionic_cmpxchg(pending, waiting, &gv->state); // Indicate there is a waiter
- __futex_wait(&gv->state, waiting, NULL);
+#define CONSTRUCTION_NOT_YET_STARTED 0
+#define CONSTRUCTION_COMPLETE 1
+#define CONSTRUCTION_UNDERWAY_WITHOUT_WAITER 0x100
+#define CONSTRUCTION_UNDERWAY_WITH_WAITER 0x200
- if (gv->state != ready) {
- // __cxa_guard_abort was called, let every thread try since there is no return code for this condition
- goto retry;
+extern "C" int __cxa_guard_acquire(_guard_t* gv) {
+ int old_value = atomic_load_explicit(&gv->state, memory_order_relaxed);
+
+ while (true) {
+ if (old_value == CONSTRUCTION_COMPLETE) {
+ // A load_acquire operation is need before exiting with COMPLETE state, as we have to ensure
+ // that all the stores performed by the construction function are observable on this CPU
+ // after we exit.
+ atomic_thread_fence(memory_order_acquire);
+ return 0;
+ } else if (old_value == CONSTRUCTION_NOT_YET_STARTED) {
+ if (!atomic_compare_exchange_weak_explicit(&gv->state, &old_value,
+ CONSTRUCTION_UNDERWAY_WITHOUT_WAITER,
+ memory_order_relaxed,
+ memory_order_relaxed)) {
+ continue;
+ }
+ // The acquire fence may not be needed. But as described in section 3.3.2 of
+ // the Itanium C++ ABI specification, it probably has to behave like the
+ // acquisition of a mutex, which needs an acquire fence.
+ atomic_thread_fence(memory_order_acquire);
+ return 1;
+ } else if (old_value == CONSTRUCTION_UNDERWAY_WITHOUT_WAITER) {
+ if (!atomic_compare_exchange_weak_explicit(&gv->state, &old_value,
+ CONSTRUCTION_UNDERWAY_WITH_WAITER,
+ memory_order_relaxed,
+ memory_order_relaxed)) {
+ continue;
+ }
}
- ANDROID_MEMBAR_FULL();
- return 0;
+ __futex_wait_ex(&gv->state, false, CONSTRUCTION_UNDERWAY_WITH_WAITER, NULL);
+ old_value = atomic_load_explicit(&gv->state, memory_order_relaxed);
+ }
}
extern "C" void __cxa_guard_release(_guard_t* gv) {
- // pending -> ready
- // waiting -> ready, and wake
-
- ANDROID_MEMBAR_FULL();
- if (__bionic_cmpxchg(pending, ready, &gv->state) == 0) {
- return;
- }
-
- gv->state = ready;
- __futex_wake(&gv->state, 0x7fffffff);
+ // Release fence is used to make all stores performed by the construction function
+ // visible in other threads.
+ int old_value = atomic_exchange_explicit(&gv->state, CONSTRUCTION_COMPLETE, memory_order_release);
+ if (old_value == CONSTRUCTION_UNDERWAY_WITH_WAITER) {
+ __futex_wake_ex(&gv->state, false, INT_MAX);
+ }
}
extern "C" void __cxa_guard_abort(_guard_t* gv) {
- ANDROID_MEMBAR_FULL();
- gv->state= 0;
- __futex_wake(&gv->state, 0x7fffffff);
+ // Release fence is used to make all stores performed by the construction function
+ // visible in other threads.
+ int old_value = atomic_exchange_explicit(&gv->state, CONSTRUCTION_NOT_YET_STARTED, memory_order_release);
+ if (old_value == CONSTRUCTION_UNDERWAY_WITH_WAITER) {
+ __futex_wake_ex(&gv->state, false, INT_MAX);
+ }
}
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
index c74a52c09..10521cf01 100644
--- a/libc/bionic/bionic_systrace.cpp
+++ b/libc/bionic/bionic_systrace.cpp
@@ -19,6 +19,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "private/bionic_systrace.h"
#include "private/libc_logging.h"
diff --git a/libc/bionic/debug_stacktrace.cpp b/libc/bionic/debug_stacktrace.cpp
index 7d3c76e9b..c6ce71412 100644
--- a/libc/bionic/debug_stacktrace.cpp
+++ b/libc/bionic/debug_stacktrace.cpp
@@ -30,6 +30,7 @@
#include <dlfcn.h>
#include <inttypes.h>
+#include <malloc.h>
#include <unistd.h>
#include <unwind.h>
#include <sys/types.h>
diff --git a/libc/bionic/dirent.cpp b/libc/bionic/dirent.cpp
index 6d8709785..fb45398b9 100644
--- a/libc/bionic/dirent.cpp
+++ b/libc/bionic/dirent.cpp
@@ -30,6 +30,8 @@
#include <errno.h>
#include <fcntl.h>
+#include <malloc.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/libc/bionic/getcwd.cpp b/libc/bionic/getcwd.cpp
index 47c807f01..a8bbcf31b 100644
--- a/libc/bionic/getcwd.cpp
+++ b/libc/bionic/getcwd.cpp
@@ -26,8 +26,10 @@
* SUCH DAMAGE.
*/
-#include <unistd.h>
#include <errno.h>
+#include <malloc.h>
+#include <string.h>
+#include <unistd.h>
extern "C" int __getcwd(char* buf, size_t size);
diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index 38c65830a..1a2765a60 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -41,6 +41,7 @@
#include <pthread.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include "private/ScopedPthreadMutexLocker.h"
diff --git a/libc/bionic/malloc_debug_qemu.cpp b/libc/bionic/malloc_debug_qemu.cpp
index 2f4949b12..fa40b3585 100644
--- a/libc/bionic/malloc_debug_qemu.cpp
+++ b/libc/bionic/malloc_debug_qemu.cpp
@@ -45,6 +45,7 @@
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
+#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/param.h>
diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp
index 3c664d9c8..999157371 100644
--- a/libc/bionic/posix_timers.cpp
+++ b/libc/bionic/posix_timers.cpp
@@ -31,6 +31,7 @@
#include "private/kernel_sigset_t.h"
#include <errno.h>
+#include <malloc.h>
#include <stdio.h>
#include <string.h>
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 7406b351d..c6d8494aa 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -29,6 +29,7 @@
#include <pthread.h>
#include <errno.h>
+#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
diff --git a/libc/bionic/pthread_once.cpp b/libc/bionic/pthread_once.cpp
index 6d9d7d17b..7688a23c4 100644
--- a/libc/bionic/pthread_once.cpp
+++ b/libc/bionic/pthread_once.cpp
@@ -27,74 +27,59 @@
*/
#include <pthread.h>
+#include <stdatomic.h>
-#include "private/bionic_atomic_inline.h"
#include "private/bionic_futex.h"
-#define ONCE_INITIALIZING (1 << 0)
-#define ONCE_COMPLETED (1 << 1)
+#define ONCE_INITIALIZATION_NOT_YET_STARTED 0
+#define ONCE_INITIALIZATION_UNDERWAY 1
+#define ONCE_INITIALIZATION_COMPLETE 2
/* NOTE: this implementation doesn't support a init function that throws a C++ exception
* or calls fork()
*/
int pthread_once(pthread_once_t* once_control, void (*init_routine)(void)) {
- volatile pthread_once_t* once_control_ptr = once_control;
+ static_assert(sizeof(atomic_int) == sizeof(pthread_once_t),
+ "pthread_once_t should actually be atomic_int in implementation.");
- // PTHREAD_ONCE_INIT is 0, we use the following bit flags
- // bit 0 set -> initialization is under way
- // bit 1 set -> initialization is complete
+ // We prefer casting to atomic_int instead of declaring pthread_once_t to be atomic_int directly.
+ // Because using the second method pollutes pthread.h, and causes an error when compiling libcxx.
+ atomic_int* once_control_ptr = reinterpret_cast<atomic_int*>(once_control);
// First check if the once is already initialized. This will be the common
// case and we want to make this as fast as possible. Note that this still
// requires a load_acquire operation here to ensure that all the
// stores performed by the initialization function are observable on
// this CPU after we exit.
- if (__predict_true((*once_control_ptr & ONCE_COMPLETED) != 0)) {
- ANDROID_MEMBAR_FULL();
- return 0;
- }
+ int old_value = atomic_load_explicit(once_control_ptr, memory_order_acquire);
while (true) {
- // Try to atomically set the INITIALIZING flag.
- // This requires a cmpxchg loop, and we may need
- // to exit prematurely if we detect that
- // COMPLETED is now set.
- int32_t old_value, new_value;
-
- do {
- old_value = *once_control_ptr;
- if ((old_value & ONCE_COMPLETED) != 0) {
- break;
- }
-
- new_value = old_value | ONCE_INITIALIZING;
- } while (__bionic_cmpxchg(old_value, new_value, once_control_ptr) != 0);
-
- if ((old_value & ONCE_COMPLETED) != 0) {
- // We detected that COMPLETED was set while in our loop.
- ANDROID_MEMBAR_FULL();
+ if (__predict_true(old_value == ONCE_INITIALIZATION_COMPLETE)) {
return 0;
}
- if ((old_value & ONCE_INITIALIZING) == 0) {
- // We got there first, we can jump out of the loop to handle the initialization.
- break;
+ // Try to atomically set the initialization underway flag. This requires a compare exchange
+ // in a loop, and we may need to exit prematurely if the initialization is complete.
+ if (!atomic_compare_exchange_weak_explicit(once_control_ptr, &old_value,
+ ONCE_INITIALIZATION_UNDERWAY,
+ memory_order_acquire, memory_order_acquire)) {
+ continue;
}
- // Another thread is running the initialization and hasn't completed
- // yet, so wait for it, then try again.
- __futex_wait_ex(once_control_ptr, 0, old_value, NULL);
- }
+ if (old_value == ONCE_INITIALIZATION_NOT_YET_STARTED) {
+ // We got here first, we can handle the initialization.
+ (*init_routine)();
- // Call the initialization function.
- (*init_routine)();
+ // Do a store_release indicating that initialization is complete.
+ atomic_store_explicit(once_control_ptr, ONCE_INITIALIZATION_COMPLETE, memory_order_release);
- // Do a store_release indicating that initialization is complete.
- ANDROID_MEMBAR_FULL();
- *once_control_ptr = ONCE_COMPLETED;
-
- // Wake up any waiters, if any.
- __futex_wake_ex(once_control_ptr, 0, INT_MAX);
+ // Wake up any waiters, if any.
+ __futex_wake_ex(once_control_ptr, 0, INT_MAX);
+ return 0;
+ }
- return 0;
+ // The initialization is underway, wait for its finish.
+ __futex_wait_ex(once_control_ptr, 0, old_value, NULL);
+ old_value = atomic_load_explicit(once_control_ptr, memory_order_acquire);
+ }
}
diff --git a/libc/bionic/pthread_setname_np.cpp b/libc/bionic/pthread_setname_np.cpp
index 93d4b2f98..c4e9fb85c 100644
--- a/libc/bionic/pthread_setname_np.cpp
+++ b/libc/bionic/pthread_setname_np.cpp
@@ -30,6 +30,7 @@
#include <fcntl.h>
#include <stdio.h> // For snprintf.
+#include <string.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
diff --git a/libc/bionic/vdso.cpp b/libc/bionic/vdso.cpp
index 645f0729c..a2406634d 100644
--- a/libc/bionic/vdso.cpp
+++ b/libc/bionic/vdso.cpp
@@ -15,6 +15,7 @@
*/
#include <link.h>
+#include <string.h>
#include <sys/auxv.h>
#include <unistd.h>
diff --git a/libc/dns/net/getservent.c b/libc/dns/net/getservent.c
index 9f6ec32f9..0a727c7b4 100644
--- a/libc/dns/net/getservent.c
+++ b/libc/dns/net/getservent.c
@@ -28,6 +28,7 @@
#include <sys/cdefs.h>
#include <sys/types.h>
#include <endian.h>
+#include <malloc.h>
#include <netdb.h>
#include "servent.h"
#include "services.h"
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 21787894d..42811329e 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -112,7 +112,7 @@ typedef struct {
typedef int pthread_key_t;
-typedef volatile int pthread_once_t;
+typedef int pthread_once_t;
#define PTHREAD_ONCE_INIT 0
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index 7017865bd..eb9bf2e84 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -36,7 +36,7 @@
__BEGIN_DECLS
-#if defined(__aarch64__)
+#if defined(__aarch64__) || (defined(__mips__) && defined(__LP64__))
#define __STAT64_BODY \
dev_t st_dev; \
ino_t st_ino; \
@@ -56,7 +56,7 @@ __BEGIN_DECLS
unsigned int __unused4; \
unsigned int __unused5; \
-#elif defined(__mips__) /* and mips64 */
+#elif defined(__mips__) && !defined(__LP64__)
#define __STAT64_BODY \
unsigned int st_dev; \
unsigned int __pad0[3]; \