Merge changes from the Witness.
This commit is contained in:
@ -33,9 +33,15 @@ extern "C"
|
||||
#if NV_CC_CLANG && POSH_CPU_STRONGARM
|
||||
// LLVM/Clang do not yet have functioning atomics as of 2.1
|
||||
// #include <atomic>
|
||||
|
||||
#endif
|
||||
|
||||
//ACS: need this if we want to use Apple's atomics.
|
||||
/*
|
||||
#if NV_OS_IOS || NV_OS_DARWIN
|
||||
// for iOS & OSX we use apple's atomics
|
||||
#include "libkern/OSAtomic.h"
|
||||
#endif
|
||||
*/
|
||||
|
||||
namespace nv {
|
||||
|
||||
@ -72,8 +78,9 @@ namespace nv {
|
||||
nvDebugCheck((intptr_t(&value) & 3) == 0);
|
||||
|
||||
#if POSH_CPU_X86 || POSH_CPU_X86_64
|
||||
*ptr = value; // on x86, stores are Release
|
||||
nvCompilerWriteBarrier();
|
||||
*ptr = value; // on x86, stores are Release
|
||||
//nvCompilerWriteBarrier(); // @@ IC: Where does this barrier go? In nvtt it was after, in Witness before. Not sure which one is right.
|
||||
#elif POSH_CPU_STRONGARM
|
||||
// this is the easiest but slowest way to do this
|
||||
nvCompilerReadWriteBarrier();
|
||||
@ -114,17 +121,90 @@ namespace nv {
|
||||
inline uint32 atomicIncrement(uint32 * value)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
|
||||
return (uint32)_InterlockedIncrement((long *)value);
|
||||
}
|
||||
|
||||
inline uint32 atomicDecrement(uint32 * value)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
|
||||
return (uint32)_InterlockedDecrement((long *)value);
|
||||
}
|
||||
|
||||
// Compare '*value' against 'expected', if equal, then stores 'desired' in '*value'.
|
||||
// @@ C++0x style CAS? Unlike the C++0x version, 'expected' is not passed by reference and not mutated.
|
||||
// @@ Is this strong or weak? Does InterlockedCompareExchange have spurious failures?
|
||||
inline bool atomicCompareAndSwap(uint32 * value, uint32 expected, uint32 desired)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
long result = _InterlockedCompareExchange((long *)value, (long)desired, (long)expected);
|
||||
return result == (long)expected;
|
||||
}
|
||||
|
||||
|
||||
inline uint32 atomicSwap(uint32 * value, uint32 desired)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
return (uint32)_InterlockedExchange((long *)value, (long)desired);
|
||||
}
|
||||
|
||||
#elif NV_CC_CLANG && (NV_OS_IOS || NV_OS_DARWIN)
|
||||
NV_COMPILER_CHECK(sizeof(uint32) == sizeof(long));
|
||||
|
||||
//ACS: Use Apple's atomics instead? I don't know if these are better in any way; there are non-barrier versions too. There's no OSAtomicSwap32 tho'
|
||||
/*
|
||||
inline uint32 atomicIncrement(uint32 * value)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
return (uint32)OSAtomicIncrement32Barrier((int32_t *)value);
|
||||
}
|
||||
|
||||
inline uint32 atomicDecrement(uint32 * value)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
return (uint32)OSAtomicDecrement32Barrier((int32_t *)value);
|
||||
}
|
||||
|
||||
// Compare '*value' against 'expected', if equal, then stores 'desired' in '*value'.
|
||||
// @@ C++0x style CAS? Unlike the C++0x version, 'expected' is not passed by reference and not mutated.
|
||||
// @@ Is this strong or weak?
|
||||
inline bool atomicCompareAndSwap(uint32 * value, uint32 expected, uint32 desired)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
return OSAtomicCompareAndSwap32Barrier((int32_t)expected, (int32_t)desired, (int32_t *)value);
|
||||
}
|
||||
*/
|
||||
|
||||
inline uint32 atomicIncrement(uint32 * value)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
|
||||
return __sync_add_and_fetch(value, 1);
|
||||
}
|
||||
|
||||
inline uint32 atomicDecrement(uint32 * value)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
|
||||
return __sync_sub_and_fetch(value, 1);
|
||||
}
|
||||
|
||||
// Compare '*value' against 'expected', if equal, then stores 'desired' in '*value'.
|
||||
// @@ C++0x style CAS? Unlike the C++0x version, 'expected' is not passed by reference and not mutated.
|
||||
// @@ Is this strong or weak?
|
||||
inline bool atomicCompareAndSwap(uint32 * value, uint32 expected, uint32 desired)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
return __sync_bool_compare_and_swap(value, expected, desired);
|
||||
}
|
||||
|
||||
inline uint32 atomicSwap(uint32 * value, uint32 desired)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
// this is confusingly named, it doesn't actually do a test but always sets
|
||||
return __sync_lock_test_and_set(value, desired);
|
||||
}
|
||||
|
||||
|
||||
#elif NV_CC_CLANG && POSH_CPU_STRONGARM
|
||||
NV_COMPILER_CHECK(sizeof(uint32) == sizeof(long));
|
||||
|
||||
@ -183,15 +263,32 @@ namespace nv {
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
|
||||
return __sync_fetch_and_add(value, 1);
|
||||
return __sync_add_and_fetch(value, 1);
|
||||
}
|
||||
|
||||
inline uint32 atomicDecrement(uint32 * value)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
|
||||
return __sync_fetch_and_sub(value, 1);
|
||||
return __sync_sub_and_fetch(value, 1);
|
||||
}
|
||||
|
||||
// Compare '*value' against 'expected', if equal, then stores 'desired' in '*value'.
|
||||
// @@ C++0x style CAS? Unlike the C++0x version, 'expected' is not passed by reference and not mutated.
|
||||
// @@ Is this strong or weak?
|
||||
inline bool atomicCompareAndSwap(uint32 * value, uint32 expected, uint32 desired)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
return __sync_bool_compare_and_swap(value, expected, desired);
|
||||
}
|
||||
|
||||
inline uint32 atomicSwap(uint32 * value, uint32 desired)
|
||||
{
|
||||
nvDebugCheck((intptr_t(value) & 3) == 0);
|
||||
// this is confusingly named, it doesn't actually do a test but always sets
|
||||
return __sync_lock_test_and_set(value, desired);
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Atomics not implemented."
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#if NV_OS_WIN32
|
||||
#include "Win32.h"
|
||||
#elif NV_OS_UNIX
|
||||
#elif NV_OS_USE_PTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
@ -32,19 +32,20 @@ void Event::wait() {
|
||||
WaitForSingleObject(m->handle, INFINITE);
|
||||
}
|
||||
|
||||
#elif NV_OS_UNIX
|
||||
|
||||
#pragma NV_MESSAGE("Implement event using pthreads!")
|
||||
#elif NV_OS_USE_PTHREAD
|
||||
|
||||
struct Event::Private {
|
||||
pthread_cond_t pt_cond;
|
||||
pthread_mutex_t pt_mutex;
|
||||
int count;
|
||||
int wait_count;
|
||||
};
|
||||
|
||||
Event::Event() : m(new Private) {
|
||||
// pthread equivalent of auto-reset event
|
||||
pthread_cond_init(&m->pt_cond, NULL);
|
||||
m->count=0;
|
||||
m->wait_count=0;
|
||||
pthread_mutex_init(&m->pt_mutex, NULL);
|
||||
pthread_cond_init(&m->pt_cond, NULL);
|
||||
}
|
||||
|
||||
Event::~Event() {
|
||||
@ -53,11 +54,29 @@ Event::~Event() {
|
||||
}
|
||||
|
||||
void Event::post() {
|
||||
pthread_mutex_lock(&m->pt_mutex);
|
||||
|
||||
m->count++;
|
||||
|
||||
//ACS: move this after the unlock?
|
||||
if(m->wait_count>0) {
|
||||
pthread_cond_signal(&m->pt_cond);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&m->pt_mutex);
|
||||
}
|
||||
|
||||
void Event::wait() {
|
||||
pthread_mutex_lock(&m->pt_mutex);
|
||||
|
||||
while(m->count==0) {
|
||||
m->wait_count++;
|
||||
pthread_cond_wait(&m->pt_cond, &m->pt_mutex);
|
||||
m->wait_count--;
|
||||
}
|
||||
m->count--;
|
||||
|
||||
pthread_mutex_unlock(&m->pt_mutex);
|
||||
}
|
||||
|
||||
#endif // NV_OS_UNIX
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "Win32.h"
|
||||
|
||||
#elif NV_OS_UNIX
|
||||
#elif NV_OS_USE_PTHREAD
|
||||
|
||||
#include <pthread.h>
|
||||
#include <errno.h> // EBUSY
|
||||
@ -48,7 +48,7 @@ void Mutex::unlock()
|
||||
LeaveCriticalSection(&m->mutex);
|
||||
}
|
||||
|
||||
#elif NV_OS_UNIX
|
||||
#elif NV_OS_USE_PTHREAD
|
||||
|
||||
struct Mutex::Private {
|
||||
pthread_mutex_t mutex;
|
||||
|
@ -9,12 +9,7 @@
|
||||
|
||||
using namespace nv;
|
||||
|
||||
// @@ nvthread is only fully implemented in win32.
|
||||
#if NV_OS_WIN32
|
||||
#define ENABLE_PARALLEL_FOR 1
|
||||
#else
|
||||
#define ENABLE_PARALLEL_FOR 0
|
||||
#endif
|
||||
|
||||
static void worker(void * arg) {
|
||||
ParallelFor * owner = (ParallelFor *)arg;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#if NV_OS_WIN32
|
||||
#include "Win32.h"
|
||||
#elif NV_OS_UNIX
|
||||
#elif NV_OS_USE_PTHREAD
|
||||
#include <pthread.h>
|
||||
#include <unistd.h> // usleep
|
||||
#endif
|
||||
@ -15,7 +15,7 @@ struct Thread::Private
|
||||
{
|
||||
#if NV_OS_WIN32
|
||||
HANDLE thread;
|
||||
#elif NV_OS_UNIX
|
||||
#elif NV_OS_USE_PTHREAD
|
||||
pthread_t thread;
|
||||
#endif
|
||||
|
||||
@ -32,7 +32,7 @@ unsigned long __stdcall threadFunc(void * arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif NV_OS_UNIX
|
||||
#elif NV_OS_USE_PTHREAD
|
||||
|
||||
extern "C" void * threadFunc(void * arg) {
|
||||
Thread::Private * thread = (Thread::Private *)arg;
|
||||
@ -62,7 +62,7 @@ void Thread::start(ThreadFunc * func, void * arg)
|
||||
p->thread = CreateThread(NULL, 0, threadFunc, p.ptr(), 0, NULL);
|
||||
//p->thread = (HANDLE)_beginthreadex (0, 0, threadFunc, p.ptr(), 0, NULL); // @@ So that we can call CRT functions...
|
||||
nvDebugCheck(p->thread != NULL);
|
||||
#elif NV_OS_UNIX
|
||||
#elif NV_OS_USE_PTHREAD
|
||||
int result = pthread_create(&p->thread, NULL, threadFunc, p.ptr());
|
||||
nvDebugCheck(result == 0);
|
||||
#endif
|
||||
@ -76,7 +76,7 @@ void Thread::wait()
|
||||
BOOL ok = CloseHandle (p->thread);
|
||||
p->thread = NULL;
|
||||
nvCheck (ok);
|
||||
#elif NV_OS_UNIX
|
||||
#elif NV_OS_USE_PTHREAD
|
||||
int result = pthread_join(p->thread, NULL);
|
||||
p->thread = 0;
|
||||
nvDebugCheck(result == 0);
|
||||
@ -87,7 +87,7 @@ bool Thread::isRunning () const
|
||||
{
|
||||
#if NV_OS_WIN32
|
||||
return p->thread != NULL;
|
||||
#elif NV_OS_UNIX
|
||||
#elif NV_OS_USE_PTHREAD
|
||||
return p->thread != 0;
|
||||
#endif
|
||||
}
|
||||
@ -101,7 +101,7 @@ bool Thread::isRunning () const
|
||||
{
|
||||
#if NV_OS_WIN32
|
||||
SwitchToThread();
|
||||
#elif NV_OS_UNIX
|
||||
#elif NV_OS_USE_PTHREAD
|
||||
int result = sched_yield();
|
||||
nvDebugCheck(result == 0);
|
||||
#endif
|
||||
@ -111,7 +111,7 @@ bool Thread::isRunning () const
|
||||
{
|
||||
#if NV_OS_WIN32
|
||||
Sleep(ms);
|
||||
#elif NV_OS_UNIX
|
||||
#elif NV_OS_USE_PTHREAD
|
||||
usleep(1000 * ms);
|
||||
#endif
|
||||
}
|
||||
|
@ -5,24 +5,24 @@
|
||||
#include "Thread.h"
|
||||
|
||||
#if NV_OS_WIN32
|
||||
# include "Win32.h"
|
||||
#include "Win32.h"
|
||||
#elif NV_OS_UNIX
|
||||
# include <sys/types.h>
|
||||
# include <sys/sysctl.h>
|
||||
# include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <unistd.h>
|
||||
#elif NV_OS_DARWIN
|
||||
# import <stdio.h>
|
||||
# import <string.h>
|
||||
# import <mach/mach_host.h>
|
||||
# import <sys/sysctl.h>
|
||||
#import <stdio.h>
|
||||
#import <string.h>
|
||||
#import <mach/mach_host.h>
|
||||
#import <sys/sysctl.h>
|
||||
|
||||
# include <CoreFoundation/CoreFoundation.h>
|
||||
//#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
# include <assert.h>
|
||||
# include <errno.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <syslog.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
using namespace nv;
|
||||
|
Reference in New Issue
Block a user