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 #endif
73 #endif
74
75 // general includes
76 #include <stdio.h>
77 #include <math.h>
78 #include <assert.h>
79
80 // missing functions on Windows
81 #ifdef WINDOWS
82 typedef __int64 FilePos;
83 #define fseeko _fseeki64
84 #define ftello _ftelli64
85
86 #else
87 typedef off_t FilePos;
88 #endif
89
90 #include "PtexVersion.h"
91
92 PTEX_NAMESPACE_BEGIN
93
94 /*
95 * Mutex
96 */
97
98 #ifdef WINDOWS
99
100 class Mutex {
101 public:
102 Mutex() { _mutex = CreateMutex(NULL, FALSE, NULL); }
103 ~Mutex() { CloseHandle(_mutex); }
104 void lock() { WaitForSingleObject(_mutex, INFINITE); }
105 bool trylock() { return WAIT_TIMEOUT != WaitForSingleObject(_mutex,0);}
106 void unlock() { ReleaseMutex(_mutex); }
107 private:
108 HANDLE _mutex;
109 };
110
111 class SpinLock {
112 public:
113 SpinLock() { InitializeCriticalSection(&_spinlock); }
114 ~SpinLock() { DeleteCriticalSection(&_spinlock); }
115 void lock() { EnterCriticalSection(&_spinlock); }
116 bool trylock() { return TryEnterCriticalSection(&_spinlock); }
117 void unlock() { LeaveCriticalSection(&_spinlock); }
118 private:
119 CRITICAL_SECTION _spinlock;
120 };
121
122 #else
123 // assume linux/unix/posix
124
125 class Mutex {
126 public:
127 Mutex() { pthread_mutex_init(&_mutex, 0); }
128 ~Mutex() { pthread_mutex_destroy(&_mutex); }
129 void lock() { pthread_mutex_lock(&_mutex); }
130 bool trylock() { return 0 == pthread_mutex_trylock(&_mutex); }
131 void unlock() { pthread_mutex_unlock(&_mutex); }
132 private:
133 pthread_mutex_t _mutex;
134 };
135
136 #ifdef __APPLE__
137 class SpinLock {
138 public:
139 SpinLock() { _spinlock = OS_UNFAIR_LOCK_INIT; }
140 ~SpinLock() { }
141 void lock() { os_unfair_lock_lock(&_spinlock); }
142 bool trylock() { return os_unfair_lock_trylock(&_spinlock); }
143 void unlock() { os_unfair_lock_unlock(&_spinlock); }
144 private:
145 os_unfair_lock _spinlock;
146 };
147 #else
148 class SpinLock {
149 public:
150 SpinLock() { pthread_spin_init(&_spinlock, PTHREAD_PROCESS_PRIVATE); }
151 ~SpinLock() { pthread_spin_destroy(&_spinlock); }
152 void lock() { pthread_spin_lock(&_spinlock); }
153 bool trylock() { return 0 == pthread_spin_trylock(&_spinlock); }
154 void unlock() { pthread_spin_unlock(&_spinlock); }
155 private:
156 pthread_spinlock_t _spinlock;
157 };
158 #endif // __APPLE__
159 #endif
160
161 /*
162 * Atomics
163 */
164
165 #ifdef WINDOWS
166 #define ATOMIC_ALIGNED __declspec(align(8))
167 #define ATOMIC_ADD32(x,y) InterlockedExchangeAdd((volatile long*)(x),(long)(y))
168 #define ATOMIC_ADD64(x,y) InterlockedExchangeAdd64((volatile long long*)(x),(long long)(y))
169 #define ATOMIC_SUB32(x,y) InterlockedExchangeAdd((volatile long*)(x),-((long)(y)))
170 #define ATOMIC_SUB64(x,y) InterlockedExchangeAdd64((volatile long long*)(x),-((long long)(y)))
171 #define MEM_FENCE() MemoryBarrier()
172 #define BOOL_CMPXCH32(x,y,z) (InterlockedCompareExchange((volatile long*)(x),(long)(z),(long)(y)) == (y))
173 #define BOOL_CMPXCH64(x,y,z) (InterlockedCompareExchange64((volatile long long*)(x),(long long)(z),(long long)(y)) == (y))
174 #ifdef NDEBUG
175 #define PTEX_INLINE __forceinline
176 #else
177 #define PTEX_INLINE inline
178 #endif
179 #else
180 #define ATOMIC_ALIGNED __attribute__((aligned(8)))
181 #define ATOMIC_ADD32(x,y) __sync_add_and_fetch(x,y)
182 #define ATOMIC_ADD64(x,y) __sync_add_and_fetch(x,y)
183 #define ATOMIC_SUB32(x,y) __sync_sub_and_fetch(x,y)
184 #define ATOMIC_SUB64(x,y) __sync_sub_and_fetch(x,y)
185 #define MEM_FENCE() __sync_synchronize()
186 #define BOOL_CMPXCH32(x,y,z) __sync_bool_compare_and_swap((x),(y),(z))
187 #define BOOL_CMPXCH64(x,y,z) __sync_bool_compare_and_swap((x),(y),(z))
188
189 #ifdef NDEBUG
190 #define PTEX_INLINE inline __attribute__((always_inline))
191 #else
192 #define PTEX_INLINE inline
193 #endif
194 #endif
195
196 template <typename T>
197 PTEX_INLINE T AtomicAdd(volatile T* target, T value)
198 {
199 switch(sizeof(T)){
200 case 4:
201 return (T)ATOMIC_ADD32(target, value);
202 break;
203 case 8:
204 return (T)ATOMIC_ADD64(target, value);
205 break;
206 default:
207 assert(0=="Can only use 32 or 64 bit atomics");
208 return *(T*)NULL;
209 }
210 }
211
212 template <typename T>
213 PTEX_INLINE T AtomicIncrement(volatile T* target)
214 {
215 return AtomicAdd(target, (T)1);
216 }
217
218 template <typename T>
219 PTEX_INLINE T AtomicSubtract(volatile T* target, T value)
220 {
221 switch(sizeof(T)){
222 case 4:
223 return (T)ATOMIC_SUB32(target, value);
224 break;
225 case 8:
226 return (T)ATOMIC_SUB64(target, value);
227 break;
228 default:
229 assert(0=="Can only use 32 or 64 bit atomics");
230 return *(T*)NULL;
231 }
232 }
233
234 template <typename T>
235 PTEX_INLINE T AtomicDecrement(volatile T* target)
236 {
237 return AtomicSubtract(target, (T)1);
238 }
239
240 // GCC is pretty forgiving, but ICC only allows int, long and long long
241 // so use partial specialization over structs (C(98)) to get certain compilers
242 // to do the specialization to sizeof(T) before doing typechecking and
243 // throwing errors for no good reason.
244 template <typename T, size_t n>
245 struct AtomicCompareAndSwapImpl;
246
247 template <typename T>
248 struct AtomicCompareAndSwapImpl<T, sizeof(uint32_t)> {
249 PTEX_INLINE bool operator()(T volatile* target, T oldvalue, T newvalue){
250 return BOOL_CMPXCH32((volatile uint32_t*)target,
251 (uint32_t)oldvalue,
252 (uint32_t)newvalue);
253 }
254 };
255
256 template <typename T>
257 struct AtomicCompareAndSwapImpl<T, sizeof(uint64_t)> {
258 PTEX_INLINE bool operator()(T volatile* target, T oldvalue, T newvalue){
259 return BOOL_CMPXCH64((volatile uint64_t*)target,
260 (uint64_t)oldvalue,
261 (uint64_t)newvalue);
262 }
263 };
264
265 template <typename T>
266 PTEX_INLINE bool AtomicCompareAndSwap(T volatile* target, T oldvalue, T newvalue)
267 {
268 return AtomicCompareAndSwapImpl<T, sizeof(T)>()(target, oldvalue, newvalue);
269 }
270
271 template <typename T>
272 PTEX_INLINE void AtomicStore(T volatile* target, T value)
273 {
274 MEM_FENCE();
275 *target = value;
276 }
277
278 PTEX_INLINE void PtexMemoryFence()
279 {
280 MEM_FENCE();
281 }
282
283
284 #ifndef CACHE_LINE_SIZE
285 #define CACHE_LINE_SIZE 64
286 #endif
287
288 #define CACHE_LINE_PAD(var,type) char var##_pad[CACHE_LINE_SIZE - sizeof(type)]
289 #define CACHE_LINE_PAD_INIT(var) memset(&var##_pad[0], 0, sizeof(var##_pad))
290
291 PTEX_NAMESPACE_END
292
293 #endif // PtexPlatform_h
BOOL_CMPXCH32
#define BOOL_CMPXCH32(x, y, z)
Definition: PtexPlatform.h:186
BOOL_CMPXCH64
#define BOOL_CMPXCH64(x, y, z)
Definition: PtexPlatform.h:187
Mutex::Mutex
Mutex()
Definition: PtexPlatform.h:127
AtomicCompareAndSwapImpl
Definition: PtexPlatform.h:245
AtomicSubtract
PTEX_INLINE T AtomicSubtract(volatile T *target, T value)
Definition: PtexPlatform.h:219
SpinLock::SpinLock
SpinLock()
Definition: PtexPlatform.h:150
SpinLock::unlock
void unlock()
Definition: PtexPlatform.h:154
SpinLock::trylock
bool trylock()
Definition: PtexPlatform.h:153
AtomicIncrement
PTEX_INLINE T AtomicIncrement(volatile T *target)
Definition: PtexPlatform.h:213
SpinLock::~SpinLock
~SpinLock()
Definition: PtexPlatform.h:151
Mutex::trylock
bool trylock()
Definition: PtexPlatform.h:130
ATOMIC_SUB64
#define ATOMIC_SUB64(x, y)
Definition: PtexPlatform.h:184
Mutex
Definition: PtexPlatform.h:125
SpinLock
Definition: PtexPlatform.h:148
AtomicDecrement
PTEX_INLINE T AtomicDecrement(volatile T *target)
Definition: PtexPlatform.h:235
AtomicCompareAndSwapImpl< T, sizeof(uint64_t)>::operator()
PTEX_INLINE bool operator()(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:258
AtomicAdd
PTEX_INLINE T AtomicAdd(volatile T *target, T value)
Definition: PtexPlatform.h:197
ATOMIC_SUB32
#define ATOMIC_SUB32(x, y)
Definition: PtexPlatform.h:183
FilePos
off_t FilePos
Definition: PtexPlatform.h:87
Mutex::~Mutex
~Mutex()
Definition: PtexPlatform.h:128
AtomicCompareAndSwap
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:266
PtexVersion.h
PTEX_INLINE
#define PTEX_INLINE
Definition: PtexPlatform.h:190
PtexMemoryFence
PTEX_INLINE void PtexMemoryFence()
Definition: PtexPlatform.h:278
SpinLock::_spinlock
pthread_spinlock_t _spinlock
Definition: PtexPlatform.h:156
MEM_FENCE
#define MEM_FENCE()
Definition: PtexPlatform.h:185
Mutex::_mutex
pthread_mutex_t _mutex
Definition: PtexPlatform.h:133
SpinLock::lock
void lock()
Definition: PtexPlatform.h:152
Mutex::unlock
void unlock()
Definition: PtexPlatform.h:131
ATOMIC_ADD64
#define ATOMIC_ADD64(x, y)
Definition: PtexPlatform.h:182
PTEX_NAMESPACE_BEGIN
Definition: PtexSeparableKernel.cpp:42
AtomicStore
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition: PtexPlatform.h:272
PtexInt.h
Portable fixed-width integer types.
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
Mutex::lock
void lock()
Definition: PtexPlatform.h:129
ATOMIC_ADD32
#define ATOMIC_ADD32(x, y)
Definition: PtexPlatform.h:181
AtomicCompareAndSwapImpl< T, sizeof(uint32_t)>::operator()
PTEX_INLINE bool operator()(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:249