⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atomic.hh

📁 Click is a modular router toolkit. To use it you ll need to know how to compile and install the sof
💻 HH
字号:
// -*- c-basic-offset: 4 -*-#ifndef CLICK_ATOMIC_HH#define CLICK_ATOMIC_HH#if CLICK_LINUXMODULE# include <click/glue.hh>#endifCLICK_DECLS#if CLICK_LINUXMODULE# if HAVE_LINUX_ASM_SYSTEM_H#  include <asm/system.h># endif# define CLICK_ATOMIC_VAL	_val.counter#else# define CLICK_ATOMIC_VAL	_val#endif#if defined(__i386__) || defined(__arch_um__) || defined(__x86_64__)# if CLICK_LINUXMODULE || HAVE_MULTITHREAD#  define CLICK_ATOMIC_X86	1# endif# if (CLICK_LINUXMODULE && defined(CONFIG_SMP)) || HAVE_MULTITHREAD#  define CLICK_ATOMIC_LOCK	"lock ; "# else#  define CLICK_ATOMIC_LOCK	/* nothing */# endif#endif/** @file <click/atomic.hh> * @brief An atomic 32-bit integer. *//** @class atomic_uint32_t * @brief A 32-bit integer with support for atomic operations. * * The atomic_uint32_t class represents a 32-bit integer, with support for * atomic operations.  The +=, -=, &=, |=, ++, and -- operations are * implemented using atomic instructions.  There are also atomic swap(), * fetch_and_add(), dec_and_test(), and compare_and_swap() operations. * * Because of some issues with compiler implementations, atomic_uint32_t has * no explicit constructor; to set an atomic_uint32_t to a value, use * operator=. * * The atomic_uint32_t only provides true atomic semantics when that has been * implemented.  It has been implemented in the Linux kernel, and at userlevel * (when --enable-multithread has been defined) for x86 machines.  In other * situations, it's not truly atomic (because it doesn't need to be). */class atomic_uint32_t { public:    // No constructors because, unfortunately, GCC generates worse code. Use    // operator= instead.    inline uint32_t value() const;    inline operator uint32_t() const;    inline atomic_uint32_t &operator=(uint32_t x);    inline atomic_uint32_t &operator+=(int32_t delta);    inline atomic_uint32_t &operator-=(int32_t delta);    inline atomic_uint32_t &operator|=(uint32_t mask);    inline atomic_uint32_t &operator&=(uint32_t mask);    inline void operator++();    inline void operator++(int);    inline void operator--();    inline void operator--(int);    inline uint32_t swap(uint32_t x);    inline uint32_t fetch_and_add(uint32_t delta);    inline bool dec_and_test();    inline bool compare_and_swap(uint32_t test_value, uint32_t new_value);    inline static void inc(volatile uint32_t &x);    inline static bool dec_and_test(volatile uint32_t &x);    inline static bool compare_and_swap(volatile uint32_t &x, uint32_t test_value, uint32_t new_value);  private:#if CLICK_LINUXMODULE    atomic_t _val;#elif HAVE_MULTITHREAD    volatile uint32_t _val;#else    uint32_t _val;#endif};/** @brief  Return the value. */inline uint32_tatomic_uint32_t::value() const{#if CLICK_LINUXMODULE    return atomic_read(&_val);#else    return CLICK_ATOMIC_VAL;#endif}/** @brief  Return the value. */inlineatomic_uint32_t::operator uint32_t() const{    return value();}/** @brief  Set the value to @a x. */inline atomic_uint32_t &atomic_uint32_t::operator=(uint32_t x){#if CLICK_LINUXMODULE    atomic_set(&_val, x);#else    CLICK_ATOMIC_VAL = x;#endif    return *this;}/** @brief  Atomically add @a delta to the value. */inline atomic_uint32_t &atomic_uint32_t::operator+=(int32_t delta){#if CLICK_LINUXMODULE    atomic_add(delta, &_val);#elif CLICK_ATOMIC_X86    asm volatile (CLICK_ATOMIC_LOCK "addl %1,%0"		  : "=m" (CLICK_ATOMIC_VAL)		  : "r" (delta), "m" (CLICK_ATOMIC_VAL)		  : "cc");#else    CLICK_ATOMIC_VAL += delta;#endif    return *this;}/** @brief  Atomically subtract @a delta from the value. */inline atomic_uint32_t &atomic_uint32_t::operator-=(int32_t delta){#if CLICK_LINUXMODULE    atomic_sub(delta, &_val);#elif CLICK_ATOMIC_X86    asm volatile (CLICK_ATOMIC_LOCK "subl %1,%0"		  : "=m" (CLICK_ATOMIC_VAL)		  : "r" (delta), "m" (CLICK_ATOMIC_VAL)		  : "cc");#else    CLICK_ATOMIC_VAL -= delta;#endif    return *this;}/** @brief  Atomically bitwise-or the value with @a mask. */inline atomic_uint32_t &atomic_uint32_t::operator|=(uint32_t mask){#if CLICK_LINUXMODULE && HAVE_LINUX_ATOMIC_SET_MASK    atomic_set_mask(mask, &_val);#elif CLICK_ATOMIC_X86    asm volatile (CLICK_ATOMIC_LOCK "orl %1,%0"		  : "=m" (CLICK_ATOMIC_VAL)		  : "r" (mask), "m" (CLICK_ATOMIC_VAL)		  : "cc");#elif CLICK_LINUXMODULE# warning "using nonatomic approximation for atomic_uint32_t::operator|="    unsigned long flags;    local_irq_save(flags);    CLICK_ATOMIC_VAL |= mask;    local_irq_restore(flags);#else    CLICK_ATOMIC_VAL |= mask;#endif     return *this;}/** @brief  Atomically bitwise-and the value with @a mask. */inline atomic_uint32_t &atomic_uint32_t::operator&=(uint32_t mask){#if CLICK_LINUXMODULE && HAVE_LINUX_ATOMIC_SET_MASK    atomic_clear_mask(~mask, &_val);#elif CLICK_ATOMIC_X86    asm volatile (CLICK_ATOMIC_LOCK "andl %1,%0"		  : "=m" (CLICK_ATOMIC_VAL)		  : "r" (mask), "m" (CLICK_ATOMIC_VAL)		  : "cc");#elif CLICK_LINUXMODULE# warning "using nonatomic approximation for atomic_uint32_t::operator&="    unsigned long flags;    local_irq_save(flags);    CLICK_ATOMIC_VAL &= mask;    local_irq_restore(flags);#else    CLICK_ATOMIC_VAL &= mask;#endif    return *this;}/** @brief  Atomically increment value @a x. */inline voidatomic_uint32_t::inc(volatile uint32_t &x){#if CLICK_LINUXMODULE    static_assert(sizeof(atomic_t) == sizeof(x));    atomic_inc((atomic_t *) &x);#elif CLICK_ATOMIC_X86    asm volatile (CLICK_ATOMIC_LOCK "incl %0"		  : "=m" (x)		  : "m" (x)		  : "cc");#else    x++;#endif}/** @brief  Atomically increment the value. */inline voidatomic_uint32_t::operator++(){#if CLICK_LINUXMODULE    atomic_inc(&_val);#elif CLICK_ATOMIC_X86    asm volatile (CLICK_ATOMIC_LOCK "incl %0"		  : "=m" (CLICK_ATOMIC_VAL)		  : "m" (CLICK_ATOMIC_VAL)		  : "cc");#else    CLICK_ATOMIC_VAL++;#endif}/** @brief  Atomically increment the value. */inline voidatomic_uint32_t::operator++(int){#if CLICK_LINUXMODULE    atomic_inc(&_val);#elif CLICK_ATOMIC_X86    asm volatile (CLICK_ATOMIC_LOCK "incl %0"		  : "=m" (CLICK_ATOMIC_VAL)		  : "m" (CLICK_ATOMIC_VAL)		  : "cc");#else    CLICK_ATOMIC_VAL++;#endif}/** @brief  Atomically decrement the value. */inline voidatomic_uint32_t::operator--(){#if CLICK_LINUXMODULE    atomic_dec(&_val);#elif CLICK_ATOMIC_X86    asm volatile (CLICK_ATOMIC_LOCK "decl %0"		  : "=m" (CLICK_ATOMIC_VAL)		  : "m" (CLICK_ATOMIC_VAL)		  : "cc");#else    CLICK_ATOMIC_VAL--;#endif}/** @brief  Atomically decrement the value. */inline voidatomic_uint32_t::operator--(int){#if CLICK_LINUXMODULE    atomic_dec(&_val);#elif CLICK_ATOMIC_X86    asm volatile (CLICK_ATOMIC_LOCK "decl %0"		  : "=m" (CLICK_ATOMIC_VAL)		  : "m" (CLICK_ATOMIC_VAL)		  : "cc");#else    CLICK_ATOMIC_VAL--;#endif}/** @brief  Atomically assign the value to @a x, returning the old value. * * Behaves like this, but in one atomic step: * @code * uint32_t old_value = value(); * *this = x; * return old_value; * @endcode * * Also acts as a memory barrier. */inline uint32_tatomic_uint32_t::swap(uint32_t x){#if CLICK_ATOMIC_X86    asm volatile ("xchgl %0,%1"		  : "=r" (x), "=m" (CLICK_ATOMIC_VAL)		  : "0" (x), "m" (CLICK_ATOMIC_VAL)		  : "memory");    return x;#elif CLICK_LINUXMODULE && defined(xchg)    return atomic_xchg(&_val, x);#elif CLICK_LINUXMODULE# error "need xchg for atomic_uint32_t::swap"#else    uint32_t old_value = value();    CLICK_ATOMIC_VAL = x;    return old_value;#endif}/** @brief  Atomically add @a delta to the value, returning the old value. * * Behaves like this, but in one atomic step: * @code * uint32_t old_value = value(); * *this += delta; * return old_value; * @endcode */inline uint32_tatomic_uint32_t::fetch_and_add(uint32_t delta){#if CLICK_ATOMIC_X86    asm volatile (CLICK_ATOMIC_LOCK "xaddl %0,%1"		  : "=r" (delta), "=m" (CLICK_ATOMIC_VAL)		  : "0" (delta), "m" (CLICK_ATOMIC_VAL)		  : "cc");    return delta;#elif CLICK_LINUXMODULE && HAVE_LINUX_ATOMIC_ADD_RETURN    return atomic_add_return(&_val, delta) - delta;#elif CLICK_LINUXMODULE# warning "using nonatomic approximation for atomic_uint32_t::fetch_and_add"    unsigned long flags;    local_irq_save(flags);    uint32_t old_value = value();    CLICK_ATOMIC_VAL += delta;    local_irq_restore(flags);    return old_value;#else    uint32_t old_value = value();    CLICK_ATOMIC_VAL += delta;    return old_value;#endif}/** @brief  Atomically decrement @a x, returning true if the new @a x *	    is 0. * * Behaves like this, but in one atomic step: * @code * --x; * return x == 0; * @endcode */inline boolatomic_uint32_t::dec_and_test(volatile uint32_t &x){#if CLICK_LINUXMODULE    static_assert(sizeof(atomic_t) == sizeof(x));    return atomic_dec_and_test((atomic_t *) &x);#elif CLICK_ATOMIC_X86    uint8_t result;    asm volatile (CLICK_ATOMIC_LOCK "decl %0 ; sete %1"		  : "=m" (x), "=qm" (result)		  : "m" (x)		  : "cc");    return result;#else    return (--x == 0);#endif}/** @brief  Perform a compare-and-swap operation. *  @param  x           value *  @param  test_value  test value *  @param  new_value   new value *  @return True if the old @a x equaled @a test_value (in which case @a x *	    was set to @a new_value), false otherwise. * * Behaves like this, but in one atomic step: * @code * uint32_t old_value = x; * if (x == test_value) *     x = new_value; * return old_value == test_value; * @endcode * * Also acts as a memory barrier. */inline boolatomic_uint32_t::compare_and_swap(volatile uint32_t &x, uint32_t test_value, uint32_t new_value){#if CLICK_ATOMIC_X86    asm volatile (CLICK_ATOMIC_LOCK "cmpxchgl %2,%0 ; sete %%al"		  : "=m" (x), "=a" (test_value)		  : "r" (new_value), "m" (x), "a" (test_value)		  : "cc", "memory");    return (uint8_t) test_value;#elif CLICK_LINUXMODULE && defined(cmpxchg)    return cmpxchg(&x, test_value, new_value) == test_value;#elif CLICK_LINUXMODULE# warning "using nonatomic approximation for atomic_uint32_t::compare_and_swap"    unsigned long flags;    local_irq_save(flags);    uint32_t old_value = x;    if (old_value == test_value)	x = new_value;    local_irq_restore(flags);    return old_value == test_value;#else    uint32_t old_value = x;    if (old_value == test_value)	x = new_value;    return old_value == test_value;#endif}/** @brief  Atomically decrement the value, returning true if the new value *	    is 0. * * Behaves like this, but in one atomic step: * @code * --*this; * return value() == 0; * @endcode */inline boolatomic_uint32_t::dec_and_test(){#if CLICK_LINUXMODULE    return atomic_dec_and_test(&_val);#elif CLICK_ATOMIC_X86    uint8_t result;    asm volatile (CLICK_ATOMIC_LOCK "decl %0 ; sete %1"		  : "=m" (CLICK_ATOMIC_VAL), "=qm" (result)		  : "m" (CLICK_ATOMIC_VAL)		  : "cc");    return result;#else    return (--CLICK_ATOMIC_VAL == 0);#endif}/** @brief  Perform a compare-and-swap operation. *  @param  test_value  test value *  @param  new_value   new value *  @return True if the old value equaled @a test_value (in which case the *	    value was set to @a new_value), false otherwise. * * Behaves like this, but in one atomic step: * @code * uint32_t old_value = value(); * if (old_value == test_value) *     *this = new_value; * return old_value == test_value; * @endcode * * Also acts as a memory barrier. */inline boolatomic_uint32_t::compare_and_swap(uint32_t test_value, uint32_t new_value){#if CLICK_ATOMIC_X86    asm volatile (CLICK_ATOMIC_LOCK "cmpxchgl %2,%0 ; sete %%al"		  : "=m" (CLICK_ATOMIC_VAL), "=a" (test_value)		  : "r" (new_value), "m" (CLICK_ATOMIC_VAL), "a" (test_value)		  : "cc", "memory");    return (uint8_t) test_value;#elif CLICK_LINUXMODULE && defined(atomic_cmpxchg)    return atomic_cmpxchg(&_val, test_value, new_value) == test_value;#elif CLICK_LINUXMODULE# warning "using nonatomic approximation for atomic_uint32_t::compare_and_swap"    unsigned long flags;    local_irq_save(flags);    uint32_t old_value = value();    if (old_value == test_value)	CLICK_ATOMIC_VAL = new_value;    local_irq_restore(flags);    return old_value == test_value;#else    uint32_t old_value = value();    if (old_value == test_value)	CLICK_ATOMIC_VAL = new_value;    return old_value == test_value;#endif}inline uint32_toperator+(const atomic_uint32_t &a, const atomic_uint32_t &b){    return a.value() + b.value();}inline uint32_toperator-(const atomic_uint32_t &a, const atomic_uint32_t &b){    return a.value() - b.value();}inline booloperator==(const atomic_uint32_t &a, const atomic_uint32_t &b){    return a.value() == b.value();}inline booloperator!=(const atomic_uint32_t &a, const atomic_uint32_t &b){    return a.value() != b.value();}inline booloperator>(const atomic_uint32_t &a, const atomic_uint32_t &b){    return a.value() > b.value();}inline booloperator<(const atomic_uint32_t &a, const atomic_uint32_t &b){    return a.value() < b.value();}inline booloperator>=(const atomic_uint32_t &a, const atomic_uint32_t &b){    return a.value() >= b.value();}inline booloperator<=(const atomic_uint32_t &a, const atomic_uint32_t &b){    return a.value() <= b.value();}typedef atomic_uint32_t uatomic32_t;CLICK_ENDDECLS#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -