Ptex
PtexPlatform.h
Go to the documentation of this file.
1 #ifndef PtexPlatform_h
2 #define PtexPlatform_h
3 #define PtexPlatform_h
4 /*
5 PTEX SOFTWARE
6 Copyright 2014 Disney Enterprises, Inc. All rights reserved
7 
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are
10 met:
11 
12  * Redistributions of source code must retain the above copyright
13  notice, this list of conditions and the following disclaimer.
14 
15  * Redistributions in binary form must reproduce the above copyright
16  notice, this list of conditions and the following disclaimer in
17  the documentation and/or other materials provided with the
18  distribution.
19 
20  * The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
21  Studios" or the names of its contributors may NOT be used to
22  endorse or promote products derived from this software without
23  specific prior written permission from Walt Disney Pictures.
24 
25 Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
26 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
27 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
28 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
29 IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
30 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37 */
38 
43 #include "PtexInt.h"
44 
45 // platform-specific includes
46 #if defined(_WIN32) || defined(_WINDOWS) || defined(_MSC_VER)
47 #ifndef WINDOWS
48 #define WINDOWS
49 #endif
50 #define _CRT_NONSTDC_NO_DEPRECATE 1
51 #define _CRT_SECURE_NO_DEPRECATE 1
52 #define NOMINMAX 1
53 
54 // windows - defined for both Win32 and Win64
55 #include <Windows.h>
56 #include <malloc.h>
57 #include <io.h>
58 #include <tchar.h>
59 #include <process.h>
60 
61 #else
62 
63 // linux/unix/posix
64 #include <stdlib.h>
65 #include <alloca.h>
66 #include <string.h>
67 #include <pthread.h>
68 
69 #ifdef __APPLE__
70 #include <os/lock.h>
71 #include <sys/types.h>
72 #include <unistd.h>
73 #endif
74 #endif
75 
76 // general includes
77 #include <stdio.h>
78 #include <math.h>
79 #include <assert.h>
80 
81 // missing functions on Windows
82 #ifdef WINDOWS
83 typedef __int64 FilePos;
84 #define fseeko _fseeki64
85 #define ftello _ftelli64
86 
87 #else
88 typedef off_t FilePos;
89 #endif
90 
91 #include "PtexVersion.h"
92 
94 
95 /*
96  * Mutex
97  */
98 
99 #ifdef WINDOWS
100 
101 class Mutex {
102 public:
103  Mutex() { _mutex = CreateMutex(NULL, FALSE, NULL); }
104  ~Mutex() { CloseHandle(_mutex); }
105  void lock() { WaitForSingleObject(_mutex, INFINITE); }
106  bool trylock() { return WAIT_TIMEOUT != WaitForSingleObject(_mutex,0);}
107  void unlock() { ReleaseMutex(_mutex); }
108 private:
109  HANDLE _mutex;
110 };
111 
112 class SpinLock {
113 public:
114  SpinLock() { InitializeCriticalSection(&_spinlock); }
115  ~SpinLock() { DeleteCriticalSection(&_spinlock); }
116  void lock() { EnterCriticalSection(&_spinlock); }
117  bool trylock() { return TryEnterCriticalSection(&_spinlock); }
118  void unlock() { LeaveCriticalSection(&_spinlock); }
119 private:
120  CRITICAL_SECTION _spinlock;
121 };
122 
123 #else
124 // assume linux/unix/posix
125 
126 class Mutex {
127 public:
128  Mutex() { pthread_mutex_init(&_mutex, 0); }
129  ~Mutex() { pthread_mutex_destroy(&_mutex); }
130  void lock() { pthread_mutex_lock(&_mutex); }
131  bool trylock() { return 0 == pthread_mutex_trylock(&_mutex); }
132  void unlock() { pthread_mutex_unlock(&_mutex); }
133 private:
134  pthread_mutex_t _mutex;
135 };
136 
137 #ifdef __APPLE__
138 class SpinLock {
139 public:
140  SpinLock() { _spinlock = OS_UNFAIR_LOCK_INIT; }
141  ~SpinLock() { }
142  void lock() { os_unfair_lock_lock(&_spinlock); }
143  bool trylock() { return os_unfair_lock_trylock(&_spinlock); }
144  void unlock() { os_unfair_lock_unlock(&_spinlock); }
145 private:
146  os_unfair_lock _spinlock;
147 };
148 #else
149 class SpinLock {
150 public:
151  SpinLock() { pthread_spin_init(&_spinlock, PTHREAD_PROCESS_PRIVATE); }
152  ~SpinLock() { pthread_spin_destroy(&_spinlock); }
153  void lock() { pthread_spin_lock(&_spinlock); }
154  bool trylock() { return 0 == pthread_spin_trylock(&_spinlock); }
155  void unlock() { pthread_spin_unlock(&_spinlock); }
156 private:
157  pthread_spinlock_t _spinlock;
158 };
159 #endif // __APPLE__
160 #endif
161 
162 /*
163  * Atomics
164  */
165 
166 #ifdef WINDOWS
167  #define ATOMIC_ALIGNED __declspec(align(8))
168  #define ATOMIC_ADD32(x,y) (InterlockedExchangeAdd((volatile long*)(x),(long)(y)) + (y))
169  #define ATOMIC_ADD64(x,y) (InterlockedExchangeAdd64((volatile long long*)(x),(long long)(y)) + (y))
170  #define ATOMIC_SUB32(x,y) (InterlockedExchangeAdd((volatile long*)(x),-((long)(y))) - (y))
171  #define ATOMIC_SUB64(x,y) (InterlockedExchangeAdd64((volatile long long*)(x),-((long long)(y))) - (y))
172  #define MEM_FENCE() MemoryBarrier()
173  #define BOOL_CMPXCH32(x,y,z) (InterlockedCompareExchange((volatile long*)(x),(long)(z),(long)(y)) == (y))
174  #define BOOL_CMPXCH64(x,y,z) (InterlockedCompareExchange64((volatile long long*)(x),(long long)(z),(long long)(y)) == (y))
175  #ifdef NDEBUG
176  #define PTEX_INLINE __forceinline
177  #else
178  #define PTEX_INLINE inline
179  #endif
180 #else
181  #define ATOMIC_ALIGNED __attribute__((aligned(8)))
182  #define ATOMIC_ADD32(x,y) __sync_add_and_fetch(x,y)
183  #define ATOMIC_ADD64(x,y) __sync_add_and_fetch(x,y)
184  #define ATOMIC_SUB32(x,y) __sync_sub_and_fetch(x,y)
185  #define ATOMIC_SUB64(x,y) __sync_sub_and_fetch(x,y)
186  #define MEM_FENCE() __sync_synchronize()
187  #define BOOL_CMPXCH32(x,y,z) __sync_bool_compare_and_swap((x),(y),(z))
188  #define BOOL_CMPXCH64(x,y,z) __sync_bool_compare_and_swap((x),(y),(z))
189 
190  #ifdef NDEBUG
191  #define PTEX_INLINE inline __attribute__((always_inline))
192  #else
193  #define PTEX_INLINE inline
194  #endif
195 #endif
196 
197 template <typename T>
198 PTEX_INLINE T AtomicAdd(volatile T* target, T value)
199 {
200  switch(sizeof(T)){
201  case 4:
202  return (T)ATOMIC_ADD32(target, value);
203  break;
204  case 8:
205  return (T)ATOMIC_ADD64(target, value);
206  break;
207  default:
208  assert(0=="Can only use 32 or 64 bit atomics");
209  return *(T*)NULL;
210  }
211 }
212 
213 template <typename T>
214 PTEX_INLINE T AtomicIncrement(volatile T* target)
215 {
216  return AtomicAdd(target, (T)1);
217 }
218 
219 template <typename T>
220 PTEX_INLINE T AtomicSubtract(volatile T* target, T value)
221 {
222  switch(sizeof(T)){
223  case 4:
224  return (T)ATOMIC_SUB32(target, value);
225  break;
226  case 8:
227  return (T)ATOMIC_SUB64(target, value);
228  break;
229  default:
230  assert(0=="Can only use 32 or 64 bit atomics");
231  return *(T*)NULL;
232  }
233 }
234 
235 template <typename T>
236 PTEX_INLINE T AtomicDecrement(volatile T* target)
237 {
238  return AtomicSubtract(target, (T)1);
239 }
240 
241 // GCC is pretty forgiving, but ICC only allows int, long and long long
242 // so use partial specialization over structs (C(98)) to get certain compilers
243 // to do the specialization to sizeof(T) before doing typechecking and
244 // throwing errors for no good reason.
245 template <typename T, size_t n>
247 
248 template <typename T>
249 struct AtomicCompareAndSwapImpl<T, sizeof(uint32_t)> {
250  PTEX_INLINE bool operator()(T volatile* target, T oldvalue, T newvalue){
251  return BOOL_CMPXCH32((volatile uint32_t*)target,
252  (uint32_t)oldvalue,
253  (uint32_t)newvalue);
254  }
255 };
256 
257 template <typename T>
258 struct AtomicCompareAndSwapImpl<T, sizeof(uint64_t)> {
259  PTEX_INLINE bool operator()(T volatile* target, T oldvalue, T newvalue){
260  return BOOL_CMPXCH64((volatile uint64_t*)target,
261  (uint64_t)oldvalue,
262  (uint64_t)newvalue);
263  }
264 };
265 
266 template <typename T>
267 PTEX_INLINE bool AtomicCompareAndSwap(T volatile* target, T oldvalue, T newvalue)
268 {
269  return AtomicCompareAndSwapImpl<T, sizeof(T)>()(target, oldvalue, newvalue);
270 }
271 
272 template <typename T>
273 PTEX_INLINE void AtomicStore(T volatile* target, T value)
274 {
275  MEM_FENCE();
276  *target = value;
277 }
278 
280 {
281  MEM_FENCE();
282 }
283 
284 
285 #ifndef CACHE_LINE_SIZE
286 #define CACHE_LINE_SIZE 64
287 #endif
288 
289 #define CACHE_LINE_PAD(var,type) char var##_pad[CACHE_LINE_SIZE - sizeof(type)]
290 #define CACHE_LINE_PAD_INIT(var) memset(&var##_pad[0], 0, sizeof(var##_pad))
291 
293 
294 #endif // PtexPlatform_h
ATOMIC_SUB32
#define ATOMIC_SUB32(x, y)
Definition: PtexPlatform.h:184
Mutex::lock
void lock()
Definition: PtexPlatform.h:130
SpinLock::lock
void lock()
Definition: PtexPlatform.h:153
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
PtexMemoryFence
PTEX_INLINE void PtexMemoryFence()
Definition: PtexPlatform.h:279
AtomicCompareAndSwapImpl< T, sizeof(uint64_t)>::operator()
PTEX_INLINE bool operator()(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:259
PTEX_INLINE
#define PTEX_INLINE
Definition: PtexPlatform.h:191
Mutex::~Mutex
~Mutex()
Definition: PtexPlatform.h:129
SpinLock::SpinLock
SpinLock()
Definition: PtexPlatform.h:151
AtomicCompareAndSwap
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:267
AtomicCompareAndSwapImpl
Definition: PtexPlatform.h:246
ATOMIC_ADD64
#define ATOMIC_ADD64(x, y)
Definition: PtexPlatform.h:183
SpinLock::_spinlock
pthread_spinlock_t _spinlock
Definition: PtexPlatform.h:157
AtomicStore
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition: PtexPlatform.h:273
Mutex::trylock
bool trylock()
Definition: PtexPlatform.h:131
BOOL_CMPXCH32
#define BOOL_CMPXCH32(x, y, z)
Definition: PtexPlatform.h:187
PTEX_NAMESPACE_BEGIN
Definition: PtexSeparableKernel.cpp:42
SpinLock::trylock
bool trylock()
Definition: PtexPlatform.h:154
MEM_FENCE
#define MEM_FENCE()
Definition: PtexPlatform.h:186
Mutex
Definition: PtexPlatform.h:126
ATOMIC_ADD32
#define ATOMIC_ADD32(x, y)
Definition: PtexPlatform.h:182
AtomicIncrement
PTEX_INLINE T AtomicIncrement(volatile T *target)
Definition: PtexPlatform.h:214
BOOL_CMPXCH64
#define BOOL_CMPXCH64(x, y, z)
Definition: PtexPlatform.h:188
AtomicCompareAndSwapImpl< T, sizeof(uint32_t)>::operator()
PTEX_INLINE bool operator()(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:250
SpinLock
Definition: PtexPlatform.h:149
AtomicSubtract
PTEX_INLINE T AtomicSubtract(volatile T *target, T value)
Definition: PtexPlatform.h:220
SpinLock::unlock
void unlock()
Definition: PtexPlatform.h:155
Mutex::Mutex
Mutex()
Definition: PtexPlatform.h:128
ATOMIC_SUB64
#define ATOMIC_SUB64(x, y)
Definition: PtexPlatform.h:185
PtexVersion.h
AtomicAdd
PTEX_INLINE T AtomicAdd(volatile T *target, T value)
Definition: PtexPlatform.h:198
SpinLock::~SpinLock
~SpinLock()
Definition: PtexPlatform.h:152
AtomicDecrement
PTEX_INLINE T AtomicDecrement(volatile T *target)
Definition: PtexPlatform.h:236
Mutex::_mutex
pthread_mutex_t _mutex
Definition: PtexPlatform.h:134
PtexInt.h
Portable fixed-width integer types.
Mutex::unlock
void unlock()
Definition: PtexPlatform.h:132
FilePos
off_t FilePos
Definition: PtexPlatform.h:88