home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 November / CMCD1104.ISO / Software / Complet / Apache / apache_2.0.52-win32-x86-no_ssl.msi / Data.Cab / F277193_apr_atomic.h < prev    next >
C/C++ Source or Header  |  2004-09-02  |  11KB  |  314 lines

  1. /* Copyright 2000-2004 The Apache Software Foundation
  2.  *
  3.  * Licensed under the Apache License, Version 2.0 (the "License");
  4.  * you may not use this file except in compliance with the License.
  5.  * You may obtain a copy of the License at
  6.  *
  7.  *     http://www.apache.org/licenses/LICENSE-2.0
  8.  *
  9.  * Unless required by applicable law or agreed to in writing, software
  10.  * distributed under the License is distributed on an "AS IS" BASIS,
  11.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12.  * See the License for the specific language governing permissions and
  13.  * limitations under the License.
  14.  */
  15.  
  16. #ifndef APR_ATOMIC_H
  17. #define APR_ATOMIC_H
  18.  
  19. /**
  20.  * @file apr_atomic.h
  21.  * @brief APR Atomic Operations
  22.  */
  23.  
  24. #include "apr.h"
  25. #include "apr_pools.h"
  26.  
  27. /* Platform includes for atomics */
  28. #if defined(NETWARE) || defined(__MVS__) /* OS/390 */
  29. #include <stdlib.h>
  30. #elif defined(__FreeBSD__)
  31. #include <machine/atomic.h>
  32. #endif
  33.  
  34. #ifdef __cplusplus
  35. extern "C" {
  36. #endif
  37.  
  38. /**
  39.  * @defgroup apr_atomic Atomic Operations
  40.  * @ingroup APR 
  41.  * @{
  42.  */
  43.  
  44. /* easiest way to get these documented for the moment */
  45. #if defined(DOXYGEN)
  46. /**
  47.  * structure for holding a atomic value.
  48.  * this number >only< has a 24 bit size on some platforms
  49.  */
  50. typedef apr_atomic_t;
  51.  
  52. /**
  53.  * this function is required on some platforms to initialize the
  54.  * atomic operation's internal structures
  55.  * @param p pool
  56.  * @return APR_SUCCESS on successful completion
  57.  */
  58. apr_status_t apr_atomic_init(apr_pool_t *p);
  59. /**
  60.  * read the value stored in a atomic variable
  61.  * @param mem the pointer
  62.  * @warning on certain platforms this number is not stored
  63.  * directly in the pointer. in others it is 
  64.  */
  65. apr_uint32_t apr_atomic_read(volatile apr_atomic_t *mem);
  66. /**
  67.  * set the value for atomic.
  68.  * @param mem the pointer
  69.  * @param val the value
  70.  */
  71. void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val);
  72. /**
  73.  * Add 'val' to the atomic variable
  74.  * @param mem pointer to the atomic value
  75.  * @param val the addition
  76.  */
  77. void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val);
  78.  
  79. /**
  80.  * increment the atomic variable by 1
  81.  * @param mem pointer to the atomic value
  82.  */
  83. void apr_atomic_inc(volatile apr_atomic_t *mem);
  84.  
  85. /**
  86.  * decrement the atomic variable by 1
  87.  * @param mem pointer to the atomic value
  88.  * @return zero if the value is zero, otherwise non-zero
  89.  */
  90. int apr_atomic_dec(volatile apr_atomic_t *mem);
  91.  
  92. /**
  93.  * compare the atomic's value with cmp.
  94.  * If they are the same swap the value with 'with'
  95.  * @param mem pointer to the atomic value
  96.  * @param with what to swap it with
  97.  * @param cmp the value to compare it to
  98.  * @return the old value of the atomic
  99.  * @warning do not mix apr_atomic's with the CAS function.
  100.  * on some platforms they may be implemented by different mechanisms
  101.  */
  102. apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem, long with, long cmp);
  103.  
  104. /**
  105.  * compare the pointer's value with cmp.
  106.  * If they are the same swap the value with 'with'
  107.  * @param mem pointer to the pointer
  108.  * @param with what to swap it with
  109.  * @param cmp the value to compare it to
  110.  * @return the old value of the pointer
  111.  */
  112. void *apr_atomic_casptr(volatile void **mem, void *with, const void *cmp);
  113. #else /* !DOXYGEN */
  114.  
  115. /* The following definitions provide optimized, OS-specific
  116.  * implementations of the APR atomic functions on various
  117.  * platforms.  Any atomic operation that isn't redefined as
  118.  * a macro here will be declared as a function later, and
  119.  * apr_atomic.c will provide a mutex-based default implementation.
  120.  */
  121.  
  122. #if defined(WIN32)
  123.  
  124. #define apr_atomic_t LONG
  125.  
  126. #define apr_atomic_add(mem, val)     InterlockedExchangeAdd(mem,val)
  127. #define apr_atomic_dec(mem)          InterlockedDecrement(mem)
  128. #define apr_atomic_inc(mem)          InterlockedIncrement(mem)
  129. #define apr_atomic_set(mem, val)     InterlockedExchange(mem, val)
  130. #define apr_atomic_read(mem)         (*mem)
  131. #define apr_atomic_cas(mem,with,cmp) InterlockedCompareExchange(mem,with,cmp)
  132. #define apr_atomic_init(pool)        APR_SUCCESS
  133. #define apr_atomic_casptr(mem,with,cmp) InterlockedCompareExchangePointer(mem,with,cmp)
  134.  
  135. #elif defined(NETWARE)
  136.  
  137. #define apr_atomic_t unsigned long
  138.  
  139. #define apr_atomic_add(mem, val)     atomic_add(mem,val)
  140. #define apr_atomic_inc(mem)          atomic_inc(mem)
  141. #define apr_atomic_set(mem, val)     (*mem = val)
  142. #define apr_atomic_read(mem)         (*mem)
  143. #define apr_atomic_init(pool)        APR_SUCCESS
  144. #define apr_atomic_cas(mem,with,cmp) atomic_cmpxchg((unsigned long *)(mem),(unsigned long)(cmp),(unsigned long)(with))
  145.     
  146. int apr_atomic_dec(apr_atomic_t *mem);
  147. void *apr_atomic_casptr(void **mem, void *with, const void *cmp);
  148. #define APR_OVERRIDE_ATOMIC_DEC 1
  149. #define APR_OVERRIDE_ATOMIC_CASPTR 1
  150.  
  151. inline int apr_atomic_dec(apr_atomic_t *mem) 
  152. {
  153.     return (atomic_xchgadd(mem, 0xFFFFFFFF) - 1);
  154. }
  155.  
  156. inline void *apr_atomic_casptr(void **mem, void *with, const void *cmp)
  157. {
  158.     return (void*)atomic_cmpxchg((unsigned long *)mem,(unsigned long)cmp,(unsigned long)with);
  159. }
  160.  
  161. #elif defined(__FreeBSD__)
  162.  
  163. #define apr_atomic_t apr_uint32_t
  164. #define apr_atomic_add(mem, val)     (atomic_add_int(mem,val),mem)
  165. #define apr_atomic_dec(mem)          (atomic_subtract_int(mem,1),mem)
  166. #define apr_atomic_inc(mem)          (atomic_add_int(mem,1),mem)
  167. #define apr_atomic_set(mem, val)     (atomic_set_int(mem, val),mem)
  168. #define apr_atomic_read(mem)         (*mem)
  169.  
  170. #elif (defined(__linux__) || defined(__EMX__)) && defined(__i386__) && !APR_FORCE_ATOMIC_GENERIC
  171.  
  172. #define apr_atomic_t apr_uint32_t
  173. #define apr_atomic_cas(mem,with,cmp) \
  174. ({ apr_atomic_t prev; \
  175.     asm volatile ("lock; cmpxchgl %1, %2"              \
  176.          : "=a" (prev)               \
  177.          : "r" (with), "m" (*(mem)), "0"(cmp) \
  178.          : "memory"); \
  179.     prev;})
  180.  
  181. #define apr_atomic_add(mem, val)                                \
  182. ({ register apr_atomic_t last;                                  \
  183.    do {                                                         \
  184.        last = *(mem);                                           \
  185.    } while (apr_atomic_cas((mem), last + (val), last) != last); \
  186.   })
  187.  
  188. #define apr_atomic_dec(mem)                                     \
  189. ({ register apr_atomic_t last;                                  \
  190.    do {                                                         \
  191.        last = *(mem);                                           \
  192.    } while (apr_atomic_cas((mem), last - 1, last) != last);     \
  193.   (--last != 0); })
  194.  
  195. #define apr_atomic_inc(mem)                                     \
  196. ({ register apr_atomic_t last;                                  \
  197.    do {                                                         \
  198.        last = *(mem);                                           \
  199.    } while (apr_atomic_cas((mem), last + 1, last) != last);     \
  200.   })
  201.  
  202. #define apr_atomic_set(mem, val)     (*(mem) = val)
  203. #define apr_atomic_read(mem)        (*(mem))
  204. #define apr_atomic_init(pool)        APR_SUCCESS
  205.  
  206. #elif defined(__MVS__) /* OS/390 */
  207.  
  208. #define apr_atomic_t cs_t
  209.  
  210. apr_int32_t apr_atomic_add(volatile apr_atomic_t *mem, apr_int32_t val);
  211. apr_uint32_t apr_atomic_cas(volatile apr_atomic_t *mem, apr_uint32_t swap, 
  212.                             apr_uint32_t cmp);
  213. #define APR_OVERRIDE_ATOMIC_ADD 1
  214. #define APR_OVERRIDE_ATOMIC_CAS 1
  215.  
  216. #define apr_atomic_inc(mem)          apr_atomic_add(mem, 1)
  217. #define apr_atomic_dec(mem)          apr_atomic_add(mem, -1)
  218. #define apr_atomic_init(pool)        APR_SUCCESS
  219.  
  220. /* warning: the following two operations, _read and _set, are atomic
  221.  * if the memory variables are aligned (the usual case).  
  222.  * 
  223.  * If you try really hard and manage to mis-align them, they are not 
  224.  * guaranteed to be atomic on S/390.  But then your program will blow up 
  225.  * with SIGBUS on a sparc, or with a S0C6 abend if you use the mis-aligned 
  226.  * variables with other apr_atomic_* operations on OS/390.
  227.  */
  228.  
  229. #define apr_atomic_read(p)           (*p)
  230. #define apr_atomic_set(mem, val)     (*mem = val)
  231.  
  232. #endif /* end big if-elseif switch for platform-specifics */
  233.  
  234.  
  235. /* Default implementation of the atomic API
  236.  * The definitions above may override some or all of the
  237.  * atomic functions with optimized, platform-specific versions.
  238.  * Any operation that hasn't been overridden as a macro above
  239.  * is declared as a function here, unless APR_OVERRIDE_ATOMIC_[OPERATION]
  240.  * is defined.  (The purpose of the APR_OVERRIDE_ATOMIC_* is
  241.  * to allow a platform to declare an apr_atomic_*() function
  242.  * with a different signature than the default.)
  243.  */
  244.  
  245. #if !defined(apr_atomic_t)
  246. #define apr_atomic_t apr_uint32_t
  247. #endif
  248.  
  249. #if !defined(apr_atomic_init) && !defined(APR_OVERRIDE_ATOMIC_INIT)
  250. apr_status_t apr_atomic_init(apr_pool_t *p);
  251. #endif
  252.  
  253. #if !defined(apr_atomic_read) && !defined(APR_OVERRIDE_ATOMIC_READ)
  254. #define apr_atomic_read(p)  *p
  255. #endif
  256.  
  257. #if !defined(apr_atomic_set) && !defined(APR_OVERRIDE_ATOMIC_SET)
  258. void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val);
  259. #define APR_ATOMIC_NEED_DEFAULT_INIT 1
  260. #endif
  261.  
  262. #if !defined(apr_atomic_add) && !defined(APR_OVERRIDE_ATOMIC_ADD)
  263. void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val);
  264. #define APR_ATOMIC_NEED_DEFAULT_INIT 1
  265. #endif
  266.  
  267. #if !defined(apr_atomic_inc) && !defined(APR_OVERRIDE_ATOMIC_INC)
  268. void apr_atomic_inc(volatile apr_atomic_t *mem);
  269. #define APR_ATOMIC_NEED_DEFAULT_INIT 1
  270. #endif
  271.  
  272. #if !defined(apr_atomic_dec) && !defined(APR_OVERRIDE_ATOMIC_DEC)
  273. int apr_atomic_dec(volatile apr_atomic_t *mem);
  274. #define APR_ATOMIC_NEED_DEFAULT_INIT 1
  275. #endif
  276.  
  277. #if !defined(apr_atomic_cas) && !defined(APR_OVERRIDE_ATOMIC_CAS)
  278. apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem,long with,long cmp);
  279. #define APR_ATOMIC_NEED_DEFAULT_INIT 1
  280. #endif
  281.  
  282. #if !defined(apr_atomic_casptr) && !defined(APR_OVERRIDE_ATOMIC_CASPTR)
  283. #if APR_SIZEOF_VOIDP == 4
  284. #define apr_atomic_casptr(mem, with, cmp) (void *)apr_atomic_cas((apr_uint32_t *)(mem), (long)(with), (long)cmp)
  285. #else
  286. void *apr_atomic_casptr(volatile void **mem, void *with, const void *cmp);
  287. #define APR_ATOMIC_NEED_DEFAULT_INIT 1
  288. #endif
  289. #endif
  290.  
  291. #ifndef APR_ATOMIC_NEED_DEFAULT_INIT
  292. #define APR_ATOMIC_NEED_DEFAULT_INIT 0
  293. #endif
  294.  
  295. /* If we're using the default versions of any of the atomic functions,
  296.  * we'll need the atomic init to set up mutexes.  If a platform-specific
  297.  * override above has replaced the atomic_init with a macro, it's an error.
  298.  */
  299. #if APR_ATOMIC_NEED_DEFAULT_INIT
  300. #if defined(apr_atomic_init) || defined(APR_OVERRIDE_ATOMIC_INIT)
  301. #error Platform has redefined apr_atomic_init, but other default default atomics require a default apr_atomic_init
  302. #endif
  303. #endif /* APR_ATOMIC_NEED_DEFAULT_INIT */
  304.  
  305. #endif /* !DOXYGEN */
  306.  
  307. /** @} */
  308.  
  309. #ifdef __cplusplus
  310. }
  311. #endif
  312.  
  313. #endif    /* !APR_ATOMIC_H */
  314.