OW_AtomicOps.hpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions are met:
00006  *
00007  *  - Redistributions of source code must retain the above copyright notice,
00008  *    this list of conditions and the following disclaimer.
00009  *
00010  *  - Redistributions in binary form must reproduce the above copyright notice,
00011  *    this list of conditions and the following disclaimer in the documentation
00012  *    and/or other materials provided with the distribution.
00013  *
00014  *  - Neither the name of Vintela, Inc. nor the names of its
00015  *    contributors may be used to endorse or promote products derived from this
00016  *    software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028  * POSSIBILITY OF SUCH DAMAGE.
00029  ******************************************************************************/
00030 
00035 #ifndef OW_ATOMIC_OPS_HPP_
00036 #define OW_ATOMIC_OPS_HPP_
00037 #include "OW_config.h"
00038 
00039 #if defined(OW_AIX)
00040 extern "C"
00041 {
00042 #include <sys/atomic_op.h>
00043 }
00044 #endif
00045 
00046 // The classes and functions defined in this file are not meant for general
00047 // use, they are internal implementation details.  They may change at any time.
00048 
00049 // x86 and x86-64 asm is identical
00050 #if (defined(OW_ARCH_X86) || defined(__i386__) || defined(OW_ARCH_X86_64) || defined(__x86_64__)) && defined(__GNUC__)
00051 
00052 namespace OW_NAMESPACE
00053 {
00054 
00055 // use fast inline assembly versions
00056 struct Atomic_t
00057 { 
00058    Atomic_t() : val(0) {}
00059    Atomic_t(int i) : val(i) {}
00060    volatile int val; 
00061 };
00062 inline void AtomicInc(Atomic_t &v)
00063 {
00064    __asm__ __volatile__(
00065       "lock ; " "incl %0"
00066       :"=m" (v.val)
00067       :"m" (v.val));
00068 }
00069 inline bool AtomicDecAndTest(Atomic_t &v)
00070 {
00071    unsigned char c;
00072    __asm__ __volatile__(
00073       "lock ; " "decl %0; sete %1"
00074       :"=m" (v.val), "=qm" (c)
00075       :"m" (v.val) : "memory");
00076    return c != 0;
00077 }
00078 inline int AtomicGet(Atomic_t const &v)
00079 {
00080    return v.val;
00081 }
00082 inline void AtomicDec(Atomic_t &v)
00083 {
00084    __asm__ __volatile__(
00085       "lock ; " "decl %0"
00086       :"=m" (v.val)
00087       :"m" (v.val));
00088 }
00089 
00090 } // end namespace OW_NAMESPACE
00091 
00092 #elif defined(OW_AIX)
00093 namespace OW_NAMESPACE
00094 {
00095 // This comment was stolen from the libstdc++ implementation of atomicity.h
00096 // (and modified). 
00097 // We cannot use the inline assembly for powerpc, since definitions for
00098 // these operations since they depend on operations that are not available on
00099 // the original POWER architecture.  AIX still runs on the POWER architecture,
00100 // so it would be incorrect to assume the existence of these instructions. 
00101 //
00102 // The definition of Atomic_t.val must match the type pointed to by atomic_p in
00103 // <sys/atomic_op.h>. 
00104 struct Atomic_t
00105 { 
00106    Atomic_t() : val(0) {}
00107    Atomic_t(int i) : val(i) {}
00108    volatile int val; 
00109 };
00110 
00111 inline void AtomicInc(Atomic_t &v)
00112 {
00113    ::fetch_and_add(const_cast<atomic_p>(&v.val), 1);
00114 }
00115 inline bool AtomicDecAndTest(Atomic_t &v)
00116 {
00117    // fetch_and_add returns the original value before the add operation.  Thus,
00118    // we must subtract one from the returned value before comparing.
00119    int c = ::fetch_and_add(const_cast<atomic_p>(&v.val), -1);
00120    --c;
00121    return c == 0;
00122 }
00123 inline int AtomicGet(Atomic_t const &v)
00124 {
00125    int c = ::fetch_and_add(const_cast<atomic_p>(&v.val), 0);
00126    return c;
00127 }
00128 inline void AtomicDec(Atomic_t &v)
00129 {
00130    ::fetch_and_add(const_cast<atomic_p>(&v.val), -1);
00131 }
00132 
00133 } // end namespace OW_NAMESPACE
00134 
00135 #elif (defined(OW_ARCH_PPC) || defined(__ppc__)) && defined(__GNUC__)
00136 
00137 namespace OW_NAMESPACE
00138 {
00139 
00140 // use fast inline assembly versions
00141 struct Atomic_t
00142 { 
00143    Atomic_t() : val(0) {}
00144    Atomic_t(int i) : val(i) {}
00145    volatile int val; 
00146 };
00147 
00148 inline void AtomicInc(Atomic_t &v)
00149 {
00150    int t;
00151    __asm__ __volatile__(
00152       "1:   lwarx   %0,0,%2\n"
00153       "  addic   %0,%0,1\n"
00154       "  stwcx.  %0,0,%2\n"
00155       "  bne-    1b"
00156       : "=&r" (t), "=m" (v.val)
00157       : "r" (&v.val), "m" (v.val)
00158       : "cc");
00159 }
00160 inline bool AtomicDecAndTest(Atomic_t &v)
00161 {
00162    int c;
00163    __asm__ __volatile__(
00164       "1:   lwarx   %0,0,%1\n"
00165       "  addic   %0,%0,-1\n"
00166       "  stwcx.  %0,0,%1\n"
00167       "  bne-    1b\n"
00168       "  isync"
00169       : "=&r" (c)
00170       : "r" (&v.val)
00171       : "cc", "memory");
00172    return c == 0;
00173 }
00174 inline int AtomicGet(Atomic_t const &v)
00175 {
00176    return v.val;
00177 }
00178 inline void AtomicDec(Atomic_t &v)
00179 {
00180    int c;
00181    __asm__ __volatile__(
00182       "1:   lwarx   %0,0,%2\n"
00183       "  addic   %0,%0,-1\n"
00184       "  stwcx.  %0,0,%2\n"
00185       "  bne-    1b"
00186       : "=&r" (c), "=m" (v.val)
00187       : "r" (&v.val), "m" (v.val)
00188       : "cc");
00189 }
00190 
00191 } // end namespace OW_NAMESPACE
00192 
00193 #elif defined(OW_WIN32)
00194 
00195 namespace OW_NAMESPACE
00196 {
00197 
00198 // use fast inline assembly versions
00199 struct OW_COMMON_API Atomic_t
00200 { 
00201    Atomic_t() : val(0) {}
00202    Atomic_t(int i) : val(i) {}
00203    volatile LONG val; 
00204 };
00205 inline void AtomicInc(Atomic_t &v)
00206 {
00207    InterlockedIncrement(&v.val); 
00208 }
00209 inline bool AtomicDecAndTest(Atomic_t &v)
00210 {
00211    return InterlockedDecrement(&v.val) == 0;
00212 }
00213 inline int AtomicGet(Atomic_t const &v)
00214 {
00215    return v.val;
00216 }
00217 inline void AtomicDec(Atomic_t &v)
00218 {
00219    InterlockedDecrement(&v.val);
00220 }
00221 
00222 } // end namespace OW_NAMESPACE
00223 
00224 #elif defined(OW_HAVE_PTHREAD_SPIN_LOCK)
00225 #include <pthread.h>
00226 
00227 #define OW_USE_PTHREAD_SPIN_LOCK_ATOMIC_OPS // used in OW_AtomicOps.cpp
00228 
00229 namespace OW_NAMESPACE
00230 {
00231 
00232 struct Atomic_t
00233 {
00234    Atomic_t();
00235    Atomic_t(int i);
00236    int val;
00237    pthread_spinlock_t spinlock;
00238 };
00239 void AtomicInc(Atomic_t &v);
00240 bool AtomicDecAndTest(Atomic_t &v);
00241 int AtomicGet(Atomic_t const &v);
00242 void AtomicDec(Atomic_t &v);
00243 
00244 } // end namespace OW_NAMESPACE
00245 
00246 #else
00247 // use slow mutex protected versions
00248 #define OW_USE_OW_DEFAULT_ATOMIC_OPS // used in OW_AtomicOps.cpp
00249 
00250 namespace OW_NAMESPACE
00251 {
00252 
00253 struct Atomic_t
00254 { 
00255    Atomic_t() : val(0) {}
00256    Atomic_t(int i) : val(i) {}
00257    volatile int val; 
00258 };
00259 void AtomicInc(Atomic_t &v);
00260 bool AtomicDecAndTest(Atomic_t &v);
00261 int AtomicGet(Atomic_t const &v);
00262 void AtomicDec(Atomic_t &v);
00263 
00264 } // end namespace OW_NAMESPACE
00265 
00266 #endif
00267 #endif

Generated on Thu Feb 9 08:47:52 2006 for openwbem by  doxygen 1.4.6