Ptex: PtexPlatform.h Source File

Ptex

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