mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 03:55:32 +00:00
Merge pull request #357 from Nekotekina/master
SC_Semaphore improved and detached from (r)wxSemaphore
This commit is contained in:
commit
5912953152
15 changed files with 286 additions and 129 deletions
|
@ -43,29 +43,22 @@ bool SSemaphore::try_wait()
|
|||
}
|
||||
}
|
||||
|
||||
void SSemaphore::post(u32 value)
|
||||
void SSemaphore::post()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (m_count >= m_max)
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
else if (value > (m_max - m_count))
|
||||
{
|
||||
value = m_max - m_count;
|
||||
return;
|
||||
}
|
||||
|
||||
while (value)
|
||||
{
|
||||
m_count++;
|
||||
value--;
|
||||
m_cond.notify_one();
|
||||
}
|
||||
m_count++;
|
||||
m_cond.notify_one();
|
||||
}
|
||||
|
||||
bool SSemaphore::post_and_wait()
|
||||
{
|
||||
// TODO: ???
|
||||
if (try_wait()) return false;
|
||||
|
||||
post();
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
|
||||
bool try_wait();
|
||||
|
||||
void post(u32 value = 1);
|
||||
void post();
|
||||
|
||||
bool post_and_wait();
|
||||
};
|
|
@ -108,6 +108,22 @@ CPUThread* CPUThreadManager::GetThread(u32 id)
|
|||
return res;
|
||||
}
|
||||
|
||||
void CPUThreadManager::NotifyThread(const u32 id)
|
||||
{
|
||||
if (!id) return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
||||
|
||||
for (u32 i = 0; i < m_threads.size(); i++)
|
||||
{
|
||||
if (m_threads[i]->GetId() == id)
|
||||
{
|
||||
m_threads[i]->Notify();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPUThreadManager::Exec()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
|
||||
CPUThread& AddThread(CPUThreadType type);
|
||||
void RemoveThread(const u32 id);
|
||||
void NotifyThread(const u32 id);
|
||||
|
||||
std::vector<CPUThread*>& GetThreads() { return m_threads; }
|
||||
s32 GetThreadNumById(CPUThreadType type, u32 id);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "lv2/SC_Event_flag.h"
|
||||
#include "lv2/SC_Condition.h"
|
||||
#include "lv2/SC_Spinlock.h"
|
||||
#include "lv2/SC_Semaphore.h"
|
||||
#include "Emu/event.h"
|
||||
#include "Static.h"
|
||||
//#define SYSCALLS_DEBUG
|
||||
|
@ -144,12 +145,12 @@ extern int sys_event_flag_cancel(u32 eflag_id, mem32_t num);
|
|||
extern int sys_event_flag_get(u32 eflag_id, mem64_t flags);
|
||||
|
||||
//sys_semaphore
|
||||
extern int sys_semaphore_create(u32 sem_addr, u32 attr_addr, int initial_val, int max_val);
|
||||
extern int sys_semaphore_destroy(u32 sem);
|
||||
extern int sys_semaphore_wait(u32 sem, u64 timeout);
|
||||
extern int sys_semaphore_trywait(u32 sem);
|
||||
extern int sys_semaphore_post(u32 sem, int count);
|
||||
extern int sys_semaphore_get_value(u32 sem, u32 count_addr);
|
||||
extern int sys_semaphore_create(mem32_t sem, mem_ptr_t<sys_semaphore_attribute> attr, int initial_count, int max_count);
|
||||
extern int sys_semaphore_destroy(u32 sem_id);
|
||||
extern int sys_semaphore_wait(u32 sem_id, u64 timeout);
|
||||
extern int sys_semaphore_trywait(u32 sem_id);
|
||||
extern int sys_semaphore_post(u32 sem_id, int count);
|
||||
extern int sys_semaphore_get_value(u32 sem_id, mem32_t count);
|
||||
|
||||
//sys_lwcond
|
||||
extern int sys_lwcond_create(mem_ptr_t<sys_lwcond_t> lwcond, mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwcond_attribute_t> attr);
|
||||
|
|
|
@ -81,6 +81,7 @@ int sys_cond_signal(u32 cond_id)
|
|||
{
|
||||
cond->signal_stamp = get_system_time();
|
||||
cond->signal.lock(target);
|
||||
Emu.GetCPU().NotifyThread(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
|
@ -105,15 +106,19 @@ int sys_cond_signal_all(u32 cond_id)
|
|||
|
||||
while (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop()))
|
||||
{
|
||||
cond->signaler = GetCurrentCPUThread()->GetId();
|
||||
cond->signal_stamp = get_system_time();
|
||||
cond->signal.lock(target);
|
||||
Emu.GetCPU().NotifyThread(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_cond_signal_all(id=%d) aborted", cond_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cond->signaler = 0;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -143,6 +148,7 @@ int sys_cond_signal_to(u32 cond_id, u32 thread_id)
|
|||
{
|
||||
cond->signal_stamp = get_system_time();
|
||||
cond->signal.lock(target);
|
||||
Emu.GetCPU().NotifyThread(target);
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
|
@ -188,6 +194,7 @@ int sys_cond_wait(u32 cond_id, u64 timeout)
|
|||
{
|
||||
if (cond->signal.unlock(tid, tid) == SMR_OK)
|
||||
{
|
||||
const u64 stamp2 = get_system_time();
|
||||
if (SMutexResult res = mutex->m_mutex.trylock(tid))
|
||||
{
|
||||
if (res != SMR_FAILED)
|
||||
|
@ -209,11 +216,12 @@ int sys_cond_wait(u32 cond_id, u64 timeout)
|
|||
mutex->recursive = 1;
|
||||
const volatile u64 stamp = cond->signal_stamp;
|
||||
cond->signal.unlock(tid);
|
||||
//ConLog.Write("sys_cond_wait(): signal latency %d", get_system_time() - stamp);
|
||||
Emu.GetCPU().NotifyThread(cond->signaler);
|
||||
//ConLog.Write("sys_cond_wait(): signal latency %lld (minimum %lld)", get_system_time() - stamp, stamp2 - stamp);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
Sleep(1);
|
||||
SM_Sleep();
|
||||
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
|
|
|
@ -17,12 +17,15 @@ struct Cond
|
|||
{
|
||||
Mutex* mutex; // associated with mutex
|
||||
SMutex signal;
|
||||
u32 signaler; // signaler thread id (for signal_all)
|
||||
SleepQueue m_queue;
|
||||
|
||||
u64 signal_stamp;
|
||||
|
||||
Cond(Mutex* mutex, u64 name)
|
||||
: mutex(mutex)
|
||||
, m_queue(name)
|
||||
, signaler(0)
|
||||
{
|
||||
}
|
||||
};
|
|
@ -190,6 +190,13 @@ bool SleepQueue::invalidate(u32 tid)
|
|||
return false;
|
||||
}
|
||||
|
||||
u32 SleepQueue::count()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
return list.size();
|
||||
}
|
||||
|
||||
bool SleepQueue::finalize()
|
||||
{
|
||||
if (!m_mutex.try_lock()) return false;
|
||||
|
|
|
@ -60,6 +60,7 @@ struct SleepQueue
|
|||
u32 pop_prio(); // SYS_SYNC_PRIORITY
|
||||
u32 pop_prio_inherit(); // (TODO)
|
||||
bool invalidate(u32 tid);
|
||||
u32 count();
|
||||
bool finalize();
|
||||
};
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ int sys_mutex_destroy(u32 mutex_id)
|
|||
|
||||
int sys_mutex_lock(u32 mutex_id, u64 timeout)
|
||||
{
|
||||
sys_mtx.Log("sys_mutex_lock(mutex_id=%d, timeout=0x%llx)", mutex_id, timeout);
|
||||
sys_mtx.Log("sys_mutex_lock(mutex_id=%d, timeout=%lld)", mutex_id, timeout);
|
||||
|
||||
Mutex* mutex;
|
||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||
|
|
|
@ -8,72 +8,72 @@ SysCallBase sys_rsx("sys_rsx");
|
|||
|
||||
int sys_rsx_device_open()
|
||||
{
|
||||
sys_rsx.Warning("Unimplemented function: sys_rsx_device_open()");
|
||||
sys_rsx.Error("TODO: sys_rsx_device_open()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_rsx_device_close()
|
||||
{
|
||||
sys_rsx.Warning("Unimplemented function: sys_rsx_device_close()");
|
||||
sys_rsx.Error("TODO: sys_rsx_device_close()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_rsx_memory_allocate()
|
||||
{
|
||||
sys_rsx.Warning("Unimplemented function: sys_rsx_memory_allocate()");
|
||||
sys_rsx.Error("TODO: sys_rsx_memory_allocate()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_rsx_memory_free()
|
||||
{
|
||||
sys_rsx.Warning("Unimplemented function: sys_rsx_memory_free()");
|
||||
sys_rsx.Error("TODO: sys_rsx_memory_free()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_rsx_context_allocate()
|
||||
{
|
||||
sys_rsx.Warning("Unimplemented function: sys_rsx_context_allocate()");
|
||||
sys_rsx.Error("TODO: sys_rsx_context_allocate()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_rsx_context_free()
|
||||
{
|
||||
sys_rsx.Warning("Unimplemented function: sys_rsx_context_free()");
|
||||
sys_rsx.Error("TODO: sys_rsx_context_free()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_rsx_context_iomap()
|
||||
{
|
||||
sys_rsx.Warning("Unimplemented function: sys_rsx_context_iomap()");
|
||||
sys_rsx.Error("TODO: sys_rsx_context_iomap()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_rsx_context_iounmap()
|
||||
{
|
||||
sys_rsx.Warning("Unimplemented function: sys_rsx_context_iounmap()");
|
||||
sys_rsx.Error("TODO: sys_rsx_context_iounmap()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_rsx_context_attribute(s32 context_id, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6)
|
||||
{
|
||||
sys_rsx.Warning("Unimplemented function: sys_rsx_context_attribute(context_id=%d, a2=%llu, a3=%llu, a4=%llu, a5=%llu, a6=%llu)", context_id, a2, a3, a4, a5, a6);
|
||||
sys_rsx.Error("TODO: sys_rsx_context_attribute(context_id=%d, a2=%llu, a3=%llu, a4=%llu, a5=%llu, a6=%llu)", context_id, a2, a3, a4, a5, a6);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_rsx_device_map(mem32_t a1, mem32_t a2, u32 a3)
|
||||
{
|
||||
sys_rsx.Warning("Unimplemented function: sys_rsx_device_map(a1_addr=0x%x, a2_addr=0x%x, a3=%d)", a1.GetAddr(), a2.GetAddr(), a3);
|
||||
sys_rsx.Error("TODO: sys_rsx_device_map(a1_addr=0x%x, a2_addr=0x%x, a3=%d)", a1.GetAddr(), a2.GetAddr(), a3);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_rsx_device_unmap()
|
||||
{
|
||||
sys_rsx.Warning("Unimplemented function: sys_rsx_device_unmap()");
|
||||
sys_rsx.Error("TODO: sys_rsx_device_unmap()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_rsx_attribute()
|
||||
{
|
||||
sys_rsx.Warning("Unimplemented function: sys_rsx_attribute()");
|
||||
sys_rsx.Error("TODO: sys_rsx_attribute()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -3,116 +3,203 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "SC_Semaphore.h"
|
||||
|
||||
SysCallBase sys_sem("sys_semaphore");
|
||||
|
||||
struct semaphore_attr
|
||||
{
|
||||
u32 protocol;
|
||||
u32 pshared;
|
||||
u64 ipc_key;
|
||||
int flags;
|
||||
u32 pad;
|
||||
char name[8];
|
||||
};
|
||||
|
||||
struct semaphore
|
||||
{
|
||||
rSemaphore sem;
|
||||
semaphore_attr attr;
|
||||
int sem_count;
|
||||
|
||||
semaphore(int initial_count, int max_count, semaphore_attr attr)
|
||||
: sem(initial_count, max_count)
|
||||
, attr(attr)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
int sys_semaphore_create(u32 sem_addr, u32 attr_addr, int initial_count, int max_count)
|
||||
int sys_semaphore_create(mem32_t sem, mem_ptr_t<sys_semaphore_attribute> attr, int initial_count, int max_count)
|
||||
{
|
||||
sys_sem.Warning("sys_semaphore_create(sem_addr=0x%x, attr_addr=0x%x, initial_count=%d, max_count=%d)",
|
||||
sem_addr, attr_addr, initial_count, max_count);
|
||||
sem.GetAddr(), attr.GetAddr(), initial_count, max_count);
|
||||
|
||||
if(!Memory.IsGoodAddr(sem_addr) || !Memory.IsGoodAddr(attr_addr)) return CELL_EFAULT;
|
||||
|
||||
semaphore_attr attr = (semaphore_attr&)Memory[attr_addr];
|
||||
attr.protocol = re(attr.protocol);
|
||||
attr.pshared = re(attr.pshared);
|
||||
attr.ipc_key = re(attr.ipc_key);
|
||||
attr.flags = re(attr.flags);
|
||||
|
||||
sys_sem.Log("*** protocol = %d", attr.protocol);
|
||||
sys_sem.Log("*** pshared = %d", attr.pshared);
|
||||
sys_sem.Log("*** ipc_key = 0x%llx", attr.ipc_key);
|
||||
sys_sem.Log("*** flags = 0x%x", attr.flags);
|
||||
sys_sem.Log("*** name = %s", attr.name);
|
||||
|
||||
Memory.Write32(sem_addr, sys_sem.GetNewId(new semaphore(initial_count, max_count, attr)));
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_semaphore_destroy(u32 sem)
|
||||
{
|
||||
sys_sem.Log("sys_semaphore_destroy(sem=%d)", sem);
|
||||
|
||||
if(!sys_sem.CheckId(sem)) return CELL_ESRCH;
|
||||
|
||||
Emu.GetIdManager().RemoveID(sem);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_semaphore_wait(u32 sem, u64 timeout)
|
||||
{
|
||||
sys_sem.Log("sys_semaphore_wait(sem=0x%x, timeout=0x%llx)", sem, timeout);
|
||||
|
||||
semaphore* sem_data = nullptr;
|
||||
if(!sys_sem.CheckId(sem, sem_data)) return CELL_ESRCH;
|
||||
|
||||
sem_data->sem_count = 0; // Reset internal counter for sys_semaphore_get_value.
|
||||
sem_data->sem.WaitTimeout(timeout ? timeout : INFINITE);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_semaphore_trywait(u32 sem)
|
||||
{
|
||||
sys_sem.Log("sys_semaphore_trywait(sem=%d)", sem);
|
||||
|
||||
semaphore* sem_data = nullptr;
|
||||
if(!sys_sem.CheckId(sem, sem_data)) return CELL_ESRCH;
|
||||
|
||||
sem_data->sem_count = 0; // Reset internal counter for sys_semaphore_get_value.
|
||||
if(sem_data->sem.TryWait()) return 1;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_semaphore_post(u32 sem, int count)
|
||||
{
|
||||
sys_sem.Log("sys_semaphore_post(sem=%d, count=%d)", sem, count);
|
||||
|
||||
semaphore* sem_data = nullptr;
|
||||
if(!sys_sem.CheckId(sem, sem_data)) return CELL_ESRCH;
|
||||
|
||||
while(count--)
|
||||
if (!sem.IsGood() || !attr.IsGood())
|
||||
{
|
||||
sem_data->sem_count++; // Increment internal counter for sys_semaphore_get_value.
|
||||
sem_data->sem.Post();
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
if (max_count <= 0)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (attr->pshared.ToBE() != se32(0x200))
|
||||
{
|
||||
sys_sem.Error("Invalid pshared attribute(0x%x)", (u32)attr->pshared);
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
switch (attr->protocol.ToBE())
|
||||
{
|
||||
case se32(SYS_SYNC_FIFO): break;
|
||||
case se32(SYS_SYNC_PRIORITY): break;
|
||||
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_sem.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT protocol"); break;
|
||||
case se32(SYS_SYNC_RETRY): sys_sem.Error("Invalid SYS_SYNC_RETRY protocol"); return CELL_EINVAL;
|
||||
default: sys_sem.Error("Unknown protocol attribute(0x%x)", (u32)attr->protocol); return CELL_EINVAL;
|
||||
}
|
||||
|
||||
sem = sys_sem.GetNewId(new Semaphore(initial_count, max_count, attr->protocol, attr->name_u64));
|
||||
ConLog.Write("*** semaphore created [%s] (protocol=0x%x): id = %d",
|
||||
std::string(attr->name, 8).c_str(), (u32)attr->protocol, sem.GetValue());
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_semaphore_destroy(u32 sem_id)
|
||||
{
|
||||
sys_sem.Warning("sys_semaphore_destroy(sem_id=%d)", sem_id);
|
||||
|
||||
Semaphore* sem;
|
||||
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!sem->m_queue.finalize())
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
Emu.GetIdManager().RemoveID(sem_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_semaphore_wait(u32 sem_id, u64 timeout)
|
||||
{
|
||||
sys_sem.Log("sys_semaphore_wait(sem_id=%d, timeout=%lld)", sem_id, timeout);
|
||||
|
||||
Semaphore* sem;
|
||||
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
const u64 start_time = get_system_time();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(sem->m_mutex);
|
||||
if (sem->m_value > 0)
|
||||
{
|
||||
sem->m_value--;
|
||||
return CELL_OK;
|
||||
}
|
||||
sem->m_queue.push(tid);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_semaphore_wait(%d) aborted", sem_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
if (timeout && get_system_time() - start_time > timeout)
|
||||
{
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (tid == sem->signal)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(sem->m_mutex);
|
||||
|
||||
sem->signal = 0;
|
||||
// TODO: notify signaler
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
SM_Sleep();
|
||||
}
|
||||
}
|
||||
|
||||
int sys_semaphore_trywait(u32 sem_id)
|
||||
{
|
||||
sys_sem.Log("sys_semaphore_trywait(sem_id=%d)", sem_id);
|
||||
|
||||
Semaphore* sem;
|
||||
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(sem->m_mutex);
|
||||
|
||||
if (sem->m_value > 0)
|
||||
{
|
||||
sem->m_value--;
|
||||
return CELL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
int sys_semaphore_post(u32 sem_id, int count)
|
||||
{
|
||||
sys_sem.Log("sys_semaphore_post(sem_id=%d, count=%d)", sem_id, count);
|
||||
|
||||
Semaphore* sem;
|
||||
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (count + sem->m_value - sem->m_queue.count() > sem->max)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_semaphore_post(%d) aborted", sem_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(sem->m_mutex);
|
||||
|
||||
if (sem->signal && sem->m_queue.count())
|
||||
{
|
||||
SM_Sleep();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (u32 target = (sem->protocol == SYS_SYNC_FIFO) ? sem->m_queue.pop() : sem->m_queue.pop_prio())
|
||||
{
|
||||
count--;
|
||||
sem->signal = target;
|
||||
Emu.GetCPU().NotifyThread(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
sem->m_value += count;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_semaphore_get_value(u32 sem, u32 count_addr)
|
||||
int sys_semaphore_get_value(u32 sem_id, mem32_t count)
|
||||
{
|
||||
sys_sem.Log("sys_semaphore_get_value(sem=%d, count_addr=0x%x)", sem, count_addr);
|
||||
sys_sem.Log("sys_semaphore_get_value(sem_id=%d, count_addr=0x%x)", sem_id, count.GetAddr());
|
||||
|
||||
semaphore* sem_data = nullptr;
|
||||
if(!sys_sem.CheckId(sem, sem_data)) return CELL_ESRCH;
|
||||
Semaphore* sem;
|
||||
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
Memory.Write32(count_addr, sem_data->sem_count);
|
||||
std::lock_guard<std::mutex> lock(sem->m_mutex);
|
||||
|
||||
count = sem->m_value;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
36
rpcs3/Emu/SysCalls/lv2/SC_Semaphore.h
Normal file
36
rpcs3/Emu/SysCalls/lv2/SC_Semaphore.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
struct sys_semaphore_attribute
|
||||
{
|
||||
be_t<u32> protocol;
|
||||
be_t<u32> pshared; // undefined
|
||||
be_t<u64> ipc_key; // undefined
|
||||
be_t<int> flags; // undefined
|
||||
be_t<u32> pad; // not used
|
||||
union
|
||||
{
|
||||
char name[8];
|
||||
u64 name_u64;
|
||||
};
|
||||
};
|
||||
|
||||
struct Semaphore
|
||||
{
|
||||
std::mutex m_mutex;
|
||||
SleepQueue m_queue;
|
||||
int m_value;
|
||||
u32 signal;
|
||||
|
||||
const int max;
|
||||
const u32 protocol;
|
||||
const u64 name;
|
||||
|
||||
Semaphore(int initial_count, int max_count, u32 protocol, u64 name)
|
||||
: m_value(initial_count)
|
||||
, signal(0)
|
||||
, max(max_count)
|
||||
, protocol(protocol)
|
||||
, name(name)
|
||||
{
|
||||
}
|
||||
};
|
|
@ -321,6 +321,7 @@
|
|||
<ClInclude Include="Emu\SysCalls\lv2\SC_Memory.h" />
|
||||
<ClInclude Include="Emu\SysCalls\lv2\SC_Mutex.h" />
|
||||
<ClInclude Include="Emu\SysCalls\lv2\SC_Rwlock.h" />
|
||||
<ClInclude Include="Emu\SysCalls\lv2\SC_Semaphore.h" />
|
||||
<ClInclude Include="Emu\SysCalls\lv2\SC_Spinlock.h" />
|
||||
<ClInclude Include="Emu\SysCalls\lv2\SC_SPU_Thread.h" />
|
||||
<ClInclude Include="Emu\SysCalls\lv2\SC_Time.h" />
|
||||
|
|
|
@ -1048,5 +1048,8 @@
|
|||
<ClInclude Include="..\Utilities\SSemaphore.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\SysCalls\lv2\SC_Semaphore.h">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Add table
Reference in a new issue