* fix the new extra thread option in the gui dialog
* implement condition variable on linux. Will need some benchmark.


git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5017 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gregory.hainaut 2011-12-26 22:30:59 +00:00
parent 2628d5bb7d
commit 7f3b11c7db
2 changed files with 73 additions and 31 deletions

View File

@ -154,7 +154,7 @@ bool RunLinuxDialog()
#endif #endif
theApp.SetConfig("swthreads", atoi((char*)gtk_entry_get_text(GTK_ENTRY(swthreads_text))) ); theApp.SetConfig("extrathreads", atoi((char*)gtk_entry_get_text(GTK_ENTRY(swthreads_text))) );
theApp.SetConfig("filter", (int)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filter_check))); theApp.SetConfig("filter", (int)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filter_check)));
theApp.SetConfig("logz", (int)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(logz_check))); theApp.SetConfig("logz", (int)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(logz_check)));

View File

@ -184,14 +184,16 @@ protected:
InitializeSRWLockPtr pInitializeSRWLock;; InitializeSRWLockPtr pInitializeSRWLock;;
AcquireSRWLockExclusivePtr pAcquireSRWLockExclusive; AcquireSRWLockExclusivePtr pAcquireSRWLockExclusive;
ReleaseSRWLockExclusivePtr pReleaseSRWLockExclusive; ReleaseSRWLockExclusivePtr pReleaseSRWLockExclusive;
#elif defined(_LINUX)
struct {pthread_mutex_t lock; pthread_cond_t notempty, empty; bool available;} m_cv;
#endif #endif
void ThreadProc() void ThreadProc()
{ {
#ifdef _WINDOWS
if(m_cv.available) if(m_cv.available)
{ {
#ifdef _WINDOWS
pAcquireSRWLockExclusive(&m_cv.lock); pAcquireSRWLockExclusive(&m_cv.lock);
while(true) while(true)
@ -222,12 +224,40 @@ protected:
pWakeConditionVariable(&m_cv.empty); pWakeConditionVariable(&m_cv.empty);
} }
} }
#elif defined(_LINUX)
pthread_mutex_lock(&m_cv.lock);
while(true)
{
while(m_queue.empty())
{
pthread_cond_wait(&m_cv.notempty, &m_cv.lock);
if(m_exit) {pthread_mutex_unlock(&m_cv.lock); return;}
}
{
// NOTE: this is scoped because we must make sure the last item is no longer around when Wait detects an empty queue
T item = m_queue.front();
pthread_mutex_unlock(&m_cv.lock);
Process(item);
pthread_mutex_lock(&m_cv.lock);
m_queue.pop();
}
if(m_queue.empty())
{
pthread_cond_signal(&m_cv.empty);
}
}
#endif
} }
else else
{ {
#endif
m_ev.lock.Lock(); m_ev.lock.Lock();
while(true) while(true)
@ -260,11 +290,7 @@ protected:
_InterlockedDecrement(&m_ev.count); _InterlockedDecrement(&m_ev.count);
} }
#ifdef _WINDOWS
} }
#endif
} }
public: public:
@ -297,6 +323,12 @@ public:
m_cv.available = true; m_cv.available = true;
} }
#elif defined(_LINUX)
m_cv.available = true;
// FIXME attribute
pthread_cond_init(&m_cv.notempty, NULL);
pthread_cond_init(&m_cv.empty, NULL);
pthread_mutex_init(&m_cv.lock, NULL);
#endif #endif
CreateThread(); CreateThread();
@ -306,29 +338,32 @@ public:
{ {
m_exit = true; m_exit = true;
#ifdef _WINDOWS
if(m_cv.available) if(m_cv.available)
{ {
#ifdef _WINDOWS
pWakeConditionVariable(&m_cv.notempty); pWakeConditionVariable(&m_cv.notempty);
#elif defined(_LINUX)
pthread_cond_signal(&m_cv.notempty);
pthread_mutex_destroy(&m_cv.lock);
pthread_cond_destroy(&m_cv.notempty);
pthread_cond_destroy(&m_cv.empty);
#endif
} }
else else
{ {
#endif
m_ev.notempty.Set(); m_ev.notempty.Set();
#ifdef _WINDOWS
} }
#ifdef _WINDOWS
if(m_kernel32 != NULL) if(m_kernel32 != NULL)
{ {
FreeLibrary(m_kernel32); // lol, decrement the refcount anyway FreeLibrary(m_kernel32); // lol, decrement the refcount anyway
} }
#endif #endif
} }
int GetCount() const int GetCount() const
@ -338,10 +373,10 @@ public:
virtual void Push(const T& item) virtual void Push(const T& item)
{ {
#ifdef _WINDOWS
if(m_cv.available) if(m_cv.available)
{ {
#ifdef _WINDOWS
pAcquireSRWLockExclusive(&m_cv.lock); pAcquireSRWLockExclusive(&m_cv.lock);
m_queue.push(item); m_queue.push(item);
@ -349,11 +384,19 @@ public:
pReleaseSRWLockExclusive(&m_cv.lock); pReleaseSRWLockExclusive(&m_cv.lock);
pWakeConditionVariable(&m_cv.notempty); pWakeConditionVariable(&m_cv.notempty);
#elif defined(_LINUX)
pthread_mutex_lock(&m_cv.lock);
m_queue.push(item);
pthread_mutex_unlock(&m_cv.lock);
pthread_cond_signal(&m_cv.notempty);
#endif
} }
else else
{ {
#endif
GSAutoLock l(&m_ev.lock); GSAutoLock l(&m_ev.lock);
@ -362,22 +405,17 @@ public:
_InterlockedIncrement(&m_ev.count); _InterlockedIncrement(&m_ev.count);
m_ev.notempty.Set(); m_ev.notempty.Set();
#ifdef _WINDOWS
} }
#endif
m_count++; m_count++;
} }
virtual void Wait() virtual void Wait()
{ {
#ifdef _WINDOWS
if(m_cv.available) if(m_cv.available)
{ {
#ifdef _WINDOWS
pAcquireSRWLockExclusive(&m_cv.lock); pAcquireSRWLockExclusive(&m_cv.lock);
while(!m_queue.empty()) while(!m_queue.empty())
@ -386,22 +424,26 @@ public:
} }
pReleaseSRWLockExclusive(&m_cv.lock); pReleaseSRWLockExclusive(&m_cv.lock);
#elif defined(_LINUX)
pthread_mutex_lock(&m_cv.lock);
while(!m_queue.empty())
{
pthread_cond_wait(&m_cv.empty, &m_cv.lock);
}
pthread_mutex_unlock(&m_cv.lock);
#endif
} }
else else
{ {
#endif
// NOTE: it is the safest to have our own counter because m_queue.pop() might decrement its own before the last item runs out of its scope and gets destroyed (implementation dependent) // NOTE: it is the safest to have our own counter because m_queue.pop() might decrement its own before the last item runs out of its scope and gets destroyed (implementation dependent)
while(m_ev.count > 0) _mm_pause(); while(m_ev.count > 0) _mm_pause();
#ifdef _WINDOWS
} }
#endif
m_count++; m_count++;
} }