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