Eneboo - Documentación para desarrolladores
src/hoard/src/heaplayers/spinlock.h
Ir a la documentación de este archivo.
00001 #include <stdio.h>
00002 /* -*- C++ -*- */
00003 
00004 /*
00005 
00006   Heap Layers: An Extensible Memory Allocation Infrastructure
00007   
00008   Copyright (C) 2000-2006 by Emery Berger
00009   http://www.cs.umass.edu/~emery
00010   emery@cs.umass.edu
00011   
00012   This program is free software; you can redistribute it and/or modify
00013   it under the terms of the GNU General Public License as published by
00014   the Free Software Foundation; either version 2 of the License, or
00015   (at your option) any later version.
00016   
00017   This program is distributed in the hope that it will be useful,
00018   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020   GNU General Public License for more details.
00021   
00022   You should have received a copy of the GNU General Public License
00023   along with this program; if not, write to the Free Software
00024   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 */
00027 
00028 #ifndef _SPINLOCK_H_
00029 #define _SPINLOCK_H_
00030 
00031 #if defined(unix)
00032 #include <sched.h>
00033 #endif
00034 
00035 #if defined(__SVR4)
00036 #include <thread.h>
00037 #endif
00038 
00039 #if defined(__sgi)
00040 #include <mutex.h>
00041 #endif
00042 
00043 #if defined(__APPLE__)
00044 #include <libkern/OSAtomic.h>
00045 #endif
00046 
00047 #include "hldefines.h"
00048 #include "cpuinfo.h"
00049 
00050 #if defined(_MSC_VER)
00051 
00052 #if !defined(NO_INLINE)
00053 #pragma inline_depth(255)
00054 #define NO_INLINE __declspec(noinline)
00055 #define INLINE __forceinline
00056 #define inline __forceinline
00057 #endif // !defined(NO_INLINE)
00058 
00059 #else
00060 
00061 #endif // defined(_MSC_VER)
00062 
00063 
00064 #if defined(__SUNPRO_CC)
00065 // x86-interchange.il, x86_64-interchange.il contributed by Markus Bernhardt.
00066 extern "C" unsigned long MyInterlockedExchange (unsigned long * oldval,
00067                                               unsigned long newval);
00068 #endif
00069 
00070 #undef _WIN32
00071 #if defined(_WIN32) && !defined(_WIN64)
00072 #define _WIN32_WINNT 0x0500
00073 
00074 // NOTE: Below is the new "pause" instruction, which is inocuous for
00075 // previous architectures, but crucial for Intel chips with
00076 // hyperthreading.  See
00077 // http://www.usenix.org/events/wiess02/tech/full_papers/nakajima/nakajima.pdf
00078 // for discussion.
00079 
00080 #define _MM_PAUSE  {__asm{_emit 0xf3};__asm {_emit 0x90}}
00081 #include <windows.h>
00082 #else
00083 #define _MM_PAUSE
00084 #endif // defined(_WIN32) && !defined(_WIN64)
00085 
00086 extern volatile int anyThreadCreated;
00087 
00088 namespace HL {
00089 
00090 class SpinLockType {
00091 private:
00092 
00093   enum { UNLOCKED = 0, LOCKED = 1 };
00094 
00095 public:
00096   
00097   SpinLockType (void)
00098 #if defined(__APPLE__)
00099     : mutex (OS_SPINLOCK_INIT)
00100 #else
00101     : mutex (UNLOCKED)
00102 #endif
00103   {}
00104   
00105   ~SpinLockType (void)
00106   {}
00107 
00108   inline void lock (void) {
00109     if (anyThreadCreated) {
00110       if (MyInterlockedExchange (const_cast<unsigned long *>(&mutex), LOCKED)
00111           != UNLOCKED) {
00112         contendedLock();
00113       }
00114     } else {
00115       mutex = LOCKED;
00116     }
00117   }
00118 
00119 
00120   inline void unlock (void) {
00121     if (anyThreadCreated) {
00122 #if defined(_WIN32) && !defined(_WIN64)
00123       __asm {}
00124 #elif defined(__GNUC__)
00125       asm volatile ("" : : : "memory");
00126 #endif
00127     }
00128     mutex = UNLOCKED;
00129   }
00130 
00131 
00132 #if !defined(__SUNPRO_CC)
00133   inline static volatile unsigned long MyInterlockedExchange (unsigned long *,unsigned long); 
00134 #endif
00135 
00136 private:
00137 
00138 #if 0 // defined(__APPLE__)
00139   OSSpinLock mutex;
00140 
00141 #else
00142 
00143   NO_INLINE
00144   void contendedLock (void) {
00145     while (1) {
00146       if (MyInterlockedExchange (const_cast<unsigned long *>(&mutex), LOCKED)
00147           == UNLOCKED) {
00148         return;
00149       }
00150       while (mutex == LOCKED) {
00151         _MM_PAUSE;
00152         yieldProcessor();
00153       }
00154     }
00155   }
00156 
00157   // Is this system a multiprocessor?
00158   inline bool onMultiprocessor (void) {
00159     static CPUInfo cpuInfo;
00160     return (cpuInfo.getNumProcessors() > 1);
00161   }
00162 
00163   inline void yieldProcessor (void) {
00164 #if defined(_WIN32)
00165     Sleep(0);
00166 #elif defined(__SVR4)
00167     thr_yield();
00168 #else
00169     sched_yield();
00170 #endif
00171   }
00172 
00173   enum { MAX_SPIN_LIMIT = 1024 };
00174 
00175   union {
00176     volatile unsigned long mutex;
00177   };
00178 #endif
00179 
00180 };
00181 
00182 }
00183 
00184 // Atomically:
00185 //   retval = *oldval;
00186 //   *oldval = newval;
00187 //   return retval;
00188 
00189 #if !defined(__SUNPRO_CC) // && !defined(__APPLE__)
00190 inline volatile unsigned long 
00191 HL::SpinLockType::MyInterlockedExchange (unsigned long * oldval,
00192                                    unsigned long newval)
00193 {
00194 #if defined(_WIN32) && defined(_MSC_VER)
00195   return InterlockedExchange ((volatile LONG *) oldval, newval);
00196 
00197   //#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
00198   //  return __sync_val_compare_and_swap(oldval, *oldval, newval);
00199 
00200 #elif defined(__sparc)
00201   asm volatile ("swap [%1],%0"
00202                 :"=r" (newval)
00203                 :"r" (oldval), "0" (newval)
00204                 : "memory");
00205   
00206 #elif defined(__i386__)
00207   asm volatile ("lock; xchgl %0, %1"
00208                 : "=r" (newval)
00209                 : "m" (*oldval), "0" (newval)
00210                 : "memory");
00211 
00212 #elif defined(__sgi)
00213   newval = test_and_set (oldval, newval);
00214 
00215 #elif defined(__x86_64__)
00216   // Contributed by Kurt Roeckx.
00217   asm volatile ("lock; xchgq %0, %1"
00218                 : "=r" (newval)
00219                 : "m" (*oldval), "0" (newval)
00220                 : "memory");
00221 
00222 #elif defined(__ppc) || defined(__powerpc__) || defined(PPC)
00223   // PPC assembly contributed by Maged Michael.
00224   int ret; 
00225   asm volatile ( 
00226                 "La..%=0:    lwarx %0,0,%1 ;" 
00227                 "      cmpw  %0,%2;" 
00228                 "      beq La..%=1;" 
00229                 "      stwcx. %2,0,%1;" 
00230                 "      bne- La..%=0;" 
00231                 "La..%=1:    isync;" 
00232                 : "=&r"(ret) 
00233                 : "r"(oldval), "r"(newval) 
00234                 : "cr0", "memory"); 
00235   return ret;
00236 
00237 #elif defined(__arm__)
00238   // Contributed by Bo Granlund.
00239   long result;
00240   asm volatile (
00241                        "\n\t"
00242                        "swp     %0,%2,[%1] \n\t"
00243                        ""
00244                        : "=&r"(result)
00245                        : "r"(oldval), "r"(newval)
00246                        : "memory");
00247   return (result);
00248 #elif defined(__APPLE__)
00249   unsigned long oldValue = *oldval;
00250   bool swapped = OSAtomicCompareAndSwapLongBarrier (oldValue, newval, oldval);
00251   if (swapped) {
00252     return newval;
00253   } else {
00254     return oldValue;
00255   }
00256 #else
00257 #error "No spin lock implementation is available for this platform."
00258 #endif
00259   return newval;
00260 }
00261 
00262 
00263 #endif
00264 
00265 #endif // _SPINLOCK_H_
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Propiedades Amigas 'defines'