diff options
Diffstat (limited to 'libc/sysdeps/linux/arc')
-rw-r--r-- | libc/sysdeps/linux/arc/bits/atomic.h | 57 | ||||
-rw-r--r-- | libc/sysdeps/linux/arc/clone.S | 36 | ||||
-rw-r--r-- | libc/sysdeps/linux/arc/jmpbuf-unwind.h | 17 | ||||
-rw-r--r-- | libc/sysdeps/linux/arc/sysdep.h | 4 | ||||
-rw-r--r-- | libc/sysdeps/linux/arc/vfork.S | 13 |
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 |