mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-01 16:13:23 +00:00
Minor cleanup
This commit is contained in:
parent
db7bde0a6f
commit
a3d400b5cc
@ -1,6 +1,14 @@
|
||||
#pragma once
|
||||
#include "SPUThread.h"
|
||||
|
||||
enum : u32
|
||||
{
|
||||
RAW_SPU_OFFSET = 0x00100000,
|
||||
RAW_SPU_BASE_ADDR = 0xE0000000,
|
||||
RAW_SPU_LS_OFFSET = 0x00000000,
|
||||
RAW_SPU_PROB_OFFSET = 0x00040000,
|
||||
};
|
||||
|
||||
__forceinline static u32 GetRawSPURegAddrByNum(int num, int offset)
|
||||
{
|
||||
return RAW_SPU_OFFSET * num + RAW_SPU_BASE_ADDR + RAW_SPU_PROB_OFFSET + offset;
|
||||
|
@ -604,19 +604,17 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
|
||||
if (!queue)
|
||||
{
|
||||
LOG_WARNING(SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (value & 0x00ffffff), data);
|
||||
ch_in_mbox.push_uncond(CELL_ENOTCONN); // TODO: check error passing
|
||||
return;
|
||||
return ch_in_mbox.push_uncond(CELL_ENOTCONN); // TODO: check error passing
|
||||
}
|
||||
|
||||
if (queue->events.size() >= queue->size)
|
||||
{
|
||||
ch_in_mbox.push_uncond(CELL_EBUSY);
|
||||
return;
|
||||
return ch_in_mbox.push_uncond(CELL_EBUSY);
|
||||
}
|
||||
|
||||
queue->push(SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (value & 0x00ffffff), data);
|
||||
ch_in_mbox.push_uncond(CELL_OK);
|
||||
return;
|
||||
|
||||
return ch_in_mbox.push_uncond(CELL_OK);
|
||||
}
|
||||
else if (code < 128)
|
||||
{
|
||||
@ -685,20 +683,22 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(data, ef))
|
||||
{
|
||||
ch_in_mbox.push_uncond(CELL_ESRCH);
|
||||
return;
|
||||
return ch_in_mbox.push_uncond(CELL_ESRCH);
|
||||
}
|
||||
|
||||
while (ef->waiters < 0)
|
||||
while (ef->cancelled)
|
||||
{
|
||||
ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
ef->flags |= 1ull << flag;
|
||||
ef->cv.notify_all();
|
||||
|
||||
ch_in_mbox.push_uncond(CELL_OK);
|
||||
return;
|
||||
if (ef->waiters)
|
||||
{
|
||||
ef->cv.notify_all();
|
||||
}
|
||||
|
||||
return ch_in_mbox.push_uncond(CELL_OK);
|
||||
}
|
||||
else if (code == 192)
|
||||
{
|
||||
@ -732,13 +732,18 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
|
||||
return;
|
||||
}
|
||||
|
||||
while (ef->waiters < 0)
|
||||
while (ef->cancelled)
|
||||
{
|
||||
ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
ef->flags |= 1ull << flag;
|
||||
ef->cv.notify_all();
|
||||
|
||||
if (ef->waiters)
|
||||
{
|
||||
ef->cv.notify_all();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -958,8 +963,7 @@ void SPUThread::stop_and_signal(u32 code)
|
||||
if (ch_in_mbox.get_count())
|
||||
{
|
||||
LOG_ERROR(SPU, "sys_spu_thread_receive_event(spuq=0x%x): In_MBox is not empty", spuq);
|
||||
ch_in_mbox.push_uncond(CELL_EBUSY);
|
||||
return;
|
||||
return ch_in_mbox.push_uncond(CELL_EBUSY);
|
||||
}
|
||||
|
||||
if (Ini.HLELogging.GetValue())
|
||||
@ -986,20 +990,17 @@ void SPUThread::stop_and_signal(u32 code)
|
||||
|
||||
if (!queue)
|
||||
{
|
||||
ch_in_mbox.push_uncond(CELL_EINVAL); // TODO: check error value
|
||||
return;
|
||||
return ch_in_mbox.push_uncond(CELL_EINVAL); // TODO: check error value
|
||||
}
|
||||
|
||||
// protocol is ignored in current implementation
|
||||
queue->waiters++; assert(queue->waiters > 0);
|
||||
queue->waiters++;
|
||||
|
||||
while (queue->events.empty())
|
||||
{
|
||||
if (queue->waiters < 0)
|
||||
if (queue->cancelled)
|
||||
{
|
||||
queue->waiters--; assert(queue->waiters < 0);
|
||||
ch_in_mbox.push_uncond(CELL_ECANCELED);
|
||||
return;
|
||||
return ch_in_mbox.push_uncond(CELL_ECANCELED);
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
@ -1018,7 +1019,7 @@ void SPUThread::stop_and_signal(u32 code)
|
||||
ch_in_mbox.push_uncond((u32)event.data3);
|
||||
|
||||
queue->events.pop_front();
|
||||
queue->waiters--; assert(queue->waiters >= 0);
|
||||
queue->waiters--;
|
||||
|
||||
if (queue->events.size())
|
||||
{
|
||||
|
@ -14,14 +14,6 @@ enum MemoryType
|
||||
Memory_PSP,
|
||||
};
|
||||
|
||||
enum : u32
|
||||
{
|
||||
RAW_SPU_OFFSET = 0x00100000,
|
||||
RAW_SPU_BASE_ADDR = 0xE0000000,
|
||||
RAW_SPU_LS_OFFSET = 0x00000000,
|
||||
RAW_SPU_PROB_OFFSET = 0x00040000,
|
||||
};
|
||||
|
||||
class MemoryBase
|
||||
{
|
||||
std::vector<MemoryBlock*> MemoryBlocks;
|
||||
@ -98,4 +90,3 @@ public:
|
||||
extern MemoryBase Memory;
|
||||
|
||||
#include "vm.h"
|
||||
|
||||
|
@ -170,11 +170,15 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout)
|
||||
}
|
||||
|
||||
// protocol is ignored in current implementation
|
||||
cond->waiters++; assert(cond->waiters > 0);
|
||||
cond->waiters++;
|
||||
|
||||
// unlock mutex
|
||||
cond->mutex->owner.reset();
|
||||
cond->mutex->cv.notify_one();
|
||||
|
||||
if (cond->mutex->waiters)
|
||||
{
|
||||
cond->mutex->cv.notify_one();
|
||||
}
|
||||
|
||||
// save recursive value
|
||||
const u32 recursive_value = cond->mutex->recursive_count.exchange(0);
|
||||
@ -189,7 +193,7 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout)
|
||||
// cancel waiting if the mutex is free, restore its owner and recursive value
|
||||
cond->mutex->owner = thread;
|
||||
cond->mutex->recursive_count = recursive_value;
|
||||
cond->waiters--; assert(cond->waiters >= 0);
|
||||
cond->waiters--;
|
||||
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ struct cond_t
|
||||
|
||||
// TODO: use sleep queue, possibly remove condition variable
|
||||
std::condition_variable cv;
|
||||
std::atomic<s32> waiters;
|
||||
std::atomic<u32> waiters;
|
||||
|
||||
cond_t(std::shared_ptr<mutex_t>& mutex, u64 name)
|
||||
: mutex(mutex)
|
||||
|
@ -49,18 +49,11 @@ s32 sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attr>
|
||||
default: sys_event.Error("sys_event_queue_create(): unknown type (0x%x)", type); return CELL_EINVAL;
|
||||
}
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
if (Emu.GetEventManager().CheckKey(event_queue_key))
|
||||
{
|
||||
return CELL_EEXIST;
|
||||
}
|
||||
|
||||
std::shared_ptr<event_queue_t> queue(new event_queue_t(protocol, type, attr->name_u64, event_queue_key, size));
|
||||
|
||||
if (!Emu.GetEventManager().RegisterKey(queue, event_queue_key))
|
||||
{
|
||||
return CELL_EAGAIN;
|
||||
return CELL_EEXIST;
|
||||
}
|
||||
|
||||
*equeue_id = Emu.GetIdManager().GetNewID(queue, TYPE_EVENT_QUEUE);
|
||||
@ -86,16 +79,18 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode)
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
assert(queue->waiters >= 0);
|
||||
|
||||
if (!mode && queue->waiters)
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
else
|
||||
|
||||
if (queue->cancelled.exchange(true))
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (queue->waiters)
|
||||
{
|
||||
// set special value for waiters
|
||||
queue->waiters.exchange(-1);
|
||||
queue->cv.notify_all();
|
||||
}
|
||||
|
||||
@ -107,7 +102,7 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode)
|
||||
|
||||
s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_t> event_array, s32 size, vm::ptr<u32> number)
|
||||
{
|
||||
sys_event.Warning("sys_event_queue_tryreceive(equeue_id=%d, event_array=*0x%x, size=%d, number=*0x%x)", equeue_id, event_array, size, number);
|
||||
sys_event.Log("sys_event_queue_tryreceive(equeue_id=%d, event_array=*0x%x, size=%d, number=*0x%x)", equeue_id, event_array, size, number);
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
@ -130,7 +125,7 @@ s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_t> event_array,
|
||||
|
||||
s32 count = 0;
|
||||
|
||||
while (count < size && queue->events.size())
|
||||
while (!queue->waiters && count < size && queue->events.size())
|
||||
{
|
||||
auto& event = queue->events.front();
|
||||
event_array[count++] = { be_t<u64>::make(event.source), be_t<u64>::make(event.data1), be_t<u64>::make(event.data2), be_t<u64>::make(event.data3) };
|
||||
@ -140,11 +135,6 @@ s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_t> event_array,
|
||||
|
||||
*number = count;
|
||||
|
||||
if (queue->events.size())
|
||||
{
|
||||
queue->cv.notify_one();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -169,19 +159,19 @@ s32 sys_event_queue_receive(PPUThread& CPU, u32 equeue_id, vm::ptr<sys_event_t>
|
||||
}
|
||||
|
||||
// protocol is ignored in current implementation
|
||||
queue->waiters++; assert(queue->waiters > 0);
|
||||
queue->waiters++;
|
||||
|
||||
while (queue->events.empty())
|
||||
{
|
||||
if (queue->waiters < 0)
|
||||
if (queue->cancelled)
|
||||
{
|
||||
queue->waiters--; assert(queue->waiters < 0);
|
||||
queue->waiters--;
|
||||
return CELL_ECANCELED;
|
||||
}
|
||||
|
||||
if (timeout && get_system_time() - start_time > timeout)
|
||||
{
|
||||
queue->waiters--; assert(queue->waiters >= 0);
|
||||
queue->waiters--;
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -202,12 +192,7 @@ s32 sys_event_queue_receive(PPUThread& CPU, u32 equeue_id, vm::ptr<sys_event_t>
|
||||
CPU.GPR[7] = event.data3;
|
||||
|
||||
queue->events.pop_front();
|
||||
queue->waiters--; assert(queue->waiters >= 0);
|
||||
|
||||
if (queue->events.size())
|
||||
{
|
||||
queue->cv.notify_one();
|
||||
}
|
||||
queue->waiters--;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -247,8 +232,6 @@ s32 sys_event_port_create(vm::ptr<u32> eport_id, s32 port_type, u64 name)
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<event_port_t> eport(new event_port_t(port_type, name));
|
||||
|
||||
*eport_id = Emu.GetIdManager().GetNewID(eport, TYPE_EVENT_PORT);
|
||||
|
@ -78,10 +78,11 @@ struct event_queue_t
|
||||
const s32 size;
|
||||
|
||||
std::deque<event_t> events;
|
||||
std::atomic<bool> cancelled;
|
||||
|
||||
// TODO: use sleep queue, possibly remove condition variable
|
||||
std::condition_variable cv;
|
||||
std::atomic<s32> waiters;
|
||||
std::atomic<u32> waiters;
|
||||
|
||||
event_queue_t(u32 protocol, s32 type, u64 name, u64 key, s32 size)
|
||||
: protocol(protocol)
|
||||
@ -89,6 +90,7 @@ struct event_queue_t
|
||||
, name(name)
|
||||
, key(key)
|
||||
, size(size)
|
||||
, cancelled(false)
|
||||
, waiters(0)
|
||||
{
|
||||
}
|
||||
@ -96,7 +98,11 @@ struct event_queue_t
|
||||
void push(u64 source, u64 data1, u64 data2, u64 data3)
|
||||
{
|
||||
events.emplace_back(source, data1, data2, data3);
|
||||
cv.notify_one();
|
||||
|
||||
if (waiters)
|
||||
{
|
||||
cv.notify_one();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -16,8 +16,6 @@ s32 sys_event_flag_create(vm::ptr<u32> id, vm::ptr<sys_event_flag_attr> attr, u6
|
||||
{
|
||||
sys_event_flag.Warning("sys_event_flag_create(id=*0x%x, attr=*0x%x, init=0x%llx)", id, attr, init);
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
if (!id || !attr)
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
@ -69,11 +67,6 @@ s32 sys_event_flag_destroy(u32 id)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
while (ef->waiters < 0)
|
||||
{
|
||||
ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
if (ef->waiters)
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
@ -124,7 +117,7 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr<u64> result, u64 t
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
while (ef->waiters < 0)
|
||||
while (ef->cancelled)
|
||||
{
|
||||
// wait until other threads return CELL_ECANCELED (to prevent modifying bit pattern)
|
||||
ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
@ -150,11 +143,9 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr<u64> result, u64 t
|
||||
break;
|
||||
}
|
||||
|
||||
if (ef->waiters <= 0)
|
||||
if (ef->cancelled)
|
||||
{
|
||||
ef->waiters++; assert(ef->waiters <= 0);
|
||||
|
||||
if (!ef->waiters)
|
||||
if (!--ef->cancelled)
|
||||
{
|
||||
ef->cv.notify_all();
|
||||
}
|
||||
@ -164,7 +155,7 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr<u64> result, u64 t
|
||||
|
||||
if (timeout && get_system_time() - start_time > timeout)
|
||||
{
|
||||
ef->waiters--; assert(ef->waiters >= 0);
|
||||
ef->waiters--;
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -187,9 +178,7 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr<u64> result, u64 t
|
||||
ef->flags = 0;
|
||||
}
|
||||
|
||||
ef->waiters--; assert(ef->waiters >= 0);
|
||||
|
||||
if (ef->flags)
|
||||
if (--ef->waiters && ef->flags)
|
||||
{
|
||||
ef->cv.notify_one();
|
||||
}
|
||||
@ -235,7 +224,7 @@ s32 sys_event_flag_trywait(u32 id, u64 bitptn, u32 mode, vm::ptr<u64> result)
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
while (ef->waiters < 0)
|
||||
while (ef->cancelled)
|
||||
{
|
||||
ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
@ -270,13 +259,17 @@ s32 sys_event_flag_set(u32 id, u64 bitptn)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
while (ef->waiters < 0)
|
||||
while (ef->cancelled)
|
||||
{
|
||||
ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
ef->flags |= bitptn;
|
||||
ef->cv.notify_all();
|
||||
|
||||
if (ef->waiters)
|
||||
{
|
||||
ef->cv.notify_all();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -294,7 +287,7 @@ s32 sys_event_flag_clear(u32 id, u64 bitptn)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
while (ef->waiters < 0)
|
||||
while (ef->cancelled)
|
||||
{
|
||||
ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
@ -322,7 +315,7 @@ s32 sys_event_flag_cancel(u32 id, vm::ptr<u32> num)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
while (ef->waiters < 0)
|
||||
while (ef->cancelled)
|
||||
{
|
||||
ef->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
@ -332,10 +325,11 @@ s32 sys_event_flag_cancel(u32 id, vm::ptr<u32> num)
|
||||
*num = ef->waiters;
|
||||
}
|
||||
|
||||
// negate value to signal waiting threads and prevent modifying bit pattern
|
||||
ef->waiters = -ef->waiters;
|
||||
ef->cv.notify_all();
|
||||
|
||||
if ((ef->cancelled = ef->waiters.exchange(0)))
|
||||
{
|
||||
ef->cv.notify_all();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -34,10 +34,11 @@ struct event_flag_t
|
||||
const u64 name;
|
||||
|
||||
std::atomic<u64> flags;
|
||||
std::atomic<u32> cancelled;
|
||||
|
||||
// TODO: use sleep queue, possibly remove condition variable
|
||||
std::condition_variable cv;
|
||||
std::atomic<s32> waiters;
|
||||
std::atomic<u32> waiters;
|
||||
|
||||
event_flag_t(u64 pattern, u32 protocol, s32 type, u64 name)
|
||||
: flags(pattern)
|
||||
|
@ -38,6 +38,7 @@ s32 _sys_lwcond_destroy(u32 lwcond_id)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lwcond_t> cond;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(lwcond_id, cond))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -60,12 +61,13 @@ s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mod
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lwcond_t> cond;
|
||||
std::shared_ptr<lwmutex_t> mutex;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(lwcond_id, cond))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
std::shared_ptr<lwmutex_t> mutex;
|
||||
if (lwmutex_id && !Emu.GetIdManager().GetIDData(lwmutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -117,8 +119,10 @@ s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mod
|
||||
cond->signaled1++;
|
||||
}
|
||||
|
||||
cond->waiters--;
|
||||
cond->cv.notify_one();
|
||||
if (--cond->waiters)
|
||||
{
|
||||
cond->cv.notify_one();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -130,12 +134,13 @@ s32 _sys_lwcond_signal_all(u32 lwcond_id, u32 lwmutex_id, u32 mode)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lwcond_t> cond;
|
||||
std::shared_ptr<lwmutex_t> mutex;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(lwcond_id, cond))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
std::shared_ptr<lwmutex_t> mutex;
|
||||
if (lwmutex_id && !Emu.GetIdManager().GetIDData(lwmutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -147,7 +152,11 @@ s32 _sys_lwcond_signal_all(u32 lwcond_id, u32 lwmutex_id, u32 mode)
|
||||
}
|
||||
|
||||
const s32 count = cond->waiters.exchange(0);
|
||||
cond->cv.notify_all();
|
||||
|
||||
if (count)
|
||||
{
|
||||
cond->cv.notify_all();
|
||||
}
|
||||
|
||||
if (mode == 1)
|
||||
{
|
||||
@ -176,12 +185,13 @@ s32 _sys_lwcond_queue_wait(u32 lwcond_id, u32 lwmutex_id, u64 timeout)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lwcond_t> cond;
|
||||
std::shared_ptr<lwmutex_t> mutex;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(lwcond_id, cond))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
std::shared_ptr<lwmutex_t> mutex;
|
||||
if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -189,10 +199,14 @@ s32 _sys_lwcond_queue_wait(u32 lwcond_id, u32 lwmutex_id, u64 timeout)
|
||||
|
||||
// finalize unlocking the mutex
|
||||
mutex->signaled++;
|
||||
mutex->cv.notify_one();
|
||||
|
||||
if (mutex->waiters)
|
||||
{
|
||||
mutex->cv.notify_one();
|
||||
}
|
||||
|
||||
// protocol is ignored in current implementation
|
||||
cond->waiters++; assert(cond->waiters > 0);
|
||||
cond->waiters++;
|
||||
|
||||
while (!(cond->signaled1 && mutex->signaled) && !cond->signaled2)
|
||||
{
|
||||
@ -202,7 +216,7 @@ s32 _sys_lwcond_queue_wait(u32 lwcond_id, u32 lwmutex_id, u64 timeout)
|
||||
if (is_timedout && !cond->signaled1)
|
||||
{
|
||||
// cancel waiting
|
||||
cond->waiters--; assert(cond->waiters >= 0);
|
||||
cond->waiters--;
|
||||
|
||||
if (mutex->signaled)
|
||||
{
|
||||
|
@ -26,7 +26,7 @@ struct lwcond_t
|
||||
|
||||
// TODO: use sleep queue
|
||||
std::condition_variable cv;
|
||||
std::atomic<s32> waiters;
|
||||
std::atomic<u32> waiters;
|
||||
|
||||
lwcond_t(u64 name)
|
||||
: name(name)
|
||||
|
@ -53,6 +53,7 @@ s32 _sys_lwmutex_destroy(u32 lwmutex_id)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lwmutex_t> mutex;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -77,19 +78,20 @@ s32 _sys_lwmutex_lock(u32 lwmutex_id, u64 timeout)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lwmutex_t> mutex;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
// protocol is ignored in current implementation
|
||||
mutex->waiters++; assert(mutex->waiters > 0);
|
||||
mutex->waiters++;
|
||||
|
||||
while (!mutex->signaled)
|
||||
{
|
||||
if (timeout && get_system_time() - start_time > timeout)
|
||||
{
|
||||
mutex->waiters--; assert(mutex->waiters >= 0);
|
||||
mutex->waiters--;
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -104,7 +106,7 @@ s32 _sys_lwmutex_lock(u32 lwmutex_id, u64 timeout)
|
||||
|
||||
mutex->signaled--;
|
||||
|
||||
mutex->waiters--; assert(mutex->waiters >= 0);
|
||||
mutex->waiters--;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -116,6 +118,7 @@ s32 _sys_lwmutex_trylock(u32 lwmutex_id)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lwmutex_t> mutex;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -138,6 +141,7 @@ s32 _sys_lwmutex_unlock(u32 lwmutex_id)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lwmutex_t> mutex;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -149,7 +153,11 @@ s32 _sys_lwmutex_unlock(u32 lwmutex_id)
|
||||
}
|
||||
|
||||
mutex->signaled++;
|
||||
mutex->cv.notify_one();
|
||||
|
||||
if (mutex->waiters)
|
||||
{
|
||||
mutex->cv.notify_one();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ struct lwmutex_t
|
||||
|
||||
// TODO: use sleep queue, possibly remove condition variable
|
||||
std::condition_variable cv;
|
||||
std::atomic<s32> waiters;
|
||||
std::atomic<u32> waiters;
|
||||
|
||||
lwmutex_t(u32 protocol, u64 name)
|
||||
: protocol(protocol)
|
||||
|
@ -16,8 +16,6 @@ s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t> attr)
|
||||
{
|
||||
sys_mutex.Warning("sys_mutex_create(mutex_id=*0x%x, attr=*0x%x)", mutex_id, attr);
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
if (!mutex_id || !attr)
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
@ -119,13 +117,13 @@ s32 sys_mutex_lock(PPUThread& CPU, u32 mutex_id, u64 timeout)
|
||||
}
|
||||
|
||||
// protocol is ignored in current implementation
|
||||
mutex->waiters++; assert(mutex->waiters > 0);
|
||||
mutex->waiters++;
|
||||
|
||||
while (!mutex->owner.expired())
|
||||
{
|
||||
if (timeout && get_system_time() - start_time > timeout)
|
||||
{
|
||||
mutex->waiters--; assert(mutex->waiters >= 0);
|
||||
mutex->waiters--;
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -139,7 +137,7 @@ s32 sys_mutex_lock(PPUThread& CPU, u32 mutex_id, u64 timeout)
|
||||
}
|
||||
|
||||
mutex->owner = thread;
|
||||
mutex->waiters--; assert(mutex->waiters >= 0);
|
||||
mutex->waiters--;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -218,7 +216,11 @@ s32 sys_mutex_unlock(PPUThread& CPU, u32 mutex_id)
|
||||
else
|
||||
{
|
||||
mutex->owner.reset();
|
||||
mutex->cv.notify_one();
|
||||
|
||||
if (mutex->waiters)
|
||||
{
|
||||
mutex->cv.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -29,7 +29,7 @@ struct mutex_t
|
||||
|
||||
// TODO: use sleep queue, possibly remove condition variable
|
||||
std::condition_variable cv;
|
||||
std::atomic<s32> waiters;
|
||||
std::atomic<u32> waiters;
|
||||
|
||||
mutex_t(bool recursive, u32 protocol, u64 name)
|
||||
: recursive(recursive)
|
||||
|
@ -50,12 +50,13 @@ s32 sys_rwlock_destroy(u32 rw_lock_id)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<rwlock_t> rwlock;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (rwlock.use_count() > 2 || rwlock->readers || rwlock->writer || rwlock->waiters)
|
||||
if (rwlock->readers || rwlock->writer || rwlock->rwaiters || rwlock->wwaiters)
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
@ -74,15 +75,20 @@ s32 sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<rwlock_t> rwlock;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
while (rwlock->writer || rwlock->waiters)
|
||||
// waiting threads are not properly registered in current implementation
|
||||
rwlock->rwaiters++;
|
||||
|
||||
while (rwlock->writer || rwlock->wwaiters)
|
||||
{
|
||||
if (timeout && get_system_time() - start_time > timeout)
|
||||
{
|
||||
rwlock->rwaiters--;
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -92,10 +98,11 @@ s32 sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
rwlock->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
rwlock->rcv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
rwlock->readers++;
|
||||
rwlock->rwaiters--;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -107,12 +114,13 @@ s32 sys_rwlock_tryrlock(u32 rw_lock_id)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<rwlock_t> rwlock;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (rwlock->writer || rwlock->waiters)
|
||||
if (rwlock->writer || rwlock->wwaiters)
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
@ -129,6 +137,7 @@ s32 sys_rwlock_runlock(u32 rw_lock_id)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<rwlock_t> rwlock;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -139,9 +148,9 @@ s32 sys_rwlock_runlock(u32 rw_lock_id)
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
if (!--rwlock->readers)
|
||||
if (!--rwlock->readers && rwlock->wwaiters)
|
||||
{
|
||||
rwlock->cv.notify_one();
|
||||
rwlock->wcv.notify_one();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@ -156,6 +165,7 @@ s32 sys_rwlock_wlock(PPUThread& CPU, u32 rw_lock_id, u64 timeout)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<rwlock_t> rwlock;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -167,13 +177,13 @@ s32 sys_rwlock_wlock(PPUThread& CPU, u32 rw_lock_id, u64 timeout)
|
||||
}
|
||||
|
||||
// protocol is ignored in current implementation
|
||||
rwlock->waiters++; assert(rwlock->waiters > 0);
|
||||
rwlock->wwaiters++;
|
||||
|
||||
while (rwlock->readers || rwlock->writer)
|
||||
{
|
||||
if (timeout && get_system_time() - start_time > timeout)
|
||||
{
|
||||
rwlock->waiters--; assert(rwlock->waiters >= 0);
|
||||
rwlock->wwaiters--;
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -183,11 +193,11 @@ s32 sys_rwlock_wlock(PPUThread& CPU, u32 rw_lock_id, u64 timeout)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
rwlock->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
rwlock->wcv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
rwlock->writer = CPU.GetId();
|
||||
rwlock->waiters--; assert(rwlock->waiters >= 0);
|
||||
rwlock->wwaiters--;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -199,6 +209,7 @@ s32 sys_rwlock_trywlock(PPUThread& CPU, u32 rw_lock_id)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<rwlock_t> rwlock;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -209,7 +220,7 @@ s32 sys_rwlock_trywlock(PPUThread& CPU, u32 rw_lock_id)
|
||||
return CELL_EDEADLK;
|
||||
}
|
||||
|
||||
if (rwlock->readers || rwlock->writer || rwlock->waiters)
|
||||
if (rwlock->readers || rwlock->writer || rwlock->wwaiters)
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
@ -226,6 +237,7 @@ s32 sys_rwlock_wunlock(PPUThread& CPU, u32 rw_lock_id)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<rwlock_t> rwlock;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -237,7 +249,15 @@ s32 sys_rwlock_wunlock(PPUThread& CPU, u32 rw_lock_id)
|
||||
}
|
||||
|
||||
rwlock->writer = 0;
|
||||
rwlock->cv.notify_all();
|
||||
|
||||
if (rwlock->wwaiters)
|
||||
{
|
||||
rwlock->wcv.notify_one();
|
||||
}
|
||||
else if (rwlock->rwaiters)
|
||||
{
|
||||
rwlock->rcv.notify_all();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -23,16 +23,19 @@ struct rwlock_t
|
||||
std::atomic<u32> readers; // reader count
|
||||
std::atomic<u32> writer; // writer id
|
||||
|
||||
// TODO: use sleep queue, possibly remove condition variable
|
||||
std::condition_variable cv;
|
||||
std::atomic<s32> waiters;
|
||||
// TODO: use sleep queue, possibly remove condition variables
|
||||
std::condition_variable rcv;
|
||||
std::condition_variable wcv;
|
||||
std::atomic<u32> rwaiters;
|
||||
std::atomic<u32> wwaiters;
|
||||
|
||||
rwlock_t(u32 protocol, u64 name)
|
||||
: protocol(protocol)
|
||||
, name(name)
|
||||
, readers(0)
|
||||
, writer(0)
|
||||
, waiters(0)
|
||||
, rwaiters(0)
|
||||
, wwaiters(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -62,6 +62,7 @@ s32 sys_semaphore_destroy(u32 sem)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<semaphore_t> semaphore;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(sem, semaphore))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -86,19 +87,20 @@ s32 sys_semaphore_wait(u32 sem, u64 timeout)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<semaphore_t> semaphore;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(sem, semaphore))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
// protocol is ignored in current implementation
|
||||
semaphore->waiters++; assert(semaphore->waiters > 0);
|
||||
semaphore->waiters++;
|
||||
|
||||
while (semaphore->value <= 0)
|
||||
{
|
||||
if (timeout && get_system_time() - start_time > timeout)
|
||||
{
|
||||
semaphore->waiters--; assert(semaphore->waiters >= 0);
|
||||
semaphore->waiters--;
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -112,7 +114,7 @@ s32 sys_semaphore_wait(u32 sem, u64 timeout)
|
||||
}
|
||||
|
||||
semaphore->value--;
|
||||
semaphore->waiters--; assert(semaphore->waiters >= 0);
|
||||
semaphore->waiters--;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -124,6 +126,7 @@ s32 sys_semaphore_trywait(u32 sem)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<semaphore_t> semaphore;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(sem, semaphore))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -146,6 +149,7 @@ s32 sys_semaphore_post(u32 sem, s32 count)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<semaphore_t> semaphore;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(sem, semaphore))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -156,13 +160,20 @@ s32 sys_semaphore_post(u32 sem, s32 count)
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (semaphore->value + count > semaphore->max + semaphore->waiters)
|
||||
const u64 new_value = semaphore->value + count;
|
||||
const u64 max_value = semaphore->max + semaphore->waiters;
|
||||
|
||||
if (new_value > max_value)
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
semaphore->value += count; assert(semaphore->value >= 0);
|
||||
semaphore->cv.notify_all();
|
||||
semaphore->value += count;
|
||||
|
||||
if (semaphore->waiters)
|
||||
{
|
||||
semaphore->cv.notify_all();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -179,6 +190,7 @@ s32 sys_semaphore_get_value(u32 sem, vm::ptr<s32> count)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<semaphore_t> semaphore;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(sem, semaphore))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -25,7 +25,7 @@ struct semaphore_t
|
||||
|
||||
// TODO: use sleep queue, possibly remove condition variable
|
||||
std::condition_variable cv;
|
||||
std::atomic<s32> waiters;
|
||||
std::atomic<u32> waiters;
|
||||
|
||||
semaphore_t(u32 protocol, s32 max, u64 name, s32 value)
|
||||
: protocol(protocol)
|
||||
|
@ -32,8 +32,7 @@ s32 sys_timer_create(vm::ptr<u32> timer_id)
|
||||
|
||||
if (queue)
|
||||
{
|
||||
queue->events.emplace_back(timer->source, timer->data1, timer->data2, timer->start);
|
||||
queue->cv.notify_one();
|
||||
queue->push(timer->source, timer->data1, timer->data2, timer->start);
|
||||
}
|
||||
|
||||
if (timer->period && queue)
|
||||
@ -64,6 +63,7 @@ s32 sys_timer_destroy(u32 timer_id)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lv2_timer_t> timer;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(timer_id, timer))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -86,6 +86,7 @@ s32 sys_timer_get_information(u32 timer_id, vm::ptr<sys_timer_information_t> inf
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lv2_timer_t> timer;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(timer_id, timer))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -94,7 +95,6 @@ s32 sys_timer_get_information(u32 timer_id, vm::ptr<sys_timer_information_t> inf
|
||||
info->next_expiration_time = timer->start;
|
||||
|
||||
info->period = timer->period;
|
||||
|
||||
info->timer_state = timer->state;
|
||||
|
||||
return CELL_OK;
|
||||
@ -109,6 +109,7 @@ s32 _sys_timer_start(u32 timer_id, u64 base_time, u64 period)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lv2_timer_t> timer;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(timer_id, timer))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -160,6 +161,7 @@ s32 sys_timer_stop(u32 timer_id)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lv2_timer_t> timer;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(timer_id, timer))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
@ -204,6 +206,7 @@ s32 sys_timer_disconnect_event_queue(u32 timer_id)
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<lv2_timer_t> timer;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(timer_id, timer))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
Loading…
x
Reference in New Issue
Block a user