Merge pull request #5987 from unknownbrackets/multithread

Fix another race in multithread, and ge sync
This commit is contained in:
Henrik Rydgård 2014-04-29 09:23:35 +02:00
commit 9164e70ae6
4 changed files with 31 additions and 11 deletions

View file

@ -71,7 +71,7 @@ Event *eventPool = 0;
Event *eventTsPool = 0;
int allocatedTsEvents = 0;
// Optimization to skip MoveEvents when possible.
volatile u32 hasTsEvents = false;
volatile u32 hasTsEvents = 0;
// Downcount has been moved to currentMIPS, to save a couple of clocks in every ARM JIT block
// as we can already reach that structure through a register.

View file

@ -32,9 +32,11 @@ bool AsyncIOManager::HasOperation(u32 handle) {
}
void AsyncIOManager::ScheduleOperation(AsyncIOEvent ev) {
lock_guard guard(resultsLock_);
if (!resultsPending_.insert(ev.handle).second) {
ERROR_LOG_REPORT(SCEIO, "Scheduling operation for file %d while one is pending (type %d)", ev.handle, ev.type);
{
lock_guard guard(resultsLock_);
if (!resultsPending_.insert(ev.handle).second) {
ERROR_LOG_REPORT(SCEIO, "Scheduling operation for file %d while one is pending (type %d)", ev.handle, ev.type);
}
}
ScheduleEvent(ev);
}

View file

@ -76,6 +76,7 @@ GlobalUIState globalUIState;
static CoreParameter coreParameter;
static PSPMixer *mixer;
static std::thread *cpuThread = NULL;
static std::thread::id cpuThreadID;
static recursive_mutex cpuThreadLock;
static condition_variable cpuThreadCond;
static condition_variable cpuThreadReplyCond;
@ -108,7 +109,7 @@ void Audio_Init() {
bool IsOnSeparateCPUThread() {
if (cpuThread != NULL) {
return cpuThread->get_id() == std::this_thread::get_id();
return cpuThreadID == std::this_thread::get_id();
} else {
return false;
}
@ -336,6 +337,7 @@ bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) {
XSetThreadProcessor(cpuThread->native_handle(), 2);
ResumeThread(cpuThread->native_handle());
#endif
cpuThreadID = cpuThread->get_id();
cpuThread->detach();
} else {
CPU_Init();
@ -411,6 +413,7 @@ void PSP_Shutdown() {
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsShutdown);
delete cpuThread;
cpuThread = 0;
cpuThreadID = std::thread::id();
} else {
CPU_Shutdown();
}

View file

@ -75,6 +75,10 @@ struct ThreadEventQueue : public B {
eventsHaveRun_ = true;
do {
if (!HasEvents()) {
eventsWait_.wait(eventsLock_);
}
for (Event ev = GetNextEvent(); EventType(ev) != EVENT_INVALID; ev = GetNextEvent()) {
eventsLock_.unlock();
switch (EventType(ev)) {
@ -96,11 +100,6 @@ struct ThreadEventQueue : public B {
if (ShouldExitEventLoop() || !threadEnabled_) {
break;
}
// coreState changes won't wake us, so recheck periodically.
if (!HasEvents()) {
eventsWait_.wait(eventsLock_);
}
} while (CoreTiming::GetTicks() < globalticks);
// This will force the waiter to check coreState, even if we didn't actually drain.
@ -113,6 +112,22 @@ struct ThreadEventQueue : public B {
eventsHaveRun_ = false;
}
inline bool ShouldSyncThread(bool force) {
if (!HasEvents())
return false;
if (coreState != CORE_RUNNING && !force)
return false;
// Don't run if it's not running, but wait for startup.
if (!eventsRunning_) {
if (eventsHaveRun_ || coreState == CORE_ERROR || coreState == CORE_POWERDOWN) {
return false;
}
}
return true;
}
// Force ignores coreState.
void SyncThread(bool force = false) {
if (!threadEnabled_) {
@ -123,7 +138,7 @@ struct ThreadEventQueue : public B {
// While processing the last event, HasEvents() will be false even while not done.
// So we schedule a nothing event and wait for that to finish.
ScheduleEvent(EVENT_SYNC);
while (HasEvents() && (eventsRunning_ || !eventsHaveRun_) && (force || coreState == CORE_RUNNING)) {
while (ShouldSyncThread(force)) {
eventsDrain_.wait(eventsLock_);
}
}