Merge "Coverage configs for bionic."
diff --git a/libc/Android.mk b/libc/Android.mk
index d0c51e4..0dc6c3b 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -51,11 +51,9 @@
     bionic/ioctl.c \
     bionic/isatty.c \
     bionic/memmem.c \
-    bionic/pathconf.c \
     bionic/pututline.c \
     bionic/sched_cpualloc.c \
     bionic/sched_cpucount.c \
-    bionic/semaphore.c \
     bionic/sigblock.c \
     bionic/siginterrupt.c \
     bionic/sigsetmask.c \
@@ -145,6 +143,7 @@
     bionic/mntent.cpp \
     bionic/NetdClientDispatch.cpp \
     bionic/open.cpp \
+    bionic/pathconf.cpp \
     bionic/pause.cpp \
     bionic/pipe.cpp \
     bionic/poll.cpp \
@@ -184,6 +183,7 @@
     bionic/scandir.cpp \
     bionic/sched_getaffinity.cpp \
     bionic/sched_getcpu.cpp \
+    bionic/semaphore.cpp \
     bionic/send.cpp \
     bionic/setegid.cpp \
     bionic/__set_errno.cpp \
@@ -243,7 +243,6 @@
     upstream-freebsd/lib/libc/gen/sleep.c \
     upstream-freebsd/lib/libc/gen/usleep.c \
     upstream-freebsd/lib/libc/stdio/fclose.c \
-    upstream-freebsd/lib/libc/stdio/flags.c \
     upstream-freebsd/lib/libc/stdio/fopen.c \
     upstream-freebsd/lib/libc/stdlib/abs.c \
     upstream-freebsd/lib/libc/stdlib/getopt_long.c \
@@ -290,7 +289,6 @@
     upstream-netbsd/lib/libc/stdlib/div.c \
     upstream-netbsd/lib/libc/stdlib/drand48.c \
     upstream-netbsd/lib/libc/stdlib/erand48.c \
-    upstream-netbsd/lib/libc/stdlib/insque.c \
     upstream-netbsd/lib/libc/stdlib/jrand48.c \
     upstream-netbsd/lib/libc/stdlib/ldiv.c \
     upstream-netbsd/lib/libc/stdlib/lldiv.c \
@@ -299,14 +297,12 @@
     upstream-netbsd/lib/libc/stdlib/nrand48.c \
     upstream-netbsd/lib/libc/stdlib/_rand48.c \
     upstream-netbsd/lib/libc/stdlib/rand_r.c \
-    upstream-netbsd/lib/libc/stdlib/remque.c \
     upstream-netbsd/lib/libc/stdlib/seed48.c \
     upstream-netbsd/lib/libc/stdlib/srand48.c \
     upstream-netbsd/lib/libc/string/memccpy.c \
     upstream-netbsd/lib/libc/string/strcasestr.c \
     upstream-netbsd/lib/libc/string/strcoll.c \
     upstream-netbsd/lib/libc/string/strxfrm.c \
-    upstream-netbsd/lib/libc/unistd/killpg.c \
 
 libc_upstream_openbsd_gdtoa_src_files := \
     upstream-openbsd/android/gdtoa_support.cpp \
@@ -336,6 +332,7 @@
     upstream-openbsd/lib/libc/gdtoa/strtorQ.c \
 
 libc_upstream_openbsd_src_files := \
+    upstream-openbsd/lib/libc/compat-43/killpg.c \
     upstream-openbsd/lib/libc/crypt/arc4random.c \
     upstream-openbsd/lib/libc/crypt/arc4random_uniform.c \
     upstream-openbsd/lib/libc/gen/alarm.c \
@@ -403,6 +400,7 @@
     upstream-openbsd/lib/libc/stdio/fgetws.c \
     upstream-openbsd/lib/libc/stdio/fileno.c \
     upstream-openbsd/lib/libc/stdio/findfp.c \
+    upstream-openbsd/lib/libc/stdio/flags.c \
     upstream-openbsd/lib/libc/stdio/fmemopen.c \
     upstream-openbsd/lib/libc/stdio/fprintf.c \
     upstream-openbsd/lib/libc/stdio/fpurge.c \
@@ -482,7 +480,9 @@
     upstream-openbsd/lib/libc/stdlib/atoll.c \
     upstream-openbsd/lib/libc/stdlib/exit.c \
     upstream-openbsd/lib/libc/stdlib/getenv.c \
+    upstream-openbsd/lib/libc/stdlib/insque.c \
     upstream-openbsd/lib/libc/stdlib/lsearch.c \
+    upstream-openbsd/lib/libc/stdlib/remque.c \
     upstream-openbsd/lib/libc/stdlib/setenv.c \
     upstream-openbsd/lib/libc/stdlib/strtoimax.c \
     upstream-openbsd/lib/libc/stdlib/strtol.c \
@@ -1138,10 +1138,7 @@
 # ========================================================
 include $(CLEAR_VARS)
 
-LOCAL_CFLAGS := \
-    $(libc_common_cflags) \
-    -DMALLOC_LEAK_CHECK \
-
+LOCAL_CFLAGS := $(libc_common_cflags)
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 0dd3c27..cdb2777 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -59,7 +59,7 @@
 endif
 cpu_variant_mk := $(LOCAL_PATH)/arch-arm64/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk
 ifeq ($(wildcard $(cpu_variant_mk)),)
-$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, generic-neon, denver64. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
+$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, denver64. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
 endif
 include $(cpu_variant_mk)
 libc_common_additional_dependencies += $(cpu_variank_mk)
diff --git a/libc/arch-arm64/generic-neon/bionic/memcpy.S b/libc/arch-arm64/generic-neon/bionic/memcpy.S
deleted file mode 100644
index 320f748..0000000
--- a/libc/arch-arm64/generic-neon/bionic/memcpy.S
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (c) 2012, Linaro Limited
-   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.
-       * Neither the name of the Linaro nor the
-         names of its contributors may be used to endorse or promote products
-         derived from this software without specific prior written permission.
-
-   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
-   HOLDER 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.
-*/
-
-/* Assumptions:
- *
- * ARMv8-a, AArch64
- * Unaligned accesses
- *
- */
-
-#include <private/bionic_asm.h>
-
-#define dstin	x0
-#define src	x1
-#define count	x2
-#define tmp1	x3
-#define tmp1w	w3
-#define tmp2	x4
-#define tmp2w	w4
-#define tmp3	x5
-#define tmp3w	w5
-#define dst	x6
-
-#define A_l	x7
-#define A_h	x8
-#define B_l	x9
-#define B_h	x10
-#define C_l	x11
-#define C_h	x12
-#define D_l	x13
-#define D_h	x14
-
-#define QA_l q0
-#define QA_h q1
-#define QB_l q2
-#define QB_h q3
-
-ENTRY(memcpy)
-
-	mov	dst, dstin
-	cmp	count, #64
-	b.ge	.Lcpy_not_short
-	cmp	count, #15
-	b.le	.Ltail15tiny
-
-	/* Deal with small copies quickly by dropping straight into the
-	 * exit block.  */
-.Ltail63:
-	/* Copy up to 48 bytes of data.  At this point we only need the
-	 * bottom 6 bits of count to be accurate.  */
-	ands	tmp1, count, #0x30
-	b.eq	.Ltail15
-	add	dst, dst, tmp1
-	add	src, src, tmp1
-	cmp	tmp1w, #0x20
-	b.eq	1f
-	b.lt	2f
-	ldp	A_l, A_h, [src, #-48]
-	stp	A_l, A_h, [dst, #-48]
-1:
-	ldp	A_l, A_h, [src, #-32]
-	stp	A_l, A_h, [dst, #-32]
-2:
-	ldp	A_l, A_h, [src, #-16]
-	stp	A_l, A_h, [dst, #-16]
-
-.Ltail15:
-	ands	count, count, #15
-	beq	1f
-	add	src, src, count
-	ldp	A_l, A_h, [src, #-16]
-	add	dst, dst, count
-	stp	A_l, A_h, [dst, #-16]
-1:
-	ret
-
-.Ltail15tiny:
-	/* Copy up to 15 bytes of data.  Does not assume additional data
-	   being copied.  */
-	tbz	count, #3, 1f
-	ldr	tmp1, [src], #8
-	str	tmp1, [dst], #8
-1:
-	tbz	count, #2, 1f
-	ldr	tmp1w, [src], #4
-	str	tmp1w, [dst], #4
-1:
-	tbz	count, #1, 1f
-	ldrh	tmp1w, [src], #2
-	strh	tmp1w, [dst], #2
-1:
-	tbz	count, #0, 1f
-	ldrb	tmp1w, [src]
-	strb	tmp1w, [dst]
-1:
-	ret
-
-.Lcpy_not_short:
-	/* We don't much care about the alignment of DST, but we want SRC
-	 * to be 128-bit (16 byte) aligned so that we don't cross cache line
-	 * boundaries on both loads and stores.  */
-	neg	tmp2, src
-	ands	tmp2, tmp2, #15		/* Bytes to reach alignment.  */
-	b.eq	2f
-	sub	count, count, tmp2
-	/* Copy more data than needed; it's faster than jumping
-	 * around copying sub-Quadword quantities.  We know that
-	 * it can't overrun.  */
-	ldp	A_l, A_h, [src]
-	add	src, src, tmp2
-	stp	A_l, A_h, [dst]
-	add	dst, dst, tmp2
-	/* There may be less than 63 bytes to go now.  */
-	cmp	count, #63
-	b.le	.Ltail63
-2:
-	subs	count, count, #128
-	b.ge	.Lcpy_body_large
-	/* Less than 128 bytes to copy, so handle 64 here and then jump
-	 * to the tail.  */
-	ldp QA_l, QA_h, [src]
-	ldp QB_l, QB_h, [src, #32]
-	stp QA_l, QA_h, [dst]
-	stp QB_l, QB_h, [dst, #32]
-	tst	count, #0x3f
-	add	src, src, #64
-	add	dst, dst, #64
-	b.ne	.Ltail63
-	ret
-
-	/* Critical loop.  Start at a new cache line boundary.  Assuming
-	 * 64 bytes per line this ensures the entire loop is in one line.  */
-	.p2align 6
-.Lcpy_body_large:
-	/* There are at least 128 bytes to copy.  */
-	ldp QA_l, QA_h, [src, #0]
-	sub	dst, dst, #32		/* Pre-bias.  */
-	ldp QB_l, QB_h, [src, #32]!	/* src += 64 - Pre-bias.  */
-1:
-	stp QA_l, QA_h, [dst, #32]
-	ldp QA_l, QA_h, [src, #32]
-	stp QB_l, QB_h, [dst, #64]!
-	ldp QB_l, QB_h, [src, #64]!
-
-	subs	count, count, #64
-	b.ge	1b
-
-	stp QA_l, QA_h, [dst, #32]
-	stp QB_l, QB_h, [dst, #64]
-	add	src, src, #32
-	add	dst, dst, #64 + 32
-	tst	count, #0x3f
-	b.ne	.Ltail63
-	ret
-END(memcpy)
diff --git a/libc/arch-arm64/generic-neon/generic-neon.mk b/libc/arch-arm64/generic-neon/generic-neon.mk
deleted file mode 100644
index 77e3861..0000000
--- a/libc/arch-arm64/generic-neon/generic-neon.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-libc_bionic_src_files_arm64 += \
-    arch-arm64/generic/bionic/memchr.S \
-    arch-arm64/generic/bionic/memcmp.S \
-    arch-arm64/generic/bionic/memmove.S \
-    arch-arm64/generic/bionic/memset.S \
-    arch-arm64/generic/bionic/stpcpy.S \
-    arch-arm64/generic/bionic/strchr.S \
-    arch-arm64/generic/bionic/strcmp.S \
-    arch-arm64/generic/bionic/strcpy.S \
-    arch-arm64/generic/bionic/strlen.S \
-    arch-arm64/generic/bionic/strncmp.S \
-    arch-arm64/generic/bionic/strnlen.S \
-    arch-arm64/generic-neon/bionic/memcpy.S \
diff --git a/libc/bionic/bionic_time_conversions.cpp b/libc/bionic/bionic_time_conversions.cpp
index 7f3c026..75e8d49 100644
--- a/libc/bionic/bionic_time_conversions.cpp
+++ b/libc/bionic/bionic_time_conversions.cpp
@@ -28,6 +28,8 @@
 
 #include "private/bionic_time_conversions.h"
 
+#include "private/bionic_constants.h"
+
 bool timespec_from_timeval(timespec& ts, const timeval& tv) {
   // Whole seconds can just be copied.
   ts.tv_sec = tv.tv_sec;
@@ -49,3 +51,19 @@
   tv.tv_sec = ts.tv_sec;
   tv.tv_usec = ts.tv_nsec / 1000;
 }
+
+// Initializes 'ts' with the difference between 'abs_ts' and the current time
+// according to 'clock'. Returns false if abstime already expired, true otherwise.
+bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock) {
+  clock_gettime(clock, &ts);
+  ts.tv_sec = abs_ts.tv_sec - ts.tv_sec;
+  ts.tv_nsec = abs_ts.tv_nsec - ts.tv_nsec;
+  if (ts.tv_nsec < 0) {
+    ts.tv_sec--;
+    ts.tv_nsec += NS_PER_S;
+  }
+  if (ts.tv_nsec < 0 || ts.tv_sec < 0) {
+    return false;
+  }
+  return true;
+}
diff --git a/libc/bionic/lfs64_support.cpp b/libc/bionic/lfs64_support.cpp
index ab795f5..45d4f7f 100644
--- a/libc/bionic/lfs64_support.cpp
+++ b/libc/bionic/lfs64_support.cpp
@@ -17,11 +17,20 @@
 #include <ftw.h>
 #include <stdlib.h>
 
-int mkstemp64(char* filename) {
-  // Delegation will work in this case because all the transitive dependencies
-  // are already 64-bit ready. In particular, we don't have non-O_LARGEFILE
-  // open (our open is actually open64) and stat and stat64 are the same.
-  return mkstemp(filename);
+// Delegation will work in these cases because all the transitive dependencies
+// are already 64-bit ready. In particular, we don't have non-O_LARGEFILE
+// open (our open is actually open64) and stat and stat64 are the same.
+int mkstemp64(char* path) {
+  return mkstemp(path);
+}
+int mkostemp64(char* path, int flags) {
+  return mkostemp(path, flags);
+}
+int mkstemps64(char* path, int suffix_length) {
+  return mkstemps(path, suffix_length);
+}
+int mkostemps64(char* path, int suffix_length, int flags) {
+  return mkostemps(path, suffix_length, flags);
 }
 
 typedef int (*ftw_fn)(const char*, const struct stat*, int);
diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index 0b6a142..38c6583 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -29,14 +29,13 @@
 // Contains definition of structures, global variables, and implementation of
 // routines that are used by malloc leak detection code and other components in
 // the system. The trick is that some components expect these data and
-// routines to be defined / implemented in libc.so library, regardless
-// whether or not MALLOC_LEAK_CHECK macro is defined. To make things even
-// more tricky, malloc leak detection code, implemented in
-// libc_malloc_debug.so also requires access to these variables and routines
-// (to fill allocation entry hash table, for example). So, all relevant
-// variables and routines are defined / implemented here and exported
-// to all, leak detection code and other components via dynamic (libc.so),
-// or static (libc.a) linking.
+// routines to be defined / implemented in libc.so, regardless whether or not
+// malloc leak detection code is going to run. To make things even more tricky,
+// malloc leak detection code, implemented in libc_malloc_debug.so also
+// requires access to these variables and routines (to fill allocation entry
+// hash table, for example). So, all relevant variables and routines are
+// defined / implemented here and exported to all, leak detection code and
+// other components via dynamic (libc.so), or static (libc.a) linking.
 
 #include "malloc_debug_common.h"
 
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index df0f997..64f2112 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -55,13 +55,6 @@
 #include "private/libc_logging.h"
 #include "private/ScopedPthreadMutexLocker.h"
 
-// This file should be included into the build only when
-// MALLOC_LEAK_CHECK, or MALLOC_QEMU_INSTRUMENT, or both
-// macros are defined.
-#ifndef MALLOC_LEAK_CHECK
-#error MALLOC_LEAK_CHECK is not defined.
-#endif  // !MALLOC_LEAK_CHECK
-
 extern int gMallocLeakZygoteChild;
 extern HashTable* g_hash_table;
 extern const MallocDebug* g_malloc_dispatch;
diff --git a/libc/bionic/pathconf.c b/libc/bionic/pathconf.c
deleted file mode 100644
index cf81272..0000000
--- a/libc/bionic/pathconf.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2008 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 <pathconf.h>
-#include <sys/vfs.h>
-#include <sys/limits.h>
-#include <errno.h>
-
-/* these may not be defined yet by our headers */
-#ifndef _POSIX_VDISABLE
-#define _POSIX_VDISABLE  -1
-#endif
-
-#ifndef _POSIX_SYNC_IO
-#define _POSIX_SYNC_IO  -1
-#endif
-
-#ifndef _POSIX_PRIO_IO
-#define _POSIX_PRIO_IO  -1
-#endif
-
-#ifndef _POSIX_ASYNC_IO
-#define _POSIX_ASYNC_IO  -1
-#endif
-
-
-static long
-__filesizebits( struct statfs*  s )
-{
-#define   EOL_MAGIC   0x0000U
-
-    /* list of known 64-bit aware filesystems */
-    static const uint32_t  known64[] = {
-        EXT2_SUPER_MAGIC,
-        UFS_MAGIC,
-        REISERFS_SUPER_MAGIC,
-        XFS_SUPER_MAGIC,
-        SMB_SUPER_MAGIC,
-        UDF_SUPER_MAGIC,
-        JFS_SUPER_MAGIC,
-        NTFS_SB_MAGIC,
-        VXFS_SUPER_MAGIC,
-        EOL_MAGIC
-    };
-    int  nn = 0;
-
-    for (; known64[nn] != EOL_MAGIC; ++nn) {
-        if (known64[nn] == s->f_type) {
-            return 64;
-        }
-    }
-    return 32;
-}
-
-
-static long
-__link_max( struct statfs*  s )
-{
-    // These constant values were taken from kernel headers.
-    // They're not available in uapi headers.
-    static const struct { uint32_t  type; int  max; }  knownMax[] =
-    {
-        { EXT2_SUPER_MAGIC, 32000 },
-        { EXT3_SUPER_MAGIC, 32000 },
-        { MINIX_SUPER_MAGIC, 250 },
-        { MINIX2_SUPER_MAGIC, 65530 },
-        { REISERFS_SUPER_MAGIC, 0xffff - 1000 },
-        { UFS_MAGIC, 32000 },
-        { EOL_MAGIC, 0 }
-    };
-    int   nn = 0;
-
-    for (; knownMax[nn].type != EOL_MAGIC; ++nn) {
-        if (knownMax[nn].type == s->f_type) {
-            return knownMax[nn].max;
-        }
-    }
-    return LINK_MAX;
-}
-
-static long
-__2_symlinks( struct statfs*  s )
-{
-    /* list of know filesystems that don't support symlinks */
-    static const uint32_t  knownNoSymlinks[] = {
-        ADFS_SUPER_MAGIC, BFS_MAGIC, CRAMFS_MAGIC,
-        EFS_SUPER_MAGIC, MSDOS_SUPER_MAGIC, NTFS_SB_MAGIC,
-        QNX4_SUPER_MAGIC,
-        EOL_MAGIC
-    };
-    int  nn = 0;
-
-    for (; knownNoSymlinks[nn] != EOL_MAGIC; ++nn) {
-        if (knownNoSymlinks[nn] == s->f_type) {
-            return 0;
-        }
-    }
-    return 1;
-}
-
-static long
-__name_max( struct statfs*  s )
-{
-    return s->f_namelen;
-}
-
-long
-pathconf(const char *path, int name)
-{
-    struct statfs  buf;
-    int            ret = statfs( path, &buf );
-
-    if (ret < 0)
-        return -1;
-
-    switch (name) {
-    case _PC_FILESIZEBITS:
-        return __filesizebits(&buf);
-
-    case _PC_LINK_MAX:
-        return __link_max(&buf);
-
-    case _PC_MAX_CANON:
-        return MAX_CANON;
-
-    case _PC_MAX_INPUT:
-        return MAX_INPUT;
-
-    case _PC_NAME_MAX:
-        return __name_max(&buf);
-
-    case _PC_PATH_MAX:
-        return PATH_MAX;
-
-    case _PC_PIPE_BUF:
-        return PIPE_BUF;
-
-    case _PC_2_SYMLINKS:
-        return __2_symlinks(&buf);
-
-#if 0  /* don't know what to do there, the specs are really weird */
-    case _PC_ALLOC_SIZE_MIN:
-    case _PC_REC_INCR_XFER_SIZE:
-    case _PC_REC_MAX_XFER_SIZE:
-    case _PC_REC_MIN_XFER_SIZE:
-    case _PC_REC_XFER_ALIGN:
-#endif
-
-    case _PC_SYMLINK_MAX:
-        return -1;  /* no limit */
-
-    case _PC_CHOWN_RESTRICTED:
-        return _POSIX_CHOWN_RESTRICTED;
-
-    case _PC_NO_TRUNC:
-        return _POSIX_NO_TRUNC;
-
-    case _PC_VDISABLE:
-        return _POSIX_VDISABLE;
-
-    case _PC_ASYNC_IO:
-        return _POSIX_ASYNC_IO;
-
-    case _PC_PRIO_IO:
-        return _POSIX_PRIO_IO;
-
-    case _PC_SYNC_IO:
-        return _POSIX_SYNC_IO;
-
-    default:
-        errno = EINVAL;
-        return -1;
-    }
-}
-
-long fpathconf(int fildes, int name)
-{
-    struct statfs  buf;
-    int            ret = fstatfs(fildes, &buf);
-
-    if (ret < 0)
-        return -1;
-
-    switch (name) {
-    case _PC_FILESIZEBITS:
-        return __filesizebits(&buf);
-
-    case _PC_LINK_MAX:
-        return __link_max(&buf);
-
-    case _PC_MAX_CANON:
-        return MAX_CANON;
-
-    case _PC_MAX_INPUT:
-        return MAX_INPUT;
-
-    case _PC_NAME_MAX:
-        return __name_max(&buf);
-
-    case _PC_PATH_MAX:
-        return PATH_MAX;
-
-    case _PC_PIPE_BUF:
-        return PIPE_BUF;
-
-    case _PC_2_SYMLINKS:
-        return __2_symlinks(&buf);
-
-#if 0  /* don't know what to do there, the specs are really weird */
-    case _PC_ALLOC_SIZE_MIN:
-    case _PC_REC_INCR_XFER_SIZE:
-    case _PC_REC_MAX_XFER_SIZE:
-    case _PC_REC_MIN_XFER_SIZE:
-    case _PC_REC_XFER_ALIGN:
-#endif
-
-    case _PC_SYMLINK_MAX:
-        return -1;  /* no limit */
-
-    case _PC_CHOWN_RESTRICTED:
-        return _POSIX_CHOWN_RESTRICTED;
-
-    case _PC_NO_TRUNC:
-        return _POSIX_NO_TRUNC;
-
-    case _PC_VDISABLE:
-        return _POSIX_VDISABLE;
-
-    case _PC_ASYNC_IO:
-        return _POSIX_ASYNC_IO;
-
-    case _PC_PRIO_IO:
-        return _POSIX_PRIO_IO;
-
-    case _PC_SYNC_IO:
-        return _POSIX_SYNC_IO;
-
-    default:
-        errno = EINVAL;
-        return -1;
-    }
-}
diff --git a/libc/bionic/pathconf.cpp b/libc/bionic/pathconf.cpp
new file mode 100644
index 0000000..de9e022
--- /dev/null
+++ b/libc/bionic/pathconf.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2008 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 <unistd.h>
+
+#include <errno.h>
+#include <sys/limits.h>
+#include <sys/vfs.h>
+
+static long __filesizebits(const struct statfs& s) {
+  switch (s.f_type) {
+    case JFFS2_SUPER_MAGIC:
+    case MSDOS_SUPER_MAGIC:
+    case NCP_SUPER_MAGIC:
+      return 32;
+  }
+  // There won't be any new 32-bit file systems.
+  return 64;
+}
+
+static long __link_max(const struct statfs& s) {
+  // These constant values were taken from kernel headers.
+  // They're not available in uapi headers.
+  switch (s.f_type) {
+    case EXT2_SUPER_MAGIC:
+      return 32000;
+    case MINIX_SUPER_MAGIC:
+      return 250;
+    case MINIX2_SUPER_MAGIC:
+      return 65530;
+    case REISERFS_SUPER_MAGIC:
+      return 0xffff - 1000;
+    case UFS_MAGIC:
+      return 32000;
+  }
+  return LINK_MAX;
+}
+
+static long __2_symlinks(const struct statfs& s) {
+  switch (s.f_type) {
+    case ADFS_SUPER_MAGIC:
+    case BFS_MAGIC:
+    case CRAMFS_MAGIC:
+    case EFS_SUPER_MAGIC:
+    case MSDOS_SUPER_MAGIC:
+    case QNX4_SUPER_MAGIC:
+      return 0;
+  }
+  return 1;
+}
+
+static long __pathconf(const struct statfs& s, int name) {
+  switch (name) {
+    case _PC_FILESIZEBITS:
+      return __filesizebits(s);
+
+    case _PC_LINK_MAX:
+      return __link_max(s);
+
+    case _PC_MAX_CANON:
+      return MAX_CANON;
+
+    case _PC_MAX_INPUT:
+      return MAX_INPUT;
+
+    case _PC_NAME_MAX:
+      return s.f_namelen;
+
+    case _PC_PATH_MAX:
+      return PATH_MAX;
+
+    case _PC_PIPE_BUF:
+      return PIPE_BUF;
+
+    case _PC_2_SYMLINKS:
+      return __2_symlinks(s);
+
+#if 0
+    case _PC_ALLOC_SIZE_MIN:
+    case _PC_REC_INCR_XFER_SIZE:
+    case _PC_REC_MAX_XFER_SIZE:
+    case _PC_REC_MIN_XFER_SIZE:
+    case _PC_REC_XFER_ALIGN:
+#endif
+
+    case _PC_SYMLINK_MAX:
+      return -1; /* no limit */
+
+    case _PC_CHOWN_RESTRICTED:
+      return _POSIX_CHOWN_RESTRICTED;
+
+    case _PC_NO_TRUNC:
+      return _POSIX_NO_TRUNC;
+
+    case _PC_VDISABLE:
+      return _POSIX_VDISABLE;
+
+    case _PC_ASYNC_IO:
+      return -1;
+
+    case _PC_PRIO_IO:
+      return -1;
+
+    case _PC_SYNC_IO:
+      return -1;
+
+    default:
+      errno = EINVAL;
+      return -1;
+  }
+}
+
+long pathconf(const char* path, int name) {
+  struct statfs sb;
+  if (statfs(path, &sb) == -1) {
+    return -1;
+  }
+  return __pathconf(sb, name);
+}
+
+long fpathconf(int fd, int name) {
+  struct statfs sb;
+  if (fstatfs(fd, &sb) == -1) {
+    return -1;
+  }
+  return __pathconf(sb, name);
+}
diff --git a/libc/bionic/pthread_cond.cpp b/libc/bionic/pthread_cond.cpp
index e623b62..32ff81a 100644
--- a/libc/bionic/pthread_cond.cpp
+++ b/libc/bionic/pthread_cond.cpp
@@ -163,12 +163,12 @@
 }
 
 __LIBC_HIDDEN__
-int __pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* abstime, clockid_t clock) {
+int __pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* abs_ts, clockid_t clock) {
   timespec ts;
   timespec* tsp;
 
-  if (abstime != NULL) {
-    if (__timespec_from_absolute(&ts, abstime, clock) < 0) {
+  if (abs_ts != NULL) {
+    if (!timespec_from_absolute_timespec(ts, *abs_ts, clock)) {
       return ETIMEDOUT;
     }
     tsp = &ts;
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index a5b3002..392e781 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -117,8 +117,6 @@
 __LIBC_HIDDEN__ extern pthread_internal_t* g_thread_list;
 __LIBC_HIDDEN__ extern pthread_mutex_t g_thread_list_lock;
 
-__LIBC_HIDDEN__ int __timespec_from_absolute(timespec*, const timespec*, clockid_t);
-
 /* Needed by fork. */
 __LIBC_HIDDEN__ extern void __bionic_atfork_run_prepare();
 __LIBC_HIDDEN__ extern void __bionic_atfork_run_child();
diff --git a/libc/bionic/pthread_internals.cpp b/libc/bionic/pthread_internals.cpp
index 4c08ba8..19c00d4 100644
--- a/libc/bionic/pthread_internals.cpp
+++ b/libc/bionic/pthread_internals.cpp
@@ -67,19 +67,3 @@
 pthread_internal_t* __get_thread(void) {
   return reinterpret_cast<pthread_internal_t*>(__get_tls()[TLS_SLOT_THREAD_ID]);
 }
-
-// Initialize 'ts' with the difference between 'abstime' and the current time
-// according to 'clock'. Returns -1 if abstime already expired, or 0 otherwise.
-int __timespec_from_absolute(timespec* ts, const timespec* abstime, clockid_t clock) {
-  clock_gettime(clock, ts);
-  ts->tv_sec  = abstime->tv_sec - ts->tv_sec;
-  ts->tv_nsec = abstime->tv_nsec - ts->tv_nsec;
-  if (ts->tv_nsec < 0) {
-    ts->tv_sec--;
-    ts->tv_nsec += 1000000000;
-  }
-  if ((ts->tv_nsec < 0) || (ts->tv_sec < 0)) {
-    return -1;
-  }
-  return 0;
-}
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index e00ffb4..cbb6ef7 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -36,7 +36,9 @@
 #include "pthread_internal.h"
 
 #include "private/bionic_atomic_inline.h"
+#include "private/bionic_constants.h"
 #include "private/bionic_futex.h"
+#include "private/bionic_time_conversions.h"
 #include "private/bionic_tls.h"
 
 #include "private/bionic_systrace.h"
@@ -615,7 +617,7 @@
     return EBUSY;
 }
 
-static int __pthread_mutex_timedlock(pthread_mutex_t* mutex, const timespec* abs_timeout, clockid_t clock) {
+static int __pthread_mutex_timedlock(pthread_mutex_t* mutex, const timespec* abs_ts, clockid_t clock) {
   timespec ts;
 
   int mvalue = mutex->value;
@@ -638,7 +640,7 @@
 
     // Loop while needed.
     while (__bionic_swap(locked_contended, &mutex->value) != unlocked) {
-      if (__timespec_from_absolute(&ts, abs_timeout, clock) < 0) {
+      if (!timespec_from_absolute_timespec(ts, *abs_ts, clock)) {
         return ETIMEDOUT;
       }
       __futex_wait_ex(&mutex->value, shared, locked_contended, &ts);
@@ -681,7 +683,7 @@
       }
       // The value changed before we could lock it. We need to check
       // the time to avoid livelocks, reload the value, then loop again.
-      if (__timespec_from_absolute(&ts, abs_timeout, clock) < 0) {
+      if (!timespec_from_absolute_timespec(ts, *abs_ts, clock)) {
         return ETIMEDOUT;
       }
 
@@ -703,7 +705,7 @@
     }
 
     // Check time and update 'ts'.
-    if (__timespec_from_absolute(&ts, abs_timeout, clock) < 0) {
+    if (timespec_from_absolute_timespec(ts, *abs_ts, clock)) {
       return ETIMEDOUT;
     }
 
@@ -726,9 +728,9 @@
   clock_gettime(CLOCK_MONOTONIC, &abs_timeout);
   abs_timeout.tv_sec  += ms / 1000;
   abs_timeout.tv_nsec += (ms % 1000) * 1000000;
-  if (abs_timeout.tv_nsec >= 1000000000) {
+  if (abs_timeout.tv_nsec >= NS_PER_S) {
     abs_timeout.tv_sec++;
-    abs_timeout.tv_nsec -= 1000000000;
+    abs_timeout.tv_nsec -= NS_PER_S;
   }
 
   int error = __pthread_mutex_timedlock(mutex, &abs_timeout, CLOCK_MONOTONIC);
diff --git a/libc/bionic/pthread_rwlock.cpp b/libc/bionic/pthread_rwlock.cpp
index 063137b..0d63457 100644
--- a/libc/bionic/pthread_rwlock.cpp
+++ b/libc/bionic/pthread_rwlock.cpp
@@ -30,6 +30,7 @@
 
 #include "pthread_internal.h"
 #include "private/bionic_futex.h"
+#include "private/bionic_time_conversions.h"
 
 /* Technical note:
  *
@@ -71,7 +72,7 @@
 
 static bool timespec_from_absolute(timespec* rel_timeout, const timespec* abs_timeout) {
   if (abs_timeout != NULL) {
-    if (__timespec_from_absolute(rel_timeout, abs_timeout, CLOCK_REALTIME) < 0) {
+    if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout, CLOCK_REALTIME)) {
       return false;
     }
   }
diff --git a/libc/bionic/semaphore.c b/libc/bionic/semaphore.c
deleted file mode 100644
index 1fa019e..0000000
--- a/libc/bionic/semaphore.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * Copyright (C) 2008 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 <semaphore.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <time.h>
-#include <limits.h>
-
-#include "private/bionic_atomic_inline.h"
-#include "private/bionic_futex.h"
-
-/* In this implementation, a semaphore contains a
- * 31-bit signed value and a 1-bit 'shared' flag
- * (for process-sharing purpose).
- *
- * We use the value -1 to indicate contention on the
- * semaphore, 0 or more to indicate uncontended state,
- * any value lower than -2 is invalid at runtime.
- *
- * State diagram:
- *
- * post(1)  ==> 2
- * post(0)  ==> 1
- * post(-1) ==> 1, then wake all waiters
- *
- * wait(2)  ==> 1
- * wait(1)  ==> 0
- * wait(0)  ==> -1 then wait for a wake up + loop
- * wait(-1) ==> -1 then wait for a wake up + loop
- *
- */
-
-/* Use the upper 31-bits for the counter, and the lower one
- * for the shared flag.
- */
-#define SEMCOUNT_SHARED_MASK      0x00000001
-#define SEMCOUNT_VALUE_MASK       0xfffffffe
-#define SEMCOUNT_VALUE_SHIFT      1
-
-/* Maximum unsigned value that can be stored in the semaphore.
- * One bit is used for the shared flag, another one for the
- * sign bit, leaving us with only 30 bits.
- */
-#define SEM_MAX_VALUE             0x3fffffff
-
-/* convert a value into the corresponding sem->count bit pattern */
-#define SEMCOUNT_FROM_VALUE(val)    (((val) << SEMCOUNT_VALUE_SHIFT) & SEMCOUNT_VALUE_MASK)
-
-/* convert a sem->count bit pattern into the corresponding signed value */
-#define SEMCOUNT_TO_VALUE(sval)  ((int)(sval) >> SEMCOUNT_VALUE_SHIFT)
-
-/* the value +1 as a sem->count bit-pattern. */
-#define SEMCOUNT_ONE              SEMCOUNT_FROM_VALUE(1)
-
-/* the value -1 as a sem->count bit-pattern. */
-#define SEMCOUNT_MINUS_ONE        SEMCOUNT_FROM_VALUE(-1)
-
-#define SEMCOUNT_DECREMENT(sval)    (((sval) - (1U << SEMCOUNT_VALUE_SHIFT)) & SEMCOUNT_VALUE_MASK)
-#define SEMCOUNT_INCREMENT(sval)    (((sval) + (1U << SEMCOUNT_VALUE_SHIFT)) & SEMCOUNT_VALUE_MASK)
-
-/* return the shared bitflag from a semaphore */
-#define SEM_GET_SHARED(sem)       ((sem)->count & SEMCOUNT_SHARED_MASK)
-
-
-int sem_init(sem_t *sem, int pshared, unsigned int value)
-{
-    if (sem == NULL) {
-        errno = EINVAL;
-        return -1;
-    }
-
-    /* ensure that 'value' can be stored in the semaphore */
-    if (value > SEM_MAX_VALUE) {
-        errno = EINVAL;
-        return -1;
-    }
-
-    sem->count = SEMCOUNT_FROM_VALUE(value);
-    if (pshared != 0)
-        sem->count |= SEMCOUNT_SHARED_MASK;
-
-    return 0;
-}
-
-
-int sem_destroy(sem_t *sem)
-{
-    int count;
-
-    if (sem == NULL) {
-        errno = EINVAL;
-        return -1;
-    }
-    count = SEMCOUNT_TO_VALUE(sem->count);
-    if (count < 0) {
-        errno = EBUSY;
-        return -1;
-    }
-    sem->count = 0;
-    return 0;
-}
-
-
-sem_t *sem_open(const char *name __unused, int oflag __unused, ...)
-{
-    errno = ENOSYS;
-    return SEM_FAILED;
-}
-
-
-int sem_close(sem_t *sem)
-{
-    if (sem == NULL) {
-        errno = EINVAL;
-        return -1;
-    }
-    errno = ENOSYS;
-    return -1;
-}
-
-
-int sem_unlink(const char* name __unused)
-{
-    errno = ENOSYS;
-    return -1;
-}
-
-
-/* Decrement a semaphore's value atomically,
- * and return the old one. As a special case,
- * this returns immediately if the value is
- * negative (i.e. -1)
- */
-static int
-__sem_dec(volatile unsigned int *pvalue)
-{
-    unsigned int shared = (*pvalue & SEMCOUNT_SHARED_MASK);
-    unsigned int old, new;
-    int          ret;
-
-    do {
-        old = (*pvalue & SEMCOUNT_VALUE_MASK);
-        ret = SEMCOUNT_TO_VALUE(old);
-        if (ret < 0)
-            break;
-
-        new = SEMCOUNT_DECREMENT(old);
-    }
-    while (__bionic_cmpxchg((int)(old|shared),
-                            (int)(new|shared),
-                            (volatile int *)pvalue) != 0);
-    return ret;
-}
-
-/* Same as __sem_dec, but will not touch anything if the
- * value is already negative *or* 0. Returns the old value.
- */
-static int
-__sem_trydec(volatile unsigned int *pvalue)
-{
-    unsigned int shared = (*pvalue & SEMCOUNT_SHARED_MASK);
-    unsigned int old, new;
-    int          ret;
-
-    do {
-        old = (*pvalue & SEMCOUNT_VALUE_MASK);
-        ret = SEMCOUNT_TO_VALUE(old);
-        if (ret <= 0)
-            break;
-
-        new = SEMCOUNT_DECREMENT(old);
-    }
-    while (__bionic_cmpxchg((int)(old|shared),
-                            (int)(new|shared),
-                            (volatile int *)pvalue) != 0);
-
-    return ret;
-}
-
-
-/* "Increment" the value of a semaphore atomically and
- * return its old value. Note that this implements
- * the special case of "incrementing" any negative
- * value to +1 directly.
- *
- * NOTE: The value will _not_ wrap above SEM_VALUE_MAX
- */
-static int
-__sem_inc(volatile unsigned int *pvalue)
-{
-    unsigned int  shared = (*pvalue & SEMCOUNT_SHARED_MASK);
-    unsigned int  old, new;
-    int           ret;
-
-    do {
-        old = (*pvalue & SEMCOUNT_VALUE_MASK);
-        ret = SEMCOUNT_TO_VALUE(old);
-
-        /* Can't go higher than SEM_MAX_VALUE */
-        if (ret == SEM_MAX_VALUE)
-            break;
-
-        /* If the counter is negative, go directly to +1,
-         * otherwise just increment */
-        if (ret < 0)
-            new = SEMCOUNT_ONE;
-        else
-            new = SEMCOUNT_INCREMENT(old);
-    }
-    while ( __bionic_cmpxchg((int)(old|shared),
-                             (int)(new|shared),
-                             (volatile int*)pvalue) != 0);
-
-    return ret;
-}
-
-/* lock a semaphore */
-int sem_wait(sem_t *sem)
-{
-    unsigned shared;
-
-    if (sem == NULL) {
-        errno = EINVAL;
-        return -1;
-    }
-
-    shared = SEM_GET_SHARED(sem);
-
-    for (;;) {
-        if (__sem_dec(&sem->count) > 0)
-            break;
-
-        __futex_wait_ex(&sem->count, shared, shared|SEMCOUNT_MINUS_ONE, NULL);
-    }
-    ANDROID_MEMBAR_FULL();
-    return 0;
-}
-
-int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
-{
-    unsigned int shared;
-
-    if (sem == NULL) {
-        errno = EINVAL;
-        return -1;
-    }
-
-    /* POSIX says we need to try to decrement the semaphore
-     * before checking the timeout value. Note that if the
-     * value is currently 0, __sem_trydec() does nothing.
-     */
-    if (__sem_trydec(&sem->count) > 0) {
-        ANDROID_MEMBAR_FULL();
-        return 0;
-    }
-
-    /* Check it as per Posix */
-    if (abs_timeout == NULL    ||
-        abs_timeout->tv_sec < 0 ||
-        abs_timeout->tv_nsec < 0 ||
-        abs_timeout->tv_nsec >= 1000000000)
-    {
-        errno = EINVAL;
-        return -1;
-    }
-
-    shared = SEM_GET_SHARED(sem);
-
-    for (;;) {
-        struct timespec ts;
-        int             ret;
-
-        /* Posix mandates CLOCK_REALTIME here */
-        clock_gettime( CLOCK_REALTIME, &ts );
-        ts.tv_sec  = abs_timeout->tv_sec - ts.tv_sec;
-        ts.tv_nsec = abs_timeout->tv_nsec - ts.tv_nsec;
-        if (ts.tv_nsec < 0) {
-            ts.tv_nsec += 1000000000;
-            ts.tv_sec  -= 1;
-        }
-
-        if (ts.tv_sec < 0 || ts.tv_nsec < 0) {
-            errno = ETIMEDOUT;
-            return -1;
-        }
-
-        /* Try to grab the semaphore. If the value was 0, this
-         * will also change it to -1 */
-        if (__sem_dec(&sem->count) > 0) {
-            ANDROID_MEMBAR_FULL();
-            break;
-        }
-
-        /* Contention detected. wait for a wakeup event */
-        ret = __futex_wait_ex(&sem->count, shared, shared|SEMCOUNT_MINUS_ONE, &ts);
-
-        /* return in case of timeout or interrupt */
-        if (ret == -ETIMEDOUT || ret == -EINTR) {
-            errno = -ret;
-            return -1;
-        }
-    }
-    return 0;
-}
-
-/* Unlock a semaphore */
-int sem_post(sem_t *sem)
-{
-    unsigned int shared;
-    int          old;
-
-    if (sem == NULL)
-        return EINVAL;
-
-    shared = SEM_GET_SHARED(sem);
-
-    ANDROID_MEMBAR_FULL();
-    old = __sem_inc(&sem->count);
-    if (old < 0) {
-        /* contention on the semaphore, wake up all waiters */
-        __futex_wake_ex(&sem->count, shared, INT_MAX);
-    }
-    else if (old == SEM_MAX_VALUE) {
-        /* overflow detected */
-        errno = EOVERFLOW;
-        return -1;
-    }
-
-    return 0;
-}
-
-int  sem_trywait(sem_t *sem)
-{
-    if (sem == NULL) {
-        errno = EINVAL;
-        return -1;
-    }
-
-    if (__sem_trydec(&sem->count) > 0) {
-        ANDROID_MEMBAR_FULL();
-        return 0;
-    } else {
-        errno = EAGAIN;
-        return -1;
-    }
-}
-
-/* Note that Posix requires that sem_getvalue() returns, in
- * case of contention, the negative of the number of waiting
- * threads.
- *
- * However, code that depends on this negative value to be
- * meaningful is most probably racy. The GLibc sem_getvalue()
- * only returns the semaphore value, which is 0, in case of
- * contention, so we will mimick this behaviour here instead
- * for better compatibility.
- */
-int  sem_getvalue(sem_t *sem, int *sval)
-{
-    int  val;
-
-    if (sem == NULL || sval == NULL) {
-        errno = EINVAL;
-        return -1;
-    }
-
-    val = SEMCOUNT_TO_VALUE(sem->count);
-    if (val < 0)
-        val = 0;
-
-    *sval = val;
-    return 0;
-}
diff --git a/libc/bionic/semaphore.cpp b/libc/bionic/semaphore.cpp
new file mode 100644
index 0000000..c23eb75
--- /dev/null
+++ b/libc/bionic/semaphore.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2008 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 <semaphore.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "private/bionic_atomic_inline.h"
+#include "private/bionic_constants.h"
+#include "private/bionic_futex.h"
+#include "private/bionic_time_conversions.h"
+
+// In this implementation, a semaphore contains a
+// 31-bit signed value and a 1-bit 'shared' flag
+// (for process-sharing purpose).
+//
+// We use the value -1 to indicate contention on the
+// semaphore, 0 or more to indicate uncontended state,
+// any value lower than -2 is invalid at runtime.
+//
+// State diagram:
+//
+// post(1)  ==> 2
+// post(0)  ==> 1
+// post(-1) ==> 1, then wake all waiters
+//
+// wait(2)  ==> 1
+// wait(1)  ==> 0
+// wait(0)  ==> -1 then wait for a wake up + loop
+// wait(-1) ==> -1 then wait for a wake up + loop
+
+// Use the upper 31-bits for the counter, and the lower one
+// for the shared flag.
+#define SEMCOUNT_SHARED_MASK      0x00000001
+#define SEMCOUNT_VALUE_MASK       0xfffffffe
+#define SEMCOUNT_VALUE_SHIFT      1
+
+// Convert a value into the corresponding sem->count bit pattern.
+#define SEMCOUNT_FROM_VALUE(val)    (((val) << SEMCOUNT_VALUE_SHIFT) & SEMCOUNT_VALUE_MASK)
+
+// Convert a sem->count bit pattern into the corresponding signed value.
+static inline int SEMCOUNT_TO_VALUE(uint32_t sval) {
+  return (static_cast<int>(sval) >> SEMCOUNT_VALUE_SHIFT);
+}
+
+// The value +1 as a sem->count bit-pattern.
+#define SEMCOUNT_ONE              SEMCOUNT_FROM_VALUE(1)
+
+// The value -1 as a sem->count bit-pattern.
+#define SEMCOUNT_MINUS_ONE        SEMCOUNT_FROM_VALUE(-1)
+
+#define SEMCOUNT_DECREMENT(sval)    (((sval) - (1U << SEMCOUNT_VALUE_SHIFT)) & SEMCOUNT_VALUE_MASK)
+#define SEMCOUNT_INCREMENT(sval)    (((sval) + (1U << SEMCOUNT_VALUE_SHIFT)) & SEMCOUNT_VALUE_MASK)
+
+// Return the shared bitflag from a semaphore.
+static inline uint32_t SEM_GET_SHARED(sem_t* sem) {
+  return (sem->count & SEMCOUNT_SHARED_MASK);
+}
+
+
+int sem_init(sem_t* sem, int pshared, unsigned int value) {
+  if (sem == NULL) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  // Ensure that 'value' can be stored in the semaphore.
+  if (value > SEM_VALUE_MAX) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  sem->count = SEMCOUNT_FROM_VALUE(value);
+  if (pshared != 0) {
+    sem->count |= SEMCOUNT_SHARED_MASK;
+  }
+  return 0;
+}
+
+int sem_destroy(sem_t* sem) {
+  if (sem == NULL) {
+    errno = EINVAL;
+    return -1;
+  }
+  return 0;
+}
+
+sem_t* sem_open(const char*, int, ...) {
+  errno = ENOSYS;
+  return SEM_FAILED;
+}
+
+int sem_close(sem_t*) {
+  errno = ENOSYS;
+  return -1;
+}
+
+int sem_unlink(const char*) {
+  errno = ENOSYS;
+  return -1;
+}
+
+// Decrement a semaphore's value atomically,
+// and return the old one. As a special case,
+// this returns immediately if the value is
+// negative (i.e. -1)
+static int __sem_dec(volatile uint32_t* sem) {
+  volatile int32_t* ptr = reinterpret_cast<volatile int32_t*>(sem);
+  uint32_t shared = (*sem & SEMCOUNT_SHARED_MASK);
+  uint32_t old_value, new_value;
+  int ret;
+
+  do {
+    old_value = (*sem & SEMCOUNT_VALUE_MASK);
+    ret = SEMCOUNT_TO_VALUE(old_value);
+    if (ret < 0) {
+      break;
+    }
+
+    new_value = SEMCOUNT_DECREMENT(old_value);
+  } while (__bionic_cmpxchg((old_value|shared), (new_value|shared), ptr) != 0);
+
+  return ret;
+}
+
+// Same as __sem_dec, but will not touch anything if the
+// value is already negative *or* 0. Returns the old value.
+static int __sem_trydec(volatile uint32_t* sem) {
+  volatile int32_t* ptr = reinterpret_cast<volatile int32_t*>(sem);
+  uint32_t shared = (*sem & SEMCOUNT_SHARED_MASK);
+  uint32_t old_value, new_value;
+  int          ret;
+
+  do {
+    old_value = (*sem & SEMCOUNT_VALUE_MASK);
+    ret = SEMCOUNT_TO_VALUE(old_value);
+    if (ret <= 0) {
+      break;
+    }
+
+    new_value = SEMCOUNT_DECREMENT(old_value);
+  } while (__bionic_cmpxchg((old_value|shared), (new_value|shared), ptr) != 0);
+
+  return ret;
+}
+
+
+// "Increment" the value of a semaphore atomically and
+// return its old value. Note that this implements
+// the special case of "incrementing" any negative
+// value to +1 directly.
+//
+// NOTE: The value will _not_ wrap above SEM_VALUE_MAX
+static int __sem_inc(volatile uint32_t* sem) {
+  volatile int32_t* ptr = reinterpret_cast<volatile int32_t*>(sem);
+  uint32_t shared = (*sem & SEMCOUNT_SHARED_MASK);
+  uint32_t old_value, new_value;
+  int ret;
+
+  do {
+    old_value = (*sem & SEMCOUNT_VALUE_MASK);
+    ret = SEMCOUNT_TO_VALUE(old_value);
+
+    // Can't go higher than SEM_VALUE_MAX.
+    if (ret == SEM_VALUE_MAX) {
+      break;
+    }
+
+    // If the counter is negative, go directly to +1, otherwise just increment.
+    if (ret < 0) {
+        new_value = SEMCOUNT_ONE;
+    } else {
+      new_value = SEMCOUNT_INCREMENT(old_value);
+    }
+  } while (__bionic_cmpxchg((old_value|shared), (new_value|shared), ptr) != 0);
+
+  return ret;
+}
+
+int sem_wait(sem_t* sem) {
+  if (sem == NULL) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  uint32_t shared = SEM_GET_SHARED(sem);
+
+  while (true) {
+    if (__sem_dec(&sem->count) > 0) {
+      ANDROID_MEMBAR_FULL();
+      return 0;
+    }
+
+    __futex_wait_ex(&sem->count, shared, shared|SEMCOUNT_MINUS_ONE, NULL);
+  }
+}
+
+int sem_timedwait(sem_t* sem, const timespec* abs_timeout) {
+  if (sem == NULL) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  // POSIX says we need to try to decrement the semaphore
+  // before checking the timeout value. Note that if the
+  // value is currently 0, __sem_trydec() does nothing.
+  if (__sem_trydec(&sem->count) > 0) {
+    ANDROID_MEMBAR_FULL();
+    return 0;
+  }
+
+  // Check it as per POSIX.
+  if (abs_timeout == NULL || abs_timeout->tv_sec < 0 || abs_timeout->tv_nsec < 0 || abs_timeout->tv_nsec >= NS_PER_S) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  uint32_t shared = SEM_GET_SHARED(sem);
+
+  while (true) {
+    // POSIX mandates CLOCK_REALTIME here.
+    timespec ts;
+    if (!timespec_from_absolute_timespec(ts, *abs_timeout, CLOCK_REALTIME)) {
+      errno = ETIMEDOUT;
+      return -1;
+    }
+
+    // Try to grab the semaphore. If the value was 0, this will also change it to -1.
+    if (__sem_dec(&sem->count) > 0) {
+      ANDROID_MEMBAR_FULL();
+      break;
+    }
+
+    // Contention detected. Wait for a wakeup event.
+    int ret = __futex_wait_ex(&sem->count, shared, shared|SEMCOUNT_MINUS_ONE, &ts);
+
+    // Return in case of timeout or interrupt.
+    if (ret == -ETIMEDOUT || ret == -EINTR) {
+      errno = -ret;
+      return -1;
+    }
+  }
+  return 0;
+}
+
+int sem_post(sem_t* sem) {
+  if (sem == NULL) {
+    return EINVAL;
+  }
+
+  uint32_t shared = SEM_GET_SHARED(sem);
+
+  ANDROID_MEMBAR_FULL();
+  int old_value = __sem_inc(&sem->count);
+  if (old_value < 0) {
+    // Contention on the semaphore. Wake up all waiters.
+    __futex_wake_ex(&sem->count, shared, INT_MAX);
+  } else if (old_value == SEM_VALUE_MAX) {
+    // Overflow detected.
+    errno = EOVERFLOW;
+    return -1;
+  }
+
+  return 0;
+}
+
+int sem_trywait(sem_t* sem) {
+  if (sem == NULL) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  if (__sem_trydec(&sem->count) > 0) {
+    ANDROID_MEMBAR_FULL();
+    return 0;
+  } else {
+    errno = EAGAIN;
+    return -1;
+  }
+}
+
+int sem_getvalue(sem_t* sem, int* sval) {
+  if (sem == NULL || sval == NULL) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  int val = SEMCOUNT_TO_VALUE(sem->count);
+  if (val < 0) {
+    val = 0;
+  }
+
+  *sval = val;
+  return 0;
+}
diff --git a/libc/bionic/strtoll_l.cpp b/libc/bionic/strtoll_l.cpp
index 05fb760..47b126e 100644
--- a/libc/bionic/strtoll_l.cpp
+++ b/libc/bionic/strtoll_l.cpp
@@ -28,6 +28,6 @@
 
 #include <stdlib.h>
 
-long long strtoll_l(const char *nptr, char **endptr, size_t base, locale_t) {
+long long strtoll_l(const char *nptr, char **endptr, int base, locale_t) {
   return strtoll(nptr, endptr, base);
 }
diff --git a/libc/bionic/strtoull_l.cpp b/libc/bionic/strtoull_l.cpp
index ba0bc6a..398ba0e 100644
--- a/libc/bionic/strtoull_l.cpp
+++ b/libc/bionic/strtoull_l.cpp
@@ -28,7 +28,7 @@
 
 #include <stdlib.h>
 
-unsigned long long strtoull_l(const char *nptr, char **endptr, size_t base,
+unsigned long long strtoull_l(const char *nptr, char **endptr, int base,
                               locale_t) {
   return strtoull(nptr, endptr, base);
 }
diff --git a/libc/bionic/sysconf.cpp b/libc/bionic/sysconf.cpp
index d8aac4f..951860d 100644
--- a/libc/bionic/sysconf.cpp
+++ b/libc/bionic/sysconf.cpp
@@ -49,7 +49,6 @@
 #define  SYSTEM_MQ_OPEN_MAX     8
 #define  SYSTEM_MQ_PRIO_MAX     32768
 #define  SYSTEM_SEM_NSEMS_MAX   256
-#define  SYSTEM_SEM_VALUE_MAX   0x3fffffff  /* see bionic/semaphore.c */
 #define  SYSTEM_SIGQUEUE_MAX    32
 #define  SYSTEM_TIMER_MAX       32
 #define  SYSTEM_LOGIN_NAME_MAX  256
@@ -151,36 +150,14 @@
 }
 
 int sysconf(int name) {
-    switch (name) {
-#ifdef _POSIX_ARG_MAX
+  switch (name) {
     case _SC_ARG_MAX:           return _POSIX_ARG_MAX;
-#endif
-#ifdef _POSIX2_BC_BASE_MAX
-    case _SC_BC_BASE_MAX:       return _POSIX2_BC_BASE_MAX;
-#endif
-#ifdef _POSIX2_BC_DIM_MAX
-    case _SC_BC_DIM_MAX:        return _POSIX2_BC_DIM_MAX;
-#endif
-#ifdef _POSIX2_BC_SCALE_MAX
-    case _SC_BC_SCALE_MAX:      return _POSIX2_BC_SCALE_MAX;
-#endif
-#ifdef _POSIX2_BC_STRING_MAX
-    case _SC_BC_STRING_MAX:     return _POSIX2_BC_STRING_MAX;
-#endif
     case _SC_CHILD_MAX:         return CHILD_MAX;
     case _SC_CLK_TCK:           return SYSTEM_CLK_TCK;
-#ifdef _POSIX2_COLL_WEIGHTS_MASK
-    case _SC_COLL_WEIGHTS_MAX:  return _POSIX2_COLL_WEIGHTS_MASK;
-#endif
-#ifdef _POSIX2_EXPR_NEST_MAX
-    case _SC_EXPR_NEST_MAX:    return _POSIX2_EXPR_NEST_MAX;
-#endif
-#ifdef _POSIX2_LINE_MAX
     case _SC_LINE_MAX:          return _POSIX2_LINE_MAX;
-#endif
     case _SC_NGROUPS_MAX:       return NGROUPS_MAX;
     case _SC_OPEN_MAX:          return OPEN_MAX;
-    //case _SC_PASS_MAX:          return PASS_MAX;
+    case _SC_PASS_MAX:          return PASS_MAX;
     case _SC_2_C_BIND:          return SYSTEM_2_C_BIND;
     case _SC_2_C_DEV:           return SYSTEM_2_C_DEV;
     case _SC_2_C_VERSION:       return SYSTEM_2_C_VER;
@@ -191,42 +168,20 @@
     case _SC_2_SW_DEV:          return SYSTEM_2_SW_DEV;
     case _SC_2_UPE:             return SYSTEM_2_UPE;
     case _SC_2_VERSION:         return SYSTEM_2_VERSION;
-#ifdef _POSIX_JOB_CONTROL
     case _SC_JOB_CONTROL:       return _POSIX_JOB_CONTROL;
-#endif
-#ifdef _POSIX_SAVED_IDS
     case _SC_SAVED_IDS:         return _POSIX_SAVED_IDS;
-#endif
-#ifdef _POSIX_VERSION
     case _SC_VERSION:           return _POSIX_VERSION;
-#endif
-    //case _SC_RE_DUP_<AX:        return ;
+    case _SC_RE_DUP_MAX:        return _POSIX_RE_DUP_MAX;
     case _SC_STREAM_MAX:        return FOPEN_MAX;
-    //case _SC_TZNAME_MAX:        return ;
-#if _XOPEN_CRYPT
+    case _SC_TZNAME_MAX:        return _POSIX_TZNAME_MAX;
     case _SC_XOPEN_CRYPT:       return _XOPEN_CRYPT;
-#endif
-#ifdef _XOPEN_ENH_I18N
     case _SC_XOPEN_ENH_I18N:    return _XOPEN_ENH_I18N;
-#endif
-#ifdef _XOPEN_SHM
-    case _SC_XOPEN_SHM:         return _XOPEN_SHM;
-#endif
-#ifdef _XOPEN_VERSION
+    //case _SC_XOPEN_SHM:         return _XOPEN_SHM;
     case _SC_XOPEN_VERSION:     return _XOPEN_VERSION;
-#endif
-#ifdef _XOPEN_XCU_VERSION
     case _SC_XOPEN_XCU_VERSION: return _XOPEN_XCU_VERSION;
-#endif
-#ifdef _XOPEN_REALTIME
     case _SC_XOPEN_REALTIME:    return _XOPEN_REALTIME;
-#endif
-#ifdef _XOPEN_REALTIME_THREADS
     case _SC_XOPEN_REALTIME_THREADS: return _XOPEN_REALTIME_THREADS;
-#endif
-#ifdef _XOPEN_LEGACY
     case _SC_XOPEN_LEGACY:      return _XOPEN_LEGACY;
-#endif
     case _SC_ATEXIT_MAX:        return SYSTEM_ATEXIT_MAX;
     case _SC_IOV_MAX:           return SYSTEM_IOV_MAX;
 
@@ -234,71 +189,35 @@
     case _SC_PAGE_SIZE:
         return PAGE_SIZE;
 
-#ifdef _XOPEN_UNIX
     case _SC_XOPEN_UNIX:        return _XOPEN_UNIX;
-#endif
 
     // XXX: TODO: XBS5 nonsense
 
-#ifdef AIO_LISTIO_MAX
-    case _SC_AIO_LISTIO_MAX:       return AIO_LISTIO_MAX;
-#endif
-#ifdef AIO_MAX
-    case _SC_AIO_MAX:              return AIO_MAX;
-#endif
-#ifdef AIO_PRIO_DELTA_MAX
-    case _SC_AIO_PRIO_DELTA_MAX:   return AIO_PRIO_DELTA_MAX;
-#endif
+    //case _SC_AIO_LISTIO_MAX:       return AIO_LISTIO_MAX;
+    //case _SC_AIO_MAX:              return AIO_MAX;
+    //case _SC_AIO_PRIO_DELTA_MAX:   return AIO_PRIO_DELTA_MAX;
     case _SC_DELAYTIMER_MAX:    return SYSTEM_DELAYTIMER_MAX;
     case _SC_MQ_OPEN_MAX:       return SYSTEM_MQ_OPEN_MAX;
     case _SC_MQ_PRIO_MAX:       return SYSTEM_MQ_PRIO_MAX;
     case _SC_RTSIG_MAX:         return RTSIG_MAX;
     case _SC_SEM_NSEMS_MAX:     return SYSTEM_SEM_NSEMS_MAX;
-    case _SC_SEM_VALUE_MAX:     return SYSTEM_SEM_VALUE_MAX;
+    case _SC_SEM_VALUE_MAX:     return SEM_VALUE_MAX;
     case _SC_SIGQUEUE_MAX:      return SYSTEM_SIGQUEUE_MAX;
     case _SC_TIMER_MAX:         return SYSTEM_TIMER_MAX;
-#ifdef _POSIX_ASYNCHRONOUS_IO
-    case _SC_ASYNCHRONOUS_IO:   return _POSIX_ASYNCHRONOUS_IO;
-#endif
-#ifdef _POSIX_FSYNC
+    //case _SC_ASYNCHRONOUS_IO:   return _POSIX_ASYNCHRONOUS_IO;
     case _SC_FSYNC:             return _POSIX_FSYNC;
-#endif
-#ifdef _POSIX_MAPPED_FILES
     case _SC_MAPPED_FILES:      return _POSIX_MAPPED_FILES;
-#endif
-#ifdef _POSIX_MEMLOCK
-    case _SC_MEMLOCK:           return _POSIX_MEMLOCK;
-#endif
-#ifdef _POSIX_MEMLOCK_RANGE
-    case _SC_MEMLOCK_RANGE:     return _POSIX_MEMLOCK_RANGE
-#endif
-#ifdef _POSIX_MEMORY_PROTECTION
-    case _SC_MEMORY_PROTECTION: return _POSIX_MEMORY_PROTECTION;
-#endif
-#ifdef _POSIX_MESSAGE_PASSING
-    case _SC_MESSAGE_PASSING:   return _POSIX_MESSAGE_PASSING;
-#endif
-#ifdef _POSIX_PRIORITIZED_IO
-    case _SC_PRIORITIZED_IO:    return _POSIX_PRIORITIZED_IO;
-#endif
-#ifdef _POSIX_PRIORITY_SCHEDULING
+    //case _SC_MEMLOCK:           return _POSIX_MEMLOCK;
+    //case _SC_MEMLOCK_RANGE:     return _POSIX_MEMLOCK_RANGE;
+    //case _SC_MEMORY_PROTECTION: return _POSIX_MEMORY_PROTECTION;
+    //case _SC_MESSAGE_PASSING:   return _POSIX_MESSAGE_PASSING;
+    //case _SC_PRIORITIZED_IO:    return _POSIX_PRIORITIZED_IO;
     case _SC_PRIORITY_SCHEDULING:  return _POSIX_PRIORITY_SCHEDULING;
-#endif
-#ifdef _POSIX_REALTIME_SIGNALS
     case _SC_REALTIME_SIGNALS:  return _POSIX_REALTIME_SIGNALS;
-#endif
-#ifdef _POSIX_SEMAPHORES
     case _SC_SEMAPHORES:        return _POSIX_SEMAPHORES;
-#endif
-#ifdef _POSIX_SHARED_MEMORY_OBJECTS
-    case _SC_SHARED_MEMORY_OBJECTS:  return _POSIX_SHARED_MEMORY_OBJECTS;
-#endif
-#ifdef _POSIX_SYNCHRONIZED_IO
+    //case _SC_SHARED_MEMORY_OBJECTS:  return _POSIX_SHARED_MEMORY_OBJECTS;
     case _SC_SYNCHRONIZED_IO:   return _POSIX_SYNCHRONIZED_IO;
-#endif
-#ifdef _POSIX_TIMERS
     case _SC_TIMERS:            return _POSIX_TIMERS;
-#endif
 
     case _SC_GETGR_R_SIZE_MAX: return 1024;
     case _SC_GETPW_R_SIZE_MAX: return 1024;
@@ -314,25 +233,15 @@
     case _SC_THREAD_STACK_MIN:    return PTHREAD_STACK_MIN;
     case _SC_THREAD_THREADS_MAX:  return SYSTEM_THREAD_THREADS_MAX;
     case _SC_TTY_NAME_MAX:        return SYSTEM_TTY_NAME_MAX;
-#ifdef _POSIX_THREADS
     case _SC_THREADS:             return _POSIX_THREADS;
-#endif
 
     case _SC_THREAD_ATTR_STACKADDR:   return -1; // Removed in POSIX 2008
     case _SC_THREAD_ATTR_STACKSIZE:   return -1; // Removed in POSIX 2008
 
-#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
-    case _SC_THREAD_PRIORITY_SCHEDULING:  return _POSIX_THREAD_PRIORITY_SCHEDULING;
-#endif
-#ifdef _POSIX_THREAD_PRIO_INHERIT
+    //case _SC_THREAD_PRIORITY_SCHEDULING:  return _POSIX_THREAD_PRIORITY_SCHEDULING;
     case _SC_THREAD_PRIO_INHERIT:         return _POSIX_THREAD_PRIO_INHERIT;
-#endif
-#ifdef _POSIX_THREAD_PRIO_PROTECT
     case _SC_THREAD_PRIO_PROTECT: return _POSIX_THREAD_PRIO_PROTECT;
-#endif
-#ifdef _POSIX_THREAD_SAFE_FUNCTIONS
-    case _SC_THREAD_SAFE_FUNCTIONS:  return _POSIX_THREAD_SAFE_FUNCTIONS
-#endif
+    //case _SC_THREAD_SAFE_FUNCTIONS:  return _POSIX_THREAD_SAFE_FUNCTIONS
 
     case _SC_MONOTONIC_CLOCK:   return __sysconf_monotonic_clock();
     case _SC_NPROCESSORS_CONF:  return __sysconf_nprocessors_conf();
@@ -341,9 +250,9 @@
     case _SC_AVPHYS_PAGES:      return __sysconf_avphys_pages();
 
     default:
-       /* Posix says EINVAL is the only error that shall be returned,
-        * but GLibc uses ENOSYS */
-        errno = ENOSYS;
-        return -1;
-    }
+      // Posix says EINVAL is the only error that shall be returned,
+      // but glibc uses ENOSYS.
+      errno = ENOSYS;
+      return -1;
+  }
 }
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index 411d6bf..170e7ac 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -471,8 +471,8 @@
 
 static int send_prop_msg(const prop_msg *msg)
 {
-    const int fd = socket(AF_LOCAL, SOCK_STREAM, 0);
-    if (fd < 0) {
+    const int fd = socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
+    if (fd == -1) {
         return -1;
     }
 
diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index 524ba07..e0879b9 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -230,13 +230,13 @@
   return wcsxfrm(dest, src, n);
 }
 
-long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, size_t base,
+long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, int base,
                     locale_t) {
   return wcstoll(nptr, endptr, base);
 }
 
 unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr,
-                              size_t base, locale_t) {
+                              int base, locale_t) {
   return wcstoull(nptr, endptr, base);
 }
 
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index db56ce3..f57c320 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -46,6 +46,7 @@
 #endif
 
 #define O_ASYNC FASYNC
+#define O_RSYNC O_SYNC
 
 #define SPLICE_F_MOVE 1
 #define SPLICE_F_NONBLOCK 2
diff --git a/libc/include/limits.h b/libc/include/limits.h
index fb09657..69df082 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -37,39 +37,6 @@
 
 #include <sys/cdefs.h>
 
-#if __POSIX_VISIBLE
-#define	_POSIX_ARG_MAX		4096
-#define	_POSIX_CHILD_MAX	25
-#define	_POSIX_LINK_MAX		8
-#define	_POSIX_MAX_CANON	255
-#define	_POSIX_MAX_INPUT	255
-#define	_POSIX_NAME_MAX		14
-#define	_POSIX_NGROUPS_MAX	0
-#define	_POSIX_OPEN_MAX		16
-#define	_POSIX_PATH_MAX		256
-#define _POSIX_PIPE_BUF		512
-#define	_POSIX_RE_DUP_MAX	255
-#define _POSIX_SSIZE_MAX	32767
-#define _POSIX_STREAM_MAX	8
-#define _POSIX_SYMLINK_MAX	255
-#define _POSIX_SYMLOOP_MAX	8
-#define _POSIX_TZNAME_MAX	3
-
-#define	_POSIX2_BC_BASE_MAX	99
-#define	_POSIX2_BC_DIM_MAX	2048
-#define	_POSIX2_BC_SCALE_MAX	99
-#define	_POSIX2_BC_STRING_MAX	1000
-#define	_POSIX2_COLL_WEIGHTS_MAX	2
-#define	_POSIX2_EXPR_NEST_MAX	32
-#define	_POSIX2_LINE_MAX	2048
-#define	_POSIX2_RE_DUP_MAX	_POSIX_RE_DUP_MAX
-
-#if __POSIX_VISIBLE >= 200112
-#define _POSIX_TTY_NAME_MAX	9	/* includes trailing NUL */
-#define _POSIX_LOGIN_NAME_MAX	9	/* includes trailing NUL */
-#endif /* __POSIX_VISIBLE >= 200112 */
-#endif /* __POSIX_VISIBLE */
-
 #if __XPG_VISIBLE
 #define PASS_MAX		128	/* _PASSWORD_LEN from <pwd.h> */
 
@@ -125,4 +92,9 @@
 /* glibc's PAGE_MASK is the bitwise negation of BSD's! TODO: remove? */
 #define PAGE_MASK (~(PAGE_SIZE - 1))
 
+#define SEM_VALUE_MAX 0x3fffffff
+
+/* POSIX says these belong in <unistd.h> but BSD has some in <limits.h>. */
+#include <machine/posix_limits.h>
+
 #endif /* !_LIMITS_H_ */
diff --git a/libc/include/machine/posix_limits.h b/libc/include/machine/posix_limits.h
new file mode 100644
index 0000000..f906e3b
--- /dev/null
+++ b/libc/include/machine/posix_limits.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef _POSIX_LIMITS_H_
+#define _POSIX_LIMITS_H_
+
+/* TODO: complete and check these. */
+#define _POSIX2_LINE_MAX            2048
+#define _POSIX2_RE_DUP_MAX          _POSIX_RE_DUP_MAX
+#define _POSIX_ARG_MAX              4096
+#define _POSIX_CHILD_MAX            25
+#define _POSIX_CHOWN_RESTRICTED     1  /* yes, chown requires appropriate privileges */
+#define _POSIX_FSYNC                1  /* fdatasync() supported */
+#define _POSIX_JOB_CONTROL          1  /* job control is a Linux feature */
+#define _POSIX_LINK_MAX             8
+#define _POSIX_LOGIN_NAME_MAX       9  /* includes trailing NUL */
+#define _POSIX_MAPPED_FILES         1  /* mmap-ed files supported */
+#define _POSIX_MAX_CANON            255
+#define _POSIX_MAX_INPUT            255
+#define _POSIX_MONOTONIC_CLOCK      0  /* the monotonic clock may be available; ask sysconf */
+#define _POSIX_NAME_MAX             14
+#define _POSIX_NGROUPS_MAX          0
+#define _POSIX_NO_TRUNC             1  /* very long pathnames generate an error */
+#define _POSIX_OPEN_MAX             16
+#define _POSIX_PATH_MAX             256
+#define _POSIX_PIPE_BUF             512
+#define _POSIX_PRIORITY_SCHEDULING  1  /* priority scheduling is a Linux feature */
+#define _POSIX_REALTIME_SIGNALS     -1 /* for now, this is not supported */
+#define _POSIX_RE_DUP_MAX           255
+#define _POSIX_SAVED_IDS            1  /* saved user ids is a Linux feature */
+#define _POSIX_SEMAPHORES           200809L
+#define _POSIX_SEM_VALUE_MAX        32767
+#define _POSIX_SSIZE_MAX            32767
+#define _POSIX_STREAM_MAX           8
+#define _POSIX_SYMLINK_MAX          255
+#define _POSIX_SYMLOOP_MAX          8
+#define _POSIX_SYNCHRONIZED_IO      1  /* synchronized i/o supported */
+#define _POSIX_THREAD_PRIO_INHERIT  200112L  /* linux feature */
+#define _POSIX_THREAD_PRIO_PROTECT  200112L  /* linux feature */
+#define _POSIX_THREADS              1  /* we support threads */
+#define _POSIX_THREAD_STACKADDR     1  /* we support thread stack address */
+#define _POSIX_THREAD_STACKSIZE     1  /* we support thread stack size */
+#define _POSIX_TIMERS               1  /* Posix timers are supported */
+#define _POSIX_TTY_NAME_MAX         9  /* includes trailing NUL */
+#define _POSIX_TZNAME_MAX           3
+#define _POSIX_VDISABLE             '\0'
+
+#endif /* _POSIX_LIMITS_H_ */
diff --git a/libc/include/pathconf.h b/libc/include/pathconf.h
deleted file mode 100644
index 94f9787..0000000
--- a/libc/include/pathconf.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-#ifndef _PATHCONF_H_
-#define _PATHCONF_H_
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-/* constants to be used for the 'name' paremeter of pathconf/fpathconf */
-
-#define  _PC_FILESIZEBITS       0x0000
-#define  _PC_LINK_MAX           0x0001
-#define  _PC_MAX_CANON          0x0002
-#define  _PC_MAX_INPUT          0x0003
-#define  _PC_NAME_MAX           0x0004
-#define  _PC_PATH_MAX           0x0005
-#define  _PC_PIPE_BUF           0x0006
-#define  _PC_2_SYMLINKS         0x0007
-#define  _PC_ALLOC_SIZE_MIN     0x0008
-#define  _PC_REC_INCR_XFER_SIZE 0x0009
-#define  _PC_REC_MAX_XFER_SIZE  0x000a
-#define  _PC_REC_MIN_XFER_SIZE  0x000b
-#define  _PC_REC_XFER_ALIGN     0x000c
-#define  _PC_SYMLINK_MAX        0x000d
-#define  _PC_CHOWN_RESTRICTED   0x000e
-#define  _PC_NO_TRUNC           0x000f
-#define  _PC_VDISABLE           0x0010
-#define  _PC_ASYNC_IO           0x0011
-#define  _PC_PRIO_IO            0x0012
-#define  _PC_SYNC_IO            0x0013
-
-extern long fpathconf(int fildes, int name);
-extern long pathconf(const char *path, int name);
-
-__END_DECLS
-
-#endif /* _PATHCONF_H_ */
-
diff --git a/libc/include/semaphore.h b/libc/include/semaphore.h
index 7ae3c3a..5827870 100644
--- a/libc/include/semaphore.h
+++ b/libc/include/semaphore.h
@@ -25,6 +25,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #ifndef _SEMAPHORE_H
 #define _SEMAPHORE_H
 
@@ -32,6 +33,8 @@
 
 __BEGIN_DECLS
 
+struct timespec;
+
 typedef struct {
   volatile unsigned int count;
 #ifdef __LP64__
@@ -41,20 +44,18 @@
 
 #define SEM_FAILED NULL
 
-extern int sem_init(sem_t *sem, int pshared, unsigned int value);
+int sem_destroy(sem_t*);
+int sem_getvalue(sem_t*, int*);
+int sem_init(sem_t*, int, unsigned int);
+int sem_post(sem_t*);
+int sem_timedwait(sem_t*, const struct timespec*);
+int sem_trywait(sem_t*);
+int sem_wait(sem_t*);
 
-extern int    sem_close(sem_t *);
-extern int    sem_destroy(sem_t *);
-extern int    sem_getvalue(sem_t *, int *);
-extern int    sem_init(sem_t *, int, unsigned int);
-extern sem_t *sem_open(const char *, int, ...);
-extern int    sem_post(sem_t *);
-extern int    sem_trywait(sem_t *);
-extern int    sem_unlink(const char *);
-extern int    sem_wait(sem_t *);
-
-struct timespec;
-extern int    sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
+/* These aren't actually implemented. */
+sem_t* sem_open(const char*, int, ...);
+int sem_close(sem_t*);
+int sem_unlink(const char*);
 
 __END_DECLS
 
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 52f71dd..fd2bf6c 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -59,8 +59,15 @@
 
 extern char* mkdtemp(char*);
 extern char* mktemp(char*) __warnattr("mktemp possibly used unsafely; consider using mkstemp");
-extern int mkstemp(char*);
+
+extern int mkostemp64(char*, int);
+extern int mkostemp(char*, int);
+extern int mkostemps64(char*, int, int);
+extern int mkostemps(char*, int, int);
 extern int mkstemp64(char*);
+extern int mkstemp(char*);
+extern int mkstemps64(char*, int);
+extern int mkstemps(char*, int);
 
 extern long strtol(const char *, char **, int);
 extern long long strtoll(const char *, char **, int);
@@ -76,8 +83,8 @@
 extern long double strtold(const char*, char**) __LIBC_ABI_PUBLIC__;
 
 extern long double strtold_l(const char *, char **, locale_t) __LIBC_ABI_PUBLIC__;
-extern long long strtoll_l(const char *, char **, size_t, locale_t) __LIBC_ABI_PUBLIC__;
-extern unsigned long long strtoull_l(const char *, char **, size_t, locale_t) __LIBC_ABI_PUBLIC__;
+extern long long strtoll_l(const char *, char **, int, locale_t) __LIBC_ABI_PUBLIC__;
+extern unsigned long long strtoull_l(const char *, char **, int, locale_t) __LIBC_ABI_PUBLIC__;
 
 extern int atoi(const char*) __purefunc;
 extern long atol(const char*) __purefunc;
diff --git a/libc/include/sys/limits.h b/libc/include/sys/limits.h
index c50eb10..edb8c47 100644
--- a/libc/include/sys/limits.h
+++ b/libc/include/sys/limits.h
@@ -135,31 +135,6 @@
 #define  _XOPEN_REALTIME          -1 /* we don't support all these functions */
 #define  _XOPEN_REALTIME_THREADS  -1  /* same here */
 
-#define  _POSIX_REALTIME_SIGNALS    -1  /* for now, this is not supported */
-#define  _POSIX_PRIORITY_SCHEDULING  1  /* priority scheduling is a Linux feature */
-#define  _POSIX_TIMERS               1  /* Posix timers are supported */
-#undef   _POSIX_ASYNCHRONOUS_IO         /* aio_ functions are not supported */
-#define  _POSIX_SYNCHRONIZED_IO      1  /* synchronized i/o supported */
-#define  _POSIX_FSYNC                1  /* fdatasync() supported */
-#define  _POSIX_MAPPED_FILES         1  /* mmap-ed files supported */
-
-/* XXX: TODO: complete and check list here */
-
-
-#define  _POSIX_THREADS             1    /* we support threads */
-#define  _POSIX_THREAD_STACKADDR    1    /* we support thread stack address */
-#define  _POSIX_THREAD_STACKSIZE    1    /* we support thread stack size */
-#define  _POSIX_THREAD_PRIO_INHERIT 200112L   /* linux feature */
-#define  _POSIX_THREAD_PRIO_PROTECT 200112L   /* linux feature */
-
-#undef   _POSIX_PROCESS_SHARED           /* we don't support process-shared synchronization */
-#undef   _POSIX_THREAD_SAFE_FUNCTIONS    /* most functions are, but not everything yet */
-#define  _POSIX_CHOWN_RESTRICTED    1    /* yes, chown requires appropriate privileges */
-#define  _POSIX_MONOTONIC_CLOCK     0    /* the monotonic clock may be available; ask sysconf */
-#define  _POSIX_NO_TRUNC            1    /* very long pathnames generate an error */
-#define  _POSIX_SAVED_IDS           1    /* saved user ids is a Linux feature */
-#define  _POSIX_JOB_CONTROL         1    /* job control is a Linux feature */
-
 #define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 /* the minimum mandated by POSIX */
 #define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
 #define _POSIX_THREAD_KEYS_MAX 128            /* the minimum mandated by POSIX */
@@ -167,5 +142,4 @@
 #define _POSIX_THREAD_THREADS_MAX 64          /* the minimum mandated by POSIX */
 #define PTHREAD_THREADS_MAX                   /* bionic has no specific limit */
 
-
 #endif
diff --git a/libc/include/sys/vfs.h b/libc/include/sys/vfs.h
index 5358ffb..1fbc8be 100644
--- a/libc/include/sys/vfs.h
+++ b/libc/include/sys/vfs.h
@@ -25,6 +25,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #ifndef _SYS_VFS_H_
 #define _SYS_VFS_H_
 
@@ -114,50 +115,27 @@
 #define _STATFS_F_FRSIZE
 #define _STATFS_F_FLAGS
 
-#define  ADFS_SUPER_MAGIC      0xadf5
-#define  AFFS_SUPER_MAGIC      0xADFF
-#define  BEFS_SUPER_MAGIC      0x42465331
-#define  BFS_MAGIC             0x1BADFACE
-#define  CIFS_MAGIC_NUMBER     0xFF534D42
-#define  CODA_SUPER_MAGIC      0x73757245
-#define  COH_SUPER_MAGIC       0x012FF7B7
-#define  CRAMFS_MAGIC          0x28cd3d45
-#define  DEVFS_SUPER_MAGIC     0x1373
-#define  EFS_SUPER_MAGIC       0x00414A53
-#define  EXT_SUPER_MAGIC       0x137D
-#define  EXT2_OLD_SUPER_MAGIC  0xEF51
-#define  EXT2_SUPER_MAGIC      0xEF53
-#define  EXT3_SUPER_MAGIC      0xEF53
-#define  HFS_SUPER_MAGIC       0x4244
-#define  HPFS_SUPER_MAGIC      0xF995E849
-#define  HUGETLBFS_MAGIC       0x958458f6
-#define  ISOFS_SUPER_MAGIC     0x9660
-#define  JFFS2_SUPER_MAGIC     0x72b6
-#define  JFS_SUPER_MAGIC       0x3153464a
-#define  MINIX_SUPER_MAGIC     0x137F /* orig. minix */
-#define  MINIX_SUPER_MAGIC2    0x138F /* 30 char minix */
-#define  MINIX2_SUPER_MAGIC    0x2468 /* minix V2 */
-#define  MINIX2_SUPER_MAGIC2   0x2478 /* minix V2, 30 char names */
-#define  MSDOS_SUPER_MAGIC     0x4d44
-#define  NCP_SUPER_MAGIC       0x564c
-#define  NFS_SUPER_MAGIC       0x6969
-#define  NTFS_SB_MAGIC         0x5346544e
-#define  OPENPROM_SUPER_MAGIC  0x9fa1
-#define  PROC_SUPER_MAGIC      0x9fa0
-#define  QNX4_SUPER_MAGIC      0x002f
-#define  REISERFS_SUPER_MAGIC  0x52654973
-#define  ROMFS_MAGIC           0x7275
-#define  SMB_SUPER_MAGIC       0x517B
-#define  SYSV2_SUPER_MAGIC     0x012FF7B6
-#define  SYSV4_SUPER_MAGIC     0x012FF7B5
-#define  TMPFS_MAGIC           0x01021994
-#define  UDF_SUPER_MAGIC       0x15013346
-#define  UFS_MAGIC             0x00011954
-#define  USBDEVICE_SUPER_MAGIC 0x9fa2
-#define  VXFS_SUPER_MAGIC      0xa501FCF5
-#define  XENIX_SUPER_MAGIC     0x012FF7B4
-#define  XFS_SUPER_MAGIC       0x58465342
-#define  _XIAFS_SUPER_MAGIC    0x012FD16D
+/* Pull in the kernel magic numbers. */
+#include <linux/magic.h>
+/* Add in ones that we had historically that aren't in the uapi header. */
+#define BEFS_SUPER_MAGIC      0x42465331
+#define BFS_MAGIC             0x1BADFACE
+#define CIFS_MAGIC_NUMBER     0xFF534D42
+#define COH_SUPER_MAGIC       0x012FF7B7
+#define DEVFS_SUPER_MAGIC     0x1373
+#define EXT_SUPER_MAGIC       0x137D
+#define EXT2_OLD_SUPER_MAGIC  0xEF51
+#define HFS_SUPER_MAGIC       0x4244
+#define JFS_SUPER_MAGIC       0x3153464a
+#define NTFS_SB_MAGIC         0x5346544e
+#define ROMFS_MAGIC           0x7275
+#define SYSV2_SUPER_MAGIC     0x012FF7B6
+#define SYSV4_SUPER_MAGIC     0x012FF7B5
+#define UDF_SUPER_MAGIC       0x15013346
+#define UFS_MAGIC             0x00011954
+#define VXFS_SUPER_MAGIC      0xa501FCF5
+#define XENIX_SUPER_MAGIC     0x012FF7B4
+#define XFS_SUPER_MAGIC       0x58465342
 
 extern int statfs(const char*, struct statfs*) __nonnull((1, 2));
 extern int statfs64(const char*, struct statfs64*) __nonnull((1, 2));
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 34ae2bc..475ee1af 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -34,7 +34,6 @@
 #include <sys/types.h>
 #include <sys/select.h>
 #include <sys/sysconf.h>
-#include <pathconf.h>
 
 __BEGIN_DECLS
 
@@ -48,6 +47,29 @@
 #define SEEK_CUR 1
 #define SEEK_END 2
 
+#define _PC_FILESIZEBITS 0
+#define _PC_LINK_MAX 1
+#define _PC_MAX_CANON 2
+#define _PC_MAX_INPUT 3
+#define _PC_NAME_MAX 4
+#define _PC_PATH_MAX 5
+#define _PC_PIPE_BUF 6
+#define _PC_2_SYMLINKS 7
+#define _PC_ALLOC_SIZE_MIN 8
+#define _PC_REC_INCR_XFER_SIZE 9
+#define _PC_REC_MAX_XFER_SIZE 10
+#define _PC_REC_MIN_XFER_SIZE 11
+#define _PC_REC_XFER_ALIGN 12
+#define _PC_SYMLINK_MAX 13
+#define _PC_CHOWN_RESTRICTED 14
+#define _PC_NO_TRUNC 15
+#define _PC_VDISABLE 16
+#define _PC_ASYNC_IO 17
+#define _PC_PRIO_IO 18
+#define _PC_SYNC_IO 19
+
+#include <machine/posix_limits.h>
+
 extern char** environ;
 
 extern __noreturn void _exit(int);
@@ -96,6 +118,9 @@
 extern void endusershell(void);
 
 
+extern long fpathconf(int, int);
+extern long pathconf(const char*, int);
+
 
 /* Macros for access() */
 #define R_OK  4  /* Read */
@@ -144,9 +169,7 @@
 
 extern int dup(int);
 extern int dup2(int, int);
-#if defined(__USE_GNU)
 extern int dup3(int, int, int);
-#endif
 extern int fcntl(int, int, ...);
 extern int ioctl(int, int, ...);
 extern int flock(int, int);
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index ae10d93..10a78b8 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -151,8 +151,8 @@
 extern int               wprintf(const wchar_t *, ...);
 extern int               wscanf(const wchar_t *, ...);
 
-extern long long          wcstoll_l(const wchar_t *, wchar_t **, size_t, locale_t);
-extern unsigned long long wcstoull_l(const wchar_t *, wchar_t **, size_t, locale_t);
+extern long long          wcstoll_l(const wchar_t *, wchar_t **, int, locale_t);
+extern unsigned long long wcstoull_l(const wchar_t *, wchar_t **, int, locale_t);
 extern long double        wcstold_l(const wchar_t *, wchar_t **, locale_t );
 
 extern int    wcscoll_l(const wchar_t *, const wchar_t *, locale_t);
diff --git a/libc/private/bionic_constants.h b/libc/private/bionic_constants.h
new file mode 100644
index 0000000..9ae1c8d
--- /dev/null
+++ b/libc/private/bionic_constants.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BIONIC_CONSTANTS_H_
+#define _BIONIC_CONSTANTS_H_
+
+#define NS_PER_S 1000000000
+
+#endif // _BIONIC_CONSTANTS_H_
diff --git a/libc/private/bionic_time_conversions.h b/libc/private/bionic_time_conversions.h
index 51f543f..cf0046a 100644
--- a/libc/private/bionic_time_conversions.h
+++ b/libc/private/bionic_time_conversions.h
@@ -39,6 +39,8 @@
 
 __LIBC_HIDDEN__ void timeval_from_timespec(timeval& tv, const timespec& ts);
 
+__LIBC_HIDDEN__ bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock);
+
 __END_DECLS
 
 #endif
diff --git a/libc/upstream-netbsd/lib/libc/unistd/killpg.c b/libc/upstream-openbsd/lib/libc/compat-43/killpg.c
similarity index 80%
rename from libc/upstream-netbsd/lib/libc/unistd/killpg.c
rename to libc/upstream-openbsd/lib/libc/compat-43/killpg.c
index ceac3f4..75b1ad9 100644
--- a/libc/upstream-netbsd/lib/libc/unistd/killpg.c
+++ b/libc/upstream-openbsd/lib/libc/compat-43/killpg.c
@@ -1,8 +1,6 @@
-/*	$NetBSD: killpg.c,v 1.8 2003/08/07 16:42:39 agc Exp $	*/
-
 /*
- * Copyright (c) 1989, 1993
- *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,15 +27,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)killpg.c	8.1 (Berkeley) 6/2/93";
-#else
-__RCSID("$NetBSD: killpg.c,v 1.8 2003/08/07 16:42:39 agc Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
 #include <sys/types.h>
 #include <signal.h>
 #include <errno.h>
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c b/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c
index 793d71c..16f6f9c 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: ldtoa.c,v 1.1 2008/09/07 20:36:08 martynas Exp $	*/
+/*	$OpenBSD: ldtoa.c,v 1.2 2014/08/10 02:15:18 guenther Exp $	*/
 /*-
  * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
  * All rights reserved.
@@ -30,7 +30,7 @@
 #include <machine/ieee.h>
 #endif /* !__vax__ */
 #include <float.h>
-#include <inttypes.h>
+#include <stdint.h>
 #include <limits.h>
 #include <math.h>
 #include <stdlib.h>
diff --git a/libc/upstream-openbsd/lib/libc/net/htonl.c b/libc/upstream-openbsd/lib/libc/net/htonl.c
index 5ab4189..6ee6e7e 100644
--- a/libc/upstream-openbsd/lib/libc/net/htonl.c
+++ b/libc/upstream-openbsd/lib/libc/net/htonl.c
@@ -1,11 +1,11 @@
-/*	$OpenBSD: htonl.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
+/*	$OpenBSD: htonl.c,v 1.7 2014/07/21 01:51:10 guenther Exp $ */
 /*
  * Written by J.T. Conklin <jtc@netbsd.org>.
  * Public domain.
  */
 
 #include <sys/types.h>
-#include <machine/endian.h>
+#include <endian.h>
 
 #undef htonl
 
diff --git a/libc/upstream-openbsd/lib/libc/net/htons.c b/libc/upstream-openbsd/lib/libc/net/htons.c
index c8b73fd..f48d91e 100644
--- a/libc/upstream-openbsd/lib/libc/net/htons.c
+++ b/libc/upstream-openbsd/lib/libc/net/htons.c
@@ -1,11 +1,11 @@
-/*	$OpenBSD: htons.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
+/*	$OpenBSD: htons.c,v 1.9 2014/07/21 01:51:10 guenther Exp $ */
 /*
  * Written by J.T. Conklin <jtc@netbsd.org>.
  * Public domain.
  */
 
 #include <sys/types.h>
-#include <machine/endian.h>
+#include <endian.h>
 
 #undef htons
 
diff --git a/libc/upstream-openbsd/lib/libc/net/ntohl.c b/libc/upstream-openbsd/lib/libc/net/ntohl.c
index 36414b7..0d05bac 100644
--- a/libc/upstream-openbsd/lib/libc/net/ntohl.c
+++ b/libc/upstream-openbsd/lib/libc/net/ntohl.c
@@ -1,11 +1,11 @@
-/*	$OpenBSD: ntohl.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
+/*	$OpenBSD: ntohl.c,v 1.7 2014/07/21 01:51:10 guenther Exp $ */
 /*
  * Written by J.T. Conklin <jtc@netbsd.org>.
  * Public domain.
  */
 
 #include <sys/types.h>
-#include <machine/endian.h>
+#include <endian.h>
 
 #undef ntohl
 
diff --git a/libc/upstream-openbsd/lib/libc/net/ntohs.c b/libc/upstream-openbsd/lib/libc/net/ntohs.c
index 8f345e8..b5ea361 100644
--- a/libc/upstream-openbsd/lib/libc/net/ntohs.c
+++ b/libc/upstream-openbsd/lib/libc/net/ntohs.c
@@ -1,11 +1,11 @@
-/*	$OpenBSD: ntohs.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
+/*	$OpenBSD: ntohs.c,v 1.9 2014/07/21 01:51:10 guenther Exp $ */
 /*
  * Written by J.T. Conklin <jtc@netbsd.org>.
  * Public domain.
  */
 
 #include <sys/types.h>
-#include <machine/endian.h>
+#include <endian.h>
 
 #undef ntohs
 
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fdopen.c b/libc/upstream-openbsd/lib/libc/stdio/fdopen.c
index 3e47f2c..1c0c813 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fdopen.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fdopen.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fdopen.c,v 1.6 2008/04/21 12:28:35 otto Exp $ */
+/*	$OpenBSD: fdopen.c,v 1.7 2014/08/31 02:21:18 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -66,6 +66,7 @@
 	if ((fp = __sfp()) == NULL)
 		return (NULL);
 	fp->_flags = flags;
+
 	/*
 	 * If opened for appending, but underlying descriptor does not have
 	 * O_APPEND bit set, assert __SAPP so that __swrite() will lseek to
@@ -73,6 +74,13 @@
 	 */
 	if ((oflags & O_APPEND) && !(fdflags & O_APPEND))
 		fp->_flags |= __SAPP;
+
+	/*
+	 * If close-on-exec was requested, then turn it on if not already
+	 */
+	if ((oflags & O_CLOEXEC) && !((tmp = fcntl(fd, F_GETFD)) & FD_CLOEXEC))
+		fcntl(fd, F_SETFD, tmp | FD_CLOEXEC);
+
 	fp->_file = fd;
 	fp->_cookie = fp;
 	fp->_read = __sread;
diff --git a/libc/upstream-freebsd/lib/libc/stdio/flags.c b/libc/upstream-openbsd/lib/libc/stdio/flags.c
similarity index 77%
rename from libc/upstream-freebsd/lib/libc/stdio/flags.c
rename to libc/upstream-openbsd/lib/libc/stdio/flags.c
index 1878c2f..d6df6da 100644
--- a/libc/upstream-freebsd/lib/libc/stdio/flags.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/flags.c
@@ -1,3 +1,4 @@
+/*	$OpenBSD: flags.c,v 1.8 2014/08/31 02:21:18 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -30,22 +31,15 @@
  * SUCH DAMAGE.
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)flags.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
 #include <sys/types.h>
 #include <sys/file.h>
 #include <stdio.h>
 #include <errno.h>
-
 #include "local.h"
 
 /*
  * Return the (stdio) flags for a given mode.  Store the flags
- * to be passed to an _open() syscall through *optr.
+ * to be passed to an open() syscall through *optr.
  * Return 0 on error.
  */
 int
@@ -78,34 +72,33 @@
 		return (0);
 	}
 
-	/* 'b' (binary) is ignored */
-	if (*mode == 'b')
-		mode++;
-
-	/* [rwa][b]\+ means read and write */
-	if (*mode == '+') {
-		mode++;
-		ret = __SRW;
-		m = O_RDWR;
-	}
-
-	/* 'b' (binary) can appear here, too -- and is ignored again */
-	if (*mode == 'b')
-		mode++;
-
-	/* 'x' means exclusive (fail if the file exists) */
-	if (*mode == 'x') {
-		mode++;
-		if (m == O_RDONLY) {
+	while (*mode != '\0') 
+		switch (*mode++) {
+		case 'b':
+			break;
+		case '+':
+			ret = __SRW;
+			m = O_RDWR;
+			break;
+		case 'e':
+			o |= O_CLOEXEC;
+			break;
+		case 'x':
+			if (o & O_CREAT)
+				o |= O_EXCL;
+			break;
+		default:
+			/*
+			 * Lots of software passes other extension mode
+			 * letters, like Window's 't'
+			 */
+#if 0
 			errno = EINVAL;
 			return (0);
+#else
+			break;
+#endif
 		}
-		o |= O_EXCL;
-	}
-
-	/* set close-on-exec */
-	if (*mode == 'e')
-		o |= O_CLOEXEC;
 
 	*optr = m | o;
 	return (ret);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/freopen.c b/libc/upstream-openbsd/lib/libc/stdio/freopen.c
index 3158fb1..82717b1 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/freopen.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/freopen.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: freopen.c,v 1.13 2009/11/09 00:18:27 kurt Exp $ */
+/*	$OpenBSD: freopen.c,v 1.14 2014/08/31 02:21:18 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -134,7 +134,7 @@
 	 * assume stderr is always fd STDERR_FILENO, even if being freopen'd.
 	 */
 	if (wantfd >= 0 && f != wantfd) {
-		if (dup2(f, wantfd) >= 0) {
+		if (dup3(f, wantfd, oflags & O_CLOEXEC) >= 0) {
 			(void) close(f);
 			f = wantfd;
 		}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/mktemp.c b/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
index cb154c4..2a17e52 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: mktemp.c,v 1.33 2014/05/06 22:55:27 millert Exp $ */
+/*	$OpenBSD: mktemp.c,v 1.34 2014/08/31 02:21:18 guenther Exp $ */
 /*
  * Copyright (c) 1996-1998, 2008 Theo de Raadt
  * Copyright (c) 1997, 2008-2009 Todd C. Miller
@@ -35,12 +35,14 @@
 #define NUM_CHARS	(sizeof(TEMPCHARS) - 1)
 #define MIN_X		6
 
+#define MKOTEMP_FLAGS	(O_APPEND | O_CLOEXEC | O_DSYNC | O_RSYNC | O_SYNC)
+
 #ifndef nitems
 #define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
 #endif
 
 static int
-mktemp_internal(char *path, int slen, int mode)
+mktemp_internal(char *path, int slen, int mode, int flags)
 {
 	char *start, *cp, *ep;
 	const char *tempchars = TEMPCHARS;
@@ -63,6 +65,12 @@
 		return(-1);
 	}
 
+	if (flags & ~MKOTEMP_FLAGS) {
+		errno = EINVAL;
+		return(-1);
+	}
+	flags |= O_CREAT | O_EXCL | O_RDWR;
+
 	tries = INT_MAX;
 	do {
 		cp = start;
@@ -85,7 +93,7 @@
 				return(errno == ENOENT ? 0 : -1);
 			break;
 		case MKTEMP_FILE:
-			fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
+			fd = open(path, flags, S_IRUSR|S_IWUSR);
 			if (fd != -1 || errno != EEXIST)
 				return(fd);
 			break;
@@ -107,7 +115,7 @@
 char *
 _mktemp(char *path)
 {
-	if (mktemp_internal(path, 0, MKTEMP_NAME) == -1)
+	if (mktemp_internal(path, 0, MKTEMP_NAME, 0) == -1)
 		return(NULL);
 	return(path);
 }
@@ -122,15 +130,27 @@
 }
 
 int
+mkostemps(char *path, int slen, int flags)
+{
+	return(mktemp_internal(path, slen, MKTEMP_FILE, flags));
+}
+
+int
 mkstemp(char *path)
 {
-	return(mktemp_internal(path, 0, MKTEMP_FILE));
+	return(mktemp_internal(path, 0, MKTEMP_FILE, 0));
+}
+
+int
+mkostemp(char *path, int flags)
+{
+	return(mktemp_internal(path, 0, MKTEMP_FILE, flags));
 }
 
 int
 mkstemps(char *path, int slen)
 {
-	return(mktemp_internal(path, slen, MKTEMP_FILE));
+	return(mktemp_internal(path, slen, MKTEMP_FILE, 0));
 }
 
 char *
@@ -138,6 +158,6 @@
 {
 	int error;
 
-	error = mktemp_internal(path, 0, MKTEMP_DIR);
+	error = mktemp_internal(path, 0, MKTEMP_DIR, 0);
 	return(error ? NULL : path);
 }
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/insque.c b/libc/upstream-openbsd/lib/libc/stdlib/insque.c
similarity index 81%
rename from libc/upstream-netbsd/lib/libc/stdlib/insque.c
rename to libc/upstream-openbsd/lib/libc/stdlib/insque.c
index 09020ae..590ff83 100644
--- a/libc/upstream-netbsd/lib/libc/stdlib/insque.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/insque.c
@@ -1,7 +1,9 @@
+/*	$OpenBSD: insque.c,v 1.3 2014/08/15 04:14:36 guenther Exp $	*/
+
 /*
  *  Copyright (c) 1993 John Brezak
  *  All rights reserved.
- *
+ * 
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that the following conditions
  *  are met:
@@ -12,7 +14,7 @@
  *     documentation and/or other materials provided with the distribution.
  *  3. The name of the author may be used to endorse or promote products
  *     derived from this software without specific prior written permission.
- *
+ * 
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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
@@ -26,12 +28,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: insque.c,v 1.3 2012/06/25 22:32:45 abs Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
+#include <stdlib.h>
 #include <search.h>
 
 struct qelem {
@@ -42,17 +39,16 @@
 void
 insque(void *entry, void *pred)
 {
-	struct qelem *e = (struct qelem *) entry;
-	struct qelem *p = (struct qelem *) pred;
+	struct qelem *e = entry;
+	struct qelem *p = pred;
 
-	_DIAGASSERT(e != 0);
-
-	e->q_back = p;
-	if (p) {
+	if (p == NULL)
+		e->q_forw = e->q_back = NULL;
+	else {
 		e->q_forw = p->q_forw;
-		if (p->q_forw)
+		e->q_back = p;
+		if (p->q_forw != NULL)
 			p->q_forw->q_back = e;
 		p->q_forw = e;
-	} else
-		e->q_forw = 0;
+	}
 }
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/remque.c b/libc/upstream-openbsd/lib/libc/stdlib/remque.c
similarity index 84%
rename from libc/upstream-netbsd/lib/libc/stdlib/remque.c
rename to libc/upstream-openbsd/lib/libc/stdlib/remque.c
index 6060ad8..71b74b2 100644
--- a/libc/upstream-netbsd/lib/libc/stdlib/remque.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/remque.c
@@ -1,7 +1,9 @@
+/*	$OpenBSD: remque.c,v 1.3 2014/08/15 04:14:36 guenther Exp $	*/
+
 /*
  *  Copyright (c) 1993 John Brezak
  *  All rights reserved.
- *
+ * 
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that the following conditions
  *  are met:
@@ -12,7 +14,7 @@
  *     documentation and/or other materials provided with the distribution.
  *  3. The name of the author may be used to endorse or promote products
  *     derived from this software without specific prior written permission.
- *
+ * 
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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
@@ -26,12 +28,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: remque.c,v 1.3 2012/06/25 22:32:45 abs Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
+#include <stdlib.h>
 #include <search.h>
 
 struct qelem {
@@ -42,12 +39,10 @@
 void
 remque(void *element)
 {
-	struct qelem *e = (struct qelem *) element;
+	struct qelem *e = element;
 
-	_DIAGASSERT(e != 0);
-
-	if (e->q_forw)
+	if (e->q_forw != NULL)
 		e->q_forw->q_back = e->q_back;
-	if (e->q_back)
+	if (e->q_back != NULL)
 		e->q_back->q_forw = e->q_forw;
 }
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoimax.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoimax.c
index 2c77f41..2fc04e4 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoimax.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoimax.c
@@ -1,6 +1,5 @@
-/*	$OpenBSD: strtoimax.c,v 1.1 2006/01/13 17:58:09 millert Exp $	*/
-
-/*-
+/*	$OpenBSD: strtoimax.c,v 1.2 2014/09/13 20:10:12 schwarze Exp $	*/
+/*
  * Copyright (c) 1992 The Regents of the University of California.
  * All rights reserved.
  *
@@ -48,6 +47,17 @@
 	int neg, any, cutlim;
 
 	/*
+	 * Ensure that base is between 2 and 36 inclusive, or the special
+	 * value of 0.
+	 */
+	if (base < 0 || base == 1 || base > 36) {
+		if (endptr != 0)
+			*endptr = (char *)nptr;
+		errno = EINVAL;
+		return 0;
+	}
+
+	/*
 	 * Skip white space and pick up leading +/- sign if any.
 	 * If base is 0, allow 0x for hex and 0 for octal, else
 	 * assume decimal; if base is already 16, allow 0x.
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtol.c b/libc/upstream-openbsd/lib/libc/stdlib/strtol.c
index dc2cf88..86cec35 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtol.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtol.c
@@ -1,5 +1,5 @@
-/*	$OpenBSD: strtol.c,v 1.9 2013/04/17 17:40:35 tedu Exp $ */
-/*-
+/*	$OpenBSD: strtol.c,v 1.10 2014/09/13 20:10:12 schwarze Exp $ */
+/*
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
  *
@@ -33,7 +33,6 @@
 #include <limits.h>
 #include <stdlib.h>
 
-
 /*
  * Convert a string to a long integer.
  *
@@ -52,7 +51,7 @@
 	 * Ensure that base is between 2 and 36 inclusive, or the special
 	 * value of 0.
 	 */
-	if (base != 0 && (base < 2 || base > 36)) {
+	if (base < 0 || base == 1 || base > 36) {
 		if (endptr != 0)
 			*endptr = (char *)nptr;
 		errno = EINVAL;
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoll.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoll.c
index 4bcc556..cf82c8e 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoll.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoll.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: strtoll.c,v 1.7 2013/03/28 18:09:38 martynas Exp $ */
-/*-
+/*	$OpenBSD: strtoll.c,v 1.8 2014/09/13 20:10:12 schwarze Exp $ */
+/*
  * Copyright (c) 1992 The Regents of the University of California.
  * All rights reserved.
  *
@@ -50,6 +50,17 @@
 	int neg, any, cutlim;
 
 	/*
+	 * Ensure that base is between 2 and 36 inclusive, or the special
+	 * value of 0.
+	 */
+	if (base < 0 || base == 1 || base > 36) {
+		if (endptr != 0)
+			*endptr = (char *)nptr;
+		errno = EINVAL;
+		return 0;
+	}
+
+	/*
 	 * Skip white space and pick up leading +/- sign if any.
 	 * If base is 0, allow 0x for hex and 0 for octal, else
 	 * assume decimal; if base is already 16, allow 0x.
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoul.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoul.c
index a236365..2aa41b7 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoul.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoul.c
@@ -1,6 +1,6 @@
-/*	$OpenBSD: strtoul.c,v 1.8 2013/04/17 17:40:35 tedu Exp $ */
+/*	$OpenBSD: strtoul.c,v 1.9 2014/09/13 20:10:12 schwarze Exp $ */
 /*
- * Copyright (c) 1990 Regents of the University of California.
+ * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,13 @@
 	/*
 	 * See strtol for comments as to the logic used.
 	 */
+	if (base < 0 || base == 1 || base > 36) {
+		if (endptr != 0)
+			*endptr = (char *)nptr;
+		errno = EINVAL;
+		return 0;
+	}
+
 	s = nptr;
 	do {
 		c = (unsigned char) *s++;
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoull.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoull.c
index 28f613a..8464176 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoull.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoull.c
@@ -1,5 +1,5 @@
-/*	$OpenBSD: strtoull.c,v 1.6 2013/03/28 18:09:38 martynas Exp $ */
-/*-
+/*	$OpenBSD: strtoull.c,v 1.7 2014/09/13 20:10:12 schwarze Exp $ */
+/*
  * Copyright (c) 1992 The Regents of the University of California.
  * All rights reserved.
  *
@@ -50,8 +50,15 @@
 	int neg, any, cutlim;
 
 	/*
-	 * See strtoq for comments as to the logic used.
+	 * See strtoll for comments as to the logic used.
 	 */
+	if (base < 0 || base == 1 || base > 36) {
+		if (endptr != 0)
+			*endptr = (char *)nptr;
+		errno = EINVAL;
+		return 0;
+	}
+
 	s = nptr;
 	do {
 		c = (unsigned char) *s++;
@@ -59,7 +66,7 @@
 	if (c == '-') {
 		neg = 1;
 		c = *s++;
-	} else { 
+	} else {
 		neg = 0;
 		if (c == '+')
 			c = *s++;
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoumax.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoumax.c
index ce6e2c0..c73f7e5 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoumax.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoumax.c
@@ -1,6 +1,5 @@
-/*	$OpenBSD: strtoumax.c,v 1.1 2006/01/13 17:58:09 millert Exp $	*/
-
-/*-
+/*	$OpenBSD: strtoumax.c,v 1.2 2014/09/13 20:10:12 schwarze Exp $	*/
+/*
  * Copyright (c) 1992 The Regents of the University of California.
  * All rights reserved.
  *
@@ -48,8 +47,15 @@
 	int neg, any, cutlim;
 
 	/*
-	 * See strtoq for comments as to the logic used.
+	 * See strtoimax for comments as to the logic used.
 	 */
+	if (base < 0 || base == 1 || base > 36) {
+		if (endptr != 0)
+			*endptr = (char *)nptr;
+		errno = EINVAL;
+		return 0;
+	}
+
 	s = nptr;
 	do {
 		c = (unsigned char) *s++;
@@ -57,7 +63,7 @@
 	if (c == '-') {
 		neg = 1;
 		c = *s++;
-	} else { 
+	} else {
 		neg = 0;
 		if (c == '+')
 			c = *s++;
diff --git a/linker/debugger.cpp b/linker/debugger.cpp
index 6565985..ac466a5 100644
--- a/linker/debugger.cpp
+++ b/linker/debugger.cpp
@@ -215,7 +215,7 @@
     return;
   }
 
-  int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);
+  int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM | SOCK_CLOEXEC);
   if (s == -1) {
     __libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
                       strerror(errno));
diff --git a/tests/Android.mk b/tests/Android.mk
index 890e203..59fe57d 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -86,6 +86,7 @@
     regex_test.cpp \
     sched_test.cpp \
     search_test.cpp \
+    semaphore_test.cpp \
     signal_test.cpp \
     stack_protector_test.cpp \
     stdatomic_test.cpp \
diff --git a/tests/TemporaryFile.h b/tests/TemporaryFile.h
index c4ee2d5..5c2fe4f 100644
--- a/tests/TemporaryFile.h
+++ b/tests/TemporaryFile.h
@@ -17,24 +17,26 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-template<int (*mk_fn)(char*)>
+#include "private/bionic_macros.h"
+
+template <typename T = int (*)(char*)>
 class GenericTemporaryFile {
  public:
-  GenericTemporaryFile(const char* dirpath = NULL) {
-    if (dirpath != NULL) {
-      init(dirpath);
-    } else {
-      // Since we might be running on the host or the target, and if we're
-      // running on the host we might be running under bionic or glibc,
-      // let's just try both possible temporary directories and take the
-      // first one that works.
-      init("/data/local/tmp");
-      if (fd == -1) {
-        init("/tmp");
-      }
+  GenericTemporaryFile(T mk_fn = mkstemp) : mk_fn(mk_fn) {
+    // Since we might be running on the host or the target, and if we're
+    // running on the host we might be running under bionic or glibc,
+    // let's just try both possible temporary directories and take the
+    // first one that works.
+    init("/data/local/tmp");
+    if (fd == -1) {
+      init("/tmp");
     }
   }
 
+  GenericTemporaryFile(const char* dirpath, T mk_fn = mkstemp) : mk_fn(mk_fn) {
+    init(dirpath);
+  }
+
   ~GenericTemporaryFile() {
     close(fd);
     unlink(filename);
@@ -49,13 +51,17 @@
   char filename[1024];
 
  private:
+  T mk_fn;
+
   void init(const char* tmp_dir) {
     snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
     fd = mk_fn(filename);
   }
+
+  DISALLOW_COPY_AND_ASSIGN(GenericTemporaryFile);
 };
 
-typedef GenericTemporaryFile<mkstemp> TemporaryFile;
+typedef GenericTemporaryFile<> TemporaryFile;
 
 class TemporaryDir {
  public:
@@ -77,4 +83,5 @@
     return (mkdtemp(dirname) != NULL);
   }
 
+  DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
 };
diff --git a/tests/ftw_test.cpp b/tests/ftw_test.cpp
index 6d3a308..7ffbfe0 100644
--- a/tests/ftw_test.cpp
+++ b/tests/ftw_test.cpp
@@ -68,7 +68,7 @@
 
 TEST(ftw, ftw64) {
   TemporaryDir td;
-  GenericTemporaryFile<mkstemp64> tf(td.dirname);
+  TemporaryFile tf(td.dirname, mkstemp64);
   ftw64(td.dirname, check_ftw64, 1);
 }
 
@@ -80,6 +80,6 @@
 
 TEST(ftw, nftw64) {
   TemporaryDir td;
-  GenericTemporaryFile<mkstemp64> tf(td.dirname);
+  TemporaryFile tf(td.dirname, mkstemp64);
   nftw64(td.dirname, check_nftw64, 1, 0);
 }
diff --git a/tests/inttypes_test.cpp b/tests/inttypes_test.cpp
index e588503..dbbb6d4 100644
--- a/tests/inttypes_test.cpp
+++ b/tests/inttypes_test.cpp
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
-#include <stdio.h>
 #include <inttypes.h>
 
+#include <errno.h>
+#include <gtest/gtest.h>
+#include <stdio.h>
+
 TEST(inttypes, misc) {
   char buf[512];
 
@@ -46,3 +47,51 @@
 TEST(inttypes, wcstoumax) {
   ASSERT_EQ(123U, wcstoumax(L"123", NULL, 10));
 }
+
+TEST(inttypes, strtoimax_EINVAL) {
+  errno = 0;
+  strtoimax("123", NULL, -1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  strtoimax("123", NULL, 1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  strtoimax("123", NULL, 37);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(inttypes, strtoumax_EINVAL) {
+  errno = 0;
+  strtoumax("123", NULL, -1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  strtoumax("123", NULL, 1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  strtoumax("123", NULL, 37);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(inttypes, wcstoimax_EINVAL) {
+  errno = 0;
+  wcstoimax(L"123", NULL, -1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoimax(L"123", NULL, 1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoimax(L"123", NULL, 37);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(inttypes, wcstoumax_EINVAL) {
+  errno = 0;
+  wcstoumax(L"123", NULL, -1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoumax(L"123", NULL, 1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoumax(L"123", NULL, 37);
+  ASSERT_EQ(EINVAL, errno);
+}
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 43587f4..9dbb4f5 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -168,8 +168,7 @@
 
 static void MakeDeadThread(pthread_t& t) {
   ASSERT_EQ(0, pthread_create(&t, NULL, IdFn, NULL));
-  void* result;
-  ASSERT_EQ(0, pthread_join(t, &result));
+  ASSERT_EQ(0, pthread_join(t, NULL));
 }
 
 TEST(pthread, pthread_create) {
@@ -201,8 +200,7 @@
   AssertDetached(t1, true);
 
   // ...pthread_join should fail.
-  void* result;
-  ASSERT_EQ(EINVAL, pthread_join(t1, &result));
+  ASSERT_EQ(EINVAL, pthread_join(t1, NULL));
 }
 
 TEST(pthread, pthread_no_op_detach_after_join) {
@@ -230,8 +228,7 @@
 }
 
 TEST(pthread, pthread_join_self) {
-  void* result;
-  ASSERT_EQ(EDEADLK, pthread_join(pthread_self(), &result));
+  ASSERT_EQ(EDEADLK, pthread_join(pthread_self(), NULL));
 }
 
 struct TestBug37410 {
@@ -481,8 +478,7 @@
   pthread_t dead_thread;
   MakeDeadThread(dead_thread);
 
-  void* result;
-  ASSERT_EQ(ESRCH, pthread_join(dead_thread, &result));
+  ASSERT_EQ(ESRCH, pthread_join(dead_thread, NULL));
 }
 
 TEST(pthread, pthread_kill__no_such_thread) {
@@ -543,8 +539,7 @@
   size_t result;
   pthread_t t;
   pthread_create(&t, &attributes, GetActualGuardSizeFn, &result);
-  void* join_result;
-  pthread_join(t, &join_result);
+  pthread_join(t, NULL);
   return result;
 }
 
@@ -559,8 +554,7 @@
   size_t result;
   pthread_t t;
   pthread_create(&t, &attributes, GetActualStackSizeFn, &result);
-  void* join_result;
-  pthread_join(t, &join_result);
+  pthread_join(t, NULL);
   return result;
 }
 
@@ -927,11 +921,47 @@
 
   pid_t t_pthread_gettid_np_result = pthread_gettid_np(t);
 
-  void* join_result;
-  pthread_join(t, &join_result);
+  pthread_join(t, NULL);
 
   ASSERT_EQ(t_gettid_result, t_pthread_gettid_np_result);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
+
+static size_t cleanup_counter = 0;
+
+void AbortCleanupRoutine(void*) {
+  abort();
+}
+
+void CountCleanupRoutine(void*) {
+  ++cleanup_counter;
+}
+
+void PthreadCleanupTester() {
+  pthread_cleanup_push(CountCleanupRoutine, NULL);
+  pthread_cleanup_push(CountCleanupRoutine, NULL);
+  pthread_cleanup_push(AbortCleanupRoutine, NULL);
+
+  pthread_cleanup_pop(0); // Pop the abort without executing it.
+  pthread_cleanup_pop(1); // Pop one count while executing it.
+  ASSERT_EQ(1U, cleanup_counter);
+  // Exit while the other count is still on the cleanup stack.
+  pthread_exit(NULL);
+
+  // Calls to pthread_cleanup_pop/pthread_cleanup_push must always be balanced.
+  pthread_cleanup_pop(0);
+}
+
+void* PthreadCleanupStartRoutine(void*) {
+  PthreadCleanupTester();
+  return NULL;
+}
+
+TEST(pthread, pthread_cleanup_push__pthread_cleanup_pop) {
+  pthread_t t;
+  ASSERT_EQ(0, pthread_create(&t, NULL, PthreadCleanupStartRoutine, NULL));
+  pthread_join(t, NULL);
+  ASSERT_EQ(2U, cleanup_counter);
+}
diff --git a/tests/semaphore_test.cpp b/tests/semaphore_test.cpp
new file mode 100644
index 0000000..e517f81
--- /dev/null
+++ b/tests/semaphore_test.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <semaphore.h>
+
+#include <errno.h>
+#include <gtest/gtest.h>
+#include <limits.h>
+#include <pthread.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "private/bionic_constants.h"
+
+TEST(semaphore, sem_init) {
+  sem_t s;
+
+  // Perfectly fine initial values.
+  ASSERT_EQ(0, sem_init(&s, 0, 0));
+  ASSERT_EQ(0, sem_init(&s, 0, 1));
+  ASSERT_EQ(0, sem_init(&s, 0, 123));
+
+  // Too small an initial value.
+  errno = 0;
+  ASSERT_EQ(-1, sem_init(&s, 0, -1));
+  ASSERT_EQ(EINVAL, errno);
+
+  ASSERT_EQ(SEM_VALUE_MAX, sysconf(_SC_SEM_VALUE_MAX));
+
+  // The largest initial value.
+  ASSERT_EQ(0, sem_init(&s, 0, SEM_VALUE_MAX));
+
+  // Too large an initial value.
+  errno = 0;
+  ASSERT_EQ(-1, sem_init(&s, 0, SEM_VALUE_MAX + 1));
+  ASSERT_EQ(EINVAL, errno);
+
+  ASSERT_EQ(0, sem_destroy(&s));
+}
+
+TEST(semaphore, sem_trywait) {
+  sem_t s;
+  ASSERT_EQ(0, sem_init(&s, 0, 3));
+  ASSERT_EQ(0, sem_trywait(&s));
+  ASSERT_EQ(0, sem_trywait(&s));
+  ASSERT_EQ(0, sem_trywait(&s));
+  errno = 0;
+  ASSERT_EQ(-1, sem_trywait(&s));
+  ASSERT_EQ(EAGAIN, errno);
+  ASSERT_EQ(0, sem_destroy(&s));
+}
+
+static void SemWaitThreadTestFn(sem_t& sem) {
+  ASSERT_EQ(0, sem_wait(&sem));
+}
+
+static void* SemWaitThreadFn(void* arg) {
+  SemWaitThreadTestFn(*reinterpret_cast<sem_t*>(arg));
+  return nullptr;
+}
+
+TEST(semaphore, sem_wait__sem_post) {
+  sem_t s;
+  ASSERT_EQ(0, sem_init(&s, 0, 0));
+
+  pthread_t t1, t2, t3;
+  ASSERT_EQ(0, pthread_create(&t1, NULL, SemWaitThreadFn, &s));
+  ASSERT_EQ(0, pthread_create(&t2, NULL, SemWaitThreadFn, &s));
+  ASSERT_EQ(0, pthread_create(&t3, NULL, SemWaitThreadFn, &s));
+
+  ASSERT_EQ(0, sem_post(&s));
+  ASSERT_EQ(0, sem_post(&s));
+  ASSERT_EQ(0, sem_post(&s));
+
+  void* result;
+  ASSERT_EQ(0, pthread_join(t1, &result));
+  ASSERT_EQ(0, pthread_join(t2, &result));
+  ASSERT_EQ(0, pthread_join(t3, &result));
+}
+
+static inline void timespec_add_ms(timespec& ts, size_t ms) {
+  ts.tv_sec  += ms / 1000;
+  ts.tv_nsec += (ms % 1000) * 1000000;
+  if (ts.tv_nsec >= NS_PER_S) {
+    ts.tv_sec++;
+    ts.tv_nsec -= NS_PER_S;
+  }
+}
+
+TEST(semaphore, sem_timedwait) {
+  sem_t s;
+  ASSERT_EQ(0, sem_init(&s, 0, 0));
+
+  timespec ts;
+  ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+  timespec_add_ms(ts, 100);
+
+  errno = 0;
+  ASSERT_EQ(-1, sem_timedwait(&s, &ts));
+  ASSERT_EQ(ETIMEDOUT, errno);
+
+  // A negative timeout is an error.
+  errno = 0;
+  ts.tv_nsec = -1;
+  ASSERT_EQ(-1, sem_timedwait(&s, &ts));
+  ASSERT_EQ(EINVAL, errno);
+
+  ASSERT_EQ(0, sem_destroy(&s));
+}
+
+TEST(semaphore, sem_getvalue) {
+  sem_t s;
+  ASSERT_EQ(0, sem_init(&s, 0, 0));
+
+  int i;
+  ASSERT_EQ(0, sem_getvalue(&s, &i));
+  ASSERT_EQ(0, i);
+
+  ASSERT_EQ(0, sem_post(&s));
+  ASSERT_EQ(0, sem_getvalue(&s, &i));
+  ASSERT_EQ(1, i);
+
+  ASSERT_EQ(0, sem_post(&s));
+  ASSERT_EQ(0, sem_getvalue(&s, &i));
+  ASSERT_EQ(2, i);
+
+  ASSERT_EQ(0, sem_wait(&s));
+  ASSERT_EQ(0, sem_getvalue(&s, &i));
+  ASSERT_EQ(1, i);
+}
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index c01ab68..6a653b4 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -756,3 +756,43 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
+
+TEST(stdio, fdopen_CLOEXEC) {
+  int fd = open("/proc/version", O_RDONLY);
+  ASSERT_TRUE(fd != -1);
+
+  // This fd doesn't have O_CLOEXEC...
+  int flags = fcntl(fd, F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(0, flags & FD_CLOEXEC);
+
+  FILE* fp = fdopen(fd, "re");
+  ASSERT_TRUE(fp != NULL);
+
+  // ...but the new one does.
+  flags = fcntl(fileno(fp), F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+
+  fclose(fp);
+  close(fd);
+}
+
+TEST(stdio, freopen_CLOEXEC) {
+  FILE* fp = fopen("/proc/version", "r");
+  ASSERT_TRUE(fp != NULL);
+
+  // This FILE* doesn't have O_CLOEXEC...
+  int flags = fcntl(fileno(fp), F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(0, flags & FD_CLOEXEC);
+
+  fp = freopen("/proc/version", "re", fp);
+
+  // ...but the new one does.
+  flags = fcntl(fileno(fp), F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+
+  fclose(fp);
+}
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 553f018..e814ef7 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -162,19 +162,33 @@
   ASSERT_EXIT(TestBug57421_main(), ::testing::ExitedWithCode(0), "");
 }
 
+TEST(stdlib, mkostemp64) {
+  TemporaryFile tf([](char* path) { return mkostemp64(path, O_CLOEXEC); });
+  int flags = fcntl(tf.fd, F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+}
+
+TEST(stdlib, mkostemp) {
+  TemporaryFile tf([](char* path) { return mkostemp(path, O_CLOEXEC); });
+  int flags = fcntl(tf.fd, F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+}
+
+TEST(stdlib, mkstemp64) {
+  TemporaryFile tf(mkstemp64);
+  struct stat64 sb;
+  ASSERT_EQ(0, fstat64(tf.fd, &sb));
+  ASSERT_EQ(O_LARGEFILE, fcntl(tf.fd, F_GETFL) & O_LARGEFILE);
+}
+
 TEST(stdlib, mkstemp) {
   TemporaryFile tf;
   struct stat sb;
   ASSERT_EQ(0, fstat(tf.fd, &sb));
 }
 
-TEST(stdlib, mkstemp64) {
-  GenericTemporaryFile<mkstemp64> tf;
-  struct stat64 sb;
-  ASSERT_EQ(0, fstat64(tf.fd, &sb));
-  ASSERT_EQ(O_LARGEFILE, fcntl(tf.fd, F_GETFL) & O_LARGEFILE);
-}
-
 TEST(stdlib, system) {
   int status;
 
@@ -361,3 +375,51 @@
   ASSERT_EQ(ENOTTY, errno);
   close(fd);
 }
+
+TEST(stdlib, strtol_EINVAL) {
+  errno = 0;
+  strtol("123", NULL, -1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  strtol("123", NULL, 1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  strtol("123", NULL, 37);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(stdlib, strtoll_EINVAL) {
+  errno = 0;
+  strtoll("123", NULL, -1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  strtoll("123", NULL, 1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  strtoll("123", NULL, 37);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(stdlib, strtoul_EINVAL) {
+  errno = 0;
+  strtoul("123", NULL, -1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  strtoul("123", NULL, 1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  strtoul("123", NULL, 37);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(stdlib, strtoull_EINVAL) {
+  errno = 0;
+  strtoull("123", NULL, -1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  strtoull("123", NULL, 1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  strtoull("123", NULL, 37);
+  ASSERT_EQ(EINVAL, errno);
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index c9ead8d..c631b6a 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -26,6 +26,8 @@
 
 #include "ScopedSignalHandler.h"
 
+#include "private/bionic_constants.h"
+
 TEST(time, gmtime) {
   time_t t = 0;
   tm* broken_down = gmtime(&t);
@@ -395,7 +397,7 @@
   ts2.tv_nsec -= ts1.tv_nsec;
   if (ts2.tv_nsec < 0) {
     --ts2.tv_sec;
-    ts2.tv_nsec += 1000000000;
+    ts2.tv_nsec += NS_PER_S;
   }
 
   // Should be less than (a very generous, to try to avoid flakiness) 1000000ns.
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 8195ea8..21c14f4 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -462,3 +462,8 @@
   ASSERT_EQ(0, pthread_join(t, &result));
   ASSERT_EQ(NULL, result);
 }
+
+TEST(unistd_DeathTest, abort) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  ASSERT_EXIT(abort(), testing::KilledBySignal(SIGABRT), "");
+}
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 760475f..887266c 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -520,3 +520,75 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
+
+TEST(wchar, wcstol_EINVAL) {
+  errno = 0;
+  wcstol(L"123", NULL, -1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstol(L"123", NULL, 1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstol(L"123", NULL, 37);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(wchar, wcstoll_EINVAL) {
+  errno = 0;
+  wcstoll(L"123", NULL, -1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoll(L"123", NULL, 1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoll(L"123", NULL, 37);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(wchar, wcstoul_EINVAL) {
+  errno = 0;
+  wcstoul(L"123", NULL, -1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoul(L"123", NULL, 1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoul(L"123", NULL, 37);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(wchar, wcstoull_EINVAL) {
+  errno = 0;
+  wcstoull(L"123", NULL, -1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoull(L"123", NULL, 1);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoull(L"123", NULL, 37);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(wchar, wcstoll_l_EINVAL) {
+  errno = 0;
+  wcstoll_l(L"123", NULL, -1, LC_GLOBAL_LOCALE);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoll_l(L"123", NULL, 1, LC_GLOBAL_LOCALE);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoll_l(L"123", NULL, 37, LC_GLOBAL_LOCALE);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(wchar, wcstoull_l_EINVAL) {
+  errno = 0;
+  wcstoull_l(L"123", NULL, -1, LC_GLOBAL_LOCALE);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoull_l(L"123", NULL, 1, LC_GLOBAL_LOCALE);
+  ASSERT_EQ(EINVAL, errno);
+  errno = 0;
+  wcstoull_l(L"123", NULL, 37, LC_GLOBAL_LOCALE);
+  ASSERT_EQ(EINVAL, errno);
+}