CHECK_EMU_STATUS, autojoin_thread_t

This commit is contained in:
Nekotekina 2015-07-04 02:22:24 +03:00
parent 8f9e1100c8
commit 3064cf8101
28 changed files with 145 additions and 179 deletions

View file

@ -19,10 +19,7 @@ void SSemaphore::wait()
while (true) while (true)
{ {
if (Emu.IsStopped()) CHECK_EMU_STATUS;
{
return;
}
m_cond.wait_for(cv_lock, std::chrono::milliseconds(1)); m_cond.wait_for(cv_lock, std::chrono::milliseconds(1));

View file

@ -1214,14 +1214,7 @@ thread_t::~thread_t() noexcept(false)
{ {
if (m_thread) if (m_thread)
{ {
if (g_tls_this_thread != m_thread.get()) throw EXCEPTION("Neither joined nor detached");
{
m_thread->m_thread.join();
}
else
{
throw EXCEPTION("Deadlock");
}
} }
} }

View file

@ -84,6 +84,28 @@ public:
bool is_current() const; bool is_current() const;
}; };
class autojoin_thread_t final : private thread_t
{
public:
using thread_t::mutex;
using thread_t::cv;
public:
autojoin_thread_t() = delete;
autojoin_thread_t(std::function<std::string()> name, std::function<void()> func)
{
start(std::move(name), std::move(func));
}
virtual ~autojoin_thread_t() override
{
join();
}
using thread_t::is_current;
};
struct waiter_map_t struct waiter_map_t
{ {
static const size_t size = 16; static const size_t size = 16;

View file

@ -609,10 +609,19 @@ u32 SPUThread::get_ch_value(u32 ch)
case SPU_RdEventStat: case SPU_RdEventStat:
{ {
std::unique_lock<std::mutex> lock(mutex, std::defer_lock);
u32 result; u32 result;
while (!(result = ch_event_stat.load() & ch_event_mask) && !Emu.IsStopped())
while ((result = ch_event_stat.load() & ch_event_mask) == 0)
{ {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack CHECK_EMU_STATUS;
if (IsStopped()) throw CPUThreadStop{};
if (!lock) lock.lock();
cv.wait_for(lock, std::chrono::milliseconds(1));
} }
return result; return result;

View file

@ -4,6 +4,7 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/CPU/CPUThread.h" #include "Emu/CPU/CPUThread.h"
#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/ARMv7/ARMv7Thread.h" #include "Emu/ARMv7/ARMv7Thread.h"
#include "Emu/SysCalls/lv2/sys_time.h" #include "Emu/SysCalls/lv2/sys_time.h"
@ -615,9 +616,7 @@ namespace vm
if (context.GPR[1] < context.stack_addr) if (context.GPR[1] < context.stack_addr)
{ {
LOG_ERROR(PPU, "vm::stack_push(0x%x,%d): stack overflow (SP=0x%llx, stack=*0x%x)", size, align_v, context.GPR[1], context.stack_addr); throw EXCEPTION("Stack overflow (size=0x%x, align=0x%x, SP=0x%llx, stack=*0x%x)", size, align_v, old_pos, context.stack_addr);
context.GPR[1] = old_pos;
return 0;
} }
else else
{ {
@ -628,8 +627,20 @@ namespace vm
case CPU_THREAD_SPU: case CPU_THREAD_SPU:
case CPU_THREAD_RAW_SPU: case CPU_THREAD_RAW_SPU:
{ {
assert(!"stack_push(): SPU not supported"); SPUThread& context = static_cast<SPUThread&>(CPU);
return 0;
old_pos = context.GPR[1]._u32[3];
context.GPR[1]._u32[3] -= align(size, 16);
context.GPR[1]._u32[3] &= ~(align_v - 1);
if (context.GPR[1]._u32[3] >= 0x40000) // extremely rough
{
throw EXCEPTION("Stack overflow (size=0x%x, align=0x%x, SP=LS:0x%05x)", size, align_v, old_pos);
}
else
{
return context.GPR[1]._u32[3] + context.offset;
}
} }
case CPU_THREAD_ARMv7: case CPU_THREAD_ARMv7:
@ -642,9 +653,7 @@ namespace vm
if (context.SP < context.stack_addr) if (context.SP < context.stack_addr)
{ {
LOG_ERROR(ARMv7, "vm::stack_push(0x%x,%d): stack overflow (SP=0x%x, stack=*0x%x)", size, align_v, context.SP, context.stack_addr); throw EXCEPTION("Stack overflow (size=0x%x, align=0x%x, SP=0x%x, stack=*0x%x)", size, align_v, context.SP, context.stack_addr);
context.SP = old_pos;
return 0;
} }
else else
{ {
@ -654,8 +663,7 @@ namespace vm
default: default:
{ {
assert(!"stack_push(): invalid thread type"); throw EXCEPTION("Invalid thread type (%d)", CPU.GetId());
return 0;
} }
} }
} }
@ -668,9 +676,9 @@ namespace vm
{ {
PPUThread& context = static_cast<PPUThread&>(CPU); PPUThread& context = static_cast<PPUThread&>(CPU);
if (context.GPR[1] != addr && !Emu.IsStopped()) if (context.GPR[1] != addr)
{ {
LOG_ERROR(PPU, "vm::stack_pop(*0x%x,*0x%x): stack inconsistency (SP=0x%llx)", addr, old_pos, context.GPR[1]); throw EXCEPTION("Stack inconsistency (addr=0x%x, SP=0x%llx, old_pos=0x%x)", addr, context.GPR[1], old_pos);
} }
context.GPR[1] = old_pos; context.GPR[1] = old_pos;
@ -680,7 +688,14 @@ namespace vm
case CPU_THREAD_SPU: case CPU_THREAD_SPU:
case CPU_THREAD_RAW_SPU: case CPU_THREAD_RAW_SPU:
{ {
assert(!"stack_pop(): SPU not supported"); SPUThread& context = static_cast<SPUThread&>(CPU);
if (context.GPR[1]._u32[3] + context.offset != addr)
{
throw EXCEPTION("Stack inconsistency (addr=0x%x, SP=LS:0x%05x, old_pos=LS:0x%05x)", addr, context.GPR[1]._u32[3], old_pos);
}
context.GPR[1]._u32[3] = old_pos;
return; return;
} }
@ -688,9 +703,9 @@ namespace vm
{ {
ARMv7Context& context = static_cast<ARMv7Thread&>(CPU); ARMv7Context& context = static_cast<ARMv7Thread&>(CPU);
if (context.SP != addr && !Emu.IsStopped()) if (context.SP != addr)
{ {
LOG_ERROR(ARMv7, "vm::stack_pop(*0x%x,*0x%x): stack inconsistency (SP=0x%x)", addr, old_pos, context.SP); throw EXCEPTION("Stack inconsistency (addr=0x%x, SP=0x%x, old_pos=0x%x)", addr, context.SP, old_pos);
} }
context.SP = old_pos; context.SP = old_pos;
@ -699,8 +714,7 @@ namespace vm
default: default:
{ {
assert(!"stack_pop(): invalid thread type"); throw EXCEPTION("Invalid thread type (%d)", CPU.GetType());
return;
} }
} }
} }

View file

@ -2456,14 +2456,16 @@ void RSXThread::Task()
m_last_flip_time = get_system_time() - 1000000; m_last_flip_time = get_system_time() - 1000000;
thread_t vblank(WRAP_EXPR("VBlank thread"), [this]() autojoin_thread_t vblank(WRAP_EXPR("VBlank Thread"), [this]()
{ {
const u64 start_time = get_system_time(); const u64 start_time = get_system_time();
m_vblank_count = 0; m_vblank_count = 0;
while (joinable() && !Emu.IsStopped()) while (joinable())
{ {
CHECK_EMU_STATUS;
if (get_system_time() - start_time > m_vblank_count * 1000000 / 60) if (get_system_time() - start_time > m_vblank_count * 1000000 / 60)
{ {
m_vblank_count++; m_vblank_count++;
@ -2567,8 +2569,6 @@ void RSXThread::Task()
}); });
} }
LOG_NOTICE(RSX, "RSX thread ended");
OnExitThread(); OnExitThread();
} }

View file

@ -569,11 +569,8 @@ s32 cellAdecClose(u32 handle)
while (!adec->is_finished) while (!adec->is_finished)
{ {
if (Emu.IsStopped()) CHECK_EMU_STATUS;
{
cellAdec.Warning("cellAdecClose(%d) aborted", handle);
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
} }

View file

@ -81,7 +81,7 @@ s32 cellAudioInit()
squeue_t<float*, BUFFER_NUM - 1> out_queue; squeue_t<float*, BUFFER_NUM - 1> out_queue;
thread_t iat(WRAP_EXPR("Internal Audio Thread"), [&out_queue]() autojoin_thread_t iat(WRAP_EXPR("Internal Audio Thread"), [&out_queue]()
{ {
const bool use_u16 = Ini.AudioConvertToU16.GetValue(); const bool use_u16 = Ini.AudioConvertToU16.GetValue();

View file

@ -121,7 +121,7 @@ struct AudioPortConfig
atomic<level_set_t> level_set; atomic<level_set_t> level_set;
}; };
struct AudioConfig //custom structure struct AudioConfig final // custom structure
{ {
atomic<AudioState> state; atomic<AudioState> state;
thread_t thread; thread_t thread;
@ -135,6 +135,14 @@ struct AudioConfig //custom structure
AudioConfig() = default; AudioConfig() = default;
~AudioConfig()
{
if (thread.joinable())
{
thread.join();
}
}
u32 open_port() u32 open_port()
{ {
for (u32 i = 0; i < AUDIO_PORT_COUNT; i++) for (u32 i = 0; i < AUDIO_PORT_COUNT; i++)

View file

@ -690,15 +690,10 @@ s32 cellFsStReadWait(u32 fd, u64 size)
std::unique_lock<std::mutex> lock(file->mutex); std::unique_lock<std::mutex> lock(file->mutex);
// wait for size availability or stream end
while (file->st_total_read - file->st_copied < size && file->st_total_read < file->st_read_size) while (file->st_total_read - file->st_copied < size && file->st_total_read < file->st_read_size)
{ {
// wait for size availability or stream end CHECK_EMU_STATUS;
if (Emu.IsStopped())
{
cellFs.Warning("cellFsStReadWait(0x%x) aborted", fd);
return CELL_OK;
}
file->cv.wait_for(lock, std::chrono::milliseconds(1)); file->cv.wait_for(lock, std::chrono::milliseconds(1));
} }

View file

@ -105,7 +105,7 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
std::string msg = msgString.get_ptr(); std::string msg = msgString.get_ptr();
thread_t(WRAP_EXPR("MsgDialog Thread"), [type, msg, callback, userData, extParam]() thread_t(WRAP_EXPR("MsgDialog Thread"), [=]()
{ {
switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE) switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE)
{ {
@ -127,11 +127,8 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
while (!m_signal) while (!m_signal)
{ {
if (Emu.IsStopped()) CHECK_EMU_STATUS;
{
cellSysutil.Warning("MsgDialog thread aborted");
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
} }

View file

@ -423,10 +423,7 @@ void spursHandlerWaitReady(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
while (true) while (true)
{ {
if (Emu.IsStopped()) CHECK_EMU_STATUS;
{
sys_ppu_thread_exit(CPU, 0);
}
if (spurs->handlerExiting.load()) if (spurs->handlerExiting.load())
{ {
@ -518,6 +515,8 @@ void spursHandlerEntry(PPUThread& CPU)
while (true) while (true)
{ {
CHECK_EMU_STATUS;
if (spurs->flags1 & SF1_EXIT_IF_NO_WORK) if (spurs->flags1 & SF1_EXIT_IF_NO_WORK)
{ {
spursHandlerWaitReady(CPU, spurs); spursHandlerWaitReady(CPU, spurs);
@ -538,14 +537,13 @@ void spursHandlerEntry(PPUThread& CPU)
throw EXCEPTION("sys_spu_thread_group_join() failed (0x%x)", rc); throw EXCEPTION("sys_spu_thread_group_join() failed (0x%x)", rc);
} }
if (Emu.IsStopped())
{
continue;
}
if ((spurs->flags1 & SF1_EXIT_IF_NO_WORK) == 0) if ((spurs->flags1 & SF1_EXIT_IF_NO_WORK) == 0)
{ {
assert(spurs->handlerExiting.load() == 1 || Emu.IsStopped()); if (spurs->handlerExiting.load() != 1)
{
throw EXCEPTION("Unexpected handlerExiting value (false)");
}
sys_ppu_thread_exit(CPU, 0); sys_ppu_thread_exit(CPU, 0);
} }
} }

View file

@ -530,9 +530,7 @@ bool spursKernelWorkloadExit(SPUThread & spu) {
bool spursKernelEntry(SPUThread & spu) { bool spursKernelEntry(SPUThread & spu) {
while (true) { while (true) {
std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (Emu.IsStopped()) { CHECK_EMU_STATUS;
return false;
}
} }
auto ctxt = vm::get_ptr<SpursKernelContext>(spu.offset + 0x100); auto ctxt = vm::get_ptr<SpursKernelContext>(spu.offset + 0x100);
@ -676,7 +674,7 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) {
// If all SPUs are idling and the exit_if_no_work flag is set then the SPU thread group must exit. Otherwise wait for external events. // If all SPUs are idling and the exit_if_no_work flag is set then the SPU thread group must exit. Otherwise wait for external events.
if (spuIdling && shouldExit == false && foundReadyWorkload == false) { if (spuIdling && shouldExit == false && foundReadyWorkload == false) {
// The system service blocks by making a reservation and waiting on the lock line reservation lost event. // The system service blocks by making a reservation and waiting on the lock line reservation lost event.
if (Emu.IsStopped()) throw SpursModuleExit(); CHECK_EMU_STATUS;
if (!lock) lock.lock(); if (!lock) lock.lock();
spu.cv.wait_for(lock, std::chrono::milliseconds(1)); spu.cv.wait_for(lock, std::chrono::milliseconds(1));
continue; continue;
@ -744,6 +742,7 @@ void spursSysServiceMain(SPUThread & spu, u32 pollStatus) {
cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); cellSpursModulePutTrace(&pkt, ctxt->dmaTagId);
while (true) { while (true) {
CHECK_EMU_STATUS;
// Process requests for the system service // Process requests for the system service
spursSysServiceProcessRequests(spu, ctxt); spursSysServiceProcessRequests(spu, ctxt);
@ -784,7 +783,7 @@ poll:
cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); cellSpursModulePutTrace(&pkt, ctxt->dmaTagId);
spursSysServiceIdleHandler(spu, ctxt); spursSysServiceIdleHandler(spu, ctxt);
if (Emu.IsStopped()) return; CHECK_EMU_STATUS;
goto poll; goto poll;
} }

View file

@ -829,10 +829,7 @@ s32 _cellSyncLFQueueGetPushPointer(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queu
{ {
while (true) while (true)
{ {
if (Emu.IsStopped()) CHECK_EMU_STATUS;
{
return -1;
}
const auto old = queue->push1.load_sync(); const auto old = queue->push1.load_sync();
auto push = old; auto push = old;
@ -1082,6 +1079,8 @@ s32 _cellSyncLFQueuePushBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm:
while (true) while (true)
{ {
CHECK_EMU_STATUS;
s32 res; s32 res;
if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY) if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY)
@ -1101,12 +1100,6 @@ s32 _cellSyncLFQueuePushBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm:
} }
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
if (Emu.IsStopped())
{
cellSync.Warning("_cellSyncLFQueuePushBody(queue=*0x%x) aborted", queue);
return CELL_OK;
}
} }
const s32 depth = queue->m_depth; const s32 depth = queue->m_depth;
@ -1142,10 +1135,7 @@ s32 _cellSyncLFQueueGetPopPointer(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue
{ {
while (true) while (true)
{ {
if (Emu.IsStopped()) CHECK_EMU_STATUS;
{
return -1;
}
const auto old = queue->pop1.load_sync(); const auto old = queue->pop1.load_sync();
auto pop = old; auto pop = old;
@ -1395,6 +1385,8 @@ s32 _cellSyncLFQueuePopBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm::
while (true) while (true)
{ {
CHECK_EMU_STATUS;
s32 res; s32 res;
if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY) if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY)
@ -1414,12 +1406,6 @@ s32 _cellSyncLFQueuePopBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm::
} }
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
if (Emu.IsStopped())
{
cellSync.Warning("_cellSyncLFQueuePopBody(queue=*0x%x) aborted", queue);
return CELL_OK;
}
} }
const s32 depth = queue->m_depth; const s32 depth = queue->m_depth;

View file

@ -330,13 +330,9 @@ s32 cellSysutilCheckCallback(PPUThread& CPU)
while (Emu.GetCallbackManager().Check(CPU, res)) while (Emu.GetCallbackManager().Check(CPU, res))
{ {
count++; CHECK_EMU_STATUS;
if (Emu.IsStopped()) count++;
{
cellSysutil.Warning("cellSysutilCheckCallback() aborted");
return CELL_OK;
}
if (res) if (res)
{ {

View file

@ -594,11 +594,8 @@ s32 cellVdecClose(u32 handle)
while (!vdec->is_finished) while (!vdec->is_finished)
{ {
if (Emu.IsStopped()) CHECK_EMU_STATUS;
{
cellVdec.Warning("cellVdecClose(%d) aborted", handle);
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
} }

View file

@ -186,6 +186,8 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout)
while (!cond->mutex->owner.expired() || !cond->signaled || cond->waiters.count(CPU.GetId())) while (!cond->mutex->owner.expired() || !cond->signaled || cond->waiters.count(CPU.GetId()))
{ {
CHECK_EMU_STATUS;
const bool is_timedout = timeout && get_system_time() - start_time > timeout; const bool is_timedout = timeout && get_system_time() - start_time > timeout;
// check timeout // check timeout
@ -203,12 +205,6 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout)
return CELL_ETIMEDOUT; return CELL_ETIMEDOUT;
} }
if (Emu.IsStopped())
{
sys_cond.Warning("sys_cond_wait(id=0x%x) aborted", cond_id);
return CELL_OK;
}
// wait on appropriate condition variable // wait on appropriate condition variable
(cond->signaled || is_timedout ? cond->mutex->cv : cond->cv).wait_for(lv2_lock, std::chrono::milliseconds(1)); (cond->signaled || is_timedout ? cond->mutex->cv : cond->cv).wait_for(lv2_lock, std::chrono::milliseconds(1));
} }

View file

@ -141,6 +141,8 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr<u64> result, u64 t
break; break;
} }
CHECK_EMU_STATUS;
if (ef->cancelled) if (ef->cancelled)
{ {
if (!--ef->cancelled) if (!--ef->cancelled)
@ -157,12 +159,6 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr<u64> result, u64 t
return CELL_ETIMEDOUT; return CELL_ETIMEDOUT;
} }
if (Emu.IsStopped())
{
sys_event_flag.Warning("sys_event_flag_wait(id=0x%x) aborted", id);
return CELL_OK;
}
ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
} }

View file

@ -103,8 +103,10 @@ s32 sys_interrupt_thread_establish(vm::ptr<u32> ih, u32 intrtag, u32 intrthread,
std::unique_lock<std::mutex> cond_lock(tag.handler_mutex); std::unique_lock<std::mutex> cond_lock(tag.handler_mutex);
while (!Emu.IsStopped()) while (!CPU.IsStopped())
{ {
CHECK_EMU_STATUS;
// call interrupt handler until int status is clear // call interrupt handler until int status is clear
if (tag.stat.load()) if (tag.stat.load())
{ {

View file

@ -180,6 +180,8 @@ s32 _sys_lwcond_queue_wait(PPUThread& CPU, u32 lwcond_id, u32 lwmutex_id, u64 ti
while ((!(cond->signaled1 && mutex->signaled) && !cond->signaled2) || cond->waiters.count(CPU.GetId())) while ((!(cond->signaled1 && mutex->signaled) && !cond->signaled2) || cond->waiters.count(CPU.GetId()))
{ {
CHECK_EMU_STATUS;
const bool is_timedout = timeout && get_system_time() - start_time > timeout; const bool is_timedout = timeout && get_system_time() - start_time > timeout;
// check timeout // check timeout
@ -210,12 +212,6 @@ s32 _sys_lwcond_queue_wait(PPUThread& CPU, u32 lwcond_id, u32 lwmutex_id, u64 ti
} }
} }
if (Emu.IsStopped())
{
sys_lwcond.Warning("_sys_lwcond_queue_wait(lwcond_id=0x%x) aborted", lwcond_id);
return CELL_OK;
}
(cond->signaled1 ? mutex->cv : cond->cv).wait_for(lv2_lock, std::chrono::milliseconds(1)); (cond->signaled1 ? mutex->cv : cond->cv).wait_for(lv2_lock, std::chrono::milliseconds(1));
} }

View file

@ -77,18 +77,14 @@ s32 _sys_lwmutex_lock(u32 lwmutex_id, u64 timeout)
while (!mutex->signaled) while (!mutex->signaled)
{ {
CHECK_EMU_STATUS;
if (timeout && get_system_time() - start_time > timeout) if (timeout && get_system_time() - start_time > timeout)
{ {
mutex->waiters--; mutex->waiters--;
return CELL_ETIMEDOUT; return CELL_ETIMEDOUT;
} }
if (Emu.IsStopped())
{
sys_lwmutex.Warning("_sys_lwmutex_lock(lwmutex_id=0x%x) aborted", lwmutex_id);
return CELL_OK;
}
mutex->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); mutex->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
} }

View file

@ -119,18 +119,14 @@ s32 sys_mutex_lock(PPUThread& CPU, u32 mutex_id, u64 timeout)
while (!mutex->owner.expired()) while (!mutex->owner.expired())
{ {
CHECK_EMU_STATUS;
if (timeout && get_system_time() - start_time > timeout) if (timeout && get_system_time() - start_time > timeout)
{ {
mutex->waiters--; mutex->waiters--;
return CELL_ETIMEDOUT; return CELL_ETIMEDOUT;
} }
if (Emu.IsStopped())
{
sys_mutex.Warning("sys_mutex_lock(mutex_id=0x%x) aborted", mutex_id);
return CELL_OK;
}
mutex->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); mutex->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
} }

View file

@ -36,8 +36,8 @@ s32 sys_process_exit(s32 status)
LV2_LOCK; LV2_LOCK;
if (!Emu.IsStopped()) CHECK_EMU_STATUS;
{
sys_process.Success("Process finished"); sys_process.Success("Process finished");
CallAfter([]() CallAfter([]()
@ -45,11 +45,12 @@ s32 sys_process_exit(s32 status)
Emu.Stop(); Emu.Stop();
}); });
while (!Emu.IsStopped()) while (true)
{ {
CHECK_EMU_STATUS;
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(std::chrono::milliseconds(1));
} }
}
return CELL_OK; return CELL_OK;
} }

View file

@ -84,18 +84,14 @@ s32 sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
while (rwlock->writer || rwlock->wwaiters) while (rwlock->writer || rwlock->wwaiters)
{ {
CHECK_EMU_STATUS;
if (timeout && get_system_time() - start_time > timeout) if (timeout && get_system_time() - start_time > timeout)
{ {
rwlock->rwaiters--; rwlock->rwaiters--;
return CELL_ETIMEDOUT; return CELL_ETIMEDOUT;
} }
if (Emu.IsStopped())
{
sys_rwlock.Warning("sys_rwlock_rlock(rw_lock_id=0x%x) aborted", rw_lock_id);
return CELL_OK;
}
rwlock->rcv.wait_for(lv2_lock, std::chrono::milliseconds(1)); rwlock->rcv.wait_for(lv2_lock, std::chrono::milliseconds(1));
} }
@ -179,18 +175,14 @@ s32 sys_rwlock_wlock(PPUThread& CPU, u32 rw_lock_id, u64 timeout)
while (rwlock->readers || rwlock->writer) while (rwlock->readers || rwlock->writer)
{ {
CHECK_EMU_STATUS;
if (timeout && get_system_time() - start_time > timeout) if (timeout && get_system_time() - start_time > timeout)
{ {
rwlock->wwaiters--; rwlock->wwaiters--;
return CELL_ETIMEDOUT; return CELL_ETIMEDOUT;
} }
if (Emu.IsStopped())
{
sys_rwlock.Warning("sys_rwlock_wlock(rw_lock_id=0x%x) aborted", rw_lock_id);
return CELL_OK;
}
rwlock->wcv.wait_for(lv2_lock, std::chrono::milliseconds(1)); rwlock->wcv.wait_for(lv2_lock, std::chrono::milliseconds(1));
} }

View file

@ -91,18 +91,14 @@ s32 sys_semaphore_wait(u32 sem, u64 timeout)
while (semaphore->value <= 0) while (semaphore->value <= 0)
{ {
CHECK_EMU_STATUS;
if (timeout && get_system_time() - start_time > timeout) if (timeout && get_system_time() - start_time > timeout)
{ {
semaphore->waiters--; semaphore->waiters--;
return CELL_ETIMEDOUT; return CELL_ETIMEDOUT;
} }
if (Emu.IsStopped())
{
sys_semaphore.Warning("sys_semaphore_wait(%d) aborted", sem);
return CELL_OK;
}
semaphore->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); semaphore->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
} }

View file

@ -546,11 +546,7 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr<u32> cause, vm::ptr<u32> status)
break; break;
} }
if (Emu.IsStopped()) CHECK_EMU_STATUS;
{
sys_spu.Warning("sys_spu_thread_group_join(id=0x%x) aborted", id);
return CELL_OK;
}
group->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); group->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
} }

View file

@ -60,7 +60,6 @@ lv2_timer_t::lv2_timer_t()
lv2_timer_t::~lv2_timer_t() lv2_timer_t::~lv2_timer_t()
{ {
thread.cv.notify_one();
thread.join(); thread.join();
} }
@ -253,13 +252,9 @@ s32 sys_timer_sleep(u32 sleep_time)
while (useconds > (passed = get_system_time() - start_time) + 1000) while (useconds > (passed = get_system_time() - start_time) + 1000)
{ {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); CHECK_EMU_STATUS;
if (Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
{
sys_timer.Warning("sys_timer_sleep(sleep_time=%d) aborted", sleep_time);
return CELL_OK;
}
} }
if (useconds > passed) if (useconds > passed)
@ -280,13 +275,9 @@ s32 sys_timer_usleep(u64 sleep_time)
while (sleep_time > (passed = get_system_time() - start_time) + 1000) while (sleep_time > (passed = get_system_time() - start_time) + 1000)
{ {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); CHECK_EMU_STATUS;
if (Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
{
sys_timer.Warning("sys_timer_usleep(sleep_time=0x%llx) aborted", sleep_time);
return CELL_OK;
}
} }
if (sleep_time > passed) if (sleep_time > passed)

View file

@ -19,7 +19,7 @@ struct sys_timer_information_t
be_t<u32> pad; be_t<u32> pad;
}; };
struct lv2_timer_t struct lv2_timer_t final
{ {
std::weak_ptr<lv2_event_queue_t> port; // event queue std::weak_ptr<lv2_event_queue_t> port; // event queue
u64 source; // event source u64 source; // event source