root/trunk/libffado/src/libutil/Atomic.h

Revision 864, 5.6 kB (checked in by ppalmers, 16 years ago)

update license to GPLv2 or GPLv3 instead of GPLv2 or any later version. Update copyrights to reflect the new year

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 /*
25  * Copied from the jackd/jackdmp sources
26  * function names changed in order to avoid naming problems when using this in
27  * a jackd backend.
28  */
29
30 /* Original license:
31  *
32  *  Copyright (C) 2004-2006 Grame
33  *
34  *  This program is free software; you can redistribute it and/or modify
35  *  it under the terms of the GNU General Public License as published by
36  *  the Free Software Foundation; either version 2 of the License, or
37  *  (at your option) version 3 of the License.
38  *
39  *  This program is distributed in the hope that it will be useful,
40  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
41  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
42  *  GNU General Public License for more details.
43  *
44  *  You should have received a copy of the GNU General Public License
45  *  along with this program; if not, write to the Free Software
46  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
47  *
48  */
49
50 #ifndef __FFADOATOMIC__
51 #define __FFADOATOMIC__
52
53 typedef unsigned short UInt16;
54 typedef unsigned long UInt32;
55 typedef long SInt32;
56 typedef unsigned long long UInt64;
57
58 #if defined(__APPLE__)
59
60 #if defined(__ppc__)
61
62 static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
63 {
64     register int result;
65     asm volatile (
66         "# CAS                    \n"
67         "    lwarx    r0, 0, %1    \n"         // creates a reservation on addr
68         "    cmpw    r0, %2        \n"            //  test value at addr
69         "    bne-    1f          \n"
70         "    sync                \n"         //  synchronize instructions
71         "    stwcx.    %3, 0, %1    \n"         //  if the reservation is not altered
72         //  stores the new value at addr
73         "    bne-    1f          \n"
74         "   li      %0, 1       \n"
75         "    b        2f          \n"
76         "1:                     \n"
77         "   li      %0, 0       \n"
78         "2:                     \n"
79         : "=r" (result)
80         : "r" (addr), "r" (value), "r" (newvalue)
81         : "r0"
82         );
83     return result;
84 }
85
86 #endif
87
88 #if defined(__i386__) || defined(__x86_64__)
89
90 #ifdef __SMP__
91 #    define LOCK "lock ; "
92 #else
93 #    define LOCK ""
94 #endif
95
96 static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
97 {
98     register char ret;
99     __asm__ __volatile__ (
100         "# CAS \n\t"
101         LOCK "cmpxchg %2, (%1) \n\t"
102         "sete %0               \n\t"
103         : "=a" (ret)
104         : "c" (addr), "d" (newvalue), "a" (value)
105         );
106     return ret;
107 }
108
109 #endif
110
111 #endif
112
113 #ifdef __linux__
114
115 #ifdef __PPC__
116
117 static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
118 {
119     register int result;
120     register UInt32 tmp;
121     asm volatile (
122         "# CAS                    \n"
123         "    lwarx    %4, 0, %1    \n"         // creates a reservation on addr
124         "    cmpw    %4, %2        \n"        //  test value at addr
125         "    bne-    1f          \n"
126         "    sync                \n"         //  synchronize instructions
127         "    stwcx.    %3, 0, %1    \n"         //  if the reservation is not altered
128         //  stores the new value at addr
129         "    bne-    1f          \n"
130         "   li      %0, 1       \n"
131         "    b        2f          \n"
132         "1:                     \n"
133         "   li      %0, 0       \n"
134         "2:                     \n"
135         : "=r" (result)
136         : "r" (addr), "r" (value), "r" (newvalue), "r" (tmp)
137         );
138     return result;
139 }
140
141 #endif
142
143 #if defined(__i386__) || defined(__x86_64__)
144
145 #ifdef __SMP__
146 #    define LOCK "lock ; "
147 #else
148 #    define LOCK ""
149 #endif
150
151 static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
152 {
153     register char ret;
154     __asm__ __volatile__ (
155         "# CAS \n\t"
156         LOCK "cmpxchg %2, (%1) \n\t"
157         "sete %0               \n\t"
158         : "=a" (ret)
159         : "c" (addr), "d" (newvalue), "a" (value)
160         );
161     return ret;
162 }
163
164 #endif
165
166 #endif
167
168 static inline long INC_ATOMIC(volatile SInt32* val)
169 {
170     SInt32 actual;
171     do {
172         actual = *val;
173     } while (!CAS(actual, actual + 1, val));
174     return actual;
175 }
176
177 static inline long DEC_ATOMIC(volatile SInt32* val)
178 {
179     SInt32 actual;
180     do {
181         actual = *val;
182     } while (!CAS(actual, actual - 1, val));
183     return actual;
184 }
185
186 static inline long ADD_ATOMIC(volatile SInt32* val, SInt32 addval)
187 {
188     SInt32 actual;
189     do {
190         actual = *val;
191     } while (!CAS(actual, actual + addval, val));
192     return actual;
193 }
194
195 static inline long SUBSTRACT_ATOMIC(volatile SInt32* val, SInt32 addval)
196 {
197     SInt32 actual;
198     do {
199         actual = *val;
200     } while (!CAS(actual, actual - addval, val));
201     return actual;
202 }
203
204 static inline long ZERO_ATOMIC(volatile SInt32* val)
205 {
206     SInt32 actual;
207     do {
208         actual = *val;
209     } while (!CAS(actual, 0, val));
210     return actual;
211 }
212
213 #endif // __FFADO_ATOMIC__
214
Note: See TracBrowser for help on using the browser.