merge from froyo-plus-aosp

Change-Id: I64de22c97a98ec4f1f288c619e3d66d6be261c6d
diff --git a/libc/Android.mk b/libc/Android.mk
index 772aa07..b0301ef 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -205,6 +205,34 @@
 	string/strtok.c \
 	string/strtotimeval.c \
 	string/strxfrm.c \
+	wchar/wcpcpy.c \
+	wchar/wcpncpy.c \
+	wchar/wcscasecmp.c \
+	wchar/wcscat.c \
+	wchar/wcschr.c \
+	wchar/wcscmp.c \
+	wchar/wcscoll.c \
+	wchar/wcscpy.c \
+	wchar/wcscspn.c \
+	wchar/wcsdup.c \
+	wchar/wcslcat.c \
+	wchar/wcslcpy.c \
+	wchar/wcslen.c \
+	wchar/wcsncasecmp.c \
+	wchar/wcsncat.c \
+	wchar/wcsncmp.c \
+	wchar/wcsncpy.c \
+	wchar/wcsnlen.c \
+	wchar/wcspbrk.c \
+	wchar/wcsrchr.c \
+	wchar/wcsspn.c \
+	wchar/wcsstr.c \
+	wchar/wcstok.c \
+	wchar/wcswidth.c \
+	wchar/wmemchr.c \
+	wchar/wmemcpy.c \
+	wchar/wmemmove.c \
+	wchar/wmemset.c \
 	inet/bindresvport.c \
 	inet/inet_addr.c \
 	inet/inet_aton.c \
@@ -324,6 +352,7 @@
 # up any thumb code.
 libc_common_src_files += \
 	bionic/pthread.c.arm \
+	bionic/pthread-rwlocks.c.arm \
 	bionic/pthread-timers.c.arm \
 	bionic/ptrace.c.arm
 
@@ -358,6 +387,7 @@
 	arch-x86/string/strncmp_wrapper.S \
 	arch-x86/string/strlen.S \
 	bionic/pthread.c \
+	bionic/pthread-rwlocks.c \
 	bionic/pthread-timers.c \
 	bionic/ptrace.c
 
@@ -395,6 +425,7 @@
 	string/strlen.c \
 	bionic/eabi.c \
 	bionic/pthread.c \
+	bionic/pthread-rwlocks.c \
 	bionic/pthread-timers.c \
 	bionic/ptrace.c \
 	unistd/socketcalls.c
@@ -454,6 +485,14 @@
   endif # x86
 endif # !arm
 
+# Define ANDROID_SMP appropriately.
+ifeq ($(TARGET_CPU_SMP),true)
+    libc_common_cflags += -DANDROID_SMP=1
+else
+    libc_common_cflags += -DANDROID_SMP=0
+endif
+
+
 # Define some common includes
 # ========================================================
 libc_common_c_includes := \
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 11407b9..bf65a6f 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -244,6 +244,7 @@
 int     init_module(void *, unsigned long, const char *)  128
 int     delete_module(const char*, unsigned int)   129
 int     klogctl:syslog(int, char *, int)   103
+int     sysinfo(struct sysinfo *)  116
 
 # futex
 int	futex(void *, int, int, void *, void *, int) 240
diff --git a/libc/arch-arm/bionic/_setjmp.S b/libc/arch-arm/bionic/_setjmp.S
index 6a27af2..5626219 100644
--- a/libc/arch-arm/bionic/_setjmp.S
+++ b/libc/arch-arm/bionic/_setjmp.S
@@ -3,6 +3,7 @@
 
 /*
  * Copyright (c) 1997 Mark Brinicombe
+ * Copyright (c) 2010 Android Open Source Project.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,6 +36,7 @@
 
 #include <machine/asm.h>
 #include <machine/setjmp.h>
+#include <machine/cpu-features.h>
 
 /*
  * C library -- _setjmp, _longjmp
@@ -51,18 +53,20 @@
 
 ENTRY(_setjmp)
 	ldr	r1, .L_setjmp_magic
-	str	r1, [r0], #4
-#ifdef SOFTFLOAT
-	add	r0, r0, #52
-#else
-	/* Store fp registers */
-	sfm	f4, 4, [r0], #48
-	/* Store fpsr */
-	rfs	r1
-	str	r1, [r0], #0x0004
-#endif	/* SOFTFLOAT */
-	/* Store integer registers */
-        stmia	r0, {r4-r14}
+	str	r1, [r0, #(_JB_MAGIC * 4)]
+
+	/* Store core registers */
+	add     r1, r0, #(_JB_CORE_BASE * 4)
+	stmia   r1, {r4-r14}
+
+#ifdef __ARM_HAVE_VFP
+	/* Store floating-point registers */
+	add     r1, r0, #(_JB_FLOAT_BASE * 4)
+	vstmia  r1, {d8-d15}
+	/* Store floating-point state */
+	fmrx    r1, fpscr
+	str     r1, [r0, #(_JB_FLOAT_STATE * 4)]
+#endif  /* __ARM_HAVE_VFP */
 
         mov	r0, #0x00000000
         bx      lr
@@ -72,21 +76,22 @@
 
 ENTRY(_longjmp)
 	ldr	r2, .L_setjmp_magic
-	ldr	r3, [r0], #4
+	ldr	r3, [r0, #(_JB_MAGIC * 4)]
 	teq	r2, r3
 	bne	botch
 
-#ifdef SOFTFLOAT
-	add	r0, r0, #52
-#else
-	/* Restore fp registers */
-	lfm	f4, 4, [r0], #48
-	/* Restore fpsr */
-	ldr	r4, [r0], #0x0004
-	wfs	r4
-#endif	/* SOFTFLOAT */
-       	/* Restore integer registers */
-        ldmia	r0, {r4-r14}
+#ifdef __ARM_HAVE_VFP
+	/* Restore floating-point registers */
+	add     r2, r0, #(_JB_FLOAT_BASE * 4)
+	vldmia  r2, {d8-d15}
+	/* Restore floating-point state */
+	ldr     r2, [r0, #(_JB_FLOAT_STATE * 4)]
+	fmxr    fpscr, r2
+#endif /* __ARM_HAVE_VFP */
+
+	/* Restore core registers */
+	add     r2, r0, #(_JB_CORE_BASE * 4)
+	ldmia   r2, {r4-r14}
 
 	/* Validate sp and r14 */
 	teq	sp, #0
diff --git a/libc/arch-arm/bionic/atomics_arm.S b/libc/arch-arm/bionic/atomics_arm.S
index 047541f..d94f6b1 100644
--- a/libc/arch-arm/bionic/atomics_arm.S
+++ b/libc/arch-arm/bionic/atomics_arm.S
@@ -26,6 +26,7 @@
  * SUCH DAMAGE.
  */
 #include <sys/linux-syscalls.h>
+#include <machine/cpu-features.h>
 
 .global __atomic_cmpxchg
 .type __atomic_cmpxchg, %function
@@ -39,9 +40,73 @@
 #define FUTEX_WAIT 0
 #define FUTEX_WAKE 1
 
-#if 1
-   .equ     kernel_cmpxchg, 0xFFFF0FC0
-   .equ     kernel_atomic_base, 0xFFFF0FFF
+#if defined(__ARM_HAVE_LDREX_STREX)
+/*
+ * ===========================================================================
+ *      ARMv6+ implementation
+ * ===========================================================================
+ */
+
+/* r0(addr) -> r0(old) */
+__atomic_dec:
+    .fnstart
+    mov     r1, r0                      @ copy addr so we don't clobber it
+1:  ldrex   r0, [r1]                    @ load current value into r0
+    sub     r2, r0, #1                  @ generate new value into r2
+    strex   r3, r2, [r1]                @ try to store new value; result in r3
+    cmp     r3, #0                      @ success?
+    bxeq    lr                          @ yes, return
+    b       1b                          @ no, retry
+    .fnend
+
+/* r0(addr) -> r0(old) */
+__atomic_inc:
+    .fnstart
+    mov     r1, r0
+1:  ldrex   r0, [r1]
+    add     r2, r0, #1
+    strex   r3, r2, [r1]
+    cmp     r3, #0
+    bxeq    lr
+    b       1b
+    .fnend
+
+/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
+__atomic_cmpxchg:
+    .fnstart
+1:  mov     ip, #2                      @ ip=2 means "new != old"
+    ldrex   r3, [r2]                    @ load current value into r3
+    teq     r0, r3                      @ new == old?
+    strexeq ip, r1, [r2]                @ yes, try store, set ip to 0 or 1
+    teq     ip, #1                      @ strex failure?
+    beq     1b                          @ yes, retry
+    mov     r0, ip                      @ return 0 on success, 2 on failure
+    bx      lr
+    .fnend
+
+/* r0(new) r1(addr) -> r0(old) */
+__atomic_swap:
+    .fnstart
+1:  ldrex   r2, [r1]
+    strex   r3, r0, [r1]
+    teq     r3, #0
+    bne     1b
+    mov     r0, r2
+    bx      lr
+    .fnend
+
+#else /*not defined __ARM_HAVE_LDREX_STREX*/
+/*
+ * ===========================================================================
+ *      Pre-ARMv6 implementation
+ * ===========================================================================
+ */
+
+    /* int __kernel_cmpxchg(int oldval, int newval, int* ptr) */
+    .equ    kernel_cmpxchg, 0xFFFF0FC0
+    .equ    kernel_atomic_base, 0xFFFF0FFF
+
+/* r0(addr) -> r0(old) */
 __atomic_dec:
     .fnstart
     .save {r4, lr}
@@ -59,6 +124,7 @@
     bx      lr
     .fnend
 
+/* r0(addr) -> r0(old) */
 __atomic_inc:
     .fnstart
     .save {r4, lr}
@@ -95,64 +161,16 @@
     ldmia   sp!, {r4, lr}
     bx      lr
     .fnend
-#else
-#define KUSER_CMPXCHG 0xffffffc0
-
-/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
-__atomic_cmpxchg:
-    stmdb   sp!, {r4, lr}
-    mov     r4, r0          /* r4 = save oldvalue */
-1:  add     lr, pc, #4
-    mov     r0, r4          /* r0 = oldvalue */
-    mov     pc, #KUSER_CMPXCHG
-    bcs     2f              /* swap was made. we're good, return. */
-    ldr     r3, [r2]        /* swap not made, see if it's because *ptr!=oldvalue */
-    cmp     r3, r4
-    beq     1b
-2:  ldmia   sp!, {r4, lr}
-    bx      lr
-
-/* r0(addr) -> r0(old) */
-__atomic_dec:
-    stmdb   sp!, {r4, lr}
-    mov     r2, r0          /* address */
-1:  ldr     r0, [r2]        /* oldvalue */
-    add     lr, pc, #4
-    sub     r1, r0, #1      /* newvalue = oldvalue - 1 */
-    mov     pc, #KUSER_CMPXCHG
-    bcc     1b              /* no swap, try again until we get it right */
-    mov     r0, ip          /* swapped, return the old value */
-    ldmia   sp!, {r4, lr}
-    bx      lr
-
-/* r0(addr) -> r0(old) */
-__atomic_inc:
-    stmdb   sp!, {r4, lr}
-    mov     r2, r0          /* address */
-1:  ldr     r0, [r2]        /* oldvalue */
-    add     lr, pc, #4
-    add     r1, r0, #1      /* newvalue = oldvalue + 1 */
-    mov     pc, #KUSER_CMPXCHG
-    bcc     1b              /* no swap, try again until we get it right */
-    mov     r0, ip          /* swapped, return the old value */
-    ldmia   sp!, {r4, lr}
-    bx      lr
-#endif
 
 /* r0(new) r1(addr) -> r0(old) */
-/* replaced swp instruction with ldrex/strex for ARMv6 & ARMv7 */
 __atomic_swap:
-#if defined (_ARM_HAVE_LDREX_STREX)
-1:  ldrex   r2, [r1]
-    strex   r3, r0, [r1]
-    teq     r3, #0
-    bne     1b
-    mov     r0, r2
-    mcr     p15, 0, r0, c7, c10, 5 /* or, use dmb */
-#else
+    .fnstart
     swp     r0, r0, [r1]
-#endif
     bx      lr
+    .fnend
+
+#endif /*not defined __ARM_HAVE_LDREX_STREX*/
+
 
 /* __futex_wait(*ftx, val, *timespec) */
 /* __futex_wake(*ftx, counter) */
@@ -197,6 +215,8 @@
     .fnend
 
 __futex_wake:
+    .fnstart
+    .save   {r4, r7}
     stmdb   sp!, {r4, r7}
     mov     r2, r1
     mov     r1, #FUTEX_WAKE
@@ -204,6 +224,7 @@
     swi     #0
     ldmia   sp!, {r4, r7}
     bx      lr
+    .fnend
 
 #else
 
diff --git a/libc/arch-arm/bionic/setjmp.S b/libc/arch-arm/bionic/setjmp.S
index a9f6ea4..59aff66 100644
--- a/libc/arch-arm/bionic/setjmp.S
+++ b/libc/arch-arm/bionic/setjmp.S
@@ -3,6 +3,7 @@
 
 /*
  * Copyright (c) 1997 Mark Brinicombe
+ * Copyright (c) 2010 Android Open Source Project.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,6 +36,7 @@
 
 #include <machine/asm.h>
 #include <machine/setjmp.h>
+#include <machine/cpu-features.h>
 
 /*
  * C library -- setjmp, longjmp
@@ -57,24 +59,26 @@
 	ldmfd	sp!, {r0, r14}
 
 	/* Store signal mask */
-	str	r1, [r0, #(25 * 4)]
+	str	r1, [r0, #(_JB_SIGMASK * 4)]
 
 	ldr	r1, .Lsetjmp_magic
-	str	r1, [r0], #4
+	str	r1, [r0, #(_JB_MAGIC * 4)]
 
-#ifdef SOFTFLOAT
-	add	r0, r0, #52
-#else
-	/* Store fp registers */
-	sfm	f4, 4, [r0], #48
-	/* Store fpsr */
-	rfs	r1
-	str	r1, [r0], #0x0004
-#endif	/*SOFTFLOAT*/
-	/* Store integer registers */
-        stmia	r0, {r4-r14}
-        mov	r0, #0x00000000
-        bx      lr
+	/* Store core registers */
+	add     r1, r0, #(_JB_CORE_BASE * 4)
+	stmia   r1, {r4-r14}
+
+#ifdef __ARM_HAVE_VFP
+	/* Store floating-point registers */
+	add     r1, r0, #(_JB_FLOAT_BASE * 4)
+	vstmia  r1, {d8-d15}
+	/* Store floating-point state */
+	fmrx    r1, fpscr
+	str     r1, [r0, #(_JB_FLOAT_STATE * 4)]
+#endif  /* __ARM_HAVE_VFP */
+
+	mov	r0, #0x00000000
+	bx      lr
 
 .Lsetjmp_magic:
 	.word	_JB_MAGIC_SETJMP
@@ -82,12 +86,12 @@
 
 ENTRY(longjmp)
 	ldr	r2, .Lsetjmp_magic
-	ldr	r3, [r0]
+	ldr	r3, [r0, #(_JB_MAGIC * 4)]
 	teq	r2, r3
 	bne	botch
 
 	/* Fetch signal mask */
-	ldr	r2, [r0, #(25 * 4)]
+	ldr	r2, [r0, #(_JB_SIGMASK * 4)]
 
 	/* Set signal mask */
 	stmfd	sp!, {r0, r1, r14}
@@ -99,18 +103,18 @@
 	add	sp, sp, #4	/* unalign the stack */
 	ldmfd	sp!, {r0, r1, r14} 
 
-	add	r0, r0, #4
-#ifdef SOFTFLOAT
-	add	r0, r0, #52
-#else
-	/* Restore fp registers */
-	lfm	f4, 4, [r0], #48
-	/* Restore FPSR */
-	ldr	r4, [r0], #0x0004
-	wfs	r4
-#endif	/* SOFTFLOAT */
-	/* Restore integer registers */
-        ldmia	r0, {r4-r14}
+#ifdef __ARM_HAVE_VFP
+	/* Restore floating-point registers */
+	add     r2, r0, #(_JB_FLOAT_BASE * 4)
+	vldmia  r2, {d8-d15}
+	/* Restore floating-point state */
+	ldr     r2, [r0, #(_JB_FLOAT_STATE * 4)]
+	fmxr    fpscr, r2
+#endif /* __ARM_HAVE_VFP */
+
+	/* Restore core registers */
+	add     r2, r0, #(_JB_CORE_BASE * 4)
+	ldmia   r2, {r4-r14}
 
 	/* Validate sp and r14 */
 	teq	sp, #0
diff --git a/libc/arch-arm/include/machine/cpu-features.h b/libc/arch-arm/include/machine/cpu-features.h
index ecf6ff6..39c1db3 100644
--- a/libc/arch-arm/include/machine/cpu-features.h
+++ b/libc/arch-arm/include/machine/cpu-features.h
@@ -38,7 +38,7 @@
  * IMPORTANT: We have no intention to support anything below an ARMv4T !
  */
 
-/* _ARM_ARCH_REVISION is a number corresponding to the ARM revision
+/* __ARM_ARCH__ is a number corresponding to the ARM revision
  * we're going to support
  *
  * it looks like our toolchain doesn't define __ARM_ARCH__
@@ -142,20 +142,47 @@
  *
  *     ldr  pc, [<some address>]
  *
- * note that this affects any instruction that explicitely changes the
+ * note that this affects any instruction that explicitly changes the
  * value of the pc register, including ldm { ...,pc } or 'add pc, #offset'
  */
 #if __ARM_ARCH__ >= 5
 #  define __ARM_HAVE_PC_INTERWORK
 #endif
 
-/* define _ARM_HAVE_LDREX_STREX for ARMv6 and ARMv7 architecure to be
- * used in replacement of depricated swp instruction
+/* define __ARM_HAVE_LDREX_STREX for ARMv6 and ARMv7 architecture to be
+ * used in replacement of deprecated swp instruction
  */
 #if __ARM_ARCH__ >= 6
-#  define _ARM_HAVE_LDREX_STREX
+#  define __ARM_HAVE_LDREX_STREX
 #endif
 
+/* define __ARM_HAVE_DMB for ARMv7 architecture
+ */
+#if __ARM_ARCH__ >= 7
+#  define __ARM_HAVE_DMB
+#endif
+
+/* define __ARM_HAVE_LDREXD for ARMv7 architecture
+ * (also present in ARMv6K, but not implemented in ARMv7-M, neither of which
+ * we care about)
+ */
+#if __ARM_ARCH__ >= 7
+#  define __ARM_HAVE_LDREXD
+#endif
+
+/* define _ARM_HAVE_VFP if we have VFPv3
+ */
+#if __ARM_ARCH__ >= 7 && defined __VFP_FP__
+#  define __ARM_HAVE_VFP
+#endif
+
+/* define _ARM_HAVE_NEON for ARMv7 architecture if we support the
+ * Neon SIMD instruction set extensions. This also implies
+ * that VFPv3-D32 is supported.
+ */
+#if __ARM_ARCH__ >= 7 && defined __ARM_NEON__
+#  define __ARM_HAVE_NEON
+#endif
 
 /* Assembly-only macros */
 
diff --git a/libc/arch-arm/include/machine/setjmp.h b/libc/arch-arm/include/machine/setjmp.h
index f20cab2..0941202 100644
--- a/libc/arch-arm/include/machine/setjmp.h
+++ b/libc/arch-arm/include/machine/setjmp.h
@@ -1,87 +1,82 @@
-/*	$OpenBSD: setjmp.h,v 1.1 2004/02/01 05:09:49 drahn Exp $	*/
-/*	$NetBSD: setjmp.h,v 1.2 2001/08/25 14:45:59 bjh21 Exp $	*/
+/*
+ * Copyright (C) 2010 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.
+ */
 
 /*
  * machine/setjmp.h: machine dependent setjmp-related information.
  */
 
-#ifdef __ELF__
-#define	_JBLEN	64		/* size, in longs, of a jmp_buf */
-#else
-#define	_JBLEN	29		/* size, in longs, of a jmp_buf */
-#endif
-
-/*
- * NOTE: The internal structure of a jmp_buf is *PRIVATE*
- *       This information is provided as there is software
- *       that fiddles with this with obtain the stack pointer
- *	 (yes really ! and its commercial !).
+/* _JBLEN is the size of a jmp_buf in longs.
+ * Do not modify this value or you will break the ABI !
  *
- * Description of the setjmp buffer
- *
- * word  0	magic number	(dependant on creator)
- *       1 -  3	f4		fp register 4
- *	 4 -  6	f5		fp register 5
- *	 7 -  9 f6		fp register 6
- *	10 - 12	f7		fp register 7
- *	13	fpsr		fp status register
- *	14	r4		register 4
- *	15	r5		register 5
- *	16	r6		register 6
- *	17	r7		register 7
- *	18	r8		register 8
- *	19	r9		register 9
- *	20	r10		register 10 (sl)
- *	21	r11		register 11 (fp)
- *	22	r12		register 12 (ip)
- *	23	r13		register 13 (sp)
- *	24	r14		register 14 (lr)
- *	25	signal mask	(dependant on magic)
- *	26	(con't)
- *	27	(con't)
- *	28	(con't)
- *
- * The magic number number identifies the jmp_buf and
- * how the buffer was created as well as providing
- * a sanity check
- *
- * A side note I should mention - Please do not tamper
- * with the floating point fields. While they are
- * always saved and restored at the moment this cannot
- * be garenteed especially if the compiler happens
- * to be generating soft-float code so no fp
- * registers will be used.
- *
- * Whilst this can be seen an encouraging people to
- * use the setjmp buffer in this way I think that it
- * is for the best then if changes occur compiles will
- * break rather than just having new builds falling over
- * mysteriously.
+ * This value comes from the original OpenBSD ARM-specific header
+ * that was replaced by this one.
  */
+#define _JBLEN  64
+
+/* According to the ARM AAPCS document, we only need to save
+ * the following registers:
+ *
+ *  Core   r4-r14
+ *
+ *  VFP    d8-d15  (see section 5.1.2.1)
+ *
+ *      Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
+ *      calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
+ *      (and can be used for passing arguments or returning results in standard
+ *      procedure-call variants). Registers d16-d31 (q8-q15), if present, do
+ *      not need to be preserved.
+ *
+ *  FPSCR  saved because GLibc does saves it too.
+ *
+ */
+
+/* The internal structure of a jmp_buf is totally private.
+ * Current layout (may change in the future):
+ *
+ * word   name         description
+ * 0      magic        magic number
+ * 1      sigmask      signal mask (not used with _setjmp / _longjmp)
+ * 2      float_base   base of float registers (d8 to d15)
+ * 18     float_state  floating-point status and control register
+ * 19     core_base    base of core registers (r4 to r14)
+ * 30     reserved     reserved entries (room to grow)
+ * 64
+ *
+ * NOTE: float_base must be at an even word index, since the
+ *       FP registers will be loaded/stored with instructions
+ *       that expect 8-byte alignment.
+ */
+
+#define _JB_MAGIC       0
+#define _JB_SIGMASK     (_JB_MAGIC+1)
+#define _JB_FLOAT_BASE  (_JB_SIGMASK+1)
+#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
+#define _JB_CORE_BASE   (_JB_FLOAT_STATE+1)
 
 #define _JB_MAGIC__SETJMP	0x4278f500
 #define _JB_MAGIC_SETJMP	0x4278f501
-
-/* Valid for all jmp_buf's */
-
-#define _JB_MAGIC		 0
-#define _JB_REG_F4		 1
-#define _JB_REG_F5		 4
-#define _JB_REG_F6		 7
-#define _JB_REG_F7		10
-#define _JB_REG_FPSR		13
-#define _JB_REG_R4		14
-#define _JB_REG_R5		15
-#define _JB_REG_R6		16
-#define _JB_REG_R7		17
-#define _JB_REG_R8		18
-#define _JB_REG_R9		19
-#define _JB_REG_R10		20
-#define _JB_REG_R11		21
-#define _JB_REG_R12		22
-#define _JB_REG_R13		23
-#define _JB_REG_R14		24
-
-/* Only valid with the _JB_MAGIC_SETJMP magic */
-
-#define _JB_SIGMASK		25
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index 9cdd28a..f6312e5 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -161,6 +161,7 @@
 syscall_src += arch-arm/syscalls/init_module.S
 syscall_src += arch-arm/syscalls/delete_module.S
 syscall_src += arch-arm/syscalls/klogctl.S
+syscall_src += arch-arm/syscalls/sysinfo.S
 syscall_src += arch-arm/syscalls/futex.S
 syscall_src += arch-arm/syscalls/epoll_create.S
 syscall_src += arch-arm/syscalls/epoll_ctl.S
diff --git a/libc/arch-arm/syscalls/sysinfo.S b/libc/arch-arm/syscalls/sysinfo.S
new file mode 100644
index 0000000..197324d
--- /dev/null
+++ b/libc/arch-arm/syscalls/sysinfo.S
@@ -0,0 +1,19 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type sysinfo, #function
+    .globl sysinfo
+    .align 4
+    .fnstart
+
+sysinfo:
+    .save   {r4, r7}
+    stmfd   sp!, {r4, r7}
+    ldr     r7, =__NR_sysinfo
+    swi     #0
+    ldmfd   sp!, {r4, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+    .fnend
diff --git a/libc/arch-sh/syscalls.mk b/libc/arch-sh/syscalls.mk
index ab2f3d1..a8a151a 100644
--- a/libc/arch-sh/syscalls.mk
+++ b/libc/arch-sh/syscalls.mk
@@ -150,6 +150,7 @@
 syscall_src += arch-sh/syscalls/init_module.S
 syscall_src += arch-sh/syscalls/delete_module.S
 syscall_src += arch-sh/syscalls/klogctl.S
+syscall_src += arch-sh/syscalls/sysinfo.S
 syscall_src += arch-sh/syscalls/futex.S
 syscall_src += arch-sh/syscalls/epoll_create.S
 syscall_src += arch-sh/syscalls/epoll_ctl.S
diff --git a/libc/arch-sh/syscalls/sysinfo.S b/libc/arch-sh/syscalls/sysinfo.S
new file mode 100644
index 0000000..ae042ab
--- /dev/null
+++ b/libc/arch-sh/syscalls/sysinfo.S
@@ -0,0 +1,32 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type sysinfo, @function
+    .globl sysinfo
+    .align 4
+
+sysinfo:
+
+    /* invoke trap */
+    mov.l   0f, r3  /* trap num */
+    trapa   #(1 + 0x10)
+
+    /* check return value */
+    cmp/pz  r0
+    bt      __NR_sysinfo_end
+
+    /* keep error number */
+    sts.l   pr, @-r15
+    mov.l   1f, r1
+    jsr     @r1
+    mov     r0, r4
+    lds.l   @r15+, pr
+
+__NR_sysinfo_end:
+    rts
+    nop
+
+    .align  2
+0:  .long   __NR_sysinfo
+1:  .long   __set_syscall_errno
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index ab026fe..bd9a9ab 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -164,6 +164,7 @@
 syscall_src += arch-x86/syscalls/init_module.S
 syscall_src += arch-x86/syscalls/delete_module.S
 syscall_src += arch-x86/syscalls/klogctl.S
+syscall_src += arch-x86/syscalls/sysinfo.S
 syscall_src += arch-x86/syscalls/futex.S
 syscall_src += arch-x86/syscalls/epoll_create.S
 syscall_src += arch-x86/syscalls/epoll_ctl.S
diff --git a/libc/arch-x86/syscalls/sysinfo.S b/libc/arch-x86/syscalls/sysinfo.S
new file mode 100644
index 0000000..c60c37b
--- /dev/null
+++ b/libc/arch-x86/syscalls/sysinfo.S
@@ -0,0 +1,23 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type sysinfo, @function
+    .globl sysinfo
+    .align 4
+
+sysinfo:
+    pushl   %ebx
+    mov     8(%esp), %ebx
+    movl    $__NR_sysinfo, %eax
+    int     $0x80
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %ebx
+    ret
diff --git a/libc/bionic/logd_write.c b/libc/bionic/logd_write.c
index 618160f..63dfd59 100644
--- a/libc/bionic/logd_write.c
+++ b/libc/bionic/logd_write.c
@@ -38,12 +38,17 @@
 #include <stdarg.h>
 #include <fcntl.h>
 
-#include <cutils/logger.h>
 #include "logd.h"
 
+/* should match system/core/include/cutils/logger.h */
+#define LOGGER_LOG_MAIN     "log/main"
+#define LOGGER_LOG_RADIO    "log/radio"
+#define LOGGER_LOG_EVENTS   "log/events"
+#define LOGGER_LOG_SYSTEM   "log/system"
+
 #include <pthread.h>
 
-#define LOG_BUF_SIZE	1024
+#define LOG_BUF_SIZE    1024
 
 typedef enum {
     LOG_ID_NONE = 0,
diff --git a/libc/bionic/pthread-rwlocks.c b/libc/bionic/pthread-rwlocks.c
new file mode 100644
index 0000000..ca3e95c
--- /dev/null
+++ b/libc/bionic/pthread-rwlocks.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2010 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 "pthread_internal.h"
+#include <errno.h>
+
+/* Technical note:
+ *
+ * Possible states of a read/write lock:
+ *
+ *  - no readers and no writer (unlocked)
+ *  - one or more readers sharing the lock at the same time (read-locked)
+ *  - one writer holding the lock (write-lock)
+ *
+ * Additionally:
+ *  - trying to get the write-lock while there are any readers blocks
+ *  - trying to get the read-lock while there is a writer blocks
+ *  - a single thread can acquire the lock multiple times in the same mode
+ *
+ *  - Posix states that behaviour is undefined it a thread tries to acquire
+ *    the lock in two distinct modes (e.g. write after read, or read after write).
+ *
+ *  - This implementation tries to avoid writer starvation by making the readers
+ *    block as soon as there is a waiting writer on the lock. However, it cannot
+ *    completely eliminate it: each time the lock is unlocked, all waiting threads
+ *    are woken and battle for it, which one gets it depends on the kernel scheduler
+ *    and is semi-random.
+ *
+ */
+
+#define  __likely(cond)    __builtin_expect(!!(cond), 1)
+#define  __unlikely(cond)  __builtin_expect(!!(cond), 0)
+
+#define  RWLOCKATTR_DEFAULT     0
+#define  RWLOCKATTR_SHARED_MASK 0x0010
+
+extern pthread_internal_t* __get_thread(void);
+
+/* Return a global kernel ID for the current thread */
+static int __get_thread_id(void)
+{
+    return __get_thread()->kernel_id;
+}
+
+int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
+{
+    if (!attr)
+        return EINVAL;
+
+    *attr = PTHREAD_PROCESS_PRIVATE;
+    return 0;
+}
+
+int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)
+{
+    if (!attr)
+        return EINVAL;
+
+    *attr = -1;
+    return 0;
+}
+
+int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int  pshared)
+{
+    if (!attr)
+        return EINVAL;
+
+    switch (pshared) {
+    case PTHREAD_PROCESS_PRIVATE:
+    case PTHREAD_PROCESS_SHARED:
+        *attr = pshared;
+        return 0;
+    default:
+        return EINVAL;
+    }
+}
+
+int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *attr, int *pshared)
+{
+    if (!attr || !pshared)
+        return EINVAL;
+
+    *pshared = *attr;
+    return 0;
+}
+
+int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
+{
+    pthread_mutexattr_t*  lock_attr = NULL;
+    pthread_condattr_t*   cond_attr = NULL;
+    pthread_mutexattr_t   lock_attr0;
+    pthread_condattr_t    cond_attr0;
+    int                   ret;
+
+    if (rwlock == NULL)
+        return EINVAL;
+
+    if (attr && *attr == PTHREAD_PROCESS_SHARED) {
+        lock_attr = &lock_attr0;
+        pthread_mutexattr_init(lock_attr);
+        pthread_mutexattr_setpshared(lock_attr, PTHREAD_PROCESS_SHARED);
+
+        cond_attr = &cond_attr0;
+        pthread_condattr_init(cond_attr);
+        pthread_condattr_setpshared(cond_attr, PTHREAD_PROCESS_SHARED);
+    }
+
+    ret = pthread_mutex_init(&rwlock->lock, lock_attr);
+    if (ret != 0)
+        return ret;
+
+    ret = pthread_cond_init(&rwlock->cond, cond_attr);
+    if (ret != 0) {
+        pthread_mutex_destroy(&rwlock->lock);
+        return ret;
+    }
+
+    rwlock->numLocks = 0;
+    rwlock->pendingReaders = 0;
+    rwlock->pendingWriters = 0;
+    rwlock->writerThreadId = 0;
+
+    return 0;
+}
+
+int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
+{
+    int  ret;
+
+    if (rwlock == NULL)
+        return EINVAL;
+
+    if (rwlock->numLocks > 0)
+        return EBUSY;
+
+    pthread_cond_destroy(&rwlock->cond);
+    pthread_mutex_destroy(&rwlock->lock);
+    return 0;
+}
+
+/* Returns TRUE iff we can acquire a read lock. */
+static __inline__ int read_precondition(pthread_rwlock_t *rwlock, int  thread_id)
+{
+    /* We can't have the lock if any writer is waiting for it (writer bias).
+     * This tries to avoid starvation when there are multiple readers racing.
+     */
+    if (rwlock->pendingWriters > 0)
+        return 0;
+
+    /* We can have the lock if there is no writer, or if we write-own it */
+    /* The second test avoids a self-dead lock in case of buggy code. */
+    if (rwlock->writerThreadId == 0 || rwlock->writerThreadId == thread_id)
+        return 1;
+
+    /* Otherwise, we can't have it */
+    return 0;
+}
+
+/* returns TRUE iff we can acquire a write lock. */
+static __inline__ int write_precondition(pthread_rwlock_t *rwlock, int  thread_id)
+{
+    /* We can get the lock if nobody has it */
+    if (rwlock->numLocks == 0)
+        return 1;
+
+    /* Or if we already own it */
+    if (rwlock->writerThreadId == thread_id)
+        return 1;
+
+    /* Otherwise, not */
+    return 0;
+}
+
+/* This function is used to waken any waiting thread contending
+ * for the lock. One of them should be able to grab it after
+ * that.
+ */
+static void _pthread_rwlock_pulse(pthread_rwlock_t *rwlock)
+{
+    if (rwlock->pendingReaders > 0 || rwlock->pendingWriters > 0)
+        pthread_cond_broadcast(&rwlock->cond);
+}
+
+
+int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
+{
+    return pthread_rwlock_timedrdlock(rwlock, NULL);
+}
+
+int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
+{
+    int ret = 0;
+
+    if (rwlock == NULL)
+        return EINVAL;
+
+    pthread_mutex_lock(&rwlock->lock);
+    if (__unlikely(!read_precondition(rwlock, __get_thread_id())))
+        ret = EBUSY;
+    else
+        rwlock->numLocks ++;
+    pthread_mutex_unlock(&rwlock->lock);
+
+    return ret;
+}
+
+int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, const struct timespec *abs_timeout)
+{
+    int thread_id, ret = 0;
+
+    if (rwlock == NULL)
+        return EINVAL;
+
+    pthread_mutex_lock(&rwlock->lock);
+    thread_id = __get_thread_id();
+    if (__unlikely(!read_precondition(rwlock, thread_id))) {
+        rwlock->pendingReaders += 1;
+        do {
+            ret = pthread_cond_timedwait(&rwlock->cond, &rwlock->lock, abs_timeout);
+        } while (ret == 0 && !read_precondition(rwlock, thread_id));
+        rwlock->pendingReaders -= 1;
+        if (ret != 0)
+            goto EXIT;
+    }
+    rwlock->numLocks ++;
+EXIT:
+    pthread_mutex_unlock(&rwlock->lock);
+    return ret;
+}
+
+
+int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
+{
+    return pthread_rwlock_timedwrlock(rwlock, NULL);
+}
+
+int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
+{
+    int thread_id, ret = 0;
+
+    if (rwlock == NULL)
+        return EINVAL;
+
+    pthread_mutex_lock(&rwlock->lock);
+    thread_id = __get_thread_id();
+    if (__unlikely(!write_precondition(rwlock, thread_id))) {
+        ret = EBUSY;
+    } else {
+        rwlock->numLocks ++;
+        rwlock->writerThreadId = thread_id;
+    }
+    pthread_mutex_unlock(&rwlock->lock);
+    return ret;
+}
+
+int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, const struct timespec *abs_timeout)
+{
+    int thread_id, ret = 0;
+
+    if (rwlock == NULL)
+        return EINVAL;
+
+    pthread_mutex_lock(&rwlock->lock);
+    thread_id = __get_thread_id();
+    if (__unlikely(!write_precondition(rwlock, thread_id))) {
+        /* If we can't read yet, wait until the rwlock is unlocked
+         * and try again. Increment pendingReaders to get the
+         * cond broadcast when that happens.
+         */
+        rwlock->pendingWriters += 1;
+        do {
+            ret = pthread_cond_timedwait(&rwlock->cond, &rwlock->lock, abs_timeout);
+        } while (ret == 0 && !write_precondition(rwlock, thread_id));
+        rwlock->pendingWriters -= 1;
+        if (ret != 0)
+            goto EXIT;
+    }
+    rwlock->numLocks ++;
+    rwlock->writerThreadId = thread_id;
+EXIT:
+    pthread_mutex_unlock(&rwlock->lock);
+    return ret;
+}
+
+
+int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
+{
+    int  ret = 0;
+
+    if (rwlock == NULL)
+        return EINVAL;
+
+    pthread_mutex_lock(&rwlock->lock);
+
+    /* The lock must be held */
+    if (rwlock->numLocks == 0) {
+        ret = EPERM;
+        goto EXIT;
+    }
+
+    /* If it has only readers, writerThreadId is 0 */
+    if (rwlock->writerThreadId == 0) {
+        if (--rwlock->numLocks == 0)
+            _pthread_rwlock_pulse(rwlock);
+    }
+    /* Otherwise, it has only a single writer, which
+     * must be ourselves.
+     */
+    else {
+        if (rwlock->writerThreadId != __get_thread_id()) {
+            ret = EPERM;
+            goto EXIT;
+        }
+        if (--rwlock->numLocks == 0) {
+            rwlock->writerThreadId = 0;
+            _pthread_rwlock_pulse(rwlock);
+        }
+    }
+EXIT:
+    pthread_mutex_unlock(&rwlock->lock);
+    return ret;
+}
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index e17e366..8eee136 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -43,7 +43,8 @@
 #include <memory.h>
 #include <assert.h>
 #include <malloc.h>
-#include <linux/futex.h>
+#include <bionic_futex.h>
+#include <bionic_atomic_inline.h>
 #include <sys/prctl.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -53,6 +54,16 @@
 extern void _exit_thread(int  retCode);
 extern int  __set_errno(int);
 
+int  __futex_wake_ex(volatile void *ftx, int pshared, int val)
+{
+    return __futex_syscall3(ftx, pshared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, val);
+}
+
+int  __futex_wait_ex(volatile void *ftx, int pshared, int val, const struct timespec *timeout)
+{
+    return __futex_syscall4(ftx, pshared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE, val, timeout);
+}
+
 #define  __likely(cond)    __builtin_expect(!!(cond), 1)
 #define  __unlikely(cond)  __builtin_expect(!!(cond), 0)
 
@@ -715,24 +726,6 @@
 }
 
 
-int __futex_wait(volatile void *ftx, int val, const struct timespec *timeout);
-int __futex_wake(volatile void *ftx, int count);
-
-int __futex_syscall3(volatile void *ftx, int op, int val);
-int __futex_syscall4(volatile void *ftx, int op, int val, const struct timespec *timeout);
-
-#ifndef FUTEX_PRIVATE_FLAG
-#define FUTEX_PRIVATE_FLAG  128
-#endif
-
-#ifndef FUTEX_WAIT_PRIVATE
-#define FUTEX_WAIT_PRIVATE  (FUTEX_WAIT|FUTEX_PRIVATE_FLAG)
-#endif
-
-#ifndef FUTEX_WAKE_PRIVATE
-#define FUTEX_WAKE_PRIVATE  (FUTEX_WAKE|FUTEX_PRIVATE_FLAG)
-#endif
-
 // mutex lock states
 //
 // 0: unlocked
@@ -934,11 +927,10 @@
          * that the mutex is in state 2 when we go to sleep on it, which
          * guarantees a wake-up call.
          */
-        int  wait_op = shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE;
-
         while (__atomic_swap(shared|2, &mutex->value ) != (shared|0))
-            __futex_syscall4(&mutex->value, wait_op, shared|2, 0);
+            __futex_wait_ex(&mutex->value, shared, shared|2, 0);
     }
+    ANDROID_MEMBAR_FULL();
 }
 
 /*
@@ -948,6 +940,8 @@
 static __inline__ void
 _normal_unlock(pthread_mutex_t*  mutex)
 {
+    ANDROID_MEMBAR_FULL();
+
     /* We need to preserve the shared flag during operations */
     int  shared = mutex->value & MUTEX_SHARED_MASK;
 
@@ -957,7 +951,6 @@
      * if it wasn't 1 we have to do some additional work.
      */
     if (__atomic_dec(&mutex->value) != (shared|1)) {
-        int  wake_op = shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE;
         /*
          * Start by releasing the lock.  The decrement changed it from
          * "contended lock" to "uncontended lock", which means we still
@@ -995,7 +988,7 @@
          * Either way we have correct behavior and nobody is orphaned on
          * the wait queue.
          */
-        __futex_syscall3(&mutex->value, wake_op, 1);
+        __futex_wake_ex(&mutex->value, shared, 1);
     }
 }
 
@@ -1015,7 +1008,7 @@
 
 int pthread_mutex_lock(pthread_mutex_t *mutex)
 {
-    int mtype, tid, new_lock_type, shared, wait_op;
+    int mtype, tid, new_lock_type, shared;
 
     if (__unlikely(mutex == NULL))
         return EINVAL;
@@ -1060,8 +1053,7 @@
     new_lock_type = 1;
 
     /* compute futex wait opcode and restore shared flag in mtype */
-    wait_op = shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE;
-    mtype  |= shared;
+    mtype |= shared;
 
     for (;;) {
         int  oldv;
@@ -1087,7 +1079,7 @@
          */
         new_lock_type = 2;
 
-        __futex_syscall4(&mutex->value, wait_op, oldv, NULL);
+        __futex_wait_ex(&mutex->value, shared, oldv, NULL);
     }
     return 0;
 }
@@ -1127,8 +1119,7 @@
 
     /* Wake one waiting thread, if any */
     if ((oldv & 3) == 2) {
-        int wake_op = shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE;
-        __futex_syscall3(&mutex->value, wake_op, 1);
+        __futex_wake_ex(&mutex->value, shared, 1);
     }
     return 0;
 }
@@ -1147,8 +1138,10 @@
     /* Handle common case first */
     if ( __likely(mtype == MUTEX_TYPE_NORMAL) )
     {
-        if (__atomic_cmpxchg(shared|0, shared|1, &mutex->value) == 0)
+        if (__atomic_cmpxchg(shared|0, shared|1, &mutex->value) == 0) {
+            ANDROID_MEMBAR_FULL();
             return 0;
+        }
 
         return EBUSY;
     }
@@ -1228,7 +1221,7 @@
     clockid_t        clock = CLOCK_MONOTONIC;
     struct timespec  abstime;
     struct timespec  ts;
-    int              mtype, tid, oldv, new_lock_type, shared, wait_op;
+    int              mtype, tid, oldv, new_lock_type, shared;
 
     /* compute absolute expiration time */
     __timespec_to_relative_msec(&abstime, msecs, clock);
@@ -1242,19 +1235,20 @@
     /* Handle common case first */
     if ( __likely(mtype == MUTEX_TYPE_NORMAL) )
     {
-        int  wait_op = shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE;
-
-        /* fast path for unconteded lock */
-        if (__atomic_cmpxchg(shared|0, shared|1, &mutex->value) == 0)
+        /* fast path for uncontended lock */
+        if (__atomic_cmpxchg(shared|0, shared|1, &mutex->value) == 0) {
+            ANDROID_MEMBAR_FULL();
             return 0;
+        }
 
         /* loop while needed */
         while (__atomic_swap(shared|2, &mutex->value) != (shared|0)) {
             if (__timespec_to_absolute(&ts, &abstime, clock) < 0)
                 return EBUSY;
 
-            __futex_syscall4(&mutex->value, wait_op, shared|2, &ts);
+            __futex_wait_ex(&mutex->value, shared, shared|2, &ts);
         }
+        ANDROID_MEMBAR_FULL();
         return 0;
     }
 
@@ -1285,7 +1279,6 @@
     new_lock_type = 1;
 
     /* Compute wait op and restore sharing bit in mtype */
-    wait_op = shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE;
     mtype  |= shared;
 
     for (;;) {
@@ -1316,7 +1309,7 @@
         if (__timespec_to_absolute(&ts, &abstime, clock) < 0)
             return EBUSY;
 
-        __futex_syscall4(&mutex->value, wait_op, oldv, &ts);
+        __futex_wait_ex(&mutex->value, shared, oldv, &ts);
     }
     return 0;
 }
@@ -1409,7 +1402,6 @@
 __pthread_cond_pulse(pthread_cond_t *cond, int  counter)
 {
     long flags;
-    int  wake_op;
 
     if (__unlikely(cond == NULL))
         return EINVAL;
@@ -1423,8 +1415,7 @@
             break;
     }
 
-    wake_op = COND_IS_SHARED(cond) ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE;
-    __futex_syscall3(&cond->value, wake_op, counter);
+    __futex_wake_ex(&cond->value, COND_IS_SHARED(cond), counter);
     return 0;
 }
 
@@ -1449,10 +1440,9 @@
 {
     int  status;
     int  oldvalue = cond->value;
-    int  wait_op  = COND_IS_SHARED(cond) ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE;
 
     pthread_mutex_unlock(mutex);
-    status = __futex_syscall4(&cond->value, wait_op, oldvalue, reltime);
+    status = __futex_wait_ex(&cond->value, COND_IS_SHARED(cond), oldvalue, reltime);
     pthread_mutex_lock(mutex);
 
     if (status == (-ETIMEDOUT)) return ETIMEDOUT;
diff --git a/libc/bionic/semaphore.c b/libc/bionic/semaphore.c
index 84b9314..0a6cab4 100644
--- a/libc/bionic/semaphore.c
+++ b/libc/bionic/semaphore.c
@@ -30,6 +30,17 @@
 #include <sys/time.h>
 #include <sys/atomics.h>
 #include <time.h>
+#include <bionic_atomic_inline.h>
+#include <bionic_futex.h>
+
+/* Use the lower 31-bits for the counter, and the high bit for
+ * the shared flag.
+ */
+#define SEM_VALUE_MASK  0x7fffffff
+#define SEM_SHARED_MASK 0x80000000
+
+#define SEM_GET_SHARED(sem)  ((sem)->count & SEM_SHARED_MASK)
+#define SEM_GET_VALUE(sem)   ((sem)->count & SEM_VALUE_MASK)
 
 int sem_init(sem_t *sem, int pshared, unsigned int value)
 {
@@ -38,12 +49,16 @@
         return -1;
     }
 
-    if (pshared != 0) {
-        errno = ENOSYS;
+    /* ensure that 'value' can be stored in the semaphore */
+    if ((value & SEM_VALUE_MASK) != value) {
+        errno = EINVAL;
         return -1;
     }
 
     sem->count = value;
+    if (pshared != 0)
+        sem->count |= SEM_SHARED_MASK;
+
     return 0;
 }
 
@@ -54,10 +69,11 @@
         errno = EINVAL;
         return -1;
     }
-    if (sem->count == 0) {
+    if ((sem->count & SEM_VALUE_MASK) == 0) {
         errno = EBUSY;
         return -1;
     }
+    sem->count = 0;
     return 0;
 }
 
@@ -90,38 +106,69 @@
 }
 
 
+/* Return 0 if a semaphore's value is 0
+ * Otherwise, decrement the value and return the old value.
+ */
 static int
-__atomic_dec_if_positive( volatile unsigned int*  pvalue )
+__sem_dec_if_positive(volatile unsigned int *pvalue)
 {
+    unsigned int  shared = (*pvalue & SEM_SHARED_MASK);
     unsigned int  old;
 
     do {
-        old = *pvalue;
+        old = (*pvalue & SEM_VALUE_MASK);
     }
-    while ( old != 0 && __atomic_cmpxchg( (int)old, (int)old-1, (volatile int*)pvalue ) != 0 );
+    while ( old != 0 &&
+            __atomic_cmpxchg((int)(old|shared),
+                             (int)((old-1)|shared),
+                             (volatile int*)pvalue) != 0 );
 
     return old;
 }
 
+/* Increment the value of a semaphore atomically.
+ * NOTE: the value will wrap above SEM_VALUE_MASK
+ */
+static int
+__sem_inc(volatile unsigned int *pvalue)
+{
+    unsigned int  shared = (*pvalue & SEM_SHARED_MASK);
+    unsigned int  old;
+
+    do {
+        old = (*pvalue & SEM_VALUE_MASK);
+    } while ( __atomic_cmpxchg((int)(old|shared),
+                               (int)(((old+1)&SEM_VALUE_MASK)|shared),
+                               (volatile int*)pvalue) != 0);
+    return old;
+}
+
+/* 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 (__atomic_dec_if_positive(&sem->count))
+        if (__sem_dec_if_positive(&sem->count))
             break;
 
-        __futex_wait(&sem->count, 0, 0);
+        __futex_wait_ex(&sem->count, shared, shared, NULL);
     }
+    ANDROID_MEMBAR_FULL();
     return 0;
 }
 
 int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
 {
     int  ret;
+    unsigned int shared;
 
     if (sem == NULL) {
         errno = EINVAL;
@@ -130,8 +177,10 @@
 
     /* POSIX says we need to try to decrement the semaphore
      * before checking the timeout value */
-    if (__atomic_dec_if_positive(&sem->count))
+    if (__sem_dec_if_positive(&sem->count)) {
+        ANDROID_MEMBAR_FULL();
         return 0;
+    }
 
     /* check it as per Posix */
     if (abs_timeout == NULL    ||
@@ -143,6 +192,8 @@
         return -1;
     }
 
+    shared = SEM_GET_SHARED(sem);
+
     for (;;) {
         struct timespec ts;
         int             ret;
@@ -161,7 +212,7 @@
             return -1;
         }
 
-        ret = __futex_wait(&sem->count, 0, &ts);
+        ret = __futex_wait_ex(&sem->count, shared, shared, &ts);
 
         /* return in case of timeout or interrupt */
         if (ret == -ETIMEDOUT || ret == -EINTR) {
@@ -169,19 +220,27 @@
             return -1;
         }
 
-        if (__atomic_dec_if_positive(&sem->count))
+        if (__sem_dec_if_positive(&sem->count)) {
+            ANDROID_MEMBAR_FULL();
             break;
+        }
     }
     return 0;
 }
 
+/* unlock a semaphore */
 int sem_post(sem_t *sem)
 {
+    unsigned int shared;
+
     if (sem == NULL)
         return EINVAL;
 
-    if (__atomic_inc((volatile int*)&sem->count) >= 0)
-        __futex_wake(&sem->count, 1);
+    shared = SEM_GET_SHARED(sem);
+
+    ANDROID_MEMBAR_FULL();
+    if (__sem_inc(&sem->count) >= 0)
+        __futex_wake_ex(&sem->count, shared, 1);
 
     return 0;
 }
@@ -193,7 +252,8 @@
         return -1;
     }
 
-    if (__atomic_dec_if_positive(&sem->count) > 0) {
+    if (__sem_dec_if_positive(&sem->count) > 0) {
+        ANDROID_MEMBAR_FULL();
         return 0;
     } else {
         errno = EAGAIN;
@@ -208,6 +268,6 @@
         return -1;
     }
 
-    *sval = sem->count;
+    *sval = SEM_GET_VALUE(sem);
     return 0;
 }
diff --git a/libc/docs/CHANGES.TXT b/libc/docs/CHANGES.TXT
index 9080685..0eae752 100644
--- a/libc/docs/CHANGES.TXT
+++ b/libc/docs/CHANGES.TXT
@@ -1,7 +1,55 @@
 Bionic ChangeLog:
 -----------------
 
-Differences between current and Android 2.1:
+Differences between current and Android 2.2:
+
+- <pthread.h>: Add reader/writer locks implementation.
+
+- <semaphore.h>: Use private futexes for semaphore implementation,
+  unless your set 'pshared' to non-0 when calling sem_init().
+
+- <math.h>: Added sincos(), sincosf() and sincosl() (GLibc compatibility).
+
+- <sys/sysinfo.h>: Added missing sysinfo() system call implementation
+  (the function was already declared in the header though).
+
+- sysconf() didn't work for some arguments due to a small bug in the
+  /proc line parser.
+
+- <termio.h>: added missing header (just includes <termios.h>)
+
+- <unistd.h>: add missing declaration for truncate(). The implementation
+  was already here since Android 1.5.
+
+- <wchar.h>: small fixes to really support wchar_t in Bionic (not there yet).
+
+     the size of wchar_t is still 32-bit (decided by the compiler)
+
+     WCHAR_MIN: changed from 0 to INT_MIN
+     WCHAR_MAX: changed from 255 to INT_MAX
+
+     wcpcpy(), wcpncpy(), wcscat(), wcschr(), wcscmp(),
+     wcscpy(), wcscspn(), wcsdup(), wcslcat(), wcslcpy(),
+     wcslen(), wcsncat(), wcsncmp(), wcsncpy(), wcsnlen(),
+     wcspbrk(), wcsrchr(), wcsrchr(), wcsspn(), wcsstr(),
+     wcstok(), wcswidth(), wmemchr(), wmemcmp(), wmemcpy(),
+     wmemmove(), wmemset(): Added proper implementations.
+
+     wcscasecmp(), wcsncasecmp(): Added implementation limited
+     to ASCII codes for lower/upper.
+
+     wcscoll(): added dummy implementation that calls wcscmp()
+     wcsxfrm(): added dummy implementation that calls wcsncpy()
+
+  NOTE: Technically, this breaks the ABI, but we never claimed to support
+        wchar_t anyway. The wchar_t support is still *NOT* official at this
+        point. We need better multi-byte support code, and wprintf/wscanf
+        stuff too.
+
+-------------------------------------------------------------------------------
+Differences between Android 2.2. and Android 2.1:
+
+- Support FP register save/load in setjmp()/longjmp() on ARMv7 builds.
 
 - Add support for SH-4 CPU architecture !
 
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 944bb68..9773dcb 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -219,6 +219,41 @@
  */
 int pthread_mutex_lock_timeout_np(pthread_mutex_t *mutex, unsigned msecs);
 
+/* read-write lock support */
+
+typedef int pthread_rwlockattr_t;
+
+typedef struct {
+    pthread_mutex_t  lock;
+    pthread_cond_t   cond;
+    int              numLocks;
+    int              writerThreadId;
+    int              pendingReaders;
+    int              pendingWriters;
+    void*            reserved[4];  /* for future extensibility */
+} pthread_rwlock_t;
+
+#define PTHREAD_RWLOCK_INITIALIZER  { PTHREAD_MUTEX_INITIALIZER, 0, NULL, 0, 0 }
+
+int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
+int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr);
+int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int  pshared);
+int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *attr, int *pshared);
+
+int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
+int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
+
+int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
+int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
+int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, const struct timespec *abs_timeout);
+
+int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
+int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
+int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, const struct timespec *abs_timeout);
+
+int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
+
+
 int pthread_key_create(pthread_key_t *key, void (*destructor_function)(void *));
 int pthread_key_delete (pthread_key_t);
 int pthread_setspecific(pthread_key_t key, const void *value);
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 41e8d26..5a991ac 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -135,7 +135,7 @@
 extern int    ptsname_r(int, char*, size_t);
 extern int    getpt(void);
 
-static __inline__ int grantpt(int __fd)
+static __inline__ int grantpt(int __fd __attribute((unused)))
 {
   (void)__fd;
   return 0;     /* devpts does this all for us! */
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index fe7033d..de1dc09 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -371,6 +371,14 @@
 
 #define	__link_set_entry(set, idx)	(__link_set_begin(set)[idx])
 
+/*
+ * Some of the recend FreeBSD sources used in Bionic need this.
+ * Originally, this is used to embed the rcs versions of each source file
+ * in the generated binary. We certainly don't want this in Bionic.
+ */
+#define	__FBSDID(s)	struct __hack
+
+
 #define  __BIONIC__   1
 
 #endif /* !_SYS_CDEFS_H_ */
diff --git a/libc/include/sys/linux-syscalls.h b/libc/include/sys/linux-syscalls.h
index 6e373e0..5f03863 100644
--- a/libc/include/sys/linux-syscalls.h
+++ b/libc/include/sys/linux-syscalls.h
@@ -126,6 +126,7 @@
 #define __NR_init_module                  (__NR_SYSCALL_BASE + 128)
 #define __NR_delete_module                (__NR_SYSCALL_BASE + 129)
 #define __NR_syslog                       (__NR_SYSCALL_BASE + 103)
+#define __NR_sysinfo                      (__NR_SYSCALL_BASE + 116)
 #define __NR_futex                        (__NR_SYSCALL_BASE + 240)
 #define __NR_poll                         (__NR_SYSCALL_BASE + 168)
 
diff --git a/libc/include/sys/linux-unistd.h b/libc/include/sys/linux-unistd.h
index b0e7822..27db2a9 100644
--- a/libc/include/sys/linux-unistd.h
+++ b/libc/include/sys/linux-unistd.h
@@ -192,6 +192,7 @@
 int              init_module (void *, unsigned long, const char *);
 int              delete_module (const char*, unsigned int);
 int              klogctl (int, char *, int);
+int              sysinfo (struct sysinfo *);
 int              futex (void *, int, int, void *, void *, int);
 int              epoll_create (int size);
 int              epoll_ctl (int epfd, int op, int fd, struct epoll_event *event);
diff --git a/libc/include/termio.h b/libc/include/termio.h
new file mode 100644
index 0000000..99d3630
--- /dev/null
+++ b/libc/include/termio.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+/* All definitions related to termio are in Linux kernel headers
+ * that are already included by <termios.h>
+ */
+#include <termios.h>
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index b4f1dda..7554198 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -124,6 +124,7 @@
 extern int chown(const char *, uid_t, gid_t);
 extern int fchown(int, uid_t, gid_t);
 extern int lchown(const char *, uid_t, gid_t);
+extern int truncate(const char *, off_t);
 extern char *getcwd(char *, size_t);
 
 extern int sync(void);
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 97e1b5c..df456ef 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -70,9 +70,9 @@
     WC_TYPE_MAX
 } wctype_t;
 
-#define  WCHAR_MAX   255
-#define  WCHAR_MIN   0
-#define  WEOF        (-1)
+#define  WCHAR_MAX   INT_MAX
+#define  WCHAR_MIN   INT_MIN
+#define  WEOF        ((wchar_t)(-1))
 
 extern wint_t            btowc(int);
 extern int               fwprintf(FILE *, const wchar_t *, ...);
diff --git a/libc/private/bionic_atomic_inline.h b/libc/private/bionic_atomic_inline.h
new file mode 100644
index 0000000..95766e1
--- /dev/null
+++ b/libc/private/bionic_atomic_inline.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010 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_ATOMIC_INLINE_H
+#define BIONIC_ATOMIC_INLINE_H
+
+/*
+ * Inline declarations and macros for some special-purpose atomic
+ * operations.  These are intended for rare circumstances where a
+ * memory barrier needs to be issued inline rather than as a function
+ * call.
+ *
+ * Most code should not use these.
+ *
+ * Anything that does include this file must set ANDROID_SMP to either
+ * 0 or 1, indicating compilation for UP or SMP, respectively.
+ *
+ * Macros defined in this header:
+ *
+ * void ANDROID_MEMBAR_FULL(void)
+ *   Full memory barrier.  Provides a compiler reordering barrier, and
+ *   on SMP systems emits an appropriate instruction.
+ */
+
+#if !defined(ANDROID_SMP)
+# error "Must define ANDROID_SMP before including atomic-inline.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Define the full memory barrier for an SMP system.  This is
+ * platform-specific.
+ */
+
+#ifdef __arm__
+#include <machine/cpu-features.h>
+
+/*
+ * For ARMv6K we need to issue a specific MCR instead of the DMB, since
+ * that wasn't added until v7.  For anything older, SMP isn't relevant.
+ * Since we don't have an ARMv6K to test with, we're not going to deal
+ * with that now.
+ *
+ * The DMB instruction is found in the ARM and Thumb2 instruction sets.
+ * This will fail on plain 16-bit Thumb.
+ */
+#if defined(__ARM_HAVE_DMB)
+# define _ANDROID_MEMBAR_FULL_SMP() \
+    do { __asm__ __volatile__ ("dmb" ::: "memory"); } while (0)
+#else
+# define _ANDROID_MEMBAR_FULL_SMP()  ARM_SMP_defined_but_no_DMB()
+#endif
+
+#elif defined(__i386__) || defined(__x86_64__)
+/*
+ * For recent x86, we can use the SSE2 mfence instruction.
+ */
+# define _ANDROID_MEMBAR_FULL_SMP() \
+    do { __asm__ __volatile__ ("mfence" ::: "memory"); } while (0)
+
+#else
+/*
+ * Implementation not defined for this platform.  Hopefully we're building
+ * in uniprocessor mode.
+ */
+# define _ANDROID_MEMBAR_FULL_SMP()  SMP_barrier_not_defined_for_platform()
+#endif
+
+
+/*
+ * Full barrier.  On uniprocessors this is just a compiler reorder barrier,
+ * which ensures that the statements appearing above the barrier in the C/C++
+ * code will be issued after the statements appearing below the barrier.
+ *
+ * For SMP this also includes a memory barrier instruction.  On an ARM
+ * CPU this means that the current core will flush pending writes, wait
+ * for pending reads to complete, and discard any cached reads that could
+ * be stale.  Other CPUs may do less, but the end result is equivalent.
+ */
+#if ANDROID_SMP != 0
+# define ANDROID_MEMBAR_FULL() _ANDROID_MEMBAR_FULL_SMP()
+#else
+# define ANDROID_MEMBAR_FULL() \
+    do { __asm__ __volatile__ ("" ::: "memory"); } while (0)
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // BIONIC_ATOMIC_INLINE_H
diff --git a/libc/private/bionic_futex.h b/libc/private/bionic_futex.h
new file mode 100644
index 0000000..eb49fb7
--- /dev/null
+++ b/libc/private/bionic_futex.h
@@ -0,0 +1,57 @@
+/*
+ * 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 _BIONIC_FUTEX_H
+#define _BIONIC_FUTEX_H
+
+#include <linux/futex.h>
+
+extern int __futex_wait(volatile void *ftx, int val, const struct timespec *timeout);
+extern int __futex_wake(volatile void *ftx, int count);
+
+extern int __futex_syscall3(volatile void *ftx, int op, int val);
+extern int __futex_syscall4(volatile void *ftx, int op, int val, const struct timespec *timeout);
+
+#ifndef FUTEX_PRIVATE_FLAG
+#define FUTEX_PRIVATE_FLAG  128
+#endif
+
+#ifndef FUTEX_WAIT_PRIVATE
+#define FUTEX_WAIT_PRIVATE  (FUTEX_WAIT|FUTEX_PRIVATE_FLAG)
+#endif
+
+#ifndef FUTEX_WAKE_PRIVATE
+#define FUTEX_WAKE_PRIVATE  (FUTEX_WAKE|FUTEX_PRIVATE_FLAG)
+#endif
+
+/* Like __futex_wait/wake, but take an additionnal 'pshared' argument.
+ * when non-0, this will use normal futexes. Otherwise, private futexes.
+ */
+extern int  __futex_wake_ex(volatile void *ftx, int pshared, int val);
+extern int  __futex_wait_ex(volatile void *ftx, int pshared, int val, const struct timespec *timeout);
+
+#endif /* _BIONIC_FUTEX_H */
diff --git a/libc/stdlib/wchar.c b/libc/stdlib/wchar.c
index 02947d4..1480212 100644
--- a/libc/stdlib/wchar.c
+++ b/libc/stdlib/wchar.c
@@ -29,6 +29,7 @@
 #include <ctype.h>
 #include <string.h>
 #include <stdlib.h>
+#include <errno.h>
 
 /* stubs for wide-char functions */
 wint_t  btowc(int c)
@@ -71,28 +72,25 @@
 
 int vwprintf(const wchar_t *format, va_list arg)
 {
-    return vprintf((const char*)format, arg);
+    return vfwprintf(stdout, format, arg);
 }
 
 int vfwprintf(FILE *stream, const wchar_t *format, va_list arg)
 {
-    return vfprintf(stream, (const char*)format, arg);
+    errno = ENOTSUP;
+    return -1;
 }
 
 int vswprintf(wchar_t *s, size_t n, const wchar_t *format, va_list arg)
 {
-    return vsnprintf( (char*)s, n, (const char*)format, arg );
+    errno = ENOTSUP;
+    return -1;
 }
 
 int fwscanf(FILE *stream, const wchar_t *format, ... )
 {
-    va_list  args;
-    int      result;
-
-    va_start (args, format);
-    result = vfscanf( stream, (const char*)format, args );
-    va_end (args);
-    return result;
+    errno = ENOTSUP;
+    return -1;
 }
 
 int wscanf(const wchar_t *format, ... )
@@ -101,20 +99,15 @@
     int      result;
 
     va_start (args, format);
-    result = vscanf( (const char*)format, args );
+    result = fwscanf(stdout, format, args );
     va_end (args);
     return result;
 }
 
 int swscanf(const wchar_t *s, const wchar_t *format, ... )
 {
-    va_list  args;
-    int      result;
-
-    va_start (args, format);
-    result = vscanf( (const char*)format, args );
-    va_end (args);
-    return result;
+    errno = ENOTSUP;
+    return -1;
 }
 
 int iswalnum(wint_t wc) { return isalnum(wc); }
@@ -150,7 +143,7 @@
 
 wint_t fgetwc(FILE *stream)
 {
-    return fgetc(stream);
+    return (wint_t)fgetc(stream);
 }
 
 wchar_t *fgetws(wchar_t *ws, int n, FILE *stream)
@@ -264,71 +257,11 @@
     return 1;
 }
 
-wchar_t *wcscat(wchar_t *ws1, const wchar_t *ws2)
-{
-    return (wchar_t*) strcat((char*)ws1, (const char*)ws2);
-}
-
-wchar_t *wcschr(const wchar_t *ws, wchar_t wc)
-{
-    return (wchar_t*)strchr( (const char*)ws, (char)wc );
-}
-
-int wcscmp(const wchar_t *ws1, const wchar_t *ws2)
-{
-    return strcmp( (const char*)ws1, (const char*)ws2 );
-}
-
-int wcscoll(const wchar_t *ws1, const wchar_t *ws2)
-{
-    return strcmp( (const char*)ws1, (const char*)ws2 );
-}
-
-wchar_t *wcscpy(wchar_t *ws1, const wchar_t *ws2)
-{
-    return (wchar_t*) strcpy( (char*)ws1, (const char*)ws2 );
-}
-
-size_t wcscspn(const wchar_t *ws1, const wchar_t *ws2)
-{
-    return strspn( (const char*)ws1, (const char*)ws2 );
-}
-
-size_t wcslen(const wchar_t *ws)
-{
-    return (size_t)strlen( (const char*)ws );
-}
-
 size_t wcsftime(wchar_t *wcs, size_t maxsize, const wchar_t *format,  const struct tm *timptr)
 {
     return strftime( (char*)wcs, maxsize, (const char*)format, timptr );
 }
 
-wchar_t *wcsncat(wchar_t *ws1, const wchar_t *ws2, size_t n)
-{
-    return (wchar_t*) strncat( (char*)ws1, (const char*)ws2, n );
-}
-
-int wcsncmp(const wchar_t *ws1, const wchar_t *ws2, size_t n)
-{
-    return strncmp( (const char*)ws1, (const char*)ws2, n );
-}
-
-wchar_t *wcsncpy(wchar_t *ws1, const wchar_t *ws2, size_t n)
-{
-    return (wchar_t*) strncpy( (char*)ws1, (const char*)ws2, n );
-}
-
-wchar_t *wcspbrk(const wchar_t *ws1, const wchar_t *ws2)
-{
-    return (wchar_t*) strpbrk( (const char*)ws1, (const char*)ws2 );
-}
-
-wchar_t *wcsrchr(const wchar_t *ws, wchar_t wc)
-{
-    return (wchar_t*) strrchr( (const char*)ws, (int)wc );
-}
-
 size_t wcsrtombs(char *dst, const wchar_t **src, size_t len, mbstate_t *ps)
 {
     const char*  s = (const char*)*src;
@@ -349,26 +282,11 @@
     return wcsrtombs(dst, &src, len, NULL);
 }
 
-size_t wcsspn(const wchar_t *ws1, const wchar_t *ws2)
-{
-    return strspn( (const char*)ws1, (const char*)ws2 );
-}
-
-wchar_t *wcsstr(const wchar_t *ws1, const wchar_t *ws2)
-{
-    return (wchar_t*) strstr( (const char*)ws1, (const char*)ws2 );
-}
-
 double wcstod(const wchar_t *nptr, wchar_t **endptr)
 {
     return strtod( (const char*)nptr, (char**)endptr );
 }
 
-wchar_t *wcstok(wchar_t *ws1, const wchar_t *ws2, wchar_t **ptr)
-{
-    return (wchar_t*) strtok_r( (char*)ws1, (const char*)ws2, (char**)ptr );
-}
-
 long int wcstol(const wchar_t *nptr, wchar_t **endptr, int base)
 {
     return strtol( (const char*)nptr, (char**)endptr, base );
@@ -384,11 +302,6 @@
     return (wchar_t*) strstr( (const char*)ws1, (const char*)ws2 );
 }
 
-int wcswidth(const wchar_t *pwcs, size_t n)
-{
-    return  strnlen( (const char*)pwcs, n );
-}
-
 size_t wcsxfrm(wchar_t *ws1, const wchar_t *ws2, size_t n)
 {
     memcpy( (char*)ws1, (const char*)ws2, n );
@@ -421,28 +334,3 @@
 {
     return (wc > 0);
 }
-
-wchar_t *wmemchr(const wchar_t *ws, wchar_t wc, size_t n)
-{
-    return (wchar_t*)  memchr( (const char*)ws, (int)wc, n );
-}
-
-int wmemcmp(const wchar_t *ws1, const wchar_t *ws2, size_t n)
-{
-    return  memcmp( (const char*)ws1, (const char*)ws2, n );
-}
-
-wchar_t *wmemcpy(wchar_t *ws1, const wchar_t *ws2, size_t n)
-{
-    return (wchar_t*) memcpy( (char*)ws1, (const char*)ws2, n );
-}
-
-wchar_t *wmemmove(wchar_t *ws1, const wchar_t *ws2, size_t n)
-{
-    return (wchar_t*)memmove( (char*)ws1, (const char*)ws2, n );
-}
-
-wchar_t *wmemset(wchar_t *ws, wchar_t wc, size_t n)
-{
-    return (wchar_t*) memset( (char*)ws, (int)wc, n );
-}
diff --git a/libc/wchar/wcpcpy.c b/libc/wchar/wcpcpy.c
new file mode 100644
index 0000000..df63d72
--- /dev/null
+++ b/libc/wchar/wcpcpy.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1999
+ *	David E. O'Brien
+ * Copyright (c) 1988, 1993
+ *	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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcpy.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcpcpy(wchar_t * __restrict to, const wchar_t * __restrict from)
+{
+
+	for (; (*to = *from); ++from, ++to);
+	return(to);
+}
diff --git a/libc/wchar/wcpncpy.c b/libc/wchar/wcpncpy.c
new file mode 100644
index 0000000..87b361c
--- /dev/null
+++ b/libc/wchar/wcpncpy.c
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcpncpy(wchar_t * __restrict dst, const wchar_t * __restrict src, size_t n)
+{
+
+	for (; n--; dst++, src++) {
+		if (!(*dst = *src)) {
+			wchar_t *ret = dst;
+			while (n--)
+				*++dst = L'\0';
+			return (ret);
+		}
+	}
+	return (dst);
+}
diff --git a/libc/wchar/wcscasecmp.c b/libc/wchar/wcscasecmp.c
new file mode 100644
index 0000000..0143543
--- /dev/null
+++ b/libc/wchar/wcscasecmp.c
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+#include <wctype.h>
+
+int
+wcscasecmp(const wchar_t *s1, const wchar_t *s2)
+{
+	wchar_t c1, c2;
+
+	for (; *s1; s1++, s2++) {
+		c1 = towlower(*s1);
+		c2 = towlower(*s2);
+		if (c1 != c2)
+			return ((int)c1 - c2);
+	}
+	return (-*s2);
+}
diff --git a/libc/wchar/wcscat.c b/libc/wchar/wcscat.c
new file mode 100644
index 0000000..7ae4e80
--- /dev/null
+++ b/libc/wchar/wcscat.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c)1999 Citrus 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcscat.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcscat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcscat(wchar_t * __restrict s1, const wchar_t * __restrict s2)
+{
+	wchar_t *cp;
+
+	cp = s1;
+	while (*cp != L'\0')
+		cp++;
+	while ((*cp++ = *s2++) != L'\0')
+		;
+
+	return (s1);
+}
diff --git a/libc/wchar/wcschr.c b/libc/wchar/wcschr.c
new file mode 100644
index 0000000..1df1fe6
--- /dev/null
+++ b/libc/wchar/wcschr.c
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcschr(const wchar_t *s, wchar_t c)
+{
+
+	while (*s != c && *s != L'\0')
+		s++;
+	if (*s == c)
+		return ((wchar_t *)s);
+	return (NULL);
+}
diff --git a/libc/wchar/wcscmp.c b/libc/wchar/wcscmp.c
new file mode 100644
index 0000000..2d48914
--- /dev/null
+++ b/libc/wchar/wcscmp.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcmp.c	8.1 (Berkeley) 6/4/93";
+#if 0
+__RCSID("$NetBSD: wcscmp.c,v 1.3 2001/01/05 12:13:12 itojun Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+/*
+ * Compare strings.
+ */
+int
+wcscmp(const wchar_t *s1, const wchar_t *s2)
+{
+
+	while (*s1 == *s2++)
+		if (*s1++ == '\0')
+			return (0);
+	/* XXX assumes wchar_t = int */
+	return (*(const unsigned int *)s1 - *(const unsigned int *)--s2);
+}
diff --git a/libc/wchar/wcscoll.c b/libc/wchar/wcscoll.c
new file mode 100644
index 0000000..6e843b7
--- /dev/null
+++ b/libc/wchar/wcscoll.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2010 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 <wchar.h>
+/*
+ * Compare strings using the current locale.  Since Bionic really does not
+ * support locales, we assume we always use the C locale and call wcscmp.
+ *
+ * This function is provided to make libstdc++-v3 usable.
+ */
+int
+wcscoll(const wchar_t *ws1, const wchar_t *ws2)
+{
+    return wcscmp(ws1, ws2);
+}
diff --git a/libc/wchar/wcscpy.c b/libc/wchar/wcscpy.c
new file mode 100644
index 0000000..0c6e1f2
--- /dev/null
+++ b/libc/wchar/wcscpy.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c)1999 Citrus 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcscpy.c,v 1.2 2000/12/21 04:51:09 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcscpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcscpy(wchar_t * __restrict s1, const wchar_t * __restrict s2)
+{
+	wchar_t *cp;
+
+	cp = s1;
+	while ((*cp++ = *s2++) != L'\0')
+		;
+
+	return (s1);
+}
diff --git a/libc/wchar/wcscspn.c b/libc/wchar/wcscspn.c
new file mode 100644
index 0000000..7729dc8
--- /dev/null
+++ b/libc/wchar/wcscspn.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c)1999 Citrus 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcscspn.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcscspn.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+size_t
+wcscspn(const wchar_t *s, const wchar_t *set)
+{
+	const wchar_t *p;
+	const wchar_t *q;
+
+	p = s;
+	while (*p) {
+		q = set;
+		while (*q) {
+			if (*p == *q)
+				goto done;
+			q++;
+		}
+		p++;
+	}
+
+done:
+	return (p - s);
+}
diff --git a/libc/wchar/wcsdup.c b/libc/wchar/wcsdup.c
new file mode 100644
index 0000000..1e5db92
--- /dev/null
+++ b/libc/wchar/wcsdup.c
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2005 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <wchar.h>
+
+wchar_t *
+wcsdup(const wchar_t *s)
+{
+	wchar_t *copy;
+	size_t len;
+
+	len = wcslen(s) + 1;
+	if ((copy = malloc(len * sizeof(wchar_t))) == NULL)
+		return (NULL);
+	return (wmemcpy(copy, s, len));
+}
diff --git a/libc/wchar/wcslcat.c b/libc/wchar/wcslcat.c
new file mode 100644
index 0000000..f5f1e1e
--- /dev/null
+++ b/libc/wchar/wcslcat.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ *	from OpenBSD: strlcat.c,v 1.3 2000/11/24 11:10:02 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslcat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <wchar.h>
+
+/*
+ * Appends src to string dst of size siz (unlike wcsncat, siz is the
+ * full size of dst, not space left).  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns wcslen(initial dst) + wcslen(src); if retval >= siz,
+ * truncation occurred.
+ */
+size_t
+wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
+{
+	wchar_t *d = dst;
+	const wchar_t *s = src;
+	size_t n = siz;
+	size_t dlen;
+
+	/* Find the end of dst and adjust bytes left but don't go past end */
+	while (*d != '\0' && n-- != 0)
+		d++;
+	dlen = d - dst;
+	n = siz - dlen;
+
+	if (n == 0)
+		return(dlen + wcslen(s));
+	while (*s != '\0') {
+		if (n != 1) {
+			*d++ = *s;
+			n--;
+		}
+		s++;
+	}
+	*d = '\0';
+
+	return(dlen + (s - src));	/* count does not include NUL */
+}
diff --git a/libc/wchar/wcslcpy.c b/libc/wchar/wcslcpy.c
new file mode 100644
index 0000000..b104a06
--- /dev/null
+++ b/libc/wchar/wcslcpy.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ *	from OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslcpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <wchar.h>
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns wcslen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
+{
+	wchar_t *d = dst;
+	const wchar_t *s = src;
+	size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0 && --n != 0) {
+		do {
+			if ((*d++ = *s++) == 0)
+				break;
+		} while (--n != 0);
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
diff --git a/libc/wchar/wcslen.c b/libc/wchar/wcslen.c
new file mode 100644
index 0000000..ca3004e
--- /dev/null
+++ b/libc/wchar/wcslen.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c)1999 Citrus 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcslen.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslen.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+size_t
+wcslen(const wchar_t *s)
+{
+	const wchar_t *p;
+
+	p = s;
+	while (*p)
+		p++;
+
+	return p - s;
+}
diff --git a/libc/wchar/wcsncasecmp.c b/libc/wchar/wcsncasecmp.c
new file mode 100644
index 0000000..a42d98c
--- /dev/null
+++ b/libc/wchar/wcsncasecmp.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+#include <wctype.h>
+
+int
+wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n)
+{
+	wchar_t c1, c2;
+
+	if (n == 0)
+		return (0);
+	for (; *s1; s1++, s2++) {
+		c1 = towlower(*s1);
+		c2 = towlower(*s2);
+		if (c1 != c2)
+			return ((int)c1 - c2);
+		if (--n == 0)
+			return (0);
+	}
+	return (-*s2);
+}
diff --git a/libc/wchar/wcsncat.c b/libc/wchar/wcsncat.c
new file mode 100644
index 0000000..44f1ff9
--- /dev/null
+++ b/libc/wchar/wcsncat.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c)1999 Citrus 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcsncat.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcsncat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcsncat(wchar_t * __restrict s1, const wchar_t * __restrict s2, size_t n)
+{
+	wchar_t *p;
+	wchar_t *q;
+	const wchar_t *r;
+
+	p = s1;
+	while (*p)
+		p++;
+	q = p;
+	r = s2;
+	while (*r && n) {
+		*q++ = *r++;
+		n--;
+	}
+	*q = '\0';
+	return s1;
+}
diff --git a/libc/wchar/wcsncmp.c b/libc/wchar/wcsncmp.c
new file mode 100644
index 0000000..86d7a51
--- /dev/null
+++ b/libc/wchar/wcsncmp.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strncmp.c	8.1 (Berkeley) 6/4/93";
+__RCSID("$NetBSD: wcsncmp.c,v 1.3 2001/01/05 12:13:13 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+int
+wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n)
+{
+
+	if (n == 0)
+		return (0);
+	do {
+		if (*s1 != *s2++) {
+			/* XXX assumes wchar_t = int */
+			return (*(const unsigned int *)s1 -
+			    *(const unsigned int *)--s2);
+		}
+		if (*s1++ == 0)
+			break;
+	} while (--n != 0);
+	return (0);
+}
diff --git a/libc/wchar/wcsncpy.c b/libc/wchar/wcsncpy.c
new file mode 100644
index 0000000..00d986b
--- /dev/null
+++ b/libc/wchar/wcsncpy.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strncpy.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+/*
+ * Copy src to dst, truncating or null-padding to always copy n bytes.
+ * Return dst.
+ */
+wchar_t *
+wcsncpy(wchar_t * __restrict dst, const wchar_t * __restrict src, size_t n)
+{
+	if (n != 0) {
+		wchar_t *d = dst;
+		const wchar_t *s = src;
+
+		do {
+			if ((*d++ = *s++) == L'\0') {
+				/* NUL pad the remaining n-1 bytes */
+				while (--n != 0)
+					*d++ = L'\0';
+				break;
+			}
+		} while (--n != 0);
+	}
+	return (dst);
+}
diff --git a/libc/wchar/wcsnlen.c b/libc/wchar/wcsnlen.c
new file mode 100644
index 0000000..f03cf76
--- /dev/null
+++ b/libc/wchar/wcsnlen.c
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+size_t
+wcsnlen(const wchar_t *s, size_t maxlen)
+{
+	size_t len;
+
+	for (len = 0; len < maxlen; len++, s++) {
+		if (!*s)
+			break;
+	}
+	return (len);
+}
diff --git a/libc/wchar/wcspbrk.c b/libc/wchar/wcspbrk.c
new file mode 100644
index 0000000..2ff71ba
--- /dev/null
+++ b/libc/wchar/wcspbrk.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c)1999 Citrus 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcspbrk.c,v 1.2 2000/12/21 05:07:25 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcspbrk.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcspbrk(const wchar_t *s, const wchar_t *set)
+{
+	const wchar_t *p;
+	const wchar_t *q;
+
+	p = s;
+	while (*p) {
+		q = set;
+		while (*q) {
+			if (*p == *q) {
+				/* LINTED interface specification */
+				return (wchar_t *)p;
+			}
+			q++;
+		}
+		p++;
+	}
+	return NULL;
+}
diff --git a/libc/wchar/wcsrchr.c b/libc/wchar/wcsrchr.c
new file mode 100644
index 0000000..37c81ec
--- /dev/null
+++ b/libc/wchar/wcsrchr.c
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcsrchr(const wchar_t *s, wchar_t c)
+{
+	const wchar_t *last;
+
+	last = NULL;
+	for (;;) {
+		if (*s == c)
+			last = s;
+		if (*s == L'\0')
+			break;
+		s++;
+	}
+
+	return ((wchar_t *)last);
+}
diff --git a/libc/wchar/wcsspn.c b/libc/wchar/wcsspn.c
new file mode 100644
index 0000000..6569206
--- /dev/null
+++ b/libc/wchar/wcsspn.c
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c)1999 Citrus 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wcsspn.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcsspn.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+size_t
+wcsspn(const wchar_t *s, const wchar_t *set)
+{
+	const wchar_t *p;
+	const wchar_t *q;
+
+	p = s;
+	while (*p) {
+		q = set;
+		while (*q) {
+			if (*p == *q)
+				break;
+			q++;
+		}
+		if (!*q)
+			goto done;
+		p++;
+	}
+
+done:
+	return (p - s);
+}
diff --git a/libc/wchar/wcsstr.c b/libc/wchar/wcsstr.c
new file mode 100644
index 0000000..a9dc27b
--- /dev/null
+++ b/libc/wchar/wcsstr.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strstr.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+/*
+ * Find the first occurrence of find in s.
+ */
+wchar_t *
+wcsstr(const wchar_t * __restrict s, const wchar_t * __restrict find)
+{
+	wchar_t c, sc;
+	size_t len;
+
+	if ((c = *find++) != L'\0') {
+		len = wcslen(find);
+		do {
+			do {
+				if ((sc = *s++) == L'\0')
+					return (NULL);
+			} while (sc != c);
+		} while (wcsncmp(s, find, len) != 0);
+		s--;
+	}
+	return ((wchar_t *)s);
+}
diff --git a/libc/wchar/wcstok.c b/libc/wchar/wcstok.c
new file mode 100644
index 0000000..5a77117
--- /dev/null
+++ b/libc/wchar/wcstok.c
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 1998 Softweyr LLC.  All rights reserved.
+ *
+ * strtok_r, from Berkeley strtok
+ * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+ *
+ * Copyright (c) 1988, 1993
+ *	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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notices, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University 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 SOFTWEYR LLC, THE REGENTS 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 SOFTWEYR LLC, THE
+ * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcstok(wchar_t * __restrict s, const wchar_t * __restrict delim,
+    wchar_t ** __restrict last)
+{
+	const wchar_t *spanp;
+	wchar_t *tok;
+	wchar_t c, sc;
+
+	if (s == NULL && (s = *last) == NULL)
+		return (NULL);
+
+	/*
+	 * Skip (span) leading delimiters (s += wcsspn(s, delim), sort of).
+	 */
+cont:
+	c = *s++;
+	for (spanp = delim; (sc = *spanp++) != L'\0';) {
+		if (c == sc)
+			goto cont;
+	}
+
+	if (c == L'\0') {	/* no non-delimiter characters */
+		*last = NULL;
+		return (NULL);
+	}
+	tok = s - 1;
+
+	/*
+	 * Scan token (scan for delimiters: s += wcscspn(s, delim), sort of).
+	 * Note that delim must have one NUL; we stop if we see that, too.
+	 */
+	for (;;) {
+		c = *s++;
+		spanp = delim;
+		do {
+			if ((sc = *spanp++) == c) {
+				if (c == L'\0')
+					s = NULL;
+				else
+					s[-1] = L'\0';
+				*last = s;
+				return (tok);
+			}
+		} while (sc != L'\0');
+	}
+	/* NOTREACHED */
+}
diff --git a/libc/wchar/wcswidth.c b/libc/wchar/wcswidth.c
new file mode 100644
index 0000000..b142074
--- /dev/null
+++ b/libc/wchar/wcswidth.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+int
+wcswidth(const wchar_t *pwcs, size_t n)
+{
+	wchar_t wc;
+	int len, l;
+
+	len = 0;
+	while (n-- > 0 && (wc = *pwcs++) != L'\0') {
+		if ((l = wcwidth(wc)) < 0)
+			return (-1);
+		len += l;
+	}
+	return (len);
+}
+
diff --git a/libc/wchar/wcsxfrm.c b/libc/wchar/wcsxfrm.c
new file mode 100644
index 0000000..042ea56
--- /dev/null
+++ b/libc/wchar/wcsxfrm.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
+ *		at Electronni Visti IA, Kiev, Ukraine.
+ *			All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 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 DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR 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 <wchar.h>
+
+/*
+ * Placeholder wcsxfrm() implementation. See wcscoll.c for a description of
+ * the logic used.
+ */
+size_t
+wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len)
+{
+    int prim, sec, l;
+    size_t slen;
+    char *mbsrc, *s, *ss;
+
+    if (*src == L'\0') {
+        if (len != 0)
+            *dest = L'\0';
+        return (0);
+    }
+
+    slen = wcslen(src);
+    if (len > 0) {
+        if (slen < len)
+            wcscpy(dest, src);
+        else {
+            wcsncpy(dest, src, len - 1);
+            dest[len - 1] = L'\0';
+        }
+    }
+    return (slen);
+}
diff --git a/libc/wchar/wmemchr.c b/libc/wchar/wmemchr.c
new file mode 100644
index 0000000..cab89c9
--- /dev/null
+++ b/libc/wchar/wmemchr.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c)1999 Citrus 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wmemchr.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemchr.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t	*
+wmemchr(const wchar_t *s, wchar_t c, size_t n)
+{
+	size_t i;
+
+	for (i = 0; i < n; i++) {
+		if (*s == c) {
+			/* LINTED const castaway */
+			return (wchar_t *)s;
+		}
+		s++;
+	}
+	return NULL;
+}
diff --git a/libc/wchar/wmemcmp.c b/libc/wchar/wmemcmp.c
new file mode 100644
index 0000000..fdb1f98
--- /dev/null
+++ b/libc/wchar/wmemcmp.c
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c)1999 Citrus 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wmemcmp.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemcmp.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+int
+wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n)
+{
+	size_t i;
+
+	for (i = 0; i < n; i++) {
+		if (*s1 != *s2) {
+			/* wchar might be unsigned */
+			return *s1 > *s2 ? 1 : -1; 
+		}
+		s1++;
+		s2++;
+	}
+	return 0;
+}
diff --git a/libc/wchar/wmemcpy.c b/libc/wchar/wmemcpy.c
new file mode 100644
index 0000000..c10770c
--- /dev/null
+++ b/libc/wchar/wmemcpy.c
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c)1999 Citrus 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wmemcpy.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemcpy.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+#include <wchar.h>
+
+wchar_t *
+wmemcpy(wchar_t * __restrict d, const wchar_t * __restrict s, size_t n)
+{
+	return (wchar_t *)memcpy(d, s, n * sizeof(wchar_t));
+}
diff --git a/libc/wchar/wmemmove.c b/libc/wchar/wmemmove.c
new file mode 100644
index 0000000..05cfd10
--- /dev/null
+++ b/libc/wchar/wmemmove.c
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c)1999 Citrus 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wmemmove.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemmove.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+#include <wchar.h>
+
+wchar_t *
+wmemmove(wchar_t *d, const wchar_t *s, size_t n)
+{
+	return (wchar_t *)memmove(d, s, n * sizeof(wchar_t));
+}
diff --git a/libc/wchar/wmemset.c b/libc/wchar/wmemset.c
new file mode 100644
index 0000000..0e96356
--- /dev/null
+++ b/libc/wchar/wmemset.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c)1999 Citrus 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	citrus Id: wmemset.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemset.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t	*
+wmemset(wchar_t *s, wchar_t c, size_t n)
+{
+	size_t i;
+	wchar_t *p;
+
+	p = (wchar_t *)s;
+	for (i = 0; i < n; i++) {
+		*p = c;
+		p++;
+	}
+	return s;
+}
diff --git a/libm/Android.mk b/libm/Android.mk
index fa73aff..28e8f33 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -3,6 +3,7 @@
 libm_common_src_files:= \
 	isinf.c  \
 	fpclassify.c \
+	sincos.c \
 	bsdsrc/b_exp.c \
 	bsdsrc/b_log.c \
 	bsdsrc/b_tgamma.c \
diff --git a/libm/include/math.h b/libm/include/math.h
index ef6a9e6..3b5660f 100644
--- a/libm/include/math.h
+++ b/libm/include/math.h
@@ -480,6 +480,13 @@
 #endif
 long double	truncl(long double);
 
+/* BIONIC: GLibc compatibility - required by the ARM toolchain */
+#ifdef _GNU_SOURCE
+void  sincos(double x, double *sin, double *cos);
+void  sincosf(float x, float *sin, float *cos);
+void  sincosl(long double x, long double *sin, long double *cos);
+#endif
+
 /* #endif */ /* __ISO_C_VISIBLE >= 1999 */
 __END_DECLS
 
diff --git a/libm/sincos.c b/libm/sincos.c
new file mode 100644
index 0000000..116b151
--- /dev/null
+++ b/libm/sincos.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2010 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ *
+ */
+#define _GNU_SOURCE 1
+#include <math.h>
+
+void  sincos(double x, double *psin, double *pcos)
+{
+    *psin = sin(x);
+    *pcos = cos(x);
+}
+
+void  sincosf(float x, float *psin, float *pcos)
+{
+    *psin = sinf(x);
+    *pcos = cosf(x);
+}
+
+void  sincosl(long double x, long double *psin, long double *pcos)
+{
+    *psin = sin(x);
+    *pcos = cos(x);
+}
diff --git a/libthread_db/include/thread_db.h b/libthread_db/include/thread_db.h
index 9c76d40..1b36cb2 100644
--- a/libthread_db/include/thread_db.h
+++ b/libthread_db/include/thread_db.h
@@ -10,6 +10,8 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+typedef void *psaddr_t;
+typedef pid_t lwpid_t;
 
 #define TD_THR_ANY_USER_FLAGS       0xffffffff
 #define TD_THR_LOWEST_PRIORITY      -20
@@ -67,6 +69,7 @@
 typedef struct
 {
     pid_t pid;
+    struct ps_prochandle *ph;
 } td_thragent_t;
 
 typedef struct
@@ -123,19 +126,37 @@
 extern "C"{
 #endif
 
-extern td_err_e td_ta_new(struct ps_prochandle const * proc_handle, td_thragent_t ** thread_agent);
+extern td_err_e td_ta_new(struct ps_prochandle * proc_handle, td_thragent_t ** thread_agent);
+
+extern td_err_e td_ta_delete(td_thragent_t * ta);
 
 extern td_err_e td_ta_set_event(td_thragent_t const * agent, td_thr_events_t * event);
 
 extern td_err_e td_ta_event_addr(td_thragent_t const * agent, td_event_e event, td_notify_t * notify);
 
+extern td_err_e td_ta_clear_event(const td_thragent_t * ta_arg,
+				  td_thr_events_t * event);
+
 extern td_err_e td_ta_event_getmsg(td_thragent_t const * agent, td_event_msg_t * event);
 
+extern td_err_e td_ta_map_lwp2thr(td_thragent_t const * agent, lwpid_t lwpid,
+				  td_thrhandle_t *th);
+
+extern td_err_e td_thr_get_info(td_thrhandle_t const * handle,
+				td_thrinfo_t * info);
+
+extern td_err_e td_thr_event_enable(td_thrhandle_t const * handle,
+				    td_event_e event);
+
 extern td_err_e td_ta_thr_iter(td_thragent_t const * agent, td_thr_iter_f * func, void * cookie,
                                td_thr_state_e state, int32_t prio, sigset_t * sigmask, uint32_t user_flags);
 
 extern char const ** td_symbol_list(void);
 
+extern td_err_e td_thr_tls_get_addr(const td_thrhandle_t * th,
+				    psaddr_t map_address, size_t offset,
+				    psaddr_t * address);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libthread_db/libthread_db.c b/libthread_db/libthread_db.c
index f1a78ac..2cf4d38 100644
--- a/libthread_db/libthread_db.c
+++ b/libthread_db/libthread_db.c
@@ -10,12 +10,7 @@
 #include <stdio.h>
 
 extern int ps_pglobal_lookup (void *, const char *obj, const char *name, void **sym_addr);
-
-struct ps_prochandle
-{
-    pid_t pid;
-};
-
+extern pid_t ps_getpid(struct ps_prochandle *ph);
 
 /*
  * This is the list of "special" symbols we care about whose addresses are
@@ -41,7 +36,7 @@
 
 
 td_err_e
-td_ta_new(struct ps_prochandle const * proc_handle, td_thragent_t ** agent_out)
+td_ta_new(struct ps_prochandle * proc_handle, td_thragent_t ** agent_out)
 {
     td_thragent_t * agent;
 
@@ -50,7 +45,8 @@
         return TD_MALLOC;
     }
 
-    agent->pid = proc_handle->pid;
+    agent->pid = ps_getpid(proc_handle);
+    agent->ph = proc_handle;
     *agent_out = agent;
 
     return TD_OK;
@@ -58,14 +54,28 @@
 
 
 td_err_e
+td_ta_delete(td_thragent_t * ta)
+{
+    free(ta);
+    // FIXME: anything else to do?
+    return TD_OK;
+}
+
+
+/* NOTE: not used by gdb 7.0 */
+
+td_err_e
 td_ta_set_event(td_thragent_t const * agent, td_thr_events_t * events)
 {
     return TD_OK;
 }
 
 
+/* NOTE: not used by gdb 7.0 */
 static td_thrhandle_t gEventMsgHandle;
 
+/* NOTE: not used by gdb 7.0 */
+
 static int
 _event_getmsg_helper(td_thrhandle_t const * handle, void * bkpt_addr)
 {
@@ -83,6 +93,8 @@
     return 0;
 }
 
+/* NOTE: not used by gdb 7.0 */
+
 td_err_e
 td_ta_event_getmsg(td_thragent_t const * agent, td_event_msg_t * event)
 {
@@ -107,6 +119,16 @@
 
 
 td_err_e
+td_ta_map_lwp2thr(td_thragent_t const * agent, lwpid_t lwpid,
+		  td_thrhandle_t *th)
+{
+    th->pid = ps_getpid(agent->ph);
+    th->tid = lwpid;
+    return TD_OK;
+}
+
+
+td_err_e
 td_thr_get_info(td_thrhandle_t const * handle, td_thrinfo_t * info)
 {
     info->ti_tid = handle->tid;
@@ -117,6 +139,8 @@
 }
 
 
+/* NOTE: not used by gdb 7.0 */
+
 td_err_e
 td_thr_event_enable(td_thrhandle_t const * handle, td_event_e event)
 {
@@ -125,6 +149,8 @@
 }
 
 
+/* NOTE: not used by gdb 7.0 */
+
 td_err_e
 td_ta_event_addr(td_thragent_t const * agent, td_event_e event, td_notify_t * notify_out)
 {
@@ -149,6 +175,15 @@
 
 
 td_err_e
+td_ta_clear_event(const td_thragent_t * ta_arg, td_thr_events_t * event)
+{
+    /* Given that gdb 7.0 doesn't use thread events,
+       there's nothing we need to do here.  */
+    return TD_OK;
+}
+
+
+td_err_e
 td_ta_thr_iter(td_thragent_t const * agent, td_thr_iter_f * func, void * cookie,
                td_thr_state_e state, int32_t prio, sigset_t * sigmask, uint32_t user_flags)
 {
@@ -170,8 +205,8 @@
             continue;
         }
         handle.tid = atoi(entry->d_name);
-        err = func(&handle, cookie);
-        if (err) {
+        if (func(&handle, cookie) != 0) {
+	    err = TD_DBERR;
             break;
         }
     }
@@ -181,3 +216,9 @@
     return err;
 }
 
+td_err_e
+td_thr_tls_get_addr(const td_thrhandle_t * th,
+		    psaddr_t map_address, size_t offset, psaddr_t * address)
+{
+    return TD_NOAPLIC; // FIXME: TODO
+}
diff --git a/linker/Android.mk b/linker/Android.mk
index 4647c8f..27a6677 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -60,7 +60,7 @@
 
 LOCAL_MODULE:= linker
 
-LOCAL_STATIC_LIBRARIES := libcutils libc_nomalloc
+LOCAL_STATIC_LIBRARIES := libc_nomalloc
 
 #LOCAL_FORCE_STATIC_EXECUTABLE := true # not necessary when not including BUILD_EXECUTABLE
 
diff --git a/linker/debugger.c b/linker/debugger.c
index 1bd3cc8..abb383c 100644
--- a/linker/debugger.c
+++ b/linker/debugger.c
@@ -37,7 +37,7 @@
 #include "linker.h"
 
 #include <sys/socket.h>
-#include <cutils/sockets.h>
+#include <sys/un.h>
 
 void notify_gdb_of_libraries();
 
@@ -46,6 +46,47 @@
         ret = (cond); \
     } while (ret < 0 && errno == EINTR)
 
+
+static int socket_abstract_client(const char *name, int type)
+{
+    struct sockaddr_un addr;
+    size_t namelen;
+    socklen_t alen;
+    int s, err;
+
+    namelen  = strlen(name);
+
+    // Test with length +1 for the *initial* '\0'.
+    if ((namelen + 1) > sizeof(addr.sun_path)) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    /* This is used for abstract socket namespace, we need
+     * an initial '\0' at the start of the Unix socket path.
+     *
+     * Note: The path in this case is *not* supposed to be
+     * '\0'-terminated. ("man 7 unix" for the gory details.)
+     */
+    memset (&addr, 0, sizeof addr);
+    addr.sun_family = AF_LOCAL;
+    addr.sun_path[0] = 0;
+    memcpy(addr.sun_path + 1, name, namelen);
+
+    alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
+
+    s = socket(AF_LOCAL, type, 0);
+    if(s < 0) return -1;
+
+    RETRY_ON_EINTR(err,connect(s, (struct sockaddr *) &addr, alen));
+    if (err < 0) {
+        close(s);
+        s = -1;
+    }
+
+    return s;
+}
+
 void debugger_signal_handler(int n)
 {
     unsigned tid;
@@ -55,8 +96,7 @@
     signal(SIGUSR1, SIG_IGN);
 
     tid = gettid();
-    s = socket_local_client("android:debuggerd",
-            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+    s = socket_abstract_client("android:debuggerd", SOCK_STREAM);
 
     if(s >= 0) {
         /* debugger knows our pid from the credentials on the