📄 apr_atomic.h
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#ifndef APR_ATOMIC_H#define APR_ATOMIC_H/** * @file apr_atomic.h * @brief APR Atomic Operations */#include "apr.h"#include "apr_pools.h"/* Platform includes for atomics */#if defined(NETWARE) || defined(__MVS__) /* OS/390 */#include <stdlib.h>#elif defined(__FreeBSD__)#include <machine/atomic.h>#endif#ifdef __cplusplusextern "C" {#endif/** * @defgroup apr_atomic Atomic Operations * @ingroup APR * @{ *//* easiest way to get these documented for the moment */#if defined(DOXYGEN)/** * structure for holding a atomic value. * this number >only< has a 24 bit size on some platforms */typedef apr_atomic_t;/** * this function is required on some platforms to initialize the * atomic operation's internal structures * @param p pool * @return APR_SUCCESS on successful completion */apr_status_t apr_atomic_init(apr_pool_t *p);/** * read the value stored in a atomic variable * @param mem the pointer * @warning on certain platforms this number is not stored * directly in the pointer. in others it is */apr_uint32_t apr_atomic_read(volatile apr_atomic_t *mem);/** * set the value for atomic. * @param mem the pointer * @param val the value */void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val);/** * Add 'val' to the atomic variable * @param mem pointer to the atomic value * @param val the addition */void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val);/** * increment the atomic variable by 1 * @param mem pointer to the atomic value */void apr_atomic_inc(volatile apr_atomic_t *mem);/** * decrement the atomic variable by 1 * @param mem pointer to the atomic value * @return zero if the value is zero, otherwise non-zero */int apr_atomic_dec(volatile apr_atomic_t *mem);/** * compare the atomic's value with cmp. * If they are the same swap the value with 'with' * @param mem pointer to the atomic value * @param with what to swap it with * @param cmp the value to compare it to * @return the old value of the atomic * @warning do not mix apr_atomic's with the CAS function. * on some platforms they may be implemented by different mechanisms */apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem, long with, long cmp);/** * compare the pointer's value with cmp. * If they are the same swap the value with 'with' * @param mem pointer to the pointer * @param with what to swap it with * @param cmp the value to compare it to * @return the old value of the pointer */void *apr_atomic_casptr(volatile void **mem, void *with, const void *cmp);#else /* !DOXYGEN *//* The following definitions provide optimized, OS-specific * implementations of the APR atomic functions on various * platforms. Any atomic operation that isn't redefined as * a macro here will be declared as a function later, and * apr_atomic.c will provide a mutex-based default implementation. */#if defined(WIN32)#define apr_atomic_t LONG#define apr_atomic_add(mem, val) InterlockedExchangeAdd(mem,val)#define apr_atomic_dec(mem) InterlockedDecrement(mem)#define apr_atomic_inc(mem) InterlockedIncrement(mem)#define apr_atomic_set(mem, val) InterlockedExchange(mem, val)#define apr_atomic_read(mem) (*mem)#define apr_atomic_cas(mem,with,cmp) InterlockedCompareExchange(mem,with,cmp)#define apr_atomic_init(pool) APR_SUCCESS#define apr_atomic_casptr(mem,with,cmp) InterlockedCompareExchangePointer(mem,with,cmp)#elif defined(NETWARE)#define apr_atomic_t unsigned long#define apr_atomic_add(mem, val) atomic_add(mem,val)#define apr_atomic_inc(mem) atomic_inc(mem)#define apr_atomic_set(mem, val) (*mem = val)#define apr_atomic_read(mem) (*mem)#define apr_atomic_init(pool) APR_SUCCESS#define apr_atomic_cas(mem,with,cmp) atomic_cmpxchg((unsigned long *)(mem),(unsigned long)(cmp),(unsigned long)(with)) int apr_atomic_dec(apr_atomic_t *mem);void *apr_atomic_casptr(void **mem, void *with, const void *cmp);#define APR_OVERRIDE_ATOMIC_DEC 1#define APR_OVERRIDE_ATOMIC_CASPTR 1inline int apr_atomic_dec(apr_atomic_t *mem) { return (atomic_xchgadd(mem, 0xFFFFFFFF) - 1);}inline void *apr_atomic_casptr(void **mem, void *with, const void *cmp){ return (void*)atomic_cmpxchg((unsigned long *)mem,(unsigned long)cmp,(unsigned long)with);}#elif defined(__FreeBSD__)#define apr_atomic_t apr_uint32_t#define apr_atomic_add(mem, val) (atomic_add_int(mem,val),mem)#define apr_atomic_dec(mem) (atomic_subtract_int(mem,1),mem)#define apr_atomic_inc(mem) (atomic_add_int(mem,1),mem)#define apr_atomic_set(mem, val) (atomic_set_int(mem, val),mem)#define apr_atomic_read(mem) (*mem)#elif (defined(__linux__) || defined(__EMX__)) && defined(__i386__) && !APR_FORCE_ATOMIC_GENERIC#define apr_atomic_t apr_uint32_t#define apr_atomic_cas(mem,with,cmp) \({ apr_atomic_t prev; \ asm volatile ("lock; cmpxchgl %1, %2" \ : "=a" (prev) \ : "r" (with), "m" (*(mem)), "0"(cmp) \ : "memory"); \ prev;})#define apr_atomic_add(mem, val) \({ register apr_atomic_t last; \ do { \ last = *(mem); \ } while (apr_atomic_cas((mem), last + (val), last) != last); \ })#define apr_atomic_dec(mem) \({ register apr_atomic_t last; \ do { \ last = *(mem); \ } while (apr_atomic_cas((mem), last - 1, last) != last); \ (--last != 0); })#define apr_atomic_inc(mem) \({ register apr_atomic_t last; \ do { \ last = *(mem); \ } while (apr_atomic_cas((mem), last + 1, last) != last); \ })#define apr_atomic_set(mem, val) (*(mem) = val)#define apr_atomic_read(mem) (*(mem))#define apr_atomic_init(pool) APR_SUCCESS#elif defined(__MVS__) /* OS/390 */#define apr_atomic_t cs_tapr_int32_t apr_atomic_add(volatile apr_atomic_t *mem, apr_int32_t val);apr_uint32_t apr_atomic_cas(volatile apr_atomic_t *mem, apr_uint32_t swap, apr_uint32_t cmp);#define APR_OVERRIDE_ATOMIC_ADD 1#define APR_OVERRIDE_ATOMIC_CAS 1#define apr_atomic_inc(mem) apr_atomic_add(mem, 1)#define apr_atomic_dec(mem) apr_atomic_add(mem, -1)#define apr_atomic_init(pool) APR_SUCCESS/* warning: the following two operations, _read and _set, are atomic * if the memory variables are aligned (the usual case). * * If you try really hard and manage to mis-align them, they are not * guaranteed to be atomic on S/390. But then your program will blow up * with SIGBUS on a sparc, or with a S0C6 abend if you use the mis-aligned * variables with other apr_atomic_* operations on OS/390. */#define apr_atomic_read(p) (*p)#define apr_atomic_set(mem, val) (*mem = val)#endif /* end big if-elseif switch for platform-specifics *//* Default implementation of the atomic API * The definitions above may override some or all of the * atomic functions with optimized, platform-specific versions. * Any operation that hasn't been overridden as a macro above * is declared as a function here, unless APR_OVERRIDE_ATOMIC_[OPERATION] * is defined. (The purpose of the APR_OVERRIDE_ATOMIC_* is * to allow a platform to declare an apr_atomic_*() function * with a different signature than the default.) */#if !defined(apr_atomic_t)#define apr_atomic_t apr_uint32_t#endif#if !defined(apr_atomic_init) && !defined(APR_OVERRIDE_ATOMIC_INIT)apr_status_t apr_atomic_init(apr_pool_t *p);#endif#if !defined(apr_atomic_read) && !defined(APR_OVERRIDE_ATOMIC_READ)#define apr_atomic_read(p) *p#endif#if !defined(apr_atomic_set) && !defined(APR_OVERRIDE_ATOMIC_SET)void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val);#define APR_ATOMIC_NEED_DEFAULT_INIT 1#endif#if !defined(apr_atomic_add) && !defined(APR_OVERRIDE_ATOMIC_ADD)void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val);#define APR_ATOMIC_NEED_DEFAULT_INIT 1#endif#if !defined(apr_atomic_inc) && !defined(APR_OVERRIDE_ATOMIC_INC)void apr_atomic_inc(volatile apr_atomic_t *mem);#define APR_ATOMIC_NEED_DEFAULT_INIT 1#endif#if !defined(apr_atomic_dec) && !defined(APR_OVERRIDE_ATOMIC_DEC)int apr_atomic_dec(volatile apr_atomic_t *mem);#define APR_ATOMIC_NEED_DEFAULT_INIT 1#endif#if !defined(apr_atomic_cas) && !defined(APR_OVERRIDE_ATOMIC_CAS)apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem,long with,long cmp);#define APR_ATOMIC_NEED_DEFAULT_INIT 1#endif#if !defined(apr_atomic_casptr) && !defined(APR_OVERRIDE_ATOMIC_CASPTR)#if APR_SIZEOF_VOIDP == 4#define apr_atomic_casptr(mem, with, cmp) (void *)apr_atomic_cas((apr_uint32_t *)(mem), (long)(with), (long)cmp)#elsevoid *apr_atomic_casptr(volatile void **mem, void *with, const void *cmp);#define APR_ATOMIC_NEED_DEFAULT_INIT 1#endif#endif#ifndef APR_ATOMIC_NEED_DEFAULT_INIT#define APR_ATOMIC_NEED_DEFAULT_INIT 0#endif/* If we're using the default versions of any of the atomic functions, * we'll need the atomic init to set up mutexes. If a platform-specific * override above has replaced the atomic_init with a macro, it's an error. */#if APR_ATOMIC_NEED_DEFAULT_INIT#if defined(apr_atomic_init) || defined(APR_OVERRIDE_ATOMIC_INIT)#error Platform has redefined apr_atomic_init, but other default default atomics require a default apr_atomic_init#endif#endif /* APR_ATOMIC_NEED_DEFAULT_INIT */#endif /* !DOXYGEN *//** @} */#ifdef __cplusplus}#endif#endif /* !APR_ATOMIC_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -