summaryrefslogtreecommitdiff
path: root/libpthread
diff options
context:
space:
mode:
authorVincent Ren-Wei Chen <vincentc@andestech.com>2017-01-17 07:31:24 +0100
committerWaldemar Brodkorb <wbx@openadk.org>2017-01-22 10:06:29 +0100
commit6af3332a4cbd1ffbc81f74759ef7c5e1a87d2e10 (patch)
tree4deae5f23fd1e2664f21c09dfb57fda799dffd10 /libpthread
parent82af21a60bc6e53dd92c1c140f20179d2ae4ad40 (diff)
nds32: add NPTL/TLS, *context function, libm changes and code cleanup
This commit includes following features. 1. Support NPTL/TLS 2. Add libm function which is used to handle FP rounding and excpetions (ex: fclrexcpt,fedisblxcpti,feenablxcpt... ) 3. Add *context function for operating user context (ex: setcontext,getcontext,makecontext... ) 4. Change the return flow from signal handler 5. Cleanup of old code The testsuite only has 2 errors, tst-cpuclock1 and tst-cputimer1, which are related to timing accuracy. (math and locale tests are disabled) Signed-off-by: Vincent Ren-Wei Chen <vincentc@andestech.com>
Diffstat (limited to 'libpthread')
-rw-r--r--libpthread/linuxthreads/sysdeps/nds32/pspinlock.c2
-rw-r--r--libpthread/linuxthreads/sysdeps/nds32/pt-machine.h2
-rw-r--r--libpthread/nptl/sysdeps/nds32/Makefile.arch16
-rw-r--r--libpthread/nptl/sysdeps/nds32/dl-tls.h59
-rw-r--r--libpthread/nptl/sysdeps/nds32/libc-dl-tlsdesc.S1
-rw-r--r--libpthread/nptl/sysdeps/nds32/pthread_spin_lock.c65
-rw-r--r--libpthread/nptl/sysdeps/nds32/pthread_spin_trylock.c26
-rw-r--r--libpthread/nptl/sysdeps/nds32/pthreaddef.h39
-rw-r--r--libpthread/nptl/sysdeps/nds32/tcb-offsets.sym12
-rw-r--r--libpthread/nptl/sysdeps/nds32/tls.h178
-rw-r--r--libpthread/nptl/sysdeps/nds32/tlsdesc.sym17
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile9
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile.arch12
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/pthreadtypes.h177
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/semaphore.h38
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/nds32/clone.S4
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/nds32/createthread.c22
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/nds32/fork.c27
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/nds32/lowlevellock.h323
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pt-raise.c18
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pthread_once.c92
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h273
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/nds32/vfork.S43
23 files changed, 1453 insertions, 2 deletions
diff --git a/libpthread/linuxthreads/sysdeps/nds32/pspinlock.c b/libpthread/linuxthreads/sysdeps/nds32/pspinlock.c
index f8adf07be..770a55ab3 100644
--- a/libpthread/linuxthreads/sysdeps/nds32/pspinlock.c
+++ b/libpthread/linuxthreads/sysdeps/nds32/pspinlock.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Andes Technology, Inc.
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
* Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
*/
diff --git a/libpthread/linuxthreads/sysdeps/nds32/pt-machine.h b/libpthread/linuxthreads/sysdeps/nds32/pt-machine.h
index 5bbb9e850..631c28491 100644
--- a/libpthread/linuxthreads/sysdeps/nds32/pt-machine.h
+++ b/libpthread/linuxthreads/sysdeps/nds32/pt-machine.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Andes Technology, Inc.
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
* Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
*/
diff --git a/libpthread/nptl/sysdeps/nds32/Makefile.arch b/libpthread/nptl/sysdeps/nds32/Makefile.arch
new file mode 100644
index 000000000..7eb852af1
--- /dev/null
+++ b/libpthread/nptl/sysdeps/nds32/Makefile.arch
@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng NPTL
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+ASFLAGS-dl-tlsdesc.S = -DNOT_IN_libc=1
+libc_arch_a_SSRC = libc-dl-tlsdesc.S
+
+CFLAGS-gen_tlsdesc.c = -S
+$(libpthread_arch_OUT)/gen_tlsdesc.c: $(libpthread_arch_DIR)/tlsdesc.sym | $(libpthread_arch_OUT)
+ $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@
+$(libpthread_arch_OUT)/gen_tlsdesc.s: $(libpthread_arch_OUT)/gen_tlsdesc.c | headers
+ $(compile.c)
+libpthread-generated-y += $(libpthread_arch_OUT)/gen_tlsdesc.s
+$(libpthread_arch_OUT)/tlsdesc.h: $(libpthread_arch_OUT)/gen_tlsdesc.s
+ $(do_sed) $(PTHREAD_GENERATE_MANGLE) $< > $@
+ @if test ! -s $@ ; then rm -f $@ ; false ; fi
+pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(libpthread_arch_OUT)/tlsdesc.h
diff --git a/libpthread/nptl/sysdeps/nds32/dl-tls.h b/libpthread/nptl/sysdeps/nds32/dl-tls.h
new file mode 100644
index 000000000..3b11e7f42
--- /dev/null
+++ b/libpthread/nptl/sysdeps/nds32/dl-tls.h
@@ -0,0 +1,59 @@
+/* Thread-local storage handling in the ELF dynamic linker. NDS32 version.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _NDS32_DL_TLS_H
+#define _NDS32_DL_TLS_H 1
+
+
+/* Type used to represent a TLS descriptor. */
+struct tlsdesc
+{
+ ptrdiff_t (*entry)(struct tlsdesc *);
+ union
+ {
+ void *pointer;
+ long value;
+ } argument;
+};
+
+/* Type used for the representation of TLS information in the GOT. */
+typedef struct
+{
+ unsigned long int ti_module;
+ unsigned long int ti_offset;
+} tls_index;
+
+
+/* Type used as the argument in a TLS descriptor for a symbol that
+ * needs dynamic TLS offsets. */
+struct tlsdesc_dynamic_arg
+{
+ tls_index tlsinfo;
+ size_t gen_count;
+};
+
+
+extern void *__tls_get_addr (tls_index *ti);
+
+extern ptrdiff_t attribute_hidden
+ _dl_tlsdesc_return(struct tlsdesc_dynamic_arg *);
+
+extern void *_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset);
+extern ptrdiff_t attribute_hidden
+ _dl_tlsdesc_dynamic(struct tlsdesc *);
+
+#endif //_NDS32_DL_TLS_H
diff --git a/libpthread/nptl/sysdeps/nds32/libc-dl-tlsdesc.S b/libpthread/nptl/sysdeps/nds32/libc-dl-tlsdesc.S
new file mode 100644
index 000000000..5892a8b28
--- /dev/null
+++ b/libpthread/nptl/sysdeps/nds32/libc-dl-tlsdesc.S
@@ -0,0 +1 @@
+#include <ldso/ldso/nds32/dl-tlsdesc.S>
diff --git a/libpthread/nptl/sysdeps/nds32/pthread_spin_lock.c b/libpthread/nptl/sysdeps/nds32/pthread_spin_lock.c
new file mode 100644
index 000000000..cec3acbc6
--- /dev/null
+++ b/libpthread/nptl/sysdeps/nds32/pthread_spin_lock.c
@@ -0,0 +1,65 @@
+/* pthread_spin_lock -- lock a spin lock. Generic version.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <atomic.h>
+#include "pthreadP.h"
+
+/* A machine-specific version can define SPIN_LOCK_READS_BETWEEN_CMPXCHG
+ to the number of plain reads that it's optimal to spin on between uses
+ of atomic_compare_and_exchange_val_acq. If spinning forever is optimal
+ then use -1. If no plain reads here would ever be optimal, use 0. */
+#define SPIN_LOCK_READS_BETWEEN_CMPXCHG 1000
+
+int
+pthread_spin_lock (pthread_spinlock_t *lock)
+{
+ /* atomic_exchange usually takes less instructions than
+ atomic_compare_and_exchange. On the other hand,
+ atomic_compare_and_exchange potentially generates less bus traffic
+ when the lock is locked.
+ We assume that the first try mostly will be successful, and we use
+ atomic_exchange. For the subsequent tries we use
+ atomic_compare_and_exchange. */
+ if (atomic_exchange_acq (lock, 1) == 0)
+ return 0;
+
+ do
+ {
+ /* The lock is contended and we need to wait. Going straight back
+ to cmpxchg is not a good idea on many targets as that will force
+ expensive memory synchronizations among processors and penalize other
+ running threads.
+ On the other hand, we do want to update memory state on the local core
+ once in a while to avoid spinning indefinitely until some event that
+ will happen to update local memory as a side-effect. */
+ if (SPIN_LOCK_READS_BETWEEN_CMPXCHG >= 0)
+ {
+ int wait = SPIN_LOCK_READS_BETWEEN_CMPXCHG;
+
+ while (*lock != 0 && wait > 0)
+ --wait;
+ }
+ else
+ {
+ while (*lock != 0)
+ ;
+ }
+ }
+ while (atomic_compare_and_exchange_val_acq (lock, 1, 0) != 0);
+
+ return 0;
+}
diff --git a/libpthread/nptl/sysdeps/nds32/pthread_spin_trylock.c b/libpthread/nptl/sysdeps/nds32/pthread_spin_trylock.c
new file mode 100644
index 000000000..4e9aa64d3
--- /dev/null
+++ b/libpthread/nptl/sysdeps/nds32/pthread_spin_trylock.c
@@ -0,0 +1,26 @@
+/* pthread_spin_trylock -- trylock a spin lock. Generic version.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <atomic.h>
+#include "pthreadP.h"
+
+int
+pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+ return atomic_exchange_acq (lock, 1) ? EBUSY : 0;
+}
diff --git a/libpthread/nptl/sysdeps/nds32/pthreaddef.h b/libpthread/nptl/sysdeps/nds32/pthreaddef.h
new file mode 100644
index 000000000..c9d3f7781
--- /dev/null
+++ b/libpthread/nptl/sysdeps/nds32/pthreaddef.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Default stack size. */
+#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024)
+
+/* Required stack pointer alignment at beginning. SSE requires 16
+ bytes. */
+#define STACK_ALIGN 16
+
+/* Minimal stack size after allocating thread descriptor and guard size. */
+#define MINIMAL_REST_STACK 2048
+
+/* Alignment requirement for TCB. */
+#define TCB_ALIGNMENT 16
+
+
+/* Location of current stack frame. */
+#define CURRENT_STACK_FRAME __builtin_frame_address (0)
+
+
+/* XXX Until we have a better place keep the definitions here. */
+#define __exit_thread_inline(val) \
+ INLINE_SYSCALL (exit, 1, (val))
+
+
diff --git a/libpthread/nptl/sysdeps/nds32/tcb-offsets.sym b/libpthread/nptl/sysdeps/nds32/tcb-offsets.sym
new file mode 100644
index 000000000..3b9e10186
--- /dev/null
+++ b/libpthread/nptl/sysdeps/nds32/tcb-offsets.sym
@@ -0,0 +1,12 @@
+#include <sysdep.h>
+#include <tls.h>
+
+--
+
+-- Derive offsets relative to the thread register.
+#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
+
+MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
+PID_OFFSET thread_offsetof (pid)
+TID_OFFSET thread_offsetof (tid)
+
diff --git a/libpthread/nptl/sysdeps/nds32/tls.h b/libpthread/nptl/sysdeps/nds32/tls.h
new file mode 100644
index 000000000..e2a38626d
--- /dev/null
+++ b/libpthread/nptl/sysdeps/nds32/tls.h
@@ -0,0 +1,178 @@
+/* Definition for thread-local data handling. NPTL/NDS32 version.
+ Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _TLS_H
+#define _TLS_H 1
+
+
+#ifndef __ASSEMBLER__
+# include <stdbool.h>
+# include <stddef.h>
+# include <stdint.h>
+
+/* Type for the dtv. */
+typedef union dtv
+{
+ size_t counter;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
+} dtv_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+
+/* We require TLS support in the tools. */
+#define HAVE_TLS_SUPPORT 1
+#define HAVE_TLS_MODEL_ATTRIBUTE 1
+#define HAVE___THREAD 1
+
+/* Signal that TLS support is available. */
+#define USE_TLS 1
+
+#ifndef __ASSEMBLER__
+
+/* Get system call information. */
+# include <sysdep.h>
+
+/* The TP points to the start of the thread blocks. */
+# define TLS_DTV_AT_TP 1
+
+/* We use the multiple_threads field in the pthread struct */
+#define TLS_MULTIPLE_THREADS_IN_TCB 1
+
+/* Get the thread descriptor definition. */
+# include <../../descr.h>
+
+/* The stack_guard is accessed directly by GCC -fstack-protector code,
+ so it is a part of public ABI. The dtv and pointer_guard fields
+ are private. */
+typedef struct
+{
+ dtv_t *dtv;
+ void *private;
+} tcbhead_t;
+
+/* This is the size of the initial TCB. */
+# define TLS_INIT_TCB_SIZE 0
+
+/* Alignment requirements for the initial TCB. */
+# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
+
+/* This is the size of the TCB. */
+# define TLS_TCB_SIZE 0
+
+/* Alignment requirements for the TCB. */
+# define TLS_TCB_ALIGN __alignof__ (struct pthread)
+
+
+
+/* This is the size we need before TCB - actually, it includes the TCB. */
+# define TLS_PRE_TCB_SIZE \
+ (sizeof (struct pthread) \
+ + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
+
+/* Return the thread descriptor (tp) for the current thread. */
+register void *__thread_pointer __asm__ ("$r25");
+
+
+/* The thread pointer (in hardware register tp) points to the end of
+ the TCB. The pthread_descr structure is immediately in front of the TCB. */
+#ifndef TLS_TCB_OFFSET
+# define TLS_TCB_OFFSET 0
+#endif
+
+/* Install the dtv pointer. The pointer passed is to the element with
+ index -1 which contain the length. */
+# define INSTALL_DTV(tcbp, dtvp) \
+ (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1)
+
+/* Install new dtv for current thread. */
+# define INSTALL_NEW_DTV(dtv) (THREAD_DTV() = (dtv))
+
+/* Return dtv of given thread descriptor. */
+# define GET_DTV(tcbp) (((tcbhead_t *) (tcbp))[-1].dtv)
+
+/* Code to initially initialize the thread pointer (tp). */
+# define TLS_INIT_TP(tcbp, secondcall) \
+ (__thread_pointer = (char *)(tcbp) + TLS_TCB_OFFSET, NULL)
+
+/* Return the address of the dtv for the current thread. */
+# define THREAD_DTV() \
+ (((tcbhead_t *) (__thread_pointer - TLS_TCB_OFFSET))[-1].dtv)
+
+/* Return the thread descriptor for the current thread. */
+# define THREAD_SELF \
+ ((struct pthread *) (__thread_pointer \
+ - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE))
+
+/* Magic for libthread_db to know how to do THREAD_SELF. */
+# define DB_THREAD_SELF \
+ REGISTER (32, 32, 152, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
+
+/* Read member of the thread descriptor directly. */
+# define THREAD_GETMEM(descr, member) (descr->member)
+
+/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
+# define THREAD_GETMEM_NC(descr, member, idx) \
+ (descr->member[idx])
+
+/* Set member of the thread descriptor directly. */
+# define THREAD_SETMEM(descr, member, value) \
+ (descr->member = (value))
+
+/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
+# define THREAD_SETMEM_NC(descr, member, idx, value) \
+ (descr->member[idx] = (value))
+
+
+/* l_tls_offset == 0 is perfectly valid on Tile, so we have to use some
+ different value to mean unset l_tls_offset. */
+# define NO_TLS_OFFSET -1
+
+/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_FLAG_UNUSED 0
+#define THREAD_GSCOPE_FLAG_USED 1
+#define THREAD_GSCOPE_FLAG_WAIT 2
+#define THREAD_GSCOPE_RESET_FLAG() \
+ do \
+ { int __res \
+ = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \
+ THREAD_GSCOPE_FLAG_UNUSED); \
+ if (__res == THREAD_GSCOPE_FLAG_WAIT) \
+ lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \
+ } \
+ while (0)
+#define THREAD_GSCOPE_SET_FLAG() \
+ do \
+ { \
+ THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \
+ atomic_write_barrier (); \
+ } \
+ while (0)
+#define THREAD_GSCOPE_WAIT() \
+ GL(dl_wait_lookup_done) ()
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* tls.h */
+
+
diff --git a/libpthread/nptl/sysdeps/nds32/tlsdesc.sym b/libpthread/nptl/sysdeps/nds32/tlsdesc.sym
new file mode 100644
index 000000000..4fa3adacf
--- /dev/null
+++ b/libpthread/nptl/sysdeps/nds32/tlsdesc.sym
@@ -0,0 +1,17 @@
+#include <stddef.h>
+#include <sysdep.h>
+#include <tls.h>
+#include <link.h>
+#include <dl-tls.h>
+
+--
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+#define dtv_offsetof(dtv) (long)(offsetof(tcbhead_t, dtv) - sizeof (tcbhead_t))
+DTV_OFFSET dtv_offsetof(dtv)
+
+TLSDESC_ARG offsetof(struct tlsdesc, argument.pointer)
+
+TLSDESC_GEN_COUNT offsetof(struct tlsdesc_dynamic_arg, gen_count)
+TLSDESC_MODID offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module)
+TLSDESC_MODOFF offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset)
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile
new file mode 100644
index 000000000..2caba11b7
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile
@@ -0,0 +1,9 @@
+# Makefile for uClibc-ng NPTL
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+top_srcdir=../../../../../../../
+top_builddir=../../../../../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.arch
+include $(top_srcdir)Makerules
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile.arch
new file mode 100644
index 000000000..3b8935ce5
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/Makefile.arch
@@ -0,0 +1,12 @@
+# Makefile for uClibc-ng NPTL
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+libpthread_linux_arch_SSRC =
+libpthread_linux_arch_CSRC = pthread_once.c
+
+libc_linux_arch_CSRC = fork.c
+libc_linux_arch_SSRC = clone.S vfork.S
+libc_linux_arch_SSRC-OMIT = waitpid.S
+
+CFLAGS += $(SSP_ALL_CFLAGS)
+
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/pthreadtypes.h
new file mode 100644
index 000000000..695a61fdd
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/pthreadtypes.h
@@ -0,0 +1,177 @@
+/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _BITS_PTHREADTYPES_H
+#define _BITS_PTHREADTYPES_H 1
+
+#define __SIZEOF_PTHREAD_ATTR_T 36
+#define __SIZEOF_PTHREAD_MUTEX_T 24
+#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
+#define __SIZEOF_PTHREAD_COND_T 48
+#define __SIZEOF_PTHREAD_COND_COMPAT_T 12
+#define __SIZEOF_PTHREAD_CONDATTR_T 4
+#define __SIZEOF_PTHREAD_RWLOCK_T 32
+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+#define __SIZEOF_PTHREAD_BARRIER_T 20
+#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+
+
+/* Thread identifiers. The structure of the attribute type is not
+ exposed on purpose. */
+typedef unsigned long int pthread_t;
+
+union pthread_attr_t
+{
+ char __size[__SIZEOF_PTHREAD_ATTR_T];
+ long int __align;
+};
+#ifndef __have_pthread_attr_t
+typedef union pthread_attr_t pthread_attr_t;
+# define __have_pthread_attr_t 1
+#endif
+
+
+typedef struct __pthread_internal_slist
+{
+ struct __pthread_internal_slist *__next;
+} __pthread_slist_t;
+
+
+/* Data structures for mutex handling. The structure of the attribute
+ type is not exposed on purpose. */
+typedef union
+{
+ struct __pthread_mutex_s
+ {
+ int __lock;
+ unsigned int __count;
+ int __owner;
+ /* KIND must stay at this position in the structure to maintain
+ binary compatibility. */
+ int __kind;
+ unsigned int __nusers;
+ __extension__ union
+ {
+ int __spins;
+ __pthread_slist_t __list;
+ };
+ } __data;
+ char __size[__SIZEOF_PTHREAD_MUTEX_T];
+ long int __align;
+} pthread_mutex_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
+ long int __align;
+} pthread_mutexattr_t;
+
+
+/* Data structure for conditional variable handling. The structure of
+ the attribute type is not exposed on purpose. */
+typedef union
+{
+ struct
+ {
+ int __lock;
+ unsigned int __futex;
+ __extension__ unsigned long long int __total_seq;
+ __extension__ unsigned long long int __wakeup_seq;
+ __extension__ unsigned long long int __woken_seq;
+ void *__mutex;
+ unsigned int __nwaiters;
+ unsigned int __broadcast_seq;
+ } __data;
+ char __size[__SIZEOF_PTHREAD_COND_T];
+ __extension__ long long int __align;
+} pthread_cond_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_CONDATTR_T];
+ long int __align;
+} pthread_condattr_t;
+
+
+/* Keys for thread-specific data */
+typedef unsigned int pthread_key_t;
+
+
+/* Once-only execution */
+typedef int pthread_once_t;
+
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+/* Data structure for read-write lock variable handling. The
+ structure of the attribute type is not exposed on purpose. */
+typedef union
+{
+ struct
+ {
+ int __lock;
+ unsigned int __nr_readers;
+ unsigned int __readers_wakeup;
+ unsigned int __writer_wakeup;
+ unsigned int __nr_readers_queued;
+ unsigned int __nr_writers_queued;
+ /* FLAGS must stay at this position in the structure to maintain
+ binary compatibility. */
+ unsigned char __flags;
+ unsigned char __shared;
+ unsigned char __pad1;
+ unsigned char __pad2;
+ int __writer;
+ } __data;
+ char __size[__SIZEOF_PTHREAD_RWLOCK_T];
+ long int __align;
+} pthread_rwlock_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
+ long int __align;
+} pthread_rwlockattr_t;
+#endif
+
+
+#ifdef __USE_XOPEN2K
+/* POSIX spinlock data type. */
+typedef volatile int pthread_spinlock_t;
+
+
+/* POSIX barriers data type. The structure of the type is
+ deliberately not exposed. */
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_BARRIER_T];
+ long int __align;
+} pthread_barrier_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
+ int __align;
+} pthread_barrierattr_t;
+#endif
+/* Extra attributes for the cleanup functions. */
+/*
+ FIXME, check this after gcc uprgrade.
+ #define __cleanup_fct_attribute __attribute__ ((__regparm__ (1)))
+ warning: '__regparm__' attribute directive ignored
+*/
+
+#endif /* bits/pthreadtypes.h */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/semaphore.h
new file mode 100644
index 000000000..8ee77429a
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/bits/semaphore.h
@@ -0,0 +1,38 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _SEMAPHORE_H
+# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
+#endif
+
+
+#define __SIZEOF_SEM_T 16
+
+
+/* Value returned if `sem_open' failed. */
+#define SEM_FAILED ((sem_t *) 0)
+
+/* Maximum value the semaphore can have. */
+#define SEM_VALUE_MAX (2147483647)
+
+
+typedef union
+{
+ char __size[__SIZEOF_SEM_T];
+ long int __align;
+} sem_t;
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/clone.S
new file mode 100644
index 000000000..94b39fcf9
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/clone.S
@@ -0,0 +1,4 @@
+/* We want an #include_next, but we are the main source file.
+ So, #include ourselves and in that incarnation we can use #include_next. */
+# define RESET_PID
+# include <libc/sysdeps/linux/nds32/clone.S>
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/createthread.c
new file mode 100644
index 000000000..486bc24f5
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/createthread.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Value passed to 'clone' for initialization of the thread register. */
+#define TLS_VALUE ((void *) (pd) \
+ + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
+
+/* Get the real implementation. */
+#include <sysdeps/pthread/createthread.c>
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/fork.c
new file mode 100644
index 000000000..beb6cb0f7
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/fork.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ Contributed by Phil Blundell <pb@nexus.co.uk>, 2005
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+#include <sched.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <tls.h>
+
+#define ARCH_FORK() \
+ INLINE_SYSCALL (clone, 5, \
+ CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \
+ NULL, NULL, &THREAD_SELF->tid)
+
+#include "../fork.c"
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/lowlevellock.h
new file mode 100644
index 000000000..32b004486
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/lowlevellock.h
@@ -0,0 +1,323 @@
+/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LOWLEVELLOCK_H
+#define _LOWLEVELLOCK_H 1
+
+#include <time.h>
+#include <sys/param.h>
+#include <bits/pthreadtypes.h>
+#include <atomic.h>
+#include <sysdep.h>
+#include <bits/kernel-features.h>
+
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+#define FUTEX_REQUEUE 3
+#define FUTEX_CMP_REQUEUE 4
+#define FUTEX_WAKE_OP 5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1)
+#define FUTEX_LOCK_PI 6
+#define FUTEX_UNLOCK_PI 7
+#define FUTEX_TRYLOCK_PI 8
+#define FUTEX_WAIT_BITSET 9
+#define FUTEX_WAKE_BITSET 10
+#define FUTEX_WAIT_REQUEUE_PI 11
+#define FUTEX_CMP_REQUEUE_PI 12
+#define FUTEX_PRIVATE_FLAG 128
+#define FUTEX_CLOCK_REALTIME 256
+
+#define FUTEX_BITSET_MATCH_ANY 0xffffffff
+
+/* Values for 'private' parameter of locking macros. Yes, the
+ definition seems to be backwards. But it is not. The bit will be
+ reversed before passing to the system call. */
+#define LLL_PRIVATE 0
+#define LLL_SHARED FUTEX_PRIVATE_FLAG
+
+
+#if !defined NOT_IN_libc || defined IS_IN_rtld
+/* In libc.so or ld.so all futexes are private. */
+# ifdef __ASSUME_PRIVATE_FUTEX
+# define __lll_private_flag(fl, private) \
+ ((fl) | FUTEX_PRIVATE_FLAG)
+# else
+# define __lll_private_flag(fl, private) \
+ ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
+# endif
+#else
+# ifdef __ASSUME_PRIVATE_FUTEX
+# define __lll_private_flag(fl, private) \
+ (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
+# else
+# define __lll_private_flag(fl, private) \
+ (__builtin_constant_p (private) \
+ ? ((private) == 0 \
+ ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \
+ : (fl)) \
+ : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \
+ & THREAD_GETMEM (THREAD_SELF, header.private_futex))))
+# endif
+#endif
+
+
+#define lll_futex_wait(futexp, val, private) \
+ lll_futex_timed_wait(futexp, val, NULL, private)
+
+#define lll_futex_timed_wait(futexp, val, timespec, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
+ __lll_private_flag (FUTEX_WAIT, private), \
+ (val), (timespec)); \
+ __ret; \
+ })
+
+#define lll_futex_timed_wait_bitset(futexp, val, timespec, clockbit, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ int __op = FUTEX_WAIT_BITSET | clockbit; \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (__op, private), \
+ (val), (timespec), NULL /* Unused. */, \
+ FUTEX_BITSET_MATCH_ANY); \
+ __ret; \
+ })
+
+#define lll_futex_wake(futexp, nr, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
+ __lll_private_flag (FUTEX_WAKE, private), \
+ (nr), 0); \
+ __ret; \
+ })
+
+#define lll_robust_dead(futexv, private) \
+ do \
+ { \
+ int *__futexp = &(futexv); \
+ atomic_or (__futexp, FUTEX_OWNER_DIED); \
+ lll_futex_wake (__futexp, 1, private); \
+ } \
+ while (0)
+
+/* Returns non-zero if error happened, zero if success. */
+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
+ (nr_wake), (nr_move), (mutex), (val)); \
+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
+ })
+
+
+/* Returns non-zero if error happened, zero if success. */
+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (FUTEX_WAKE_OP, private), \
+ (nr_wake), (nr_wake2), (futexp2), \
+ FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \
+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
+ })
+
+/* Priority Inheritance support. */
+#define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \
+ lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private)
+
+#define lll_futex_timed_wait_requeue_pi(futexp, val, timespec, clockbit, \
+ mutex, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ int __op = FUTEX_WAIT_REQUEUE_PI | clockbit; \
+ \
+ INTERNAL_SYSCALL (futex, __err, 5, (futexp), \
+ __lll_private_flag (__op, private), \
+ (val), (timespec), mutex); \
+ })
+
+#define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, val, priv) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (FUTEX_CMP_REQUEUE_PI, priv),\
+ (nr_wake), (nr_move), (mutex), (val)); \
+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
+ })
+
+
+#define lll_trylock(lock) \
+ atomic_compare_and_exchange_val_acq(&(lock), 1, 0)
+
+#define lll_cond_trylock(lock) \
+ atomic_compare_and_exchange_val_acq(&(lock), 2, 0)
+
+#define __lll_robust_trylock(futex, id) \
+ (atomic_compare_and_exchange_val_acq (futex, id, 0) != 0)
+#define lll_robust_trylock(lock, id) \
+ __lll_robust_trylock (&(lock), id)
+
+extern void __lll_lock_wait_private (int *futex) attribute_hidden;
+extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
+extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
+
+#define __lll_lock(futex, private) \
+ ((void) ({ \
+ int *__futex = (futex); \
+ if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, \
+ 1, 0), 0)) \
+ { \
+ if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \
+ __lll_lock_wait_private (__futex); \
+ else \
+ __lll_lock_wait (__futex, private); \
+ } \
+ }))
+#define lll_lock(futex, private) __lll_lock (&(futex), private)
+
+
+#define __lll_robust_lock(futex, id, private) \
+ ({ \
+ int *__futex = (futex); \
+ int __val = 0; \
+ \
+ if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \
+ 0), 0)) \
+ __val = __lll_robust_lock_wait (__futex, private); \
+ __val; \
+ })
+#define lll_robust_lock(futex, id, private) \
+ __lll_robust_lock (&(futex), id, private)
+
+
+#define __lll_cond_lock(futex, private) \
+ ((void) ({ \
+ int *__futex = (futex); \
+ if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0)) \
+ __lll_lock_wait (__futex, private); \
+ }))
+#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
+
+
+#define lll_robust_cond_lock(futex, id, private) \
+ __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
+
+
+extern int __lll_timedlock_wait (int *futex, const struct timespec *,
+ int private) attribute_hidden;
+extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
+ int private) attribute_hidden;
+
+#define __lll_timedlock(futex, abstime, private) \
+ ({ \
+ int *__futex = (futex); \
+ int __val = 0; \
+ \
+ if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0)) \
+ __val = __lll_timedlock_wait (__futex, abstime, private); \
+ __val; \
+ })
+#define lll_timedlock(futex, abstime, private) \
+ __lll_timedlock (&(futex), abstime, private)
+
+
+#define __lll_robust_timedlock(futex, abstime, id, private) \
+ ({ \
+ int *__futex = (futex); \
+ int __val = 0; \
+ \
+ if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \
+ 0), 0)) \
+ __val = __lll_robust_timedlock_wait (__futex, abstime, private); \
+ __val; \
+ })
+#define lll_robust_timedlock(futex, abstime, id, private) \
+ __lll_robust_timedlock (&(futex), abstime, id, private)
+
+
+#define __lll_unlock(futex, private) \
+ (void) \
+ ({ int *__futex = (futex); \
+ int __oldval = atomic_exchange_rel (__futex, 0); \
+ if (__builtin_expect (__oldval > 1, 0)) \
+ lll_futex_wake (__futex, 1, private); \
+ lll_futex_wake (__futex, 1, private); \
+ })
+#define lll_unlock(futex, private) __lll_unlock(&(futex), private)
+
+
+#define __lll_robust_unlock(futex, private) \
+ (void) \
+ ({ int *__futex = (futex); \
+ int __oldval = atomic_exchange_rel (__futex, 0); \
+ if (__builtin_expect (__oldval & FUTEX_WAITERS, 0)) \
+ lll_futex_wake (__futex, 1, private); \
+ lll_futex_wake (__futex, 1, private); \
+ })
+#define lll_robust_unlock(futex, private) \
+ __lll_robust_unlock(&(futex), private)
+
+
+#define lll_islocked(futex) \
+ (futex != 0)
+
+
+/* Our internal lock implementation is identical to the binary-compatible
+ mutex implementation. */
+
+/* Initializers for lock. */
+#define LLL_LOCK_INITIALIZER (0)
+#define LLL_LOCK_INITIALIZER_LOCKED (1)
+
+/* The states of a lock are:
+ 0 - untaken
+ 1 - taken by one user
+ >1 - taken by more users */
+
+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
+ wakeup when the clone terminates. The memory location contains the
+ thread ID while the clone is running and is reset to zero
+ afterwards. */
+#define lll_wait_tid(tid) \
+ do { \
+ __typeof (tid) __tid; \
+ while ((__tid = (tid)) != 0) \
+ lll_futex_wait (&(tid), __tid, LLL_SHARED);\
+ } while (0)
+
+extern int __lll_timedwait_tid (int *, const struct timespec *)
+ attribute_hidden;
+
+#define lll_timedwait_tid(tid, abstime) \
+ ({ \
+ int __res = 0; \
+ if ((tid) != 0) \
+ __res = __lll_timedwait_tid (&(tid), (abstime)); \
+ __res; \
+ })
+
+#endif /* lowlevellock.h */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pt-raise.c b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pt-raise.c
new file mode 100644
index 000000000..6c0d4b5d3
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pt-raise.c
@@ -0,0 +1,18 @@
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <nptl/sysdeps/unix/sysv/linux/raise.c>
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pthread_once.c
new file mode 100644
index 000000000..ce68ce68c
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/pthread_once.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+#include <lowlevellock.h>
+
+
+unsigned long int __fork_generation attribute_hidden;
+
+
+static void
+clear_once_control (void *arg)
+{
+ pthread_once_t *once_control = (pthread_once_t *) arg;
+
+ *once_control = 0;
+ lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
+}
+
+
+int
+__pthread_once (once_control, init_routine)
+ pthread_once_t *once_control;
+ void (*init_routine) (void);
+{
+ while (1)
+ {
+ int oldval, val, newval;
+
+ val = *once_control;
+ do
+ {
+ /* Check if the initialized has already been done. */
+ if ((val & 2) != 0)
+ return 0;
+
+ oldval = val;
+ newval = (oldval & 3) | __fork_generation | 1;
+ val = atomic_compare_and_exchange_val_acq (once_control, newval,
+ oldval);
+ }
+ while (__builtin_expect (val != oldval, 0));
+
+ /* Check if another thread already runs the initializer. */
+ if ((oldval & 1) != 0)
+ {
+ /* Check whether the initializer execution was interrupted
+ by a fork. */
+ if (((oldval ^ newval) & -4) == 0)
+ {
+ /* Same generation, some other thread was faster. Wait. */
+ lll_futex_wait (once_control, newval, LLL_PRIVATE);
+ continue;
+ }
+ }
+
+ /* This thread is the first here. Do the initialization.
+ Register a cleanup handler so that in case the thread gets
+ interrupted the initialization can be restarted. */
+ pthread_cleanup_push (clear_once_control, once_control);
+
+ init_routine ();
+
+ pthread_cleanup_pop (0);
+
+
+ /* Add one to *once_control. */
+ atomic_increment (once_control);
+
+ /* Wake up all other threads. */
+ lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
+ break;
+ }
+
+ return 0;
+}
+weak_alias (__pthread_once, pthread_once)
+strong_alias (__pthread_once, __pthread_once_internal)
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h
new file mode 100644
index 000000000..a0f4de5c8
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/sysdep-cancel.h
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 2003-2013 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+# include <pthreadP.h>
+#endif
+
+
+
+#define PUSHARGS_0
+#define PUSHARGS_1 smw.adm $r0, [$sp], $r0, #0; \
+ cfi_adjust_cfa_offset(4); \
+ cfi_rel_offset(r0,0); \
+ addi $sp, $sp, -4; \
+ cfi_adjust_cfa_offset(4);
+#define PUSHARGS_2 smw.adm $r0, [$sp], $r1, #0; \
+ cfi_adjust_cfa_offset(8); \
+ cfi_rel_offset(r1, 4); \
+ cfi_rel_offset(r0, 0);
+#define PUSHARGS_3 smw.adm $r0, [$sp], $r2, #0; \
+ cfi_adjust_cfa_offset(12); \
+ cfi_rel_offset(r2, 8); \
+ cfi_rel_offset(r1, 4); \
+ cfi_rel_offset(r0, 0); \
+ addi $sp, $sp, -4; \
+ cfi_adjust_cfa_offset(4);
+#define PUSHARGS_4 smw.adm $r0, [$sp], $r3, #0; \
+ cfi_adjust_cfa_offset(16); \
+ cfi_rel_offset(r3, 12); \
+ cfi_rel_offset(r2, 8); \
+ cfi_rel_offset(r1, 4); \
+ cfi_rel_offset(r0, 0);
+#define PUSHARGS_5 smw.adm $r0, [$sp], $r4, #0; \
+ cfi_adjust_cfa_offset(20); \
+ cfi_rel_offset(r4, 16); \
+ cfi_rel_offset(r3, 12); \
+ cfi_rel_offset(r2, 8); \
+ cfi_rel_offset(r1, 4); \
+ cfi_rel_offset(r0, 0); \
+ addi $sp, $sp, -4; \
+ cfi_adjust_cfa_offset(4);
+#define PUSHARGS_6 smw.adm $r0, [$sp], $r5, #0; \
+ cfi_adjust_cfa_offset(24); \
+ cfi_rel_offset(r5, 20); \
+ cfi_rel_offset(r4, 16); \
+ cfi_rel_offset(r3, 12); \
+ cfi_rel_offset(r2, 8); \
+ cfi_rel_offset(r1, 4); \
+ cfi_rel_offset(r0, 0);
+
+#define POPARGS2_0
+#define POPARGS2_1 addi $sp, $sp, 4; \
+ cfi_adjust_cfa_offset(-4); \
+ lmw.bim $r0, [$sp], $r0, #0; \
+ cfi_adjust_cfa_offset(-4); \
+ cfi_restore(r0);
+#define POPARGS2_2 lmw.bim $r0, [$sp], $r1, #0; \
+ cfi_adjust_cfa_offset(-8); \
+ cfi_restore(r0); \
+ cfi_restore(r1);
+#define POPARGS2_3 addi $sp, $sp, 4; \
+ cfi_adjust_cfa_offset(-4); \
+ lmw.bim $r0, [$sp], $r2, #0; \
+ cfi_adjust_cfa_offset(-12); \
+ cfi_restore(r0); \
+ cfi_restore(r1); \
+ cfi_restore(r2);
+#define POPARGS2_4 lmw.bim $r0, [$sp], $r3, #0; \
+ cfi_adjust_cfa_offset(-16); \
+ cfi_restore(r0); \
+ cfi_restore(r1); \
+ cfi_restore(r2); \
+ cfi_restore(r3);
+#define POPARGS2_5 addi $sp, $sp, 4; \
+ cfi_adjust_cfa_offset(-4); \
+ lmw.bim $r0, [$sp], $r4, #0; \
+ cfi_adjust_cfa_offset(-20); \
+ cfi_restore(r0); \
+ cfi_restore(r1); \
+ cfi_restore(r2); \
+ cfi_restore(r3); \
+ cfi_restore(r4);
+#define POPARGS2_6 lmw.bim $r0, [$sp], $r5, #0; \
+ cfi_adjust_cfa_offset(-24); \
+ cfi_restore(r0); \
+ cfi_restore(r1); \
+ cfi_restore(r2); \
+ cfi_restore(r3); \
+ cfi_restore(r4); \
+ cfi_restore(r5);
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+/* NOTE: We do mark syscalls with unwind annotations, for the benefit of
+ cancellation; but they're really only accurate at the point of the
+ syscall. The ARM unwind directives are not rich enough without adding
+ a custom personality function. */
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+ .align 2; \
+ ENTRY (__##syscall_name##_nocancel); \
+ __do_syscall(syscall_name); \
+ PSEUDO_RET; \
+ ret; \
+ END (__##syscall_name##_nocancel); \
+ ENTRY (name); \
+ smw.adm $r6,[$sp],$r6,0x2; \
+ cfi_adjust_cfa_offset(8); \
+ cfi_offset(r6,-8); \
+ cfi_offset(lp,-4); \
+ SINGLE_THREAD_P ($r15); \
+ bgtz $r15, .Lpseudo_cancel; \
+ __do_syscall(syscall_name); \
+ j 50f; \
+ .Lpseudo_cancel: \
+ PUSHARGS_##args; /* save syscall args etc. around CENABLE. */ \
+ CENABLE ($r5); \
+ mov55 $r6, $r0; /* put mask in safe place. */ \
+ POPARGS2_##args; \
+ __do_syscall(syscall_name); /* do the call. */ \
+ push $r0; \
+ cfi_adjust_cfa_offset(4); \
+ cfi_rel_offset(r0, 0); \
+ addi $sp, $sp, -4; \
+ cfi_adjust_cfa_offset(4); \
+ mov55 $r0, $r6; /* save syscall return value. */\
+ CDISABLE($r5); \
+ addi $sp, $sp, 4; \
+ cfi_adjust_cfa_offset(-4); \
+ pop $r0; /* retrieve return value. */ \
+ cfi_adjust_cfa_offset(-4); \
+ cfi_restore(r0); \
+50: \
+ lmw.bim $r6,[$sp],$r6, 0x2; \
+ cfi_adjust_cfa_offset(-8); \
+ cfi_restore(lp); \
+ cfi_restore(r6); \
+ PSEUDO_RET;
+# ifndef __ASSEMBLER__
+//# if defined IS_IN_libpthread || !defined NOT_IN_libc
+//extern int __local_multiple_threads attribute_hidden;
+//# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+//# else
+/* There is no __local_multiple_threads for librt */
+# define SINGLE_THREAD_P __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+ header.multiple_threads) == 0, 1)
+//# endif
+# else
+# define SINGLE_THREAD_P(reg) \
+ addi reg, $r25, MULTIPLE_THREADS_OFFSET; \
+ lw reg, [reg];
+# define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P(x)
+# endif
+
+
+# ifdef IS_IN_libpthread
+# define CENABLE(reg) jmp(reg, __pthread_enable_asynccancel)
+# define CDISABLE(reg) jmp(reg, __pthread_disable_asynccancel)
+# define __local_multiple_threads __pthread_multiple_threads
+# elif !defined NOT_IN_libc
+# define CENABLE(reg) jmp(reg, __libc_enable_asynccancel)
+# define CDISABLE(reg) jmp(reg, __libc_disable_asynccancel)
+# define __local_multiple_threads __libc_multiple_threads
+# elif defined IS_IN_librt
+# define CENABLE(reg) jmp(reg, __librt_enable_asynccancel)
+# define CDISABLE(reg) jmp(reg, __librt_disable_asynccancel)
+# else
+# error Unsupported library
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* For rtld, et cetera. */
+# define SINGLE_THREAD_P 1
+# define NO_CANCELLATION 1
+
+#endif
+
+
+
+
+
+
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+ header.multiple_threads) == 0, 1)
+#endif
+
+
+
+#ifdef PIC
+#define PSEUDO_RET \
+ .pic \
+ .align 2; \
+ bgez $r0, 1f; \
+ sltsi $r1, $r0, -4096; \
+ bgtz $r1, 1f; \
+ PIC_jmp_err \
+ nop; \
+ 1:
+#else /* PIC*/
+#define PSEUDO_RET \
+ .align 2; \
+ bgez $r0, 1f; \
+ sltsi $r1, $r0, -4096; \
+ bgtz $r1, 1f; \
+ j SYSCALL_ERROR; \
+ 1:
+#endif
+
+#ifdef PIC
+#define jmp(reg, symble) PIC_jmpr(reg, symble)
+/* reg: available register */
+#define PIC_jmp_err \
+ smw.adm $sp,[$sp],$sp,#0x6; \
+ mfusr $r15, $PC; \
+ sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_ + 4); \
+ ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_ + 8); \
+ add $gp, $r15, $gp; \
+ sethi $r15, hi20(SYSCALL_ERROR@PLT); \
+ ori $r15, $r15, lo12(SYSCALL_ERROR@PLT); \
+ add $r15, $r15, $gp; \
+ jral $r15; \
+ lmw.bim $sp,[$sp],$sp,#0x6; \
+ ret;
+
+#define PIC_jmp(reg, symble) \
+ mfusr $r15, $PC; \
+ sethi reg, hi20(_GLOBAL_OFFSET_TABLE_ + 4); \
+ ori reg, reg, lo12(_GLOBAL_OFFSET_TABLE_ + 8); \
+ add reg, $r15, reg; \
+ sethi $r15, hi20(symble@PLT); \
+ ori $r15, $r15, lo12(symble@PLT); \
+ add $r15, $r15, reg; \
+ jr $r15;
+
+
+#define PIC_jmpr(reg, symble) \
+ mfusr $r15, $PC; \
+ sethi reg, hi20(_GLOBAL_OFFSET_TABLE_ + 4); \
+ ori reg, reg, lo12(_GLOBAL_OFFSET_TABLE_ + 8); \
+ add reg, $r15, reg; \
+ sethi $r15, hi20(symble@PLT); \
+ ori $r15, $r15, lo12(symble@PLT); \
+ add $r15, $r15, reg; \
+ jral $r15;
+
+#else
+#define jmp(reg, symble) jal symble
+#endif
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/vfork.S
new file mode 100644
index 000000000..f11f76ae1
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nds32/vfork.S
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <tls.h>
+
+/* Save the PID value. */
+#define SAVE_PID \
+ lwi $r1, [$r25 + PID_OFFSET];/* Get the thread pointer. */ \
+ subri $r1, $r1, 0x0; /* Negate it. */ \
+ bnez $r1, 1f; /* If it was zero... */ \
+ sethi $r1, 0x80000; /* use 0x80000000 instead. */ \
+1: swi $r1, [$r25 + PID_OFFSET];/* Store the temporary PID. */
+
+/* Restore the old PID value in the parent. */
+#define RESTORE_PID \
+ beqz $r0, 1f; /* If we are the parent... */ \
+ lwi $r1, [$r25 + PID_OFFSET];/* Get the thread pointer. */ \
+ subri $r1, $r1, 0x0; /* Re-negate it. */ \
+ sethi $r2, 0x80000; /* Load 0x80000000... */ \
+ bne $r1, $r2, 2f; /* ... compare against it... */ \
+ movi $r1, 0; /* ... use 0 instead. */ \
+2: swi $r1, [$r25 + PID_OFFSET];/* Restore the PID. */ \
+1:
+
+#include <../../../../../../../libc/sysdeps/linux/nds32/vfork.S>