From 597cc5edd624525563e6549dc0057eca2a51c81d Mon Sep 17 00:00:00 2001 From: Micah Anderson Date: Tue, 11 Nov 2014 13:30:46 -0500 Subject: upgrade to new version --- src/atomic_ptr.hpp | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 src/atomic_ptr.hpp (limited to 'src/atomic_ptr.hpp') diff --git a/src/atomic_ptr.hpp b/src/atomic_ptr.hpp new file mode 100644 index 0000000..066d54b --- /dev/null +++ b/src/atomic_ptr.hpp @@ -0,0 +1,202 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef __ZMQ_ATOMIC_PTR_HPP_INCLUDED__ +#define __ZMQ_ATOMIC_PTR_HPP_INCLUDED__ + +#include "platform.hpp" + +#if defined ZMQ_FORCE_MUTEXES +#define ZMQ_ATOMIC_PTR_MUTEX +#elif (defined __i386__ || defined __x86_64__) && defined __GNUC__ +#define ZMQ_ATOMIC_PTR_X86 +#elif defined __ARM_ARCH_7A__ && defined __GNUC__ +#define ZMQ_ATOMIC_PTR_ARM +#elif defined __tile__ +#define ZMQ_ATOMIC_PTR_TILE +#elif defined ZMQ_HAVE_WINDOWS +#define ZMQ_ATOMIC_PTR_WINDOWS +#elif (defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_NETBSD) +#define ZMQ_ATOMIC_PTR_ATOMIC_H +#else +#define ZMQ_ATOMIC_PTR_MUTEX +#endif + +#if defined ZMQ_ATOMIC_PTR_MUTEX +#include "mutex.hpp" +#elif defined ZMQ_ATOMIC_PTR_WINDOWS +#include "windows.hpp" +#elif defined ZMQ_ATOMIC_PTR_ATOMIC_H +#include +#elif defined ZMQ_ATOMIC_PTR_TILE +#include +#endif + +namespace zmq +{ + + // This class encapsulates several atomic operations on pointers. + + template class atomic_ptr_t + { + public: + + // Initialise atomic pointer + inline atomic_ptr_t () + { + ptr = NULL; + } + + // Destroy atomic pointer + inline ~atomic_ptr_t () + { + } + + // Set value of atomic pointer in a non-threadsafe way + // Use this function only when you are sure that at most one + // thread is accessing the pointer at the moment. + inline void set (T *ptr_) + { + this->ptr = ptr_; + } + + // Perform atomic 'exchange pointers' operation. Pointer is set + // to the 'val' value. Old value is returned. + inline T *xchg (T *val_) + { +#if defined ZMQ_ATOMIC_PTR_WINDOWS + return (T*) InterlockedExchangePointer ((PVOID*) &ptr, val_); +#elif defined ZMQ_ATOMIC_PTR_ATOMIC_H + return (T*) atomic_swap_ptr (&ptr, val_); +#elif defined ZMQ_ATOMIC_PTR_TILE + return (T*) arch_atomic_exchange (&ptr, val_); +#elif defined ZMQ_ATOMIC_PTR_X86 + T *old; + __asm__ volatile ( + "lock; xchg %0, %2" + : "=r" (old), "=m" (ptr) + : "m" (ptr), "0" (val_)); + return old; +#elif defined ZMQ_ATOMIC_PTR_ARM + T* old; + unsigned int flag; + __asm__ volatile ( + " dmb sy\n\t" + "1: ldrex %1, [%3]\n\t" + " strex %0, %4, [%3]\n\t" + " teq %0, #0\n\t" + " bne 1b\n\t" + " dmb sy\n\t" + : "=&r"(flag), "=&r"(old), "+Qo"(ptr) + : "r"(&ptr), "r"(val_) + : "cc"); + return old; +#elif defined ZMQ_ATOMIC_PTR_MUTEX + sync.lock (); + T *old = (T*) ptr; + ptr = val_; + sync.unlock (); + return old; +#else +#error atomic_ptr is not implemented for this platform +#endif + } + + // Perform atomic 'compare and swap' operation on the pointer. + // The pointer is compared to 'cmp' argument and if they are + // equal, its value is set to 'val'. Old value of the pointer + // is returned. + inline T *cas (T *cmp_, T *val_) + { +#if defined ZMQ_ATOMIC_PTR_WINDOWS + return (T*) InterlockedCompareExchangePointer ( + (volatile PVOID*) &ptr, val_, cmp_); +#elif defined ZMQ_ATOMIC_PTR_ATOMIC_H + return (T*) atomic_cas_ptr (&ptr, cmp_, val_); +#elif defined ZMQ_ATOMIC_PTR_TILE + return (T*) arch_atomic_val_compare_and_exchange (&ptr, cmp_, val_); +#elif defined ZMQ_ATOMIC_PTR_X86 + T *old; + __asm__ volatile ( + "lock; cmpxchg %2, %3" + : "=a" (old), "=m" (ptr) + : "r" (val_), "m" (ptr), "0" (cmp_) + : "cc"); + return old; +#elif defined ZMQ_ATOMIC_PTR_ARM + T *old; + unsigned int flag; + __asm__ volatile ( + " dmb sy\n\t" + "1: ldrex %1, [%3]\n\t" + " mov %0, #0\n\t" + " teq %1, %4\n\t" + " it eq\n\t" + " strexeq %0, %5, [%3]\n\t" + " teq %0, #0\n\t" + " bne 1b\n\t" + " dmb sy\n\t" + : "=&r"(flag), "=&r"(old), "+Qo"(ptr) + : "r"(&ptr), "r"(cmp_), "r"(val_) + : "cc"); + return old; +#elif defined ZMQ_ATOMIC_PTR_MUTEX + sync.lock (); + T *old = (T*) ptr; + if (ptr == cmp_) + ptr = val_; + sync.unlock (); + return old; +#else +#error atomic_ptr is not implemented for this platform +#endif + } + + private: + + volatile T *ptr; +#if defined ZMQ_ATOMIC_PTR_MUTEX + mutex_t sync; +#endif + + atomic_ptr_t (const atomic_ptr_t&); + const atomic_ptr_t &operator = (const atomic_ptr_t&); + }; + +} + +// Remove macros local to this file. +#if defined ZMQ_ATOMIC_PTR_WINDOWS +#undef ZMQ_ATOMIC_PTR_WINDOWS +#endif +#if defined ZMQ_ATOMIC_PTR_ATOMIC_H +#undef ZMQ_ATOMIC_PTR_ATOMIC_H +#endif +#if defined ZMQ_ATOMIC_PTR_X86 +#undef ZMQ_ATOMIC_PTR_X86 +#endif +#if defined ZMQ_ATOMIC_PTR_ARM +#undef ZMQ_ATOMIC_PTR_ARM +#endif +#if defined ZMQ_ATOMIC_PTR_MUTEX +#undef ZMQ_ATOMIC_PTR_MUTEX +#endif + +#endif + -- cgit v1.2.3