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

apr_atomic.h

Go to the documentation of this file.
00001 /* ==================================================================== 00002 * The Apache Software License, Version 1.1 00003 * 00004 * Copyright (c) 2000-2003 The Apache Software Foundation. All rights 00005 * reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * 1. Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * 00014 * 2. Redistributions in binary form must reproduce the above copyright 00015 * notice, this list of conditions and the following disclaimer in 00016 * the documentation and/or other materials provided with the 00017 * distribution. 00018 * 00019 * 3. The end-user documentation included with the redistribution, 00020 * if any, must include the following acknowledgment: 00021 * "This product includes software developed by the 00022 * Apache Software Foundation (http://www.apache.org/)." 00023 * Alternately, this acknowledgment may appear in the software itself, 00024 * if and wherever such third-party acknowledgments normally appear. 00025 * 00026 * 4. The names "Apache" and "Apache Software Foundation" must 00027 * not be used to endorse or promote products derived from this 00028 * software without prior written permission. For written 00029 * permission, please contact apache@apache.org. 00030 * 00031 * 5. Products derived from this software may not be called "Apache", 00032 * nor may "Apache" appear in their name, without prior written 00033 * permission of the Apache Software Foundation. 00034 * 00035 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 00036 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00037 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00038 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 00039 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00040 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00041 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 00042 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00043 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00044 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00045 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00046 * SUCH DAMAGE. 00047 * ==================================================================== 00048 * 00049 * This software consists of voluntary contributions made by many 00050 * individuals on behalf of the Apache Software Foundation. For more 00051 * information on the Apache Software Foundation, please see 00052 * <http://www.apache.org/>. 00053 * 00054 * Portions of this software are based upon public domain software 00055 * originally written at the National Center for Supercomputing Applications, 00056 * University of Illinois, Urbana-Champaign. 00057 */ 00058 00059 #ifndef APR_ATOMIC_H 00060 #define APR_ATOMIC_H 00061 00067 #include "apr.h" 00068 #include "apr_pools.h" 00069 00070 /* Platform includes for atomics */ 00071 #if defined(NETWARE) || defined(__MVS__) /* OS/390 */ 00072 #include <stdlib.h> 00073 #elif defined(__FreeBSD__) 00074 #include <machine/atomic.h> 00075 #endif 00076 00077 #ifdef __cplusplus 00078 extern "C" { 00079 #endif 00080 00087 /* easiest way to get these documented for the moment */ 00088 #if defined(DOXYGEN) 00089 00093 typedef apr_atomic_t; 00094 00101 apr_status_t apr_atomic_init(apr_pool_t *p); 00108 apr_uint32_t apr_atomic_read(volatile apr_atomic_t *mem); 00114 void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val); 00120 void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val); 00121 00126 void apr_atomic_inc(volatile apr_atomic_t *mem); 00127 00133 int apr_atomic_dec(volatile apr_atomic_t *mem); 00134 00145 apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem, long with, long cmp); 00146 00155 void *apr_atomic_casptr(volatile void **mem, void *with, const void *cmp); 00156 #else /* !DOXYGEN */ 00157 00158 /* The following definitions provide optimized, OS-specific 00159 * implementations of the APR atomic functions on various 00160 * platforms. Any atomic operation that isn't redefined as 00161 * a macro here will be declared as a function later, and 00162 * apr_atomic.c will provide a mutex-based default implementation. 00163 */ 00164 00165 #if defined(WIN32) 00166 00167 #define apr_atomic_t LONG 00168 00169 #define apr_atomic_add(mem, val) InterlockedExchangeAdd(mem,val) 00170 #define apr_atomic_dec(mem) InterlockedDecrement(mem) 00171 #define apr_atomic_inc(mem) InterlockedIncrement(mem) 00172 #define apr_atomic_set(mem, val) InterlockedExchange(mem, val) 00173 #define apr_atomic_read(mem) (*mem) 00174 #define apr_atomic_cas(mem,with,cmp) InterlockedCompareExchange(mem,with,cmp) 00175 #define apr_atomic_init(pool) APR_SUCCESS 00176 #define apr_atomic_casptr(mem,with,cmp) InterlockedCompareExchangePointer(mem,with,cmp) 00177 00178 #elif defined(NETWARE) 00179 00180 #define apr_atomic_t unsigned long 00181 00182 #define apr_atomic_add(mem, val) atomic_add(mem,val) 00183 #define apr_atomic_inc(mem) atomic_inc(mem) 00184 #define apr_atomic_set(mem, val) (*mem = val) 00185 #define apr_atomic_read(mem) (*mem) 00186 #define apr_atomic_init(pool) APR_SUCCESS 00187 #define apr_atomic_cas(mem,with,cmp) atomic_cmpxchg((unsigned long *)(mem),(unsigned long)(cmp),(unsigned long)(with)) 00188 00189 int apr_atomic_dec(apr_atomic_t *mem); 00190 void *apr_atomic_casptr(void **mem, void *with, const void *cmp); 00191 #define APR_OVERRIDE_ATOMIC_DEC 1 00192 #define APR_OVERRIDE_ATOMIC_CASPTR 1 00193 00194 inline int apr_atomic_dec(apr_atomic_t *mem) 00195 { 00196 atomic_dec(mem); 00197 return *mem; 00198 } 00199 00200 inline void *apr_atomic_casptr(void **mem, void *with, const void *cmp) 00201 { 00202 return (void*)atomic_cmpxchg((unsigned long *)mem,(unsigned long)cmp,(unsigned long)with); 00203 } 00204 00205 #elif defined(__FreeBSD__) 00206 00207 #define apr_atomic_t apr_uint32_t 00208 #define apr_atomic_add(mem, val) atomic_add_int(mem,val) 00209 #define apr_atomic_dec(mem) atomic_subtract_int(mem,1) 00210 #define apr_atomic_inc(mem) atomic_add_int(mem,1) 00211 #define apr_atomic_set(mem, val) atomic_set_int(mem, val) 00212 #define apr_atomic_read(mem) (*mem) 00213 00214 #elif (defined(__linux__) || defined(__EMX__)) && defined(__i386__) && !APR_FORCE_ATOMIC_GENERIC 00215 00216 #define apr_atomic_t apr_uint32_t 00217 #define apr_atomic_cas(mem,with,cmp) \ 00218 ({ apr_atomic_t prev; \ 00219 asm volatile ("lock; cmpxchgl %1, %2" \ 00220 : "=a" (prev) \ 00221 : "r" (with), "m" (*(mem)), "0"(cmp) \ 00222 : "memory"); \ 00223 prev;}) 00224 00225 #define apr_atomic_add(mem, val) \ 00226 ({ register apr_atomic_t last; \ 00227 do { \ 00228 last = *(mem); \ 00229 } while (apr_atomic_cas((mem), last + (val), last) != last); \ 00230 }) 00231 00232 #define apr_atomic_dec(mem) \ 00233 ({ register apr_atomic_t last; \ 00234 do { \ 00235 last = *(mem); \ 00236 } while (apr_atomic_cas((mem), last - 1, last) != last); \ 00237 (--last != 0); }) 00238 00239 #define apr_atomic_inc(mem) \ 00240 ({ register apr_atomic_t last; \ 00241 do { \ 00242 last = *(mem); \ 00243 } while (apr_atomic_cas((mem), last + 1, last) != last); \ 00244 }) 00245 00246 #define apr_atomic_set(mem, val) (*(mem) = val) 00247 #define apr_atomic_read(mem) (*(mem)) 00248 #define apr_atomic_init(pool) APR_SUCCESS 00249 00250 #elif defined(__MVS__) /* OS/390 */ 00251 00252 #define apr_atomic_t cs_t 00253 00254 apr_int32_t apr_atomic_add(volatile apr_atomic_t *mem, apr_int32_t val); 00255 apr_uint32_t apr_atomic_cas(volatile apr_atomic_t *mem, apr_uint32_t swap, 00256 apr_uint32_t cmp); 00257 #define APR_OVERRIDE_ATOMIC_ADD 1 00258 #define APR_OVERRIDE_ATOMIC_CAS 1 00259 00260 #define apr_atomic_inc(mem) apr_atomic_add(mem, 1) 00261 #define apr_atomic_dec(mem) apr_atomic_add(mem, -1) 00262 #define apr_atomic_init(pool) APR_SUCCESS 00263 00264 /* warning: the following two operations, _read and _set, are atomic 00265 * if the memory variables are aligned (the usual case). 00266 * 00267 * If you try really hard and manage to mis-align them, they are not 00268 * guaranteed to be atomic on S/390. But then your program will blow up 00269 * with SIGBUS on a sparc, or with a S0C6 abend if you use the mis-aligned 00270 * variables with other apr_atomic_* operations on OS/390. 00271 */ 00272 00273 #define apr_atomic_read(p) (*p) 00274 #define apr_atomic_set(mem, val) (*mem = val) 00275 00276 #endif /* end big if-elseif switch for platform-specifics */ 00277 00278 00279 /* Default implementation of the atomic API 00280 * The definitions above may override some or all of the 00281 * atomic functions with optimized, platform-specific versions. 00282 * Any operation that hasn't been overridden as a macro above 00283 * is declared as a function here, unless APR_OVERRIDE_ATOMIC_[OPERATION] 00284 * is defined. (The purpose of the APR_OVERRIDE_ATOMIC_* is 00285 * to allow a platform to declare an apr_atomic_*() function 00286 * with a different signature than the default.) 00287 */ 00288 00289 #if !defined(apr_atomic_t) 00290 #define apr_atomic_t apr_uint32_t 00291 #endif 00292 00293 #if !defined(apr_atomic_init) && !defined(APR_OVERRIDE_ATOMIC_INIT) 00294 apr_status_t apr_atomic_init(apr_pool_t *p); 00295 #endif 00296 00297 #if !defined(apr_atomic_read) && !defined(APR_OVERRIDE_ATOMIC_READ) 00298 #define apr_atomic_read(p) *p 00299 #endif 00300 00301 #if !defined(apr_atomic_set) && !defined(APR_OVERRIDE_ATOMIC_SET) 00302 void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val); 00303 #define APR_ATOMIC_NEED_DEFAULT_INIT 1 00304 #endif 00305 00306 #if !defined(apr_atomic_add) && !defined(APR_OVERRIDE_ATOMIC_ADD) 00307 void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val); 00308 #define APR_ATOMIC_NEED_DEFAULT_INIT 1 00309 #endif 00310 00311 #if !defined(apr_atomic_inc) && !defined(APR_OVERRIDE_ATOMIC_INC) 00312 void apr_atomic_inc(volatile apr_atomic_t *mem); 00313 #define APR_ATOMIC_NEED_DEFAULT_INIT 1 00314 #endif 00315 00316 #if !defined(apr_atomic_dec) && !defined(APR_OVERRIDE_ATOMIC_DEC) 00317 int apr_atomic_dec(volatile apr_atomic_t *mem); 00318 #define APR_ATOMIC_NEED_DEFAULT_INIT 1 00319 #endif 00320 00321 #if !defined(apr_atomic_cas) && !defined(APR_OVERRIDE_ATOMIC_CAS) 00322 apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem,long with,long cmp); 00323 #define APR_ATOMIC_NEED_DEFAULT_INIT 1 00324 #endif 00325 00326 #if !defined(apr_atomic_casptr) && !defined(APR_OVERRIDE_ATOMIC_CASPTR) 00327 #if APR_SIZEOF_VOIDP == 4 00328 #define apr_atomic_casptr(mem, with, cmp) (void *)apr_atomic_cas((apr_uint32_t *)(mem), (long)(with), (long)cmp) 00329 #else 00330 void *apr_atomic_casptr(volatile void **mem, void *with, const void *cmp); 00331 #define APR_ATOMIC_NEED_DEFAULT_INIT 1 00332 #endif 00333 #endif 00334 00335 #ifndef APR_ATOMIC_NEED_DEFAULT_INIT 00336 #define APR_ATOMIC_NEED_DEFAULT_INIT 0 00337 #endif 00338 00339 /* If we're using the default versions of any of the atomic functions, 00340 * we'll need the atomic init to set up mutexes. If a platform-specific 00341 * override above has replaced the atomic_init with a macro, it's an error. 00342 */ 00343 #if APR_ATOMIC_NEED_DEFAULT_INIT 00344 #if defined(apr_atomic_init) || defined(APR_OVERRIDE_ATOMIC_INIT) 00345 #error Platform has redefined apr_atomic_init, but other default default atomics require a default apr_atomic_init 00346 #endif 00347 #endif /* APR_ATOMIC_NEED_DEFAULT_INIT */ 00348 00349 #endif /* !DOXYGEN */ 00350 00353 #ifdef __cplusplus 00354 } 00355 #endif 00356 00357 #endif /* !APR_ATOMIC_H */

Generated on Wed Sep 1 05:16:35 2004 for Apache Portable Runtime by doxygen 1.3.8