diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2016-05-24 20:37:14 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2016-05-24 20:39:09 +0200 |
commit | 0ff3c7882867f1270e072a6d93dd085bf9728be1 (patch) | |
tree | 8d533865540848879dd71df4a6a3f52ba368e35f | |
parent | 2559592659fe8225fc7d67fa5bc83a1589819054 (diff) |
microblaze: fix linuxthreads support
Got the working code from https://github.com/jdkoftinoff/mb-linux-msli/,
otherwise SIGILL while using linuxthreads.
-rw-r--r-- | libpthread/linuxthreads/sysdeps/microblaze/pt-machine.h | 86 |
1 files changed, 30 insertions, 56 deletions
diff --git a/libpthread/linuxthreads/sysdeps/microblaze/pt-machine.h b/libpthread/linuxthreads/sysdeps/microblaze/pt-machine.h index e8c03f9e5..2184c9236 100644 --- a/libpthread/linuxthreads/sysdeps/microblaze/pt-machine.h +++ b/libpthread/linuxthreads/sysdeps/microblaze/pt-machine.h @@ -9,7 +9,6 @@ * General Public License. See the file COPYING.LIB in the main * directory of this archive for more details. * - * Written by Miles Bader <miles@gnu.org> */ #ifndef _PT_MACHINE_H @@ -18,12 +17,9 @@ #include <features.h> #ifndef PT_EI -# define PT_EI extern inline +# define PT_EI __extern_always_inline #endif -extern long int testandset (int *spinlock); -extern int __compare_and_swap (long *ptr, long old, long new); - /* Get some notion of the current stack. Need not be exactly the top of the stack, just something somewhere in the current frame. */ #define CURRENT_STACK_FRAME __stack_pointer @@ -31,76 +27,54 @@ register char *__stack_pointer __asm__ ("r1"); #define HAS_COMPARE_AND_SWAP #define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS -#define IMPLEMENT_TAS_WITH_CAS +#define MEMORY_BARRIER() __asm__ __volatile__("": : :"memory") /* Atomically: If *PTR == OLD, set *PTR to NEW and return true, otherwise do nothing and return false. */ PT_EI int __compare_and_swap (long *ptr, long old, long new) { - unsigned long psw; - - /* disable interrupts */ - /* This is ugly ugly ugly! */ - __asm__ __volatile__ ("mfs %0, rmsr;" - "andi r3, %0, ~2;" - "mts rmsr, r3;" - : "=&r" (psw) - : - : "r3"); + long prev, cmp, retval; + __asm__ __volatile__ (" addi %2, r0, 0;" + "1: lwx %0, %3, r0;" + " cmp %1, %0, %4;" + " bnei %1, 2f;" + " swx %5, %3, r0;" + " addic %1, r0, 0;" + " bnei %1, 1b;" + " addi %2, r0, 1;" + "2:" + : "=&r" (prev), "=&r" (cmp), "=&r" (retval) + : "r" (ptr), "r" (old), "r" (new) + : "cc", "memory"); - if (likely (*ptr == old)) - { - *ptr = new; - __asm__ __volatile__ ("mts rmsr, %0;" :: "r" (psw)); /* re-enable */ - return 1; - } - else - { - __asm__ __volatile__ ("mts rmsr, %0;" :: "r" (psw)); /* re-enable */ - return 0; - } + return retval; } -/* like above's __compare_and_swap() but it first syncs the memory - (This is also the difference between both functions in e.g. - ../powerpc/pt-machine.h) - Doing this additional sync fixes a hang of __pthread_alt_unlock() - (Falk Brettschneider <fbrettschneider@baumeroptronic.de>) */ PT_EI int __compare_and_swap_with_release_semantics (long *p, long oldval, long newval) { - __asm__ __volatile__ ("" : : : "memory"); /*MEMORY_BARRIER ();*/ + MEMORY_BARRIER(); return __compare_and_swap (p, oldval, newval); } - -#ifndef IMPLEMENT_TAS_WITH_CAS -/* Spinlock implementation; required. */ +/* Spinlock implementation; required. */ PT_EI long int testandset (int *spinlock) { - unsigned psw; + long int retval; - /* disable interrupts */ - __asm__ __volatile__ ("mfs %0, rmsr;" - "andi r3, %0, ~2;" - "mts rmsr, r3;" - : "=&r" (psw) - : - : "r3"); + __asm__ __volatile__ ("1: lwx %0, %1, r0;" + " bnei %0, 2f;" + " addik %0, r0, 1;" + " swx %0, %1, r0;" + " addic %0, r0, 0;" + " bnei %0, 1b;" + "2:" + : "=&r" (retval) + : "r" (spinlock) + : "cc", "memory"); - if (*spinlock) - { - /* Enable ints */ - __asm__ __volatile__ ("mts rmsr, %0;" :: "r" (psw)); - return 1; - } else { - *spinlock=1; - /* Enable ints */ - __asm__ __volatile__ ("mts rmsr, %0;" :: "r" (psw)); - return 0; - } + return retval; } -#endif #endif /* pt-machine.h */ |