From 3103b920b6bc851a8a22735aed4755a9b12caa84 Mon Sep 17 00:00:00 2001 From: Sonicadvance1 Date: Thu, 29 Apr 2010 12:50:12 +0000 Subject: [PATCH] [OSX] Use spinlocks instead of mutexes since mutexes are really semaphores, gives me a decent speed up. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5420 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Common/Src/Thread.cpp | 116 +++++++++++++++++++++++++++--- Source/Core/Common/Src/Thread.h | 15 +++- 2 files changed, 121 insertions(+), 10 deletions(-) diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp index 13ee37cd89..01e6be0c37 100644 --- a/Source/Core/Common/Src/Thread.cpp +++ b/Source/Core/Common/Src/Thread.cpp @@ -17,6 +17,7 @@ #include "Setup.h" #include "Thread.h" +#include "Atomic.h" #include "Common.h" #ifdef USE_BEGINTHREADEX @@ -305,16 +306,22 @@ pthread_key_t threadname_key; CriticalSection::CriticalSection(int spincount_unused) { - pthread_mutex_init(&mutex, NULL); + #ifdef __APPLE__ + lock = OS_SPINLOCK_INIT; + #else + pthread_mutex_init(&mutex, NULL); + #endif } CriticalSection::~CriticalSection() { - pthread_mutex_destroy(&mutex); + #ifndef __APPLE__ + pthread_mutex_destroy(&mutex); + #endif } - +#ifndef __APPLE__ void CriticalSection::Enter() { int ret = pthread_mutex_lock(&mutex); @@ -335,8 +342,26 @@ void CriticalSection::Leave() if (ret) ERROR_LOG(COMMON, "%s: pthread_mutex_unlock(%p) failed: %s\n", __FUNCTION__, &mutex, strerror(ret)); } +#else +void CriticalSection::Enter() +{ + OSSpinLockLock(&lock); +} +bool CriticalSection::TryEnter() +{ + return(!OSSpinLockTry(&lock)); +} + + +void CriticalSection::Leave() +{ + OSSpinLockUnlock(&lock); +} + +#endif + Thread::Thread(ThreadFunc function, void* arg) : thread_id(0) { @@ -440,35 +465,46 @@ void SetCurrentThreadName(const TCHAR* szThreadName) Event::Event() { +#ifdef __APPLE__ + lock = OS_SPINLOCK_INIT; + event_ = 0; +#endif is_set_ = false; } void Event::Init() { +#ifndef __APPLE__ pthread_cond_init(&event_, 0); pthread_mutex_init(&mutex_, 0); +#else + lock = OS_SPINLOCK_INIT; + event_ = 0; +#endif } void Event::Shutdown() { +#ifndef __APPLE__ pthread_mutex_destroy(&mutex_); pthread_cond_destroy(&event_); +#endif } - +#ifdef __APPLE__ void Event::Set() { - pthread_mutex_lock(&mutex_); + OSSpinLockLock(&lock); if (!is_set_) { is_set_ = true; - pthread_cond_signal(&event_); + Common::AtomicStore(event_, 1); } - pthread_mutex_unlock(&mutex_); + OSSpinLockUnlock(&lock); } @@ -476,7 +512,6 @@ bool Event::Wait(const u32 timeout) { bool timedout = false; struct timespec wait; - pthread_mutex_lock(&mutex_); if (timeout != INFINITE) { @@ -491,7 +526,69 @@ bool Event::Wait(const u32 timeout) //wait.tv_nsec = (now.tv_usec + (timeout % 1000) * 1000) * 1000); wait.tv_sec = now.tv_sec + (timeout / 1000); } + + int Slept = 0; + while (!timedout) + { + if (timeout == INFINITE) + { + if(Common::AtomicLoad(event_) == 1) + break; + } + else + { + if(Slept >= wait.tv_sec * 1000000) + timedout = true; + else + if(Common::AtomicLoad(event_) == 1) + break; + } + usleep(250); + Slept += 250; + } + OSSpinLockLock(&lock); + is_set_ = false; + Common::AtomicStore(event_, 0); + OSSpinLockUnlock(&lock); + + return timedout; +} +#else +void Event::Set() +{ + pthread_mutex_lock(&mutex_); + + if (!is_set_) + { + is_set_ = true; + pthread_cond_signal(&event_); + } + + pthread_mutex_unlock(&mutex_); +} + + +bool Event::Wait(const u32 timeout) +{ + bool timedout = false; + struct timespec wait; + pthread_mutex_lock(&mutex_); + + if (timeout != INFINITE) + { + struct timeval now; + gettimeofday(&now, NULL); + + memset(&wait, 0, sizeof(wait)); + //TODO: timespec also has nanoseconds, but do we need them? + //as consequence, waiting is limited to seconds for now. + //the following just looks ridiculous, and probably fails for + //values 429 < ms <= 999 since it overflows the long. + //wait.tv_nsec = (now.tv_usec + (timeout % 1000) * 1000) * 1000); + wait.tv_sec = now.tv_sec + (timeout / 1000); + } + while (!is_set_ && !timedout) { if (timeout == INFINITE) @@ -503,12 +600,13 @@ bool Event::Wait(const u32 timeout) timedout = pthread_cond_timedwait(&event_, &mutex_, &wait) == ETIMEDOUT; } } - + is_set_ = false; pthread_mutex_unlock(&mutex_); return timedout; } +#endif #endif diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index 6905d32eb0..6147ec712b 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -47,6 +47,10 @@ #error unsupported platform (no pthreads?) #endif +#ifdef __APPLE__ +#include +#endif + #endif // Don't include common.h here as it will break LogManager @@ -75,7 +79,11 @@ class CriticalSection CRITICAL_SECTION section; #else #ifdef _POSIX_THREADS - pthread_mutex_t mutex; + #ifdef __APPLE__ + OSSpinLock lock; + #else + pthread_mutex_t mutex; + #endif #endif #endif public: @@ -197,9 +205,14 @@ private: bool is_set_; #ifdef _POSIX_THREADS +#ifdef __APPLE__ + OSSpinLock lock; + u32 event_; +#else pthread_cond_t event_; pthread_mutex_t mutex_; #endif +#endif #endif };