This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: perl 5.0061 unable to build on sparc 5 Sol2.5.1 threads.
[perl5.git] / atomic.h
1 #ifdef __GNUC__
2
3 /*
4  * These atomic operations copied from the linux kernel and altered
5  * only slightly. I need to get official permission to distribute
6  * under the Artistic License.
7  */
8 /* We really need to integrate the atomic typedef with the typedef
9  * used by sv_refcnt of an SV. It's possible that for CPUs like alpha
10  * where we'd need to up sv_refcnt from 32 to 64 bits, we may be better
11  * off sticking with EMULATE_ATOMIC_REFCOUNTS instead.
12  */
13 typedef U32 atomic_t;   /* kludge */
14
15 #ifdef i386
16
17 #  ifdef NO_SMP
18 #    define LOCK ""
19 #  else
20 #    define LOCK "lock ; "
21 #  endif
22
23 #  define __atomic_fool_gcc(x) (*(struct { int a[100]; } *)x)
24 static __inline__ void atomic_inc(atomic_t *v)
25 {
26     __asm__ __volatile__(
27             LOCK "incl %0"
28             :"=m" (__atomic_fool_gcc(v))
29             :"m" (__atomic_fool_gcc(v)));
30 }
31
32 static __inline__ int atomic_dec_and_test(atomic_t *v)
33 {
34     unsigned char c;
35
36     __asm__ __volatile__(
37             LOCK "decl %0; sete %1"
38             :"=m" (__atomic_fool_gcc(v)), "=qm" (c)
39             :"m" (__atomic_fool_gcc(v)));
40     return c != 0;
41 }
42 #  else
43 /* XXX What symbol does gcc define for sparc64? */
44 #  ifdef sparc64
45 #    define __atomic_fool_gcc(x) ((struct { int a[100]; } *)x)
46 typedef U32 atomic_t;
47 extern __inline__ void atomic_add(int i, atomic_t *v)
48 {
49         __asm__ __volatile__("
50 1:      lduw            [%1], %%g5
51         add             %%g5, %0, %%g7
52         cas             [%1], %%g5, %%g7
53         sub             %%g5, %%g7, %%g5
54         brnz,pn         %%g5, 1b
55          nop"
56         : /* No outputs */
57         : "HIr" (i), "r" (__atomic_fool_gcc(v))
58         : "g5", "g7", "memory");
59 }
60
61 extern __inline__ int atomic_sub_return(int i, atomic_t *v)
62 {
63         unsigned long oldval;
64         __asm__ __volatile__("
65 1:      lduw            [%2], %%g5
66         sub             %%g5, %1, %%g7
67         cas             [%2], %%g5, %%g7
68         sub             %%g5, %%g7, %%g5
69         brnz,pn         %%g5, 1b
70          sub            %%g7, %1, %0"
71         : "=&r" (oldval)
72         : "HIr" (i), "r" (__atomic_fool_gcc(v))
73         : "g5", "g7", "memory");
74         return (int)oldval;
75 }
76
77 #define atomic_inc(v) atomic_add(1,(v))
78 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
79 /* Add further gcc architectures here */
80 #  else
81 #    define EMULATE_ATOMIC_REFCOUNTS
82 #  endif /* sparc64 */
83 #endif /* i386 */
84 #else
85 /* Add non-gcc native atomic operations here */
86 #  define EMULATE_ATOMIC_REFCOUNTS
87 #endif