home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / include / apr_atomic.h < prev    next >
Encoding:
C/C++ Source or Header  |  2004-02-13  |  10.6 KB  |  315 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.     atomic_dec(mem);
  154.     return *mem; 
  155. }
  156.  
  157. inline void *apr_atomic_casptr(void **mem, void *with, const void *cmp)
  158. {
  159.     return (void*)atomic_cmpxchg((unsigned long *)mem,(unsigned long)cmp,(unsigned long)with);
  160. }
  161.  
  162. #elif defined(__FreeBSD__)
  163.  
  164. #define apr_atomic_t apr_uint32_t
  165. #define apr_atomic_add(mem, val)     atomic_add_int(mem,val)
  166. #define apr_atomic_dec(mem)          atomic_subtract_int(mem,1)
  167. #define apr_atomic_inc(mem)          atomic_add_int(mem,1)
  168. #define apr_atomic_set(mem, val)     atomic_set_int(mem, val)
  169. #define apr_atomic_read(mem)         (*mem)
  170.  
  171. #elif (defined(__linux__) || defined(__EMX__)) && defined(__i386__) && !APR_FORCE_ATOMIC_GENERIC
  172.  
  173. #define apr_atomic_t apr_uint32_t
  174. #define apr_atomic_cas(mem,with,cmp) \
  175. ({ apr_atomic_t prev; \
  176.     asm volatile ("lock; cmpxchgl %1, %2"              \
  177.          : "=a" (prev)               \
  178.          : "r" (with), "m" (*(mem)), "0"(cmp) \
  179.          : "memory"); \
  180.     prev;})
  181.  
  182. #define apr_atomic_add(mem, val)                                \
  183. ({ register apr_atomic_t last;                                  \
  184.    do {                                                         \
  185.        last = *(mem);                                           \
  186.    } while (apr_atomic_cas((mem), last + (val), last) != last); \
  187.   })
  188.  
  189. #define apr_atomic_dec(mem)                                     \
  190. ({ register apr_atomic_t last;                                  \
  191.    do {                                                         \
  192.        last = *(mem);                                           \
  193.    } while (apr_atomic_cas((mem), last - 1, last) != last);     \
  194.   (--last != 0); })
  195.  
  196. #define apr_atomic_inc(mem)                                     \
  197. ({ register apr_atomic_t last;                                  \
  198.    do {                                                         \
  199.        last = *(mem);                                           \
  200.    } while (apr_atomic_cas((mem), last + 1, last) != last);     \
  201.   })
  202.  
  203. #define apr_atomic_set(mem, val)     (*(mem) = val)
  204. #define apr_atomic_read(mem)        (*(mem))
  205. #define apr_atomic_init(pool)        APR_SUCCESS
  206.  
  207. #elif defined(__MVS__) /* OS/390 */
  208.  
  209. #define apr_atomic_t cs_t
  210.  
  211. apr_int32_t apr_atomic_add(volatile apr_atomic_t *mem, apr_int32_t val);
  212. apr_uint32_t apr_atomic_cas(volatile apr_atomic_t *mem, apr_uint32_t swap, 
  213.                             apr_uint32_t cmp);
  214. #define APR_OVERRIDE_ATOMIC_ADD 1
  215. #define APR_OVERRIDE_ATOMIC_CAS 1
  216.  
  217. #define apr_atomic_inc(mem)          apr_atomic_add(mem, 1)
  218. #define apr_atomic_dec(mem)          apr_atomic_add(mem, -1)
  219. #define apr_atomic_init(pool)        APR_SUCCESS
  220.  
  221. /* warning: the following two operations, _read and _set, are atomic
  222.  * if the memory variables are aligned (the usual case).  
  223.  * 
  224.  * If you try really hard and manage to mis-align them, they are not 
  225.  * guaranteed to be atomic on S/390.  But then your program will blow up 
  226.  * with SIGBUS on a sparc, or with a S0C6 abend if you use the mis-aligned 
  227.  * variables with other apr_atomic_* operations on OS/390.
  228.  */
  229.  
  230. #define apr_atomic_read(p)           (*p)
  231. #define apr_atomic_set(mem, val)     (*mem = val)
  232.  
  233. #endif /* end big if-elseif switch for platform-specifics */
  234.  
  235.  
  236. /* Default implementation of the atomic API
  237.  * The definitions above may override some or all of the
  238.  * atomic functions with optimized, platform-specific versions.
  239.  * Any operation that hasn't been overridden as a macro above
  240.  * is declared as a function here, unless APR_OVERRIDE_ATOMIC_[OPERATION]
  241.  * is defined.  (The purpose of the APR_OVERRIDE_ATOMIC_* is
  242.  * to allow a platform to declare an apr_atomic_*() function
  243.  * with a different signature than the default.)
  244.  */
  245.  
  246. #if !defined(apr_atomic_t)
  247. #define apr_atomic_t apr_uint32_t
  248. #endif
  249.  
  250. #if !defined(apr_atomic_init) && !defined(APR_OVERRIDE_ATOMIC_INIT)
  251. apr_status_t apr_atomic_init(apr_pool_t *p);
  252. #endif
  253.  
  254. #if !defined(apr_atomic_read) && !defined(APR_OVERRIDE_ATOMIC_READ)
  255. #define apr_atomic_read(p)  *p
  256. #endif
  257.  
  258. #if !defined(apr_atomic_set) && !defined(APR_OVERRIDE_ATOMIC_SET)
  259. void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val);
  260. #define APR_ATOMIC_NEED_DEFAULT_INIT 1
  261. #endif
  262.  
  263. #if !defined(apr_atomic_add) && !defined(APR_OVERRIDE_ATOMIC_ADD)
  264. void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val);
  265. #define APR_ATOMIC_NEED_DEFAULT_INIT 1
  266. #endif
  267.  
  268. #if !defined(apr_atomic_inc) && !defined(APR_OVERRIDE_ATOMIC_INC)
  269. void apr_atomic_inc(volatile apr_atomic_t *mem);
  270. #define APR_ATOMIC_NEED_DEFAULT_INIT 1
  271. #endif
  272.  
  273. #if !defined(apr_atomic_dec) && !defined(APR_OVERRIDE_ATOMIC_DEC)
  274. int apr_atomic_dec(volatile apr_atomic_t *mem);
  275. #define APR_ATOMIC_NEED_DEFAULT_INIT 1
  276. #endif
  277.  
  278. #if !defined(apr_atomic_cas) && !defined(APR_OVERRIDE_ATOMIC_CAS)
  279. apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem,long with,long cmp);
  280. #define APR_ATOMIC_NEED_DEFAULT_INIT 1
  281. #endif
  282.  
  283. #if !defined(apr_atomic_casptr) && !defined(APR_OVERRIDE_ATOMIC_CASPTR)
  284. #if APR_SIZEOF_VOIDP == 4
  285. #define apr_atomic_casptr(mem, with, cmp) (void *)apr_atomic_cas((apr_uint32_t *)(mem), (long)(with), (long)cmp)
  286. #else
  287. void *apr_atomic_casptr(volatile void **mem, void *with, const void *cmp);
  288. #define APR_ATOMIC_NEED_DEFAULT_INIT 1
  289. #endif
  290. #endif
  291.  
  292. #ifndef APR_ATOMIC_NEED_DEFAULT_INIT
  293. #define APR_ATOMIC_NEED_DEFAULT_INIT 0
  294. #endif
  295.  
  296. /* If we're using the default versions of any of the atomic functions,
  297.  * we'll need the atomic init to set up mutexes.  If a platform-specific
  298.  * override above has replaced the atomic_init with a macro, it's an error.
  299.  */
  300. #if APR_ATOMIC_NEED_DEFAULT_INIT
  301. #if defined(apr_atomic_init) || defined(APR_OVERRIDE_ATOMIC_INIT)
  302. #error Platform has redefined apr_atomic_init, but other default default atomics require a default apr_atomic_init
  303. #endif
  304. #endif /* APR_ATOMIC_NEED_DEFAULT_INIT */
  305.  
  306. #endif /* !DOXYGEN */
  307.  
  308. /** @} */
  309.  
  310. #ifdef __cplusplus
  311. }
  312. #endif
  313.  
  314. #endif    /* !APR_ATOMIC_H */
  315.