source: proiecte/swift/trunk/lib/hoard-371/src/heaplayers/spinlock.h @ 176

Last change on this file since 176 was 176, checked in by (none), 14 years ago
  • imported repo from "guagal"
File size: 5.6 KB
Line 
1/* -*- C++ -*- */
2
3/*
4
5  Heap Layers: An Extensible Memory Allocation Infrastructure
6 
7  Copyright (C) 2000-2006 by Emery Berger
8  http://www.cs.umass.edu/~emery
9  emery@cs.umass.edu
10 
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2 of the License, or
14  (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
25*/
26
27#ifndef _SPINLOCK_H_
28#define _SPINLOCK_H_
29
30#if defined(unix)
31#include <sched.h>
32#endif
33
34#if defined(__SVR4)
35#include <thread.h>
36#endif
37
38#if defined(__sgi)
39#include <mutex.h>
40#endif
41
42#if defined(__APPLE__)
43#include <libkern/OSAtomic.h>
44#endif
45
46#include "hldefines.h"
47#include "cpuinfo.h"
48
49#if defined(_MSC_VER)
50
51#if !defined(NO_INLINE)
52#pragma inline_depth(255)
53#define NO_INLINE __declspec(noinline)
54#define INLINE __forceinline
55#define inline __forceinline
56#endif // !defined(NO_INLINE)
57
58#else
59
60#endif // defined(_MSC_VER)
61
62
63#if defined(__SUNPRO_CC)
64// x86-interchange.il, x86_64-interchange.il contributed by Markus Bernhardt.
65extern "C" unsigned long MyInterlockedExchange (unsigned long * oldval,
66                                              unsigned long newval);
67#endif
68
69#if defined(_WIN32) && !defined(_WIN64)
70#define _WIN32_WINNT 0x0500
71
72// NOTE: Below is the new "pause" instruction, which is inocuous for
73// previous architectures, but crucial for Intel chips with
74// hyperthreading.  See
75// http://www.usenix.org/events/wiess02/tech/full_papers/nakajima/nakajima.pdf
76// for discussion.
77
78#define _MM_PAUSE  {__asm{_emit 0xf3};__asm {_emit 0x90}}
79#include <windows.h>
80#else
81#define _MM_PAUSE
82#endif // defined(_WIN32) && !defined(_WIN64)
83
84extern volatile int anyThreadCreated;
85
86namespace HL {
87
88class SpinLockType {
89private:
90
91  enum { UNLOCKED = 0, LOCKED = 1 };
92
93public:
94 
95  SpinLockType (void)
96#if defined(__APPLE__)
97    : mutex (OS_SPINLOCK_INIT)
98#else
99    : mutex (UNLOCKED)
100#endif
101  {}
102 
103  ~SpinLockType (void)
104  {}
105
106  inline void lock (void) {
107    if (anyThreadCreated) {
108#if defined(__APPLE__)
109      OSSpinLockLock(&mutex);
110#else
111      // A yielding lock (with an initial spin).
112      if (MyInterlockedExchange (const_cast<unsigned long *>(&mutex), LOCKED)
113          != UNLOCKED) {
114        contendedLock();
115      }
116#endif
117    } else {
118      mutex = LOCKED;
119    }
120  }
121
122 
123  inline void unlock (void) {
124#if defined(__APPLE__)
125    OSSpinLockUnlock(&mutex);
126#else
127    if (anyThreadCreated) {
128#if defined(_WIN32) && !defined(_WIN64)
129      __asm {}
130#elif defined(__GNUC__)
131      asm volatile ("" : : : "memory");
132#endif
133    }
134    mutex = UNLOCKED;
135#endif
136  }
137
138
139#if !defined(__SUNPRO_CC)
140  inline static volatile unsigned long MyInterlockedExchange (unsigned long *,unsigned long); 
141#endif
142
143private:
144
145#if defined(__APPLE__)
146  OSSpinLock mutex;
147
148#else
149
150  NO_INLINE
151  void contendedLock (void) {
152    while (1) {
153      if (MyInterlockedExchange (const_cast<unsigned long *>(&mutex), LOCKED)
154          == UNLOCKED) {
155        return;
156      }
157      while (mutex == LOCKED) {
158        _MM_PAUSE;
159        yieldProcessor();
160      }
161    }
162  }
163
164  // Is this system a multiprocessor?
165  inline bool onMultiprocessor (void) {
166    static CPUInfo cpuInfo;
167    return (cpuInfo.getNumProcessors() > 1);
168  }
169
170  inline void yieldProcessor (void) {
171#if defined(_WIN32)
172    Sleep(0);
173#elif defined(__SVR4)
174    thr_yield();
175#else
176    sched_yield();
177#endif
178  }
179
180  enum { MAX_SPIN_LIMIT = 1024 };
181
182  union {
183    volatile unsigned long mutex;
184  };
185#endif
186
187};
188
189}
190
191// Atomically:
192//   retval = *oldval;
193//   *oldval = newval;
194//   return retval;
195
196#if !defined(__SUNPRO_CC) && !defined(__APPLE__)
197inline volatile unsigned long 
198HL::SpinLockType::MyInterlockedExchange (unsigned long * oldval,
199                                   unsigned long newval)
200{
201#if defined(_WIN32) && defined(_MSC_VER)
202  return InterlockedExchange ((volatile LONG *) oldval, newval);
203
204#elif defined(__sparc)
205  asm volatile ("swap [%1],%0"
206                :"=r" (newval)
207                :"r" (oldval), "0" (newval)
208                : "memory");
209 
210#elif defined(__i386__)
211  asm volatile ("lock; xchgl %0, %1"
212                : "=r" (newval)
213                : "m" (*oldval), "0" (newval)
214                : "memory");
215
216#elif defined(__sgi)
217  newval = test_and_set (oldval, newval);
218
219#elif defined(__x86_64__)
220  // Contributed by Kurt Roeckx.
221  asm volatile ("lock; xchgq %0, %1"
222                : "=r" (newval)
223                : "m" (*oldval), "0" (newval)
224                : "memory");
225
226#elif defined(__ppc) || defined(__powerpc__) || defined(PPC)
227  // PPC assembly contributed by Maged Michael.
228  int ret; 
229  asm volatile ( 
230                "La..%=0:    lwarx %0,0,%1 ;" 
231                "      cmpw  %0,%2;" 
232                "      beq La..%=1;" 
233                "      stwcx. %2,0,%1;" 
234                "      bne- La..%=0;" 
235                "La..%=1:    isync;" 
236                : "=&r"(ret) 
237                : "r"(oldval), "r"(newval) 
238                : "cr0", "memory"); 
239  return ret;
240
241#elif defined(__arm__)
242  // Contributed by Bo Granlund.
243  long result;
244  asm volatile (
245                       "\n\t"
246                       "swp     %0,%2,[%1] \n\t"
247                       ""
248                       : "=&r"(result)
249                       : "r"(oldval), "r"(newval)
250                       : "memory");
251  return (result);
252#else
253#error "No spin lock implementation is available for this platform."
254#endif
255  return newval;
256}
257
258
259#endif
260
261#endif // _SPINLOCK_H_
Note: See TracBrowser for help on using the repository browser.