Massive Poo storm, had to take shelter. Hacks, fixes, etc etc

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5421 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Sonicadvance1 2010-04-29 13:46:20 +00:00
parent 3103b920b6
commit 81f06220ce
2 changed files with 567 additions and 679 deletions

File diff suppressed because it is too large Load Diff

View File

@ -47,10 +47,6 @@
#error unsupported platform (no pthreads?) #error unsupported platform (no pthreads?)
#endif #endif
#ifdef __APPLE__
#include <libkern/OSAtomic.h>
#endif
#endif #endif
// Don't include common.h here as it will break LogManager // Don't include common.h here as it will break LogManager
@ -60,9 +56,9 @@
// This may not be defined outside _WIN32 // This may not be defined outside _WIN32
#ifndef _WIN32 #ifndef _WIN32
#ifndef INFINITE #ifndef INFINITE
#define INFINITE 0xffffffff #define INFINITE 0xffffffff
#endif #endif
//for gettimeofday and struct time(val|spec) //for gettimeofday and struct time(val|spec)
#include <sys/time.h> #include <sys/time.h>
@ -72,169 +68,159 @@
namespace Common namespace Common
{ {
class CriticalSection class CriticalSection
{ {
#ifdef _WIN32 #ifdef _WIN32
CRITICAL_SECTION section; CRITICAL_SECTION section;
#else #else
#ifdef _POSIX_THREADS #ifdef _POSIX_THREADS
#ifdef __APPLE__
OSSpinLock lock;
#else
pthread_mutex_t mutex; pthread_mutex_t mutex;
#endif
#endif #endif
#endif #endif
public: public:
CriticalSection(int spincount = 1000); CriticalSection(int spincount = 1000);
~CriticalSection(); ~CriticalSection();
void Enter(); void Enter();
bool TryEnter(); bool TryEnter();
void Leave(); void Leave();
}; };
#ifdef _WIN32 #ifdef _WIN32
#ifdef USE_BEGINTHREADEX #ifdef USE_BEGINTHREADEX
typedef unsigned (__stdcall *ThreadFunc)(void* arg); typedef unsigned (__stdcall *ThreadFunc)(void* arg);
#else #else
typedef DWORD (WINAPI *ThreadFunc)(void* arg); typedef DWORD (WINAPI *ThreadFunc)(void* arg);
#endif #endif
#else #else
typedef void* (*ThreadFunc)(void* arg); typedef void* (*ThreadFunc)(void* arg);
#endif #endif
class Thread class Thread
{ {
public: public:
Thread(ThreadFunc entry, void* arg); Thread(ThreadFunc entry, void* arg);
~Thread(); ~Thread();
void SetAffinity(int mask); void SetAffinity(int mask);
static void SetCurrentThreadAffinity(int mask); static void SetCurrentThreadAffinity(int mask);
static int CurrentId(); static int CurrentId();
bool IsCurrentThread(); bool IsCurrentThread();
#ifdef _WIN32 #ifdef _WIN32
void SetPriority(int priority); void SetPriority(int priority);
DWORD WaitForDeath(const int iWait = INFINITE); DWORD WaitForDeath(const int iWait = INFINITE);
#else #else
void WaitForDeath(); void WaitForDeath();
#endif #endif
private: private:
#ifdef _WIN32 #ifdef _WIN32
HANDLE m_hThread; HANDLE m_hThread;
#ifdef USE_BEGINTHREADEX #ifdef USE_BEGINTHREADEX
unsigned m_threadId; unsigned m_threadId;
#else #else
DWORD m_threadId; DWORD m_threadId;
#endif #endif
#else #else
#ifdef _POSIX_THREADS #ifdef _POSIX_THREADS
pthread_t thread_id; pthread_t thread_id;
#endif #endif
#endif #endif
}; };
#ifdef _WIN32 #ifdef _WIN32
// Event(WaitForSingleObject) is too expensive // Event(WaitForSingleObject) is too expensive
// as it always enters Ring0 regardless of the state of lock // as it always enters Ring0 regardless of the state of lock
// This EventEx will try to stay in Ring3 as much as possible // This EventEx will try to stay in Ring3 as much as possible
// If the lock can be obtained in the first time, Ring0 won't be entered at all // If the lock can be obtained in the first time, Ring0 won't be entered at all
class EventEx class EventEx
{ {
public: public:
EventEx(); EventEx();
void Init(); void Init();
void Shutdown(); void Shutdown();
void Set(); void Set();
// Infinite wait // Infinite wait
void Spin(); void Spin();
// Infinite wait with sleep // Infinite wait with sleep
void Wait(); void Wait();
// Wait with message processing and sleep // Wait with message processing and sleep
bool MsgWait(); bool MsgWait();
private: private:
volatile long m_Lock; volatile long m_Lock;
}; };
#else #else
// TODO: implement for Linux // TODO: implement for Linux
#define EventEx Event #define EventEx Event
#endif #endif
class Event class Event
{ {
public: public:
Event(); Event();
void Init();
void Init(); void Shutdown();
void Shutdown();
void Set();
void Set(); //returns whether the wait timed out
//returns whether the wait timed out bool Wait(const u32 timeout = INFINITE);
bool Wait(const u32 timeout = INFINITE);
#ifdef _WIN32 #ifdef _WIN32
void MsgWait(); void MsgWait();
#else #else
void MsgWait() {Wait();} void MsgWait() {Wait();}
#endif #endif
private: private:
#ifdef _WIN32 #ifdef _WIN32
HANDLE m_hEvent; HANDLE m_hEvent;
/* If we have waited more than five seconds we can be pretty sure that the thread is deadlocked. /* If we have waited more than five seconds we can be pretty sure that the thread is deadlocked.
So then we can just as well continue and hope for the best. I could try several times that So then we can just as well continue and hope for the best. I could try several times that
this works after a five second timeout (with works meaning that the game stopped and I could this works after a five second timeout (with works meaning that the game stopped and I could
start another game without any noticable problems). But several times it failed to, and ended start another game without any noticable problems). But several times it failed to, and ended
with a crash. But it's better than an infinite deadlock. */ with a crash. But it's better than an infinite deadlock. */
static const int THREAD_WAIT_TIMEOUT = 5000; // INFINITE or 5000 for example static const int THREAD_WAIT_TIMEOUT = 5000; // INFINITE or 5000 for example
#else #else
bool is_set_; bool is_set_;
#ifdef _POSIX_THREADS #ifdef _POSIX_THREADS
#ifdef __APPLE__ pthread_cond_t event_;
OSSpinLock lock; pthread_mutex_t mutex_;
u32 event_;
#else
pthread_cond_t event_;
pthread_mutex_t mutex_;
#endif #endif
#endif #endif
};
#endif
}; void InitThreading();
void SleepCurrentThread(int ms);
void InitThreading();
void SleepCurrentThread(int ms); // YieldCPU: This function is only effective on HyperThreading CPU
// Use this function during a spin-wait to make the current thread
// YieldCPU: This function is only effective on HyperThreading CPU // relax while another thread is working. This may be more efficient
// Use this function during a spin-wait to make the current thread // than using events because event functions use kernel calls.
// relax while another thread is working. This may be more efficient inline void YieldCPU()
// than using events because event functions use kernel calls. {
inline void YieldCPU()
{
#ifdef _WIN32 #ifdef _WIN32
YieldProcessor(); YieldProcessor();
#elif defined(_M_IX86) || defined(_M_X64) #elif defined(_M_IX86) || defined(_M_X64)
_mm_pause(); _mm_pause();
#endif #endif
} }
void SetCurrentThreadName(const char *name); void SetCurrentThreadName(const char *name);
} // namespace Common } // namespace Common
#endif // _THREAD_H_ #endif // _THREAD_H_