1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-26 04:32:35 +01:00

SC_Rwlock implementation, SC_Lwcond draft

Other small changes
This commit is contained in:
Nekotekina 2014-01-30 00:31:09 +04:00
parent 4de64e5afe
commit 67a144df2a
11 changed files with 451 additions and 34 deletions

View File

@ -365,6 +365,8 @@ int cellPamfStreamTypeToEsFilterId(u8 type, u8 ch, mem_ptr_t<CellCodecEsFilterId
int cellPamfReaderGetStreamIndex(mem_ptr_t<CellPamfReader> pSelf)
{
cellPamf.Log("cellPamfReaderGetStreamIndex(pSelf=0x%x)", pSelf.GetAddr());
return pSelf->stream;
}
@ -506,7 +508,7 @@ int cellPamfReaderGetNumberOfEp(mem_ptr_t<CellPamfReader> pSelf)
int cellPamfReaderGetEpIteratorWithIndex(mem_ptr_t<CellPamfReader> pSelf, u32 epIndex, mem_ptr_t<CellPamfEpIterator> pIt)
{
cellPamf.Warning("cellPamfReaderGetEpIteratorWithIndex(pSelf=0x%x (stream=%d), epIndex=%d, pIt_addr=0x%x)",
cellPamf.Error("cellPamfReaderGetEpIteratorWithIndex(pSelf=0x%x (stream=%d), epIndex=%d, pIt_addr=0x%x)",
pSelf.GetAddr(), pSelf->stream, epIndex, pIt.GetAddr());
const mem_ptr_t<PamfHeader> pAddr(pSelf->pAddr);
@ -516,19 +518,25 @@ int cellPamfReaderGetEpIteratorWithIndex(mem_ptr_t<CellPamfReader> pSelf, u32 ep
int cellPamfReaderGetEpIteratorWithTimeStamp(mem_ptr_t<CellPamfReader> pSelf, mem_ptr_t<CellCodecTimeStamp> pTimeStamp, mem_ptr_t<CellPamfEpIterator> pIt)
{
UNIMPLEMENTED_FUNC(cellPamf);
cellPamf.Error("cellPamfReaderGetEpIteratorWithTimeStamp(pSelf=0x%x, pTimeStamp_addr=0x%x, pIt_addr=0x%x)",
pSelf.GetAddr(), pTimeStamp.GetAddr(), pIt.GetAddr());
const mem_ptr_t<PamfHeader> pAddr(pSelf->pAddr);
//TODO:
return CELL_OK;
}
int cellPamfEpIteratorGetEp(mem_ptr_t<CellPamfEpIterator> pIt, mem_ptr_t<CellPamfEp> pEp)
{
UNIMPLEMENTED_FUNC(cellPamf);
cellPamf.Error("cellPamfEpIteratorGetEp(pIt_addr=0x%x, pEp_addr=0x%x)", pIt.GetAddr(), pEp.GetAddr());
//TODO:
return CELL_OK;
}
int cellPamfEpIteratorMove(mem_ptr_t<CellPamfEpIterator> pIt, int steps, mem_ptr_t<CellPamfEp> pEp)
{
UNIMPLEMENTED_FUNC(cellPamf);
cellPamf.Error("cellPamfEpIteratorMove(pIt_addr=0x%x, steps=%d, pEp_addr=0x%x)", pIt.GetAddr(), steps, pEp.GetAddr());
//TODO:
return CELL_OK;
}

View File

@ -175,4 +175,11 @@ void sysPrxForUser_init()
sysPrxForUser.AddFunc(0x893305fa, sys_raw_spu_load);
sysPrxForUser.AddFunc(0xb995662e, sys_raw_spu_image_load);
sysPrxForUser.AddFunc(0xda0eb71a, sys_lwcond_create);
sysPrxForUser.AddFunc(0x1c9a942c, sys_lwcond_destroy);
sysPrxForUser.AddFunc(0xef87a695, sys_lwcond_signal);
sysPrxForUser.AddFunc(0xe9a1bd84, sys_lwcond_signal_all);
sysPrxForUser.AddFunc(0x52aadadf, sys_lwcond_signal_to);
sysPrxForUser.AddFunc(0x2a6d9d51, sys_lwcond_wait);
}

View File

@ -6,6 +6,7 @@
#include "lv2/SC_Rwlock.h"
#include "lv2/SC_SPU_Thread.h"
#include "lv2/SC_Lwmutex.h"
#include "lv2/SC_Lwcond.h"
#include "Emu/event.h"
//#define SYSCALLS_DEBUG
@ -147,6 +148,14 @@ 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);
//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);
extern int sys_lwcond_destroy(mem_ptr_t<sys_lwcond_t> lwcond);
extern int sys_lwcond_signal(mem_ptr_t<sys_lwcond_t> lwcond);
extern int sys_lwcond_signal_all(mem_ptr_t<sys_lwcond_t> lwcond);
extern int sys_lwcond_signal_to(mem_ptr_t<sys_lwcond_t> lwcond, u32 ppu_thread_id);
extern int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout);
//sys_lwmutex
extern int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_t> attr);
extern int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex);

View File

@ -0,0 +1,81 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "SC_Lwmutex.h"
#include "SC_Lwcond.h"
SysCallBase sys_lwcond("sys_lwcond");
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)
{
sys_lwcond.Warning("sys_lwcond_create(lwcond_addr=0x%x, lwmutex_addr=0x%x, attr_addr=0x%x)",
lwcond.GetAddr(), lwmutex.GetAddr(), attr.GetAddr());
if (!lwcond.IsGood() || !lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
lwcond->lwmutex_addr = lwmutex.GetAddr();
lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(*(u64*)&attr->name));
sys_lwcond.Warning("*** lwcond created [%s]", attr->name);
return CELL_OK;
}
int sys_lwcond_destroy(mem_ptr_t<sys_lwcond_t> lwcond)
{
sys_lwcond.Warning("sys_lwcond_destroy(lwcond_addr=0x%x)", lwcond.GetAddr());
if (!lwcond.IsGood()) return CELL_EFAULT;
LWCond* lwc;
u32 id = (u32)lwcond->lwcond_queue;
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
Emu.GetIdManager().RemoveID(id);
return CELL_OK;
}
int sys_lwcond_signal(mem_ptr_t<sys_lwcond_t> lwcond)
{
sys_lwcond.Warning("sys_lwcond_signal(lwcond_addr=0x%x)", lwcond.GetAddr());
if (!lwcond.IsGood()) return CELL_EFAULT;
LWCond* lwc;
u32 id = (u32)lwcond->lwcond_queue;
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
return CELL_OK;
}
int sys_lwcond_signal_all(mem_ptr_t<sys_lwcond_t> lwcond)
{
sys_lwcond.Warning("sys_lwcond_signal_all(lwcond_addr=0x%x)", lwcond.GetAddr());
if (!lwcond.IsGood()) return CELL_EFAULT;
LWCond* lwc;
u32 id = (u32)lwcond->lwcond_queue;
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
return CELL_OK;
}
int sys_lwcond_signal_to(mem_ptr_t<sys_lwcond_t> lwcond, u32 ppu_thread_id)
{
sys_lwcond.Warning("sys_lwcond_signal_to(lwcond_addr=0x%x, ppu_thread_id=%d)", lwcond.GetAddr(), ppu_thread_id);
if (!lwcond.IsGood()) return CELL_EFAULT;
LWCond* lwc;
u32 id = (u32)lwcond->lwcond_queue;
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
return CELL_OK;
}
int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout)
{
sys_lwcond.Warning("sys_lwcond_wait(lwcond_addr=0x%x, timeout=%llu)", lwcond.GetAddr(), timeout);
if (!lwcond.IsGood()) return CELL_EFAULT;
LWCond* lwc;
u32 id = (u32)lwcond->lwcond_queue;
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
return CELL_OK;
}

View File

@ -0,0 +1,24 @@
#pragma once
struct sys_lwcond_attribute_t
{
char name[8];
};
struct sys_lwcond_t
{
be_t<u32> lwmutex_addr;
be_t<u32> lwcond_queue;
};
#pragma pack()
struct LWCond
{
u64 m_name;
LWCond(u64 name)
: m_name(name)
{
}
};

View File

@ -23,10 +23,10 @@ int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_a
switch ((u32)attr->attr_protocol)
{
case SYS_SYNC_PRIORITY: break;
case SYS_SYNC_RETRY: sc_lwmutex.Error("TODO: SYS_SYNC_RETRY attr"); break;
case SYS_SYNC_PRIORITY_INHERIT: sc_lwmutex.Error("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
case SYS_SYNC_FIFO: sc_lwmutex.Error("TODO: SYS_SYNC_FIFO attr"); break;
case SYS_SYNC_PRIORITY: sc_lwmutex.Log("TODO: SYS_SYNC_PRIORITY attr"); break;
case SYS_SYNC_RETRY: sc_lwmutex.Warning("TODO: SYS_SYNC_RETRY attr"); break;
case SYS_SYNC_PRIORITY_INHERIT: sc_lwmutex.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
case SYS_SYNC_FIFO: sc_lwmutex.Log("TODO: SYS_SYNC_FIFO attr"); break;
default: return CELL_EINVAL;
}
@ -36,15 +36,31 @@ int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_a
lwmutex->recursive_count = 0;
lwmutex->sleep_queue = 0;
sc_lwmutex.Log("*** lwmutex created [%s] (protocol=0x%x, recursive=0x%x)",
attr->name, (u32)attr->attr_protocol, (u32)attr->attr_recursive);
sc_lwmutex.Log("*** lwmutex created [%s] (attribute=0x%x)", attr->name, (u32)lwmutex->attribute);
return CELL_OK;
}
int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex)
{
sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr());
sc_lwmutex.Log("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr());
if (!lwmutex.IsGood()) return CELL_EFAULT;
if (!lwmutex->attribute) return CELL_EINVAL;
{ // global lock
std::lock_guard<std::mutex> lock(g_lwmutex);
if (!lwmutex->owner)
{
lwmutex->attribute = 0;
}
else
{
return CELL_EBUSY;
}
}
return CELL_OK;
}
@ -55,6 +71,8 @@ int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
if (!lwmutex.IsGood()) return CELL_EFAULT;
if (!lwmutex->attribute) return CELL_EINVAL;
PPCThread& thr = GetCurrentPPUThread();
const u32 id = thr.GetId();
@ -91,6 +109,7 @@ int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
do // waiting
{
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
Sleep(1);
{ // global lock
@ -108,9 +127,9 @@ int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
if (counter++ > max_counter)
{
if (!timeout)
{ // endless waiter
sc_lwmutex.Error("sys_lwmutex_lock(lwmutex_addr=0x%x): TIMEOUT", lwmutex.GetAddr());
return CELL_OK;
{
sc_lwmutex.Warning("sys_lwmutex_lock(lwmutex_addr=0x%x): TIMEOUT", lwmutex.GetAddr());
counter = 0;
}
else
{
@ -126,6 +145,8 @@ int sys_lwmutex_trylock(mem_ptr_t<sys_lwmutex_t> lwmutex)
if (!lwmutex.IsGood()) return CELL_EFAULT;
if (!lwmutex->attribute) return CELL_EINVAL;
PPCThread& thr = GetCurrentPPUThread();
const u32 id = thr.GetId();

View File

@ -6,48 +6,169 @@ SysCallBase sys_rwlock("sys_rwlock");
int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t<sys_rwlock_attribute_t> attr)
{
sys_rwlock.Warning("Unimplemented function: sys_rwlock_create(rw_lock_id_addr=0x%x, attr_addr=0x%x)", rw_lock_id.GetAddr(), attr.GetAddr());
sys_rwlock.Warning("sys_rwlock_create(rw_lock_id_addr=0x%x, attr_addr=0x%x)", rw_lock_id.GetAddr(), attr.GetAddr());
if (!rw_lock_id.IsGood() || !attr.IsGood()) return CELL_EFAULT;
switch ((u32)attr->attr_protocol)
{
case SYS_SYNC_PRIORITY: sys_rwlock.Log("TODO: SYS_SYNC_PRIORITY attr"); break;
case SYS_SYNC_RETRY: sys_rwlock.Error("Invalid SYS_SYNC_RETRY attr"); break;
case SYS_SYNC_PRIORITY_INHERIT: sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
case SYS_SYNC_FIFO: break;
default: return CELL_EINVAL;
}
if ((u32)attr->attr_pshared != 0x200)
{
sys_rwlock.Error("Invalid attr_pshared(0x%x)", (u32)attr->attr_pshared);
return CELL_EINVAL;
}
rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, (u32)attr->attr_pshared,
(u64)attr->key, (s32)attr->flags, *(u64*)&attr->name));
sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x)", attr->name, (u32)attr->attr_protocol);
return CELL_OK;
}
int sys_rwlock_destroy(u32 rw_lock_id)
{
sys_rwlock.Warning("Unimplemented function: sys_rwlock_destroy(rw_lock_id=%d)", rw_lock_id);
sys_rwlock.Warning("sys_rwlock_destroy(rw_lock_id=%d)", rw_lock_id);
RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
std::lock_guard<std::mutex> lock(rw->m_lock);
if (rw->wlock_queue.GetCount() || rw->rlock_list.GetCount() || rw->wlock_thread) return CELL_EBUSY;
Emu.GetIdManager().RemoveID(rw_lock_id);
return CELL_OK;
}
int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
{
sys_rwlock.Warning("Unimplemented function: sys_rwlock_rlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout);
return CELL_OK;
sys_rwlock.Warning("sys_rwlock_rlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout);
RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
PPCThread& thr = GetCurrentPPUThread();
const u32 id = thr.GetId();
if (rw->rlock_trylock(id)) return CELL_OK;
u32 counter = 0;
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
do
{
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
Sleep(1);
if (rw->rlock_trylock(id)) return CELL_OK;
if (counter++ > max_counter)
{
if (!timeout)
{
sys_rwlock.Warning("sys_rwlock_rlock(rw_lock_id=%d): TIMEOUT", rw_lock_id);
counter = 0;
}
else
{
return CELL_ETIMEDOUT;
}
}
} while (true);
}
int sys_rwlock_tryrlock(u32 rw_lock_id)
{
sys_rwlock.Warning("Unimplemented function: sys_rwlock_tryrlock(rw_lock_id=%d)", rw_lock_id);
sys_rwlock.Warning("sys_rwlock_tryrlock(rw_lock_id=%d)", rw_lock_id);
RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
if (!rw->rlock_trylock(GetCurrentPPUThread().GetId())) return CELL_EBUSY;
return CELL_OK;
}
int sys_rwlock_runlock(u32 rw_lock_id)
{
sys_rwlock.Warning("Unimplemented function: sys_rwlock_runlock(rw_lock_id=%d)", rw_lock_id);
sys_rwlock.Warning("sys_rwlock_runlock(rw_lock_id=%d)", rw_lock_id);
RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
if (!rw->rlock_unlock(GetCurrentPPUThread().GetId())) return CELL_EPERM;
return CELL_OK;
}
int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout)
{
sys_rwlock.Warning("Unimplemented function: sys_rwlock_wlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout);
return CELL_OK;
sys_rwlock.Warning("sys_rwlock_wlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout);
RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
PPCThread& thr = GetCurrentPPUThread();
const u32 id = thr.GetId();
if (!rw->wlock_check(id)) return CELL_EDEADLK;
if (rw->wlock_trylock(id, true)) return CELL_OK;
u32 counter = 0;
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
do
{
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
Sleep(1);
if (rw->wlock_trylock(id, true)) return CELL_OK;
if (counter++ > max_counter)
{
if (!timeout)
{
sys_rwlock.Warning("sys_rwlock_wlock(rw_lock_id=%d): TIMEOUT", rw_lock_id);
counter = 0;
}
else
{
return CELL_ETIMEDOUT;
}
}
} while (true);
}
int sys_rwlock_trywlock(u32 rw_lock_id)
{
sys_rwlock.Warning("Unimplemented function: sys_rwlock_trywlock(rw_lock_id=%d)", rw_lock_id);
sys_rwlock.Warning("sys_rwlock_trywlock(rw_lock_id=%d)", rw_lock_id);
RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
PPCThread& thr = GetCurrentPPUThread();
const u32 id = thr.GetId();
if (!rw->wlock_check(id)) return CELL_EDEADLK;
if (!rw->wlock_trylock(id, false)) return CELL_EBUSY;
return CELL_OK;
}
int sys_rwlock_wunlock(u32 rw_lock_id)
{
sys_rwlock.Warning("Unimplemented function: sys_rwlock_wunlock(rw_lock_id=%d)", rw_lock_id);
sys_rwlock.Warning("sys_rwlock_wunlock(rw_lock_id=%d)", rw_lock_id);
RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
if (!rw->wlock_unlock(GetCurrentPPUThread().GetId())) return CELL_EPERM;
return CELL_OK;
}

View File

@ -2,11 +2,153 @@
struct sys_rwlock_attribute_t
{
u32 attr_protocol; //sys_protocol_t
u32 attr_pshared; //sys_process_shared_t
u64 key; //sys_ipc_key_t
s32 flags;
u8 name[8];
be_t<u32> attr_protocol;
be_t<u32> attr_pshared; // == 0x200 (NOT SHARED)
be_t<u64> key; // process-shared key (not used)
be_t<s32> flags; // process-shared flags (not used)
be_t<u32> pad;
char name[8];
};
#pragma pack()
struct RWLock
{
std::mutex m_lock; // internal lock
u32 wlock_thread; // write lock owner
Array<u32> wlock_queue; // write lock queue
Array<u32> rlock_list; // read lock list
u32 m_protocol; // TODO
u32 m_pshared; // not used
u64 m_key; // not used
s32 m_flags; // not used
union
{
u64 m_name_data; // not used
char m_name[8];
};
RWLock(u32 protocol, u32 pshared, u64 key, s32 flags, u64 name)
: m_protocol(protocol)
, m_pshared(pshared)
, m_key(key)
, m_flags(flags)
, m_name_data(name)
, wlock_thread(0)
{
}
bool rlock_trylock(u32 id)
{
std::lock_guard<std::mutex> lock(m_lock);
if (!wlock_thread && !wlock_queue.GetCount())
{
rlock_list.AddCpy(id);
return true;
}
return false;
}
bool rlock_unlock(u32 id)
{
std::lock_guard<std::mutex> lock(m_lock);
for (u32 i = rlock_list.GetCount() - 1; ~i; i--)
{
if (rlock_list[i] == id)
{
rlock_list.RemoveAt(i);
return true;
}
}
return false;
}
bool wlock_check(u32 id)
{
std::lock_guard<std::mutex> lock(m_lock);
if (wlock_thread == id)
{
return false; // deadlock
}
for (u32 i = rlock_list.GetCount() - 1; ~i; i--)
{
if (rlock_list[i] == id)
{
return false; // deadlock
}
}
return true;
}
bool wlock_trylock(u32 id, bool enqueue)
{
std::lock_guard<std::mutex> lock(m_lock);
if (wlock_thread || rlock_list.GetCount()) // already locked
{
if (!enqueue)
{
return false; // do not enqueue
}
for (u32 i = wlock_queue.GetCount() - 1; ~i; i--)
{
if (wlock_queue[i] == id)
{
return false; // already enqueued
}
}
wlock_queue.AddCpy(id); // enqueue new thread
return false;
}
else
{
if (wlock_queue.GetCount())
{
// SYNC_FIFO only yet
if (wlock_queue[0] == id)
{
wlock_thread = id;
wlock_queue.RemoveAt(0);
return true;
}
else
{
if (!enqueue)
{
return false; // do not enqueue
}
for (u32 i = wlock_queue.GetCount() - 1; ~i; i--)
{
if (wlock_queue[i] == id)
{
return false; // already enqueued
}
}
wlock_queue.AddCpy(id); // enqueue new thread
return false;
}
}
else
{
wlock_thread = id; // easy way
return true;
}
}
}
bool wlock_unlock(u32 id)
{
std::lock_guard<std::mutex> lock(m_lock);
if (wlock_thread == id)
{
wlock_thread = 0;
return true;
}
return false;
}
};

View File

@ -15,7 +15,7 @@ struct SpuGroupInfo
{
CPUThread* threads[g_spu_group_thr_count];
sys_spu_thread_group_attribute& attr;
volatile long lock;
std::atomic<u32> lock;
SpuGroupInfo(sys_spu_thread_group_attribute& attr) : attr(attr), lock(0)
{
@ -259,7 +259,7 @@ int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status)
return CELL_ESRCH;
}
if (_InterlockedCompareExchange(&group_info->lock, 1, 0)) //get lock
if (group_info->lock.exchange(1)) //get lock
{
return CELL_EBUSY;
}
@ -275,7 +275,7 @@ int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status)
}
}
_InterlockedExchange(&group_info->lock, 0); //release lock
group_info->lock = 0; //release lock
return CELL_OK;
}

View File

@ -249,6 +249,7 @@
<ClCompile Include="Emu\SysCalls\lv2\SC_GCM.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Heap.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Keyboard.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Lwcond.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Lwmutex.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Memory.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Mouse.cpp" />

View File

@ -370,6 +370,9 @@
<ClCompile Include="Emu\SysCalls\Modules\cellDmux.cpp">
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\lv2\SC_Lwcond.cpp">
<Filter>Emu\SysCalls\lv2</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="rpcs3.rc" />