OWBI1_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 OWBI1_ATOMIC_OPS_HPP_
00036 #define OWBI1_ATOMIC_OPS_HPP_
00037 #include "OWBI1_config.h"
00038 
00039 #if defined(OWBI1_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 #if (defined(OWBI1_ARCH_X86) || defined(__i386__)) && defined(__GNUC__)
00050 
00051 namespace OWBI1
00052 {
00053 
00054 // use fast inline assembly versions
00055 struct Atomic_t
00056 { 
00057    Atomic_t() : val(0) {}
00058    Atomic_t(int i) : val(i) {}
00059    volatile int val; 
00060 };
00061 inline void AtomicInc(Atomic_t &v)
00062 {
00063    __asm__ __volatile__(
00064       "lock ; " "incl %0"
00065       :"=m" (v.val)
00066       :"m" (v.val));
00067 }
00068 inline bool AtomicDecAndTest(Atomic_t &v)
00069 {
00070    unsigned char c;
00071    __asm__ __volatile__(
00072       "lock ; " "decl %0; sete %1"
00073       :"=m" (v.val), "=qm" (c)
00074       :"m" (v.val) : "memory");
00075    return c != 0;
00076 }
00077 inline int AtomicGet(Atomic_t const &v)
00078 {
00079    return v.val;
00080 }
00081 inline void AtomicDec(Atomic_t &v)
00082 {
00083    __asm__ __volatile__(
00084       "lock ; " "decl %0"
00085       :"=m" (v.val)
00086       :"m" (v.val));
00087 }
00088 
00089 } // end namespace OWBI1
00090 
00091 #elif defined(OWBI1_AIX)
00092 namespace OWBI1
00093 {
00094 // This comment was stolen from the libstdc++ implementation of atomicity.h
00095 // (and modified). 
00096 // We cannot use the inline assembly for powerpc, since definitions for
00097 // these operations since they depend on operations that are not available on
00098 // the original POWER architecture.  AIX still runs on the POWER architecture,
00099 // so it would be incorrect to assume the existence of these instructions. 
00100 //
00101 // The definition of Atomic_t.val must match the type pointed to by atomic_p in
00102 // <sys/atomic_op.h>. 
00103 struct Atomic_t
00104 { 
00105    Atomic_t() : val(0) {}
00106    Atomic_t(int i) : val(i) {}
00107    volatile int val; 
00108 };
00109 
00110 inline void AtomicInc(Atomic_t &v)
00111 {
00112    ::fetch_and_add(const_cast<atomic_p>(&v.val), 1);
00113 }
00114 inline bool AtomicDecAndTest(Atomic_t &v)
00115 {
00116    // fetch_and_add returns the original value before the add operation.  Thus,
00117    // we must subtract one from the returned value before comparing.
00118    int c = ::fetch_and_add(const_cast<atomic_p>(&v.val), -1);
00119    --c;
00120    return c == 0;
00121 }
00122 inline int AtomicGet(Atomic_t const &v)
00123 {
00124    int c = ::fetch_and_add(const_cast<atomic_p>(&v.val), 0);
00125    return c;
00126 }
00127 inline void AtomicDec(Atomic_t &v)
00128 {
00129    ::fetch_and_add(const_cast<atomic_p>(&v.val), -1);
00130 }
00131 
00132 } // end namespace OWBI1
00133 
00134 #elif (defined(OWBI1_ARCH_PPC) || defined(__ppc__)) && defined(__GNUC__)
00135 
00136 namespace OWBI1
00137 {
00138 
00139 // use fast inline assembly versions
00140 struct Atomic_t
00141 { 
00142    Atomic_t() : val(0) {}
00143    Atomic_t(int i) : val(i) {}
00144    volatile int val; 
00145 };
00146 
00147 inline void AtomicInc(Atomic_t &v)
00148 {
00149    int t;
00150    __asm__ __volatile__(
00151       "1:   lwarx   %0,0,%2\n"
00152       "  addic   %0,%0,1\n"
00153       "  stwcx.  %0,0,%2\n"
00154       "  bne-    1b"
00155       : "=&r" (t), "=m" (v.val)
00156       : "r" (&v.val), "m" (v.val)
00157       : "cc");
00158 }
00159 inline bool AtomicDecAndTest(Atomic_t &v)
00160 {
00161    int c;
00162    __asm__ __volatile__(
00163       "1:   lwarx   %0,0,%1\n"
00164       "  addic   %0,%0,-1\n"
00165       "  stwcx.  %0,0,%1\n"
00166       "  bne-    1b\n"
00167       "  isync"
00168       : "=&r" (c)
00169       : "r" (&v.val)
00170       : "cc", "memory");
00171    return c == 0;
00172 }
00173 inline int AtomicGet(Atomic_t const &v)
00174 {
00175    return v.val;
00176 }
00177 inline void AtomicDec(Atomic_t &v)
00178 {
00179    int c;
00180    __asm__ __volatile__(
00181       "1:   lwarx   %0,0,%2\n"
00182       "  addic   %0,%0,-1\n"
00183       "  stwcx.  %0,0,%2\n"
00184       "  bne-    1b"
00185       : "=&r" (c), "=m" (v.val)
00186       : "r" (&v.val), "m" (v.val)
00187       : "cc");
00188 }
00189 
00190 } // end namespace OWBI1
00191 
00192 #elif defined(OWBI1_WIN32)
00193 
00194 namespace OWBI1
00195 {
00196 
00197 // use fast inline assembly versions
00198 struct OWBI1_OWBI1PROVIFC_API Atomic_t
00199 { 
00200    Atomic_t() : val(0) {}
00201    Atomic_t(int i) : val(i) {}
00202    volatile LONG val; 
00203 };
00204 inline void AtomicInc(Atomic_t &v)
00205 {
00206    InterlockedIncrement(&v.val); 
00207 }
00208 inline bool AtomicDecAndTest(Atomic_t &v)
00209 {
00210    return InterlockedDecrement(&v.val) == 0;
00211 }
00212 inline int AtomicGet(Atomic_t const &v)
00213 {
00214    return v.val;
00215 }
00216 inline void AtomicDec(Atomic_t &v)
00217 {
00218    InterlockedDecrement(&v.val);
00219 }
00220 
00221 } // end namespace OWBI1
00222 
00223 #elif defined(OWBI1_HAVE_PTHREAD_SPIN_LOCK)
00224 #include <pthread.h>
00225 
00226 #define OWBI1_USE_PTHREAD_SPIN_LOCK_ATOMIC_OPS // used in OWBI1_AtomicOps.cpp
00227 
00228 namespace OWBI1
00229 {
00230 
00231 struct Atomic_t
00232 {
00233    Atomic_t();
00234    Atomic_t(int i);
00235    int val;
00236    pthread_spinlock_t spinlock;
00237 };
00238 void AtomicInc(Atomic_t &v);
00239 bool AtomicDecAndTest(Atomic_t &v);
00240 int AtomicGet(Atomic_t const &v);
00241 void AtomicDec(Atomic_t &v);
00242 
00243 } // end namespace OWBI1
00244 
00245 #else
00246 // use slow mutex protected versions
00247 #define OWBI1_USE_OWBI1_DEFAULT_ATOMIC_OPS // used in OWBI1_AtomicOps.cpp
00248 
00249 namespace OWBI1
00250 {
00251 
00252 struct Atomic_t
00253 { 
00254    Atomic_t() : val(0) {}
00255    Atomic_t(int i) : val(i) {}
00256    volatile int val; 
00257 };
00258 void AtomicInc(Atomic_t &v);
00259 bool AtomicDecAndTest(Atomic_t &v);
00260 int AtomicGet(Atomic_t const &v);
00261 void AtomicDec(Atomic_t &v);
00262 
00263 } // end namespace OWBI1
00264 
00265 #endif
00266 #endif

Generated on Thu Feb 9 08:48:25 2006 for openwbem by  doxygen 1.4.6