* Makefile (MCS) [PROFILE=default]: Force testing of 'mcs'.
[mono.git] / mono / io-layer / atomic.c
1 /*
2  * atomic.c:  Workarounds for atomic operations for platforms that dont have
3  *            really atomic asm functions in atomic.h
4  *
5  * Author:
6  *      Dick Porter (dick@ximian.com)
7  *
8  * (C) 2002 Ximian, Inc.
9  */
10
11 #include <config.h>
12 #include <glib.h>
13 #include <pthread.h>
14
15 #include "mono/io-layer/wapi.h"
16
17 #ifdef WAPI_ATOMIC_ASM
18 #if defined(sparc) || defined (__sparc__)
19 volatile unsigned char _wapi_sparc_lock;
20 #endif
21 #else
22
23 static pthread_mutex_t spin = PTHREAD_MUTEX_INITIALIZER;
24 static mono_once_t spin_once=MONO_ONCE_INIT;
25
26 static void spin_init(void)
27 {
28         g_warning("Using non-atomic functions!");
29 }
30
31 gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch,
32                                   gint32 comp)
33 {
34         gint32 old;
35         int ret;
36         
37         mono_once(&spin_once, spin_init);
38         
39         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
40                               (void *)&spin);
41         ret = pthread_mutex_lock(&spin);
42         g_assert (ret == 0);
43         
44         old= *dest;
45         if(old==comp) {
46                 *dest=exch;
47         }
48         
49         ret = pthread_mutex_unlock(&spin);
50         g_assert (ret == 0);
51         
52         pthread_cleanup_pop (0);
53
54         return(old);
55 }
56
57 gpointer InterlockedCompareExchangePointer(volatile gpointer *dest,
58                                            gpointer exch, gpointer comp)
59 {
60         gpointer old;
61         int ret;
62         
63         mono_once(&spin_once, spin_init);
64         
65         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
66                               (void *)&spin);
67         ret = pthread_mutex_lock(&spin);
68         g_assert (ret == 0);
69         
70         old= *dest;
71         if(old==comp) {
72                 *dest=exch;
73         }
74         
75         ret = pthread_mutex_unlock(&spin);
76         g_assert (ret == 0);
77         
78         pthread_cleanup_pop (0);
79
80         return(old);
81 }
82
83 gint32 InterlockedIncrement(volatile gint32 *dest)
84 {
85         gint32 ret;
86         int thr_ret;
87         
88         mono_once(&spin_once, spin_init);
89         
90         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
91                               (void *)&spin);
92         thr_ret = pthread_mutex_lock(&spin);
93         g_assert (thr_ret == 0);
94         
95         *dest++;
96         ret= *dest;
97         
98         thr_ret = pthread_mutex_unlock(&spin);
99         g_assert (thr_ret == 0);
100         
101         pthread_cleanup_pop (0);
102         
103         return(ret);
104 }
105
106 gint32 InterlockedDecrement(volatile gint32 *dest)
107 {
108         gint32 ret;
109         int thr_ret;
110         
111         mono_once(&spin_once, spin_init);
112         
113         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
114                               (void *)&spin);
115         thr_ret = pthread_mutex_lock(&spin);
116         g_assert (thr_ret == 0);
117         
118         *dest--;
119         ret= *dest;
120         
121         thr_ret = pthread_mutex_unlock(&spin);
122         g_assert (thr_ret == 0);
123         
124         pthread_cleanup_pop (0);
125         
126         return(ret);
127 }
128
129 gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
130 {
131         gint32 ret;
132         int thr_ret;
133         
134         mono_once(&spin_once, spin_init);
135         
136         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
137                               (void *)&spin);
138         thr_ret = pthread_mutex_lock(&spin);
139         g_assert (thr_ret == 0);
140
141         ret=*dest;
142         *dest=exch;
143         
144         thr_ret = pthread_mutex_unlock(&spin);
145         g_assert (thr_ret == 0);
146         
147         pthread_cleanup_pop (0);
148         
149         return(ret);
150 }
151
152 gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
153 {
154         gpointer ret;
155         int thr_ret;
156         
157         mono_once(&spin_once, spin_init);
158         
159         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
160                               (void *)&spin);
161         thr_ret = pthread_mutex_lock(&spin);
162         g_assert (thr_ret == 0);
163         
164         ret=*dest;
165         *dest=exch;
166         
167         thr_ret = pthread_mutex_unlock(&spin);
168         g_assert (thr_ret == 0);
169         
170         pthread_cleanup_pop (0);
171         
172         return(ret);
173 }
174
175 gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
176 {
177         gint32 ret;
178         int thr_ret;
179         
180         mono_once(&spin_once, spin_init);
181         
182         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
183                               (void *)&spin);
184         thr_ret = pthread_mutex_lock(&spin);
185         g_assert (thr_ret == 0);
186
187         ret= *dest;
188         *dest+=add;
189         
190         thr_ret = pthread_mutex_unlock(&spin);
191         g_assert (thr_ret == 0);
192
193         pthread_cleanup_pop (0);
194
195         return(ret);
196 }
197
198 #endif