New files to implement atomic operations for different platforms. Fixes
[platform/upstream/glib.git] / glib / gatomic.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * GAtomic: atomic integer operation.
5  * Copyright (C) 2003 Sebastian Wilhelmi
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22  
23 #include <glib.h>
24
25 #ifdef G_THREADS_ENABLED
26 # if !defined (G_ATOMIC_USE_FALLBACK_IMPLEMENTATION)
27 /* We have an inline implementation, which we can now use for the
28  * fallback implementation. This fallback implementation is only used by
29  * modules, which are not compliled with gcc 
30  */
31
32 gint32
33 g_atomic_int_exchange_and_add_fallback (gint32 *atomic, 
34                                         gint32  val)
35 {
36   return g_atomic_int_exchange_and_add (atomic, val);
37 }
38
39
40 void
41 g_atomic_int_add_fallback (gint32 *atomic,
42                            gint32  val)
43 {
44   g_atomic_int_add (atomic, val);
45 }
46
47 gboolean
48 g_atomic_int_compare_and_exchange_fallback (gint32 *atomic, 
49                                             gint32  oldval, 
50                                             gint32  newval)
51 {
52   return g_atomic_int_compare_and_exchange (atomic, oldval, newval);
53 }
54
55 gboolean
56 g_atomic_pointer_compare_and_exchange_fallback (gpointer *atomic, 
57                                                 gpointer  oldval, 
58                                                 gpointer  newval)
59 {
60   return g_atomic_pointer_compare_and_exchange (atomic, oldval, newval);
61 }
62
63 gint32
64 g_atomic_int_get_fallback (gint32 *atomic)
65 {
66   return g_atomic_int_get (atomic);
67 }
68
69 gint32
70 g_atomic_pointer_get_fallback (gpointer *atomic)
71 {
72   return g_atomic_int_get (atomic);
73 }   
74
75 # else /* !G_ATOMIC_USE_FALLBACK_IMPLEMENTATION */
76 /* We have to use the slow, but safe locking method */
77 G_LOCK_DEFINE_STATIC (g_atomic_lock);
78
79 gint32
80 g_atomic_int_exchange_and_add_fallback (gint32 *atomic, 
81                                         gint32  val)
82 {
83   gint32 result;
84     
85   G_LOCK (g_atomic_lock);
86   result = *atomic;
87   *atomic += val;
88   G_UNLOCK (g_atomic_lock);
89
90   return result;
91 }
92
93
94 void
95 g_atomic_int_add_fallback (gint32 *atomic,
96                            gint32  val)
97 {
98   G_LOCK (g_atomic_lock);
99   *atomic += val;
100   G_UNLOCK (g_atomic_lock);
101 }
102
103 gboolean
104 g_atomic_int_compare_and_exchange_fallback (gint32 *atomic, 
105                                             gint32  oldval, 
106                                             gint32  newval)
107 {
108   gboolean result;
109     
110   G_LOCK (g_atomic_lock);
111   if (*atomic == oldval)
112     {
113       result = TRUE;
114       *atomic = newval;
115     }
116   else
117     result = FALSE;
118   G_UNLOCK (g_atomic_lock);
119
120   return result;
121 }
122
123 gboolean
124 g_atomic_pointer_compare_and_exchange_fallback (gpointer *atomic, 
125                                                 gpointer  oldval, 
126                                                 gpointer  newval)
127 {
128   gboolean result;
129     
130   G_LOCK (g_atomic_lock);
131   if (*atomic == oldval)
132     {
133       result = TRUE;
134       *atomic = newval;
135     }
136   else
137     result = FALSE;
138   G_UNLOCK (g_atomic_lock);
139
140   return result;
141 }
142
143 static inline gint32
144 g_atomic_int_get_fallback (gint32 *atomic)
145 {
146   gint32 result;
147
148   G_LOCK (g_atomic_lock);
149   result = *atomic;
150   G_UNLOCK (g_atomic_lock);
151
152   return result;
153 }
154
155 static inline gpointer
156 g_atomic_pointer_get_fallback (gpointer *atomic)
157 {
158   gpointer result;
159
160   G_LOCK (g_atomic_lock);
161   result = *atomic;
162   G_UNLOCK (g_atomic_lock);
163
164   return result;
165 }   
166
167
168 # endif /* G_ATOMIC_USE_FALLBACK_IMPLEMENTATION */
169 #else /* !G_THREADS_ENABLED */
170 gint32 g_atomic_int_exchange_and_add (gint32 *atomic, 
171                                       gint32  val)
172 {
173   gint32 result = *atomic;
174   *atomic += val;
175   return result;
176 }
177 #endif /* G_THREADS_ENABLED */
178