Merge pull request #601 from knocte/sock_improvements
[mono.git] / mono / utils / 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/utils/atomic.h>
16
17 #ifdef WAPI_NO_ATOMIC_ASM
18
19 static pthread_mutex_t spin = PTHREAD_MUTEX_INITIALIZER;
20 static mono_once_t spin_once=MONO_ONCE_INIT;
21
22 static void spin_init(void)
23 {
24         g_warning("Using non-atomic functions!  Expect race conditions when using process-shared handles!");
25 }
26
27 gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch,
28                                   gint32 comp)
29 {
30         gint32 old;
31         int ret;
32         
33         mono_once(&spin_once, spin_init);
34         
35         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
36                               (void *)&spin);
37         ret = pthread_mutex_lock(&spin);
38         g_assert (ret == 0);
39         
40         old= *dest;
41         if(old==comp) {
42                 *dest=exch;
43         }
44         
45         ret = pthread_mutex_unlock(&spin);
46         g_assert (ret == 0);
47         
48         pthread_cleanup_pop (0);
49
50         return(old);
51 }
52
53 gpointer InterlockedCompareExchangePointer(volatile gpointer *dest,
54                                            gpointer exch, gpointer comp)
55 {
56         gpointer old;
57         int ret;
58         
59         mono_once(&spin_once, spin_init);
60         
61         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
62                               (void *)&spin);
63         ret = pthread_mutex_lock(&spin);
64         g_assert (ret == 0);
65         
66         old= *dest;
67         if(old==comp) {
68                 *dest=exch;
69         }
70         
71         ret = pthread_mutex_unlock(&spin);
72         g_assert (ret == 0);
73         
74         pthread_cleanup_pop (0);
75
76         return(old);
77 }
78
79 gint32 InterlockedIncrement(volatile gint32 *dest)
80 {
81         gint32 ret;
82         int thr_ret;
83         
84         mono_once(&spin_once, spin_init);
85         
86         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
87                               (void *)&spin);
88         thr_ret = pthread_mutex_lock(&spin);
89         g_assert (thr_ret == 0);
90
91         (*dest)++;
92         ret= *dest;
93         
94         thr_ret = pthread_mutex_unlock(&spin);
95         g_assert (thr_ret == 0);
96         
97         pthread_cleanup_pop (0);
98         
99         return(ret);
100 }
101
102 gint32 InterlockedDecrement(volatile gint32 *dest)
103 {
104         gint32 ret;
105         int thr_ret;
106         
107         mono_once(&spin_once, spin_init);
108         
109         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
110                               (void *)&spin);
111         thr_ret = pthread_mutex_lock(&spin);
112         g_assert (thr_ret == 0);
113         
114         (*dest)--;
115         ret= *dest;
116         
117         thr_ret = pthread_mutex_unlock(&spin);
118         g_assert (thr_ret == 0);
119         
120         pthread_cleanup_pop (0);
121         
122         return(ret);
123 }
124
125 gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
126 {
127         gint32 ret;
128         int thr_ret;
129         
130         mono_once(&spin_once, spin_init);
131         
132         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
133                               (void *)&spin);
134         thr_ret = pthread_mutex_lock(&spin);
135         g_assert (thr_ret == 0);
136
137         ret=*dest;
138         *dest=exch;
139         
140         thr_ret = pthread_mutex_unlock(&spin);
141         g_assert (thr_ret == 0);
142         
143         pthread_cleanup_pop (0);
144         
145         return(ret);
146 }
147
148 gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
149 {
150         gpointer ret;
151         int thr_ret;
152         
153         mono_once(&spin_once, spin_init);
154         
155         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
156                               (void *)&spin);
157         thr_ret = pthread_mutex_lock(&spin);
158         g_assert (thr_ret == 0);
159         
160         ret=*dest;
161         *dest=exch;
162         
163         thr_ret = pthread_mutex_unlock(&spin);
164         g_assert (thr_ret == 0);
165         
166         pthread_cleanup_pop (0);
167         
168         return(ret);
169 }
170
171 gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
172 {
173         gint32 ret;
174         int thr_ret;
175         
176         mono_once(&spin_once, spin_init);
177         
178         pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
179                               (void *)&spin);
180         thr_ret = pthread_mutex_lock(&spin);
181         g_assert (thr_ret == 0);
182
183         ret= *dest;
184         *dest+=add;
185         
186         thr_ret = pthread_mutex_unlock(&spin);
187         g_assert (thr_ret == 0);
188
189         pthread_cleanup_pop (0);
190
191         return(ret);
192 }
193
194 #endif