Merge changes from the Witness.

This commit is contained in:
castano@gmail.com
2013-06-07 17:53:55 +00:00
parent 634229a842
commit 94d0635285
49 changed files with 1974 additions and 625 deletions

View File

@ -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."

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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
}

View File

@ -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;