Commit | Line | Data |
dce16143 |
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 */ |
4dab3d39 |
80 | # else |
81 | # define EMULATE_ATOMIC_REFCOUNTS |
dce16143 |
82 | # endif /* sparc64 */ |
83 | #endif /* i386 */ |
84 | #else |
85 | /* Add non-gcc native atomic operations here */ |
86 | # define EMULATE_ATOMIC_REFCOUNTS |
87 | #endif |