1 /* atomic/gcc_x86.c
2  *  Copyright (C) 2006-2010, Parrot Foundation.
3  */
4 
5 #include "parrot/parrot.h"
6 #include "parrot/atomic/gcc_x86.h"
7 
8 /* HEADERIZER HFILE: include/parrot/atomic/gcc_x86.h */
9 
10 /*
11 
12 =head1 NAME
13 
14 src/atomic/gcc_x86.c
15 
16 =head1 DESCRIPTION
17 
18 An implementation of atomic operations on x86 platforms with GCC-style inline
19 assembly suppport.
20 
21 =head2 Functions
22 
23 =over 4
24 
25 =cut
26 
27 */
28 
29 /*
30  * if both I386 and X86_64 cmpxchg are defined, we are on x86_64 -
31  * reuse existing code
32  */
33 /*
34 
35 =item C<void * parrot_i386_cmpxchg(void *volatile *ptr, void *expect, void
36 *update)>
37 
38 The CMPXCHG assembly instruction is a single cycle x86 instruction
39 that compares C<expect> and C<*ptr>. If they are equal, sets
40 C<*ptr> to C<update>. Otherwise sets C<expect> to C<*ptr>.
41 
42 =cut
43 
44 */
45 
46 
47 PARROT_EXPORT
48 PARROT_CANNOT_RETURN_NULL
49 void *
parrot_i386_cmpxchg(ARGMOD (void * volatile * ptr),ARGIN_NULLOK (void * expect),ARGIN_NULLOK (void * update))50 parrot_i386_cmpxchg(ARGMOD(void *volatile *ptr), ARGIN_NULLOK(void *expect),
51                                         ARGIN_NULLOK(void *update))
52 {
53     ASSERT_ARGS(parrot_i386_cmpxchg)
54 #if defined(PARROT_HAS_AMD64_GCC_CMPXCHG)
55     __asm__ __volatile__("lock\n"
56                          "cmpxchgq %1,%2":"=a"(expect):"q"(update), "m"(*ptr),
57                          "0"(expect)
58                          :"memory");
59 #elif defined(PARROT_HAS_I386_GCC_CMPXCHG)
60     __asm__ __volatile__("lock\n"
61                          "cmpxchgl %1,%2":"=a"(expect):"q"(update), "m"(*ptr),
62                          "0"(expect)
63                          :"memory");
64 #endif
65     return expect;
66 }
67 
68 /*
69 
70 =item C<long parrot_i386_xadd(volatile long *l, long amount)>
71 
72 C<xadd> is an x86 instruction that performs the following operation:
73 Temporary = C<result>;
74 C<result> = C<result> + C<l>;
75 C<l> = C<result>;
76 
77 =cut
78 
79 */
80 
81 
82 PARROT_EXPORT
83 long
parrot_i386_xadd(ARGIN (volatile long * l),long amount)84 parrot_i386_xadd(ARGIN(volatile long *l), long amount)
85 {
86     ASSERT_ARGS(parrot_i386_xadd)
87     long result = amount;
88 #if defined(PARROT_HAS_AMD64_GCC_CMPXCHG)
89     __asm__ __volatile__("lock\n" "xaddq %0, %1" : "=r"(result), "=m"(*l) :
90             "0"(result), "m"(*l));
91 #elif defined(PARROT_HAS_I386_GCC_CMPXCHG)
92     __asm__ __volatile__("lock\n" "xaddl %0, %1" : "=r"(result), "=m"(*l) :
93             "0"(result), "m"(*l));
94 #endif
95     return result + amount;
96 }
97 
98 /*
99 
100 =back
101 
102 =cut
103 
104 */
105 
106 /*
107  * Local variables:
108  *   c-file-style: "parrot"
109  * End:
110  * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
111  */
112