Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

apr_atomic.h

Go to the documentation of this file.
00001 /* Copyright 2000-2004 The Apache Software Foundation 00002 * 00003 * Licensed under the Apache License, Version 2.0 (the "License"); 00004 * you may not use this file except in compliance with the License. 00005 * You may obtain a copy of the License at 00006 * 00007 * http://www.apache.org/licenses/LICENSE-2.0 00008 * 00009 * Unless required by applicable law or agreed to in writing, software 00010 * distributed under the License is distributed on an "AS IS" BASIS, 00011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 * See the License for the specific language governing permissions and 00013 * limitations under the License. 00014 */ 00015 00016 #ifndef APR_ATOMIC_H 00017 #define APR_ATOMIC_H 00018 00024 #include "apr.h" 00025 #include "apr_pools.h" 00026 00027 /* Platform includes for atomics */ 00028 #if defined(NETWARE) || defined(__MVS__) /* OS/390 */ 00029 #include <stdlib.h> 00030 #elif defined(__FreeBSD__) 00031 #include <machine/atomic.h> 00032 #endif 00033 00034 #ifdef __cplusplus 00035 extern "C" { 00036 #endif 00037 00044 /* easiest way to get these documented for the moment */ 00045 #if defined(DOXYGEN) 00046 00050 typedef apr_atomic_t; 00051 00058 apr_status_t apr_atomic_init(apr_pool_t *p); 00065 apr_uint32_t apr_atomic_read(volatile apr_atomic_t *mem); 00071 void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val); 00077 void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val); 00078 00083 void apr_atomic_inc(volatile apr_atomic_t *mem); 00084 00090 int apr_atomic_dec(volatile apr_atomic_t *mem); 00091 00102 apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem, long with, long cmp); 00103 00112 void *apr_atomic_casptr(volatile void **mem, void *with, const void *cmp); 00113 #else /* !DOXYGEN */ 00114 00115 /* The following definitions provide optimized, OS-specific 00116 * implementations of the APR atomic functions on various 00117 * platforms. Any atomic operation that isn't redefined as 00118 * a macro here will be declared as a function later, and 00119 * apr_atomic.c will provide a mutex-based default implementation. 00120 */ 00121 00122 #if defined(WIN32) 00123 00124 #define apr_atomic_t LONG 00125 00126 #define apr_atomic_add(mem, val) InterlockedExchangeAdd(mem,val) 00127 #define apr_atomic_dec(mem) InterlockedDecrement(mem) 00128 #define apr_atomic_inc(mem) InterlockedIncrement(mem) 00129 #define apr_atomic_set(mem, val) InterlockedExchange(mem, val) 00130 #define apr_atomic_read(mem) (*mem) 00131 #define apr_atomic_cas(mem,with,cmp) InterlockedCompareExchange(mem,with,cmp) 00132 #define apr_atomic_init(pool) APR_SUCCESS 00133 #define apr_atomic_casptr(mem,with,cmp) InterlockedCompareExchangePointer(mem,with,cmp) 00134 00135 #elif defined(NETWARE) 00136 00137 #define apr_atomic_t unsigned long 00138 00139 #define apr_atomic_add(mem, val) atomic_add(mem,val) 00140 #define apr_atomic_inc(mem) atomic_inc(mem) 00141 #define apr_atomic_set(mem, val) (*mem = val) 00142 #define apr_atomic_read(mem) (*mem) 00143 #define apr_atomic_init(pool) APR_SUCCESS 00144 #define apr_atomic_cas(mem,with,cmp) atomic_cmpxchg((unsigned long *)(mem),(unsigned long)(cmp),(unsigned long)(with)) 00145 00146 int apr_atomic_dec(apr_atomic_t *mem); 00147 void *apr_atomic_casptr(void **mem, void *with, const void *cmp); 00148 #define APR_OVERRIDE_ATOMIC_DEC 1 00149 #define APR_OVERRIDE_ATOMIC_CASPTR 1 00150 00151 inline int apr_atomic_dec(apr_atomic_t *mem) 00152 { 00153 atomic_dec(mem); 00154 return *mem; 00155 } 00156 00157 inline void *apr_atomic_casptr(void **mem, void *with, const void *cmp) 00158 { 00159 return (void*)atomic_cmpxchg((unsigned long *)mem,(unsigned long)cmp,(unsigned long)with); 00160 } 00161 00162 #elif defined(__FreeBSD__) 00163 00164 #define apr_atomic_t apr_uint32_t 00165 #define apr_atomic_add(mem, val) atomic_add_int(mem,val) 00166 #define apr_atomic_dec(mem) atomic_subtract_int(mem,1) 00167 #define apr_atomic_inc(mem) atomic_add_int(mem,1) 00168 #define apr_atomic_set(mem, val) atomic_set_int(mem, val) 00169 #define apr_atomic_read(mem) (*mem) 00170 00171 #elif (defined(__linux__) || defined(__EMX__)) && defined(__i386__) && !APR_FORCE_ATOMIC_GENERIC 00172 00173 #define apr_atomic_t apr_uint32_t 00174 #define apr_atomic_cas(mem,with,cmp) \ 00175 ({ apr_atomic_t prev; \ 00176 asm volatile ("lock; cmpxchgl %1, %2" \ 00177 : "=a" (prev) \ 00178 : "r" (with), "m" (*(mem)), "0"(cmp) \ 00179 : "memory"); \ 00180 prev;}) 00181 00182 #define apr_atomic_add(mem, val) \ 00183 ({ register apr_atomic_t last; \ 00184 do { \ 00185 last = *(mem); \ 00186 } while (apr_atomic_cas((mem), last + (val), last) != last); \ 00187 }) 00188 00189 #define apr_atomic_dec(mem) \ 00190 ({ register apr_atomic_t last; \ 00191 do { \ 00192 last = *(mem); \ 00193 } while (apr_atomic_cas((mem), last - 1, last) != last); \ 00194 (--last != 0); }) 00195 00196 #define apr_atomic_inc(mem) \ 00197 ({ register apr_atomic_t last; \ 00198 do { \ 00199 last = *(mem); \ 00200 } while (apr_atomic_cas((mem), last + 1, last) != last); \ 00201 }) 00202 00203 #define apr_atomic_set(mem, val) (*(mem) = val) 00204 #define apr_atomic_read(mem) (*(mem)) 00205 #define apr_atomic_init(pool) APR_SUCCESS 00206 00207 #elif defined(__MVS__) /* OS/390 */ 00208 00209 #define apr_atomic_t cs_t 00210 00211 apr_int32_t apr_atomic_add(volatile apr_atomic_t *mem, apr_int32_t val); 00212 apr_uint32_t apr_atomic_cas(volatile apr_atomic_t *mem, apr_uint32_t swap, 00213 apr_uint32_t cmp); 00214 #define APR_OVERRIDE_ATOMIC_ADD 1 00215 #define APR_OVERRIDE_ATOMIC_CAS 1 00216 00217 #define apr_atomic_inc(mem) apr_atomic_add(mem, 1) 00218 #define apr_atomic_dec(mem) apr_atomic_add(mem, -1) 00219 #define apr_atomic_init(pool) APR_SUCCESS 00220 00221 /* warning: the following two operations, _read and _set, are atomic 00222 * if the memory variables are aligned (the usual case). 00223 * 00224 * If you try really hard and manage to mis-align them, they are not 00225 * guaranteed to be atomic on S/390. But then your program will blow up 00226 * with SIGBUS on a sparc, or with a S0C6 abend if you use the mis-aligned 00227 * variables with other apr_atomic_* operations on OS/390. 00228 */ 00229 00230 #define apr_atomic_read(p) (*p) 00231 #define apr_atomic_set(mem, val) (*mem = val) 00232 00233 #endif /* end big if-elseif switch for platform-specifics */ 00234 00235 00236 /* Default implementation of the atomic API 00237 * The definitions above may override some or all of the 00238 * atomic functions with optimized, platform-specific versions. 00239 * Any operation that hasn't been overridden as a macro above 00240 * is declared as a function here, unless APR_OVERRIDE_ATOMIC_[OPERATION] 00241 * is defined. (The purpose of the APR_OVERRIDE_ATOMIC_* is 00242 * to allow a platform to declare an apr_atomic_*() function 00243 * with a different signature than the default.) 00244 */ 00245 00246 #if !defined(apr_atomic_t) 00247 #define apr_atomic_t apr_uint32_t 00248 #endif 00249 00250 #if !defined(apr_atomic_init) && !defined(APR_OVERRIDE_ATOMIC_INIT) 00251 apr_status_t apr_atomic_init(apr_pool_t *p); 00252 #endif 00253 00254 #if !defined(apr_atomic_read) && !defined(APR_OVERRIDE_ATOMIC_READ) 00255 #define apr_atomic_read(p) *p 00256 #endif 00257 00258 #if !defined(apr_atomic_set) && !defined(APR_OVERRIDE_ATOMIC_SET) 00259 void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val); 00260 #define APR_ATOMIC_NEED_DEFAULT_INIT 1 00261 #endif 00262 00263 #if !defined(apr_atomic_add) && !defined(APR_OVERRIDE_ATOMIC_ADD) 00264 void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val); 00265 #define APR_ATOMIC_NEED_DEFAULT_INIT 1 00266 #endif 00267 00268 #if !defined(apr_atomic_inc) && !defined(APR_OVERRIDE_ATOMIC_INC) 00269 void apr_atomic_inc(volatile apr_atomic_t *mem); 00270 #define APR_ATOMIC_NEED_DEFAULT_INIT 1 00271 #endif 00272 00273 #if !defined(apr_atomic_dec) && !defined(APR_OVERRIDE_ATOMIC_DEC) 00274 int apr_atomic_dec(volatile apr_atomic_t *mem); 00275 #define APR_ATOMIC_NEED_DEFAULT_INIT 1 00276 #endif 00277 00278 #if !defined(apr_atomic_cas) && !defined(APR_OVERRIDE_ATOMIC_CAS) 00279 apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem,long with,long cmp); 00280 #define APR_ATOMIC_NEED_DEFAULT_INIT 1 00281 #endif 00282 00283 #if !defined(apr_atomic_casptr) && !defined(APR_OVERRIDE_ATOMIC_CASPTR) 00284 #if APR_SIZEOF_VOIDP == 4 00285 #define apr_atomic_casptr(mem, with, cmp) (void *)apr_atomic_cas((apr_uint32_t *)(mem), (long)(with), (long)cmp) 00286 #else 00287 void *apr_atomic_casptr(volatile void **mem, void *with, const void *cmp); 00288 #define APR_ATOMIC_NEED_DEFAULT_INIT 1 00289 #endif 00290 #endif 00291 00292 #ifndef APR_ATOMIC_NEED_DEFAULT_INIT 00293 #define APR_ATOMIC_NEED_DEFAULT_INIT 0 00294 #endif 00295 00296 /* If we're using the default versions of any of the atomic functions, 00297 * we'll need the atomic init to set up mutexes. If a platform-specific 00298 * override above has replaced the atomic_init with a macro, it's an error. 00299 */ 00300 #if APR_ATOMIC_NEED_DEFAULT_INIT 00301 #if defined(apr_atomic_init) || defined(APR_OVERRIDE_ATOMIC_INIT) 00302 #error Platform has redefined apr_atomic_init, but other default default atomics require a default apr_atomic_init 00303 #endif 00304 #endif /* APR_ATOMIC_NEED_DEFAULT_INIT */ 00305 00306 #endif /* !DOXYGEN */ 00307 00310 #ifdef __cplusplus 00311 } 00312 #endif 00313 00314 #endif /* !APR_ATOMIC_H */

Generated on Tue Aug 10 17:42:34 2004 for Apache Portable Runtime by doxygen 1.3.7