1 /* FluidSynth - A Software Synthesizer
2 *
3 * Copyright (C) 2003 Peter Hanappe and others.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public License
7 * as published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 */
20
21
22 /**
23
24 This header contains an implementation of atomic operations.
25
26 */
27
28 #ifndef _FLUID_ATOMIC_H
29 #define _FLUID_ATOMIC_H
30
31
32 #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
33
34 #ifdef __ATOMIC_SEQ_CST
35 // Use GCC's new atomic operations.
36
37 #define fluid_atomic_order __ATOMIC_SEQ_CST
38
39 #define fluid_atomic_int_exchange_and_add(_pi, _val) (__atomic_add_fetch(_pi, \
40 _val, fluid_atomic_order))
41
42 #define fluid_atomic_int_get(_pi) __atomic_load_n(_pi, fluid_atomic_order)
43 #define fluid_atomic_int_set(_pi, _val) __atomic_store_n(_pi, _val, \
44 fluid_atomic_order)
45 #define fluid_atomic_int_dec_and_test(_pi) (__atomic_sub_fetch(_pi, 1, \
46 fluid_atomic_order) == 0)
47
48 static FLUID_INLINE int
fluid_atomic_int_compare_and_exchange(volatile int * _pi,int _old,int _new)49 fluid_atomic_int_compare_and_exchange(volatile int* _pi, int _old, int _new)
50 {
51 return __atomic_compare_exchange_n(_pi, &_old, _new, 0, fluid_atomic_order,
52 fluid_atomic_order);
53 }
54
55
56 #define fluid_atomic_pointer_get(_pp) __atomic_load_n(_pp, fluid_atomic_order)
57 #define fluid_atomic_pointer_set(_pp, _val) __atomic_store_n(_pp, _val, \
58 fluid_atomic_order)
59
60 static FLUID_INLINE int
fluid_atomic_pointer_compare_and_exchange(volatile void * _pi,volatile void * _old,void * _new)61 fluid_atomic_pointer_compare_and_exchange(volatile void* _pi, volatile void* _old,
62 void* _new)
63 {
64 return __atomic_compare_exchange_n((volatile void**)_pi, &_old, _new, 0,
65 fluid_atomic_order, fluid_atomic_order);
66 }
67
68 #else
69 // Use older __sync atomics.
70
71 #define fluid_atomic_int_exchange_and_add(_pi, _val) __sync_add_and_fetch(_pi, \
72 _val)
73
74 static FLUID_INLINE int
fluid_atomic_int_get(volatile int * _pi)75 fluid_atomic_int_get(volatile int* _pi)
76 {
77 __sync_synchronize();
78 return (int)*_pi;
79 }
80
81 static FLUID_INLINE void
fluid_atomic_int_set(volatile int * _pi,int _val)82 fluid_atomic_int_set(volatile int* _pi, int _val) {
83 *_pi = _val;
84 __sync_synchronize();
85 }
86
87 #define fluid_atomic_int_dec_and_test(_pi) (__sync_sub_and_fetch(_pi, 1) == 0)
88 #define fluid_atomic_int_compare_and_exchange(_pi, _old, _new) \
89 ((int)__sync_bool_compare_and_swap(_pi, _old, _new))
90
91 static FLUID_INLINE void*
fluid_atomic_pointer_get(volatile void * _pi)92 fluid_atomic_pointer_get(volatile void* _pi)
93 {
94 __sync_synchronize();
95 return *(void**)_pi;
96 }
97
98 static FLUID_INLINE void
fluid_atomic_pointer_set(volatile void * _pi,void * _val)99 fluid_atomic_pointer_set(volatile void* _pi, void* _val) {
100 *(void**)_pi = _val;
101 __sync_synchronize();
102 }
103
104 #define fluid_atomic_pointer_compare_and_exchange \
105 fluid_atomic_int_compare_and_exchange
106
107 #endif // ifdef __ATOMIC_SEQ_CST
108
109 #elif defined(_WIN32)
110
111 #include <Windows.h>
112
113 #define fluid_atomic_int_exchange_and_add(_pi, _val) \
114 ((LONG)InterlockedExchangeAdd((LONG volatile*)(_pi), (LONG)(_val)))
115
116 #define fluid_atomic_int_get(_pi) (*(int*)(_pi))
117 #define fluid_atomic_int_set(_pi, _val) (void)(InterlockedExchange (\
118 (LONG volatile*)(_pi), \
119 (LONG)(_val)))
120 #define fluid_atomic_int_dec_and_test(_pi) (InterlockedDecrement( \
121 (LONG volatile*)(_pi)) == 0)
122
123 #define fluid_atomic_int_compare_and_exchange(_pi, _old, _new) \
124 InterlockedCompareExchange((LONG volatile*)(_pi), (LONG)(_new), (LONG)(_old))
125
126 #define fluid_atomic_pointer_get(_pp) (*(void**)pp)
127 #define fluid_atomic_pointer_set(_pp, _val) (void)(InterlockedExchangePointer(_pp,\
128 _val))
129
130 #define fluid_atomic_pointer_compare_and_exchange(_pp, _old, _new) \
131 InterlockedCompareExchangePointer(_pp, _new, _old)
132
133 #else
134
135 #error Unsupported system.
136
137 #endif // defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4), defined(_WIN32)
138
139 #define fluid_atomic_int_add(_pi, _val) (void)(fluid_atomic_int_exchange_and_add(\
140 _pi, _val))
141 #define fluid_atomic_int_inc(_pi) fluid_atomic_int_add(_pi, 1)
142
143 static FLUID_INLINE void
fluid_atomic_float_set(volatile float * fptr,float val)144 fluid_atomic_float_set(volatile float *fptr, float val)
145 {
146 sint32 ival;
147 memcpy (&ival, &val, 4);
148 fluid_atomic_int_set ((volatile int *)fptr, ival);
149 }
150
151 static FLUID_INLINE float
fluid_atomic_float_get(volatile float * fptr)152 fluid_atomic_float_get(volatile float *fptr)
153 {
154 sint32 ival;
155 float fval;
156 ival = fluid_atomic_int_get ((volatile int *)fptr);
157 memcpy (&fval, &ival, 4);
158 return fval;
159 }
160
161 #endif
162