summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/sysdeps/linux/arc/bits/atomic.h57
-rw-r--r--libc/sysdeps/linux/arc/clone.S36
-rw-r--r--libc/sysdeps/linux/arc/jmpbuf-unwind.h17
-rw-r--r--libc/sysdeps/linux/arc/sysdep.h4
-rw-r--r--libc/sysdeps/linux/arc/vfork.S13
5 files changed, 120 insertions, 7 deletions
diff --git a/libc/sysdeps/linux/arc/bits/atomic.h b/libc/sysdeps/linux/arc/bits/atomic.h
new file mode 100644
index 000000000..d4abf4eb7
--- /dev/null
+++ b/libc/sysdeps/linux/arc/bits/atomic.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
+ *
+ * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+ */
+
+#include <stdint.h>
+#include <sysdep.h>
+
+typedef int8_t atomic8_t;
+typedef uint8_t uatomic8_t;
+typedef int_fast8_t atomic_fast8_t;
+typedef uint_fast8_t uatomic_fast8_t;
+
+typedef int32_t atomic32_t;
+typedef uint32_t uatomic32_t;
+typedef int_fast32_t atomic_fast32_t;
+typedef uint_fast32_t uatomic_fast32_t;
+
+typedef intptr_t atomicptr_t;
+typedef uintptr_t uatomicptr_t;
+typedef intmax_t atomic_max_t;
+typedef uintmax_t uatomic_max_t;
+
+void __arc_link_error (void);
+
+#define atomic_full_barrier() \
+ __asm__ __volatile__("": : :"memory")
+
+/* Atomic compare and exchange. */
+
+#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
+ ({ __arc_link_error (); oldval; })
+
+#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
+ ({ __arc_link_error (); oldval; })
+
+#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
+ ({ \
+ __typeof(oldval) prev; \
+ \
+ __asm__ __volatile__( \
+ "1: llock %0, [%1] \n" \
+ " brne %0, %2, 2f \n" \
+ " scond %3, [%1] \n" \
+ " bnz 1b \n" \
+ "2: \n" \
+ : "=&r"(prev) \
+ : "r"(mem), "ir"(oldval), \
+ "r"(newval) /* can't be "ir". scond can't take limm for "b" */\
+ : "cc", "memory"); \
+ \
+ prev; \
+ })
+
+#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
+ ({ __arc_link_error (); oldval; })
diff --git a/libc/sysdeps/linux/arc/clone.S b/libc/sysdeps/linux/arc/clone.S
index 9aa8d92cd..db5000caf 100644
--- a/libc/sysdeps/linux/arc/clone.S
+++ b/libc/sysdeps/linux/arc/clone.S
@@ -19,25 +19,32 @@
; Current (Jul 2012) upstream powerpc/clone.S assumes similarly.
; Our LTP (from 2007) doesn't seem to have tests to prove otherwise
-; clone syscall in kernel
+; clone syscall in kernel (ABI: CONFIG_CLONE_BACKWARDS)
;
-; int sys_clone(unsigned long clone_flags, unsigned long newsp,
-; int __user *parent_tidptr, void *tls,
+; int sys_clone(unsigned long clone_flags,
+; unsigned long newsp,
+; int __user *parent_tidptr,
+; void *tls,
; int __user *child_tidptr)
+#define CLONE_VM 0x00000100
+#define CLONE_THREAD 0x00010000
+#define CLONE_THREAD_N_VM (CLONE_THREAD | CLONE_VM)
ENTRY(clone)
cmp r0, 0 ; @fn can't be NULL
cmp.ne r1, 0 ; @child_stack can't be NULL
bz .L__sys_err
- ; @fn and @args needed after the syscall for child
- ; However r3 containing @arg will be clobbered BEFORE syscall
+ ; save some of the orig args
; r0 containg @fn will be clobbered AFTER syscall (with ret val)
- mov r10, r0
- mov r11, r3
+ ; rest are clobbered BEFORE syscall due to different arg ordering
+ mov r10, r0 ; @fn
+ mov r11, r3 ; @args
+ mov r12, r2 ; @clone_flags
; adjust libc args for syscall
+
mov r0, r2 ; libc @flags is 1st syscall arg
mov r2, r4 ; libc @ptid
mov r3, r5 ; libc @tls
@@ -49,6 +56,21 @@ ENTRY(clone)
blt .L__sys_err2 ; < 0 (signed) error
jnz [blink] ; Parent returns
+ ; ----- child starts here ---------
+#ifdef RESET_PID
+ mov_s r2, CLONE_THREAD_N_VM
+ and_s r2, r2, r12
+ brne r2, r12, .Lgo_thread
+
+ mov r8, __NR_clone
+ ARC_TRAP_INSN ; r0 has PID
+ THREAD_SELF r1 ; Get to struct pthread (just before TCB)
+ st r0, [r1, PTHREAD_PID]
+ st r0, [r1, PTHREAD_TID]
+
+.Lgo_thread:
+#endif
+
; child jumps off to @fn with @arg as argument, and returns here
jl.d [r10]
mov r0, r11
diff --git a/libc/sysdeps/linux/arc/jmpbuf-unwind.h b/libc/sysdeps/linux/arc/jmpbuf-unwind.h
index e4ed8fe75..8c41816c5 100644
--- a/libc/sysdeps/linux/arc/jmpbuf-unwind.h
+++ b/libc/sysdeps/linux/arc/jmpbuf-unwind.h
@@ -11,3 +11,20 @@
containing a local variable at ADDRESS. */
#define _JMPBUF_UNWINDS(jmpbuf, address) \
((void *) (address) < (void *) (jmpbuf[__JMP_BUF_SP]))
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <stdint.h>
+#include <unwind.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+ containing a local variable at ADDRESS. */
+#undef _JMPBUF_UNWINDS
+#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
+ ((void *) (address) < (void *) demangle (jmpbuf[__JMP_BUF_SP]))
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+ _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+ ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[__JMP_BUF_SP] - (_adj))
+#endif
diff --git a/libc/sysdeps/linux/arc/sysdep.h b/libc/sysdeps/linux/arc/sysdep.h
index 76d3788e5..d75d89100 100644
--- a/libc/sysdeps/linux/arc/sysdep.h
+++ b/libc/sysdeps/linux/arc/sysdep.h
@@ -19,4 +19,8 @@ nm:
#include <common/sysdep.h>
+/* Pointer mangling is not yet supported */
+#define PTR_MANGLE(var) (void) (var)
+#define PTR_DEMANGLE(var) (void) (var)
+
#endif
diff --git a/libc/sysdeps/linux/arc/vfork.S b/libc/sysdeps/linux/arc/vfork.S
index 11959b66b..573a29f26 100644
--- a/libc/sysdeps/linux/arc/vfork.S
+++ b/libc/sysdeps/linux/arc/vfork.S
@@ -16,12 +16,25 @@
#define CLONE_FLAGS_FOR_VFORK (CLONE_VM|CLONE_VFORK|SIGCHLD)
ENTRY(__vfork)
+#ifdef SAVE_PID
+ THREAD_SELF r1 ; Get to struct pthread (just before TCB)
+ ld r2, [r1, PTHREAD_PID]
+ neg.f r3, r2
+ bset.z r3, r3, 31
+ st r3, [r1, PTHREAD_PID]
+#endif
mov r0, CLONE_FLAGS_FOR_VFORK
mov_s r1, sp
mov r8, __NR_clone
ARC_TRAP_INSN
cmp r0, 0
+#ifdef RESTORE_PID
+ bz 1f ; child continues
+ THREAD_SELF r1 ; Get to struct pthread (just before TCB)
+ st r2, [r1, PTHREAD_PID]
+1:
+#endif
jge [blink] ; pid >=0 return, else detour via tailcall to errno
b __syscall_error