Lv2 lwcond "true" syscalls

This commit is contained in:
Nekotekina 2015-03-10 17:42:08 +03:00
parent 3cf80b0831
commit befc0f62b8
27 changed files with 212 additions and 71 deletions

View file

@ -106,7 +106,7 @@ void CPUThreadManager::RemoveThread(u32 id)
}
// Removing the ID should trigger the actual deletion of the thread
Emu.GetIdManager().RemoveID(id);
Emu.GetIdManager().RemoveID<CPUThread>(id);
Emu.CheckStatus();
}

View file

@ -2,8 +2,6 @@
#define ID_MANAGER_INCLUDED
#define rID_ANY -1 // was wxID_ANY
enum IDType
{
// Special objects
@ -133,11 +131,13 @@ public:
Clear();
}
bool CheckID(const u32 id)
template<typename T> bool CheckID(const u32 id)
{
std::lock_guard<std::mutex> lock(m_mtx_main);
return m_id_map.find(id) != m_id_map.end();
auto f = m_id_map.find(id);
return f != m_id_map.end() && f->second.GetInfo() == typeid(T);
}
void Clear()
@ -148,12 +148,7 @@ public:
m_cur_id = s_first_id;
}
template<typename T
#ifdef __GNUG__
= char
#endif
>
u32 GetNewID(std::shared_ptr<T>& data = nullptr, const IDType type = TYPE_OTHER)
template<typename T> u32 GetNewID(std::shared_ptr<T>& data, const IDType type = TYPE_OTHER)
{
std::lock_guard<std::mutex> lock(m_mtx_main);
@ -172,12 +167,12 @@ public:
return m_id_map[id];
}
template<typename T>
bool GetIDData(const u32 id, std::shared_ptr<T>& result)
template<typename T> bool GetIDData(const u32 id, std::shared_ptr<T>& result)
{
std::lock_guard<std::mutex> lock(m_mtx_main);
auto f = m_id_map.find(id);
if (f == m_id_map.end() || f->second.GetInfo() != typeid(T)) {
return false;
}
@ -189,23 +184,18 @@ public:
bool HasID(const u32 id)
{
{
std::lock_guard<std::mutex> lock(m_mtx_main);
std::lock_guard<std::mutex> lock(m_mtx_main);
if(id == rID_ANY) {
return m_id_map.begin() != m_id_map.end();
}
}
return CheckID(id);
return m_id_map.find(id) != m_id_map.end();
}
bool RemoveID(const u32 id)
template<typename T> bool RemoveID(const u32 id)
{
std::lock_guard<std::mutex> lock(m_mtx_main);
auto item = m_id_map.find(id);
if (item == m_id_map.end()) {
if (item == m_id_map.end() || item->second.GetInfo() != typeid(T)) {
return false;
}
if (item->second.GetType() < TYPE_OTHER) {

View file

@ -571,7 +571,7 @@ int cellAdecClose(u32 handle)
}
if (adec->adecCb) Emu.GetCPU().RemoveThread(adec->adecCb->GetId());
Emu.GetIdManager().RemoveID(handle);
Emu.GetIdManager().RemoveID<AudioDecoder>(handle);
return CELL_OK;
}

View file

@ -710,7 +710,7 @@ u32 dmuxOpen(Demuxer* dmux_ptr)
}
}
es.dmux = nullptr;
Emu.GetIdManager().RemoveID(task.es.es);
Emu.GetIdManager().RemoveID<ElementaryStream>(task.es.es);
break;
}
@ -880,7 +880,7 @@ int cellDmuxClose(u32 demuxerHandle)
}
if (dmux->dmuxCb) Emu.GetCPU().RemoveThread(dmux->dmuxCb->GetId());
Emu.GetIdManager().RemoveID(demuxerHandle);
Emu.GetIdManager().RemoveID<Demuxer>(demuxerHandle);
return CELL_OK;
}

View file

@ -266,7 +266,7 @@ int cellGifDecClose(u32 mainHandle, u32 subHandle)
return CELL_GIFDEC_ERROR_FATAL;
cellFsClose(subHandle_data->fd);
Emu.GetIdManager().RemoveID(subHandle);
Emu.GetIdManager().RemoveID<CellGifDecSubHandle>(subHandle);
return CELL_OK;
}

View file

@ -75,7 +75,7 @@ int cellJpgDecClose(u32 mainHandle, u32 subHandle)
return CELL_JPGDEC_ERROR_FATAL;
cellFsClose(subHandle_data->fd);
Emu.GetIdManager().RemoveID(subHandle);
Emu.GetIdManager().RemoveID<CellJpgDecSubHandle>(subHandle);
return CELL_OK;
}

View file

@ -615,7 +615,7 @@ int cellVdecClose(u32 handle)
}
if (vdec->vdecCb) Emu.GetCPU().RemoveThread(vdec->vdecCb->GetId());
Emu.GetIdManager().RemoveID(handle);
Emu.GetIdManager().RemoveID<VideoDecoder>(handle);
return CELL_OK;
}

View file

@ -67,7 +67,7 @@ int cellVpostClose(u32 handle)
return CELL_VPOST_ERROR_C_ARG_HDL_INVALID;
}
Emu.GetIdManager().RemoveID(handle);
Emu.GetIdManager().RemoveID<VpostInstance>(handle);
return CELL_OK;
}

View file

@ -352,9 +352,9 @@ s32 sys_lwcond_create(vm::ptr<sys_lwcond_t> lwcond, vm::ptr<sys_lwmutex_t> lwmut
{
sysPrxForUser.Warning("sys_lwcond_create(lwcond=*0x%x, lwmutex=*0x%x, attr=*0x%x)", lwcond, lwmutex, attr);
std::shared_ptr<lwcond_t> lwc(new lwcond_t(attr->name_u64));
std::shared_ptr<lwcond_t> cond(new lwcond_t(attr->name_u64));
lwcond->lwcond_queue = Emu.GetIdManager().GetNewID(lwc, TYPE_LWCOND);
lwcond->lwcond_queue = Emu.GetIdManager().GetNewID(cond, TYPE_LWCOND);
lwcond->lwmutex = lwmutex;
return CELL_OK;
@ -368,7 +368,7 @@ s32 sys_lwcond_destroy(vm::ptr<sys_lwcond_t> lwcond)
if (res == CELL_OK)
{
lwcond->lwcond_queue = lwmutex::dead;
lwcond->lwcond_queue = lwmutex_dead;
}
return res;
@ -383,6 +383,7 @@ s32 sys_lwcond_signal(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond)
if ((lwmutex->attribute.data() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK)) == se32(SYS_SYNC_RETRY))
{
// TODO (protocol ignored)
//return _sys_lwcond_signal(lwcond->lwcond_queue, 0, -1, 2);
}
if (lwmutex->owner.read_relaxed() == CPU.GetId())
@ -440,6 +441,7 @@ s32 sys_lwcond_signal_all(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond)
if ((lwmutex->attribute.data() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK)) == se32(SYS_SYNC_RETRY))
{
// TODO (protocol ignored)
//return _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 2);
}
if (lwmutex->owner.read_relaxed() == CPU.GetId())
@ -496,6 +498,7 @@ s32 sys_lwcond_signal_to(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_t
if ((lwmutex->attribute.data() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK)) == se32(SYS_SYNC_RETRY))
{
// TODO (protocol ignored)
//return _sys_lwcond_signal(lwcond->lwcond_queue, 0, ppu_thread_id, 2);
}
if (lwmutex->owner.read_relaxed() == CPU.GetId())
@ -613,7 +616,7 @@ s32 sys_lwcond_wait(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
return CELL_ETIMEDOUT;
}
sysPrxForUser.Fatal("sys_lwconde_wait(lwcond=*0x%x): unexpected syscall result (0x%x)", lwcond, res);
sysPrxForUser.Fatal("sys_lwcond_wait(lwcond=*0x%x): unexpected syscall result (0x%x)", lwcond, res);
return res;
}

View file

@ -165,7 +165,7 @@ s32 cellFsClose(u32 fd)
{
sys_fs.Warning("cellFsClose(fd=0x%x)", fd);
if (!Emu.GetIdManager().RemoveID(fd))
if (!Emu.GetIdManager().RemoveID<vfsStream>(fd))
return CELL_ESRCH;
return CELL_OK;
@ -214,7 +214,7 @@ s32 cellFsClosedir(u32 fd)
{
sys_fs.Warning("cellFsClosedir(fd=0x%x)", fd);
if (!Emu.GetIdManager().RemoveID(fd))
if (!Emu.GetIdManager().RemoveID<vfsDirBase>(fd))
return CELL_ESRCH;
return CELL_OK;

View file

@ -125,7 +125,7 @@ u32 sleep_queue_t::signal(u32 protocol)
if (m_waiting.size())
{
res = m_waiting[0];
if (!Emu.GetIdManager().CheckID(res))
if (!Emu.GetIdManager().CheckID<CPUThread>(res))
{
LOG_ERROR(HLE, "sleep_queue_t['%s']::signal(SYS_SYNC_FIFO) failed: invalid thread (%d)", m_name.c_str(), res);
Emu.Pause();

View file

@ -67,7 +67,7 @@ s32 sys_cond_destroy(u32 cond_id)
throw __FUNCTION__;
}
Emu.GetIdManager().RemoveID(cond_id);
Emu.GetIdManager().RemoveID<cond_t>(cond_id);
return CELL_OK;
}
@ -130,7 +130,7 @@ s32 sys_cond_signal_to(u32 cond_id, u32 thread_id)
return CELL_ESRCH;
}
if (!Emu.GetIdManager().CheckID(thread_id))
if (!Emu.GetIdManager().CheckID<CPUThread>(thread_id))
{
return CELL_ESRCH;
}
@ -180,10 +180,16 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout)
while (!cond->mutex->owner.expired() || !cond->signaled)
{
if (!cond->signaled && timeout && get_system_time() - start_time > timeout)
const bool is_timedout = timeout && get_system_time() - start_time > timeout;
// check timeout only if no thread signaled (the flaw of avoiding sleep queue)
if (is_timedout && cond->mutex->owner.expired() && !cond->signaled)
{
// TODO: mutex not locked, timeout is possible only when signaled == 0
// 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);
return CELL_ETIMEDOUT;
}
@ -194,14 +200,13 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout)
}
// wait on appropriate condition variable
(cond->signaled ? 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));
}
// reown the mutex and restore recursive value
// reown the mutex and restore its recursive value
cond->mutex->owner = thread;
cond->mutex->recursive_count = recursive_value;
cond->signaled--; assert(cond->signaled >= 0);
cond->signaled--;
return CELL_OK;
}

View file

@ -20,10 +20,11 @@ struct cond_t
const u64 name;
const std::shared_ptr<mutex_t> mutex; // associated mutex
std::atomic<u32> signaled;
// TODO: use sleep queue, possibly remove condition variable
std::condition_variable cv;
std::atomic<s32> waiters;
std::atomic<s32> signaled;
cond_t(std::shared_ptr<mutex_t>& mutex, u64 name)
: mutex(mutex)

View file

@ -100,7 +100,7 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode)
}
Emu.GetEventManager().UnregisterKey(queue->key);
Emu.GetIdManager().RemoveID(equeue_id);
Emu.GetIdManager().RemoveID<event_queue_t>(equeue_id);
return CELL_OK;
}
@ -274,7 +274,7 @@ s32 sys_event_port_destroy(u32 eport_id)
return CELL_EISCONN;
}
Emu.GetIdManager().RemoveID(eport_id);
Emu.GetIdManager().RemoveID<event_port_t>(eport_id);
return CELL_OK;
}

View file

@ -79,7 +79,7 @@ s32 sys_event_flag_destroy(u32 id)
return CELL_EBUSY;
}
Emu.GetIdManager().RemoveID(id);
Emu.GetIdManager().RemoveID<event_flag_t>(id);
return CELL_OK;
}

View file

@ -15,18 +15,18 @@ SysCallBase sys_lwcond("sys_lwcond");
void lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name)
{
std::shared_ptr<lwcond_t> lwc(new lwcond_t(name));
std::shared_ptr<lwcond_t> cond(new lwcond_t(name));
lwcond.lwcond_queue = Emu.GetIdManager().GetNewID(lwc, TYPE_LWCOND);
lwcond.lwcond_queue = Emu.GetIdManager().GetNewID(cond, TYPE_LWCOND);
}
s32 _sys_lwcond_create(vm::ptr<u32> lwcond_id, u32 lwmutex_id, vm::ptr<sys_lwcond_t> control, u64 name, u32 arg5)
{
sys_lwcond.Warning("_sys_lwcond_create(lwcond_id=*0x%x, lwmutex_id=%d, control=*0x%x, name=0x%llx, arg5=0x%x)", lwcond_id, lwmutex_id, control, name, arg5);
std::shared_ptr<lwcond_t> lwc(new lwcond_t(name));
std::shared_ptr<lwcond_t> cond(new lwcond_t(name));
*lwcond_id = Emu.GetIdManager().GetNewID(lwc, TYPE_LWCOND);
*lwcond_id = Emu.GetIdManager().GetNewID(cond, TYPE_LWCOND);
return CELL_OK;
}
@ -37,39 +37,177 @@ s32 _sys_lwcond_destroy(u32 lwcond_id)
LV2_LOCK;
std::shared_ptr<lwcond_t> lwc;
if (!Emu.GetIdManager().GetIDData(lwcond_id, lwc))
std::shared_ptr<lwcond_t> cond;
if (!Emu.GetIdManager().GetIDData(lwcond_id, cond))
{
return CELL_ESRCH;
}
if (lwc->waiters)
if (cond->waiters)
{
return CELL_EBUSY;
}
Emu.GetIdManager().RemoveID(lwcond_id);
Emu.GetIdManager().RemoveID<lwcond_t>(lwcond_id);
return CELL_OK;
}
s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mode)
{
sys_lwcond.Fatal("_sys_lwcond_signal(lwcond_id=%d, lwmutex_id=%d, ppu_thread_id=%d, mode=%d)", lwcond_id, lwmutex_id, ppu_thread_id, mode);
sys_lwcond.Log("_sys_lwcond_signal(lwcond_id=%d, lwmutex_id=%d, ppu_thread_id=%d, mode=%d)", lwcond_id, lwmutex_id, ppu_thread_id, mode);
LV2_LOCK;
std::shared_ptr<lwcond_t> cond;
if (!Emu.GetIdManager().GetIDData(lwcond_id, cond))
{
return CELL_ESRCH;
}
// lwmutex_id, ppu_thread_id are ignored in current implementation
if (mode != 1 && mode != 2 && mode != 3)
{
sys_lwcond.Error("_sys_lwcond_signal(%d): invalid mode (%d)", lwcond_id, mode);
}
if (~ppu_thread_id)
{
sys_lwcond.Todo("_sys_lwcond_signal(%d): ppu_thread_id (%d)", lwcond_id, ppu_thread_id);
}
if (mode == 1)
{
// mode 1: lightweight mutex was initially owned by the calling thread
if (!cond->waiters)
{
return CELL_EPERM;
}
cond->signaled1++;
}
else if (mode == 2)
{
// mode 2: lightweight mutex was not owned by the calling thread and waiter hasn't been increased
if (!cond->waiters)
{
return CELL_OK;
}
cond->signaled2++;
}
else
{
// in mode 3, lightweight mutex was forcefully owned by the calling thread
if (!cond->waiters)
{
return ~ppu_thread_id ? CELL_ENOENT : CELL_EPERM;
}
cond->signaled1++;
}
cond->waiters--;
cond->cv.notify_one();
return CELL_OK;
}
s32 _sys_lwcond_signal_all(u32 lwcond_id, u32 lwmutex_id, u32 mode)
{
sys_lwcond.Fatal("_sys_lwcond_signal_all(lwcond_id=%d, lwmutex_id=%d, mode=%d)", lwcond_id, lwmutex_id, mode);
sys_lwcond.Log("_sys_lwcond_signal_all(lwcond_id=%d, lwmutex_id=%d, mode=%d)", lwcond_id, lwmutex_id, mode);
return CELL_OK;
LV2_LOCK;
std::shared_ptr<lwcond_t> cond;
if (!Emu.GetIdManager().GetIDData(lwcond_id, cond))
{
return CELL_ESRCH;
}
// lwmutex_id is ignored in current implementation
if (mode != 1 && mode != 2)
{
sys_lwcond.Error("_sys_lwcond_signal_all(%d): invalid mode (%d)", lwcond_id, mode);
}
const s32 count = cond->waiters.exchange(0);
cond->cv.notify_all();
if (mode == 1)
{
// in mode 1, lightweight mutex was initially owned by the calling thread
cond->signaled1 += count;
return count;
}
else
{
// in mode 2, lightweight mutex was not owned by the calling thread and waiter hasn't been increased
cond->signaled2 += count;
return CELL_OK;
}
}
s32 _sys_lwcond_queue_wait(u32 lwcond_id, u32 lwmutex_id, u64 timeout)
{
sys_lwcond.Fatal("_sys_lwcond_queue_wait(lwcond_id=%d, lwmutex_id=%d, timeout=0x%llx)", lwcond_id, lwmutex_id, timeout);
sys_lwcond.Log("_sys_lwcond_queue_wait(lwcond_id=%d, lwmutex_id=%d, timeout=0x%llx)", lwcond_id, lwmutex_id, timeout);
return CELL_OK;
const u64 start_time = get_system_time();
LV2_LOCK;
std::shared_ptr<lwcond_t> cond;
if (!Emu.GetIdManager().GetIDData(lwcond_id, cond))
{
return CELL_ESRCH;
}
// lwmutex_id, protocol are ignored in current implementation
cond->waiters++; assert(cond->waiters > 0);
while (!cond->signaled1 && !cond->signaled2)
{
const bool is_timedout = timeout && get_system_time() - start_time > timeout;
// check timeout (TODO)
if (is_timedout)
{
sys_lwcond.Fatal("_sys_lwcond_queue_wait(%d): TIMED OUT", lwcond_id);
// cancel waiting
cond->waiters--; assert(cond->waiters >= 0);
return CELL_ETIMEDOUT;
}
if (Emu.IsStopped())
{
sys_lwcond.Warning("_sys_lwcond_queue_wait(lwcond_id=%d) aborted", lwcond_id);
return CELL_OK;
}
cond->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
}
if (cond->signaled1)
{
cond->signaled1--;
return CELL_OK;
}
else
{
cond->signaled2--;
return CELL_EBUSY;
}
}

View file

@ -21,6 +21,9 @@ struct lwcond_t
{
const u64 name;
std::atomic<u32> signaled1; // mode 1 signals
std::atomic<u32> signaled2; // mode 2 signals
// TODO: use sleep queue
std::condition_variable cv;
std::atomic<s32> waiters;

View file

@ -63,7 +63,7 @@ s32 _sys_lwmutex_destroy(u32 lwmutex_id)
return CELL_EBUSY;
}
Emu.GetIdManager().RemoveID(lwmutex_id);
Emu.GetIdManager().RemoveID<lwmutex_t>(lwmutex_id);
return CELL_OK;
}

View file

@ -141,7 +141,7 @@ s32 sys_memory_container_destroy(u32 cid)
// Release the allocated memory and remove the ID.
Memory.Free(ct->addr);
Emu.GetIdManager().RemoveID(cid);
Emu.GetIdManager().RemoveID<MemoryContainerInfo>(cid);
return CELL_OK;
}

View file

@ -78,7 +78,7 @@ s32 sys_mmapper_allocate_memory(u32 size, u64 flags, vm::ptr<u32> mem_id)
// Generate a new mem ID.
std::shared_ptr<mmapper_info> info(new mmapper_info(size, flags));
*mem_id = Emu.GetIdManager().GetNewID(info);
*mem_id = Emu.GetIdManager().GetNewID(info, TYPE_MEM);
return CELL_OK;
}
@ -147,7 +147,7 @@ s32 sys_mmapper_free_memory(u32 mem_id)
return CELL_ESRCH;
// Release the allocated memory and remove the ID.
Emu.GetIdManager().RemoveID(mem_id);
Emu.GetIdManager().RemoveID<mmapper_info>(mem_id);
return CELL_OK;
}

View file

@ -79,7 +79,7 @@ s32 sys_mutex_destroy(u32 mutex_id)
return CELL_EPERM;
}
Emu.GetIdManager().RemoveID(mutex_id);
Emu.GetIdManager().RemoveID<mutex_t>(mutex_id);
return CELL_OK;
}

View file

@ -101,7 +101,7 @@ s32 sys_prx_unload_module(s32 id, u64 flags, vm::ptr<sys_prx_unload_module_optio
if (!Emu.GetIdManager().GetIDData(id, prx))
return CELL_ESRCH;
Memory.Free(prx->address);
Emu.GetIdManager().RemoveID(id);
Emu.GetIdManager().RemoveID<sys_prx_t>(id);
return CELL_OK;
}

View file

@ -60,7 +60,7 @@ s32 sys_rwlock_destroy(u32 rw_lock_id)
return CELL_EBUSY;
}
Emu.GetIdManager().RemoveID(rw_lock_id);
Emu.GetIdManager().RemoveID<rwlock_t>(rw_lock_id);
return CELL_OK;
}

View file

@ -72,7 +72,7 @@ s32 sys_semaphore_destroy(u32 sem)
return CELL_EBUSY;
}
Emu.GetIdManager().RemoveID(sem);
Emu.GetIdManager().RemoveID<semaphore_t>(sem);
return CELL_OK;
}

View file

@ -272,7 +272,7 @@ s32 sys_spu_thread_group_destroy(u32 id)
}
group->state = SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED; // hack
Emu.GetIdManager().RemoveID(id);
Emu.GetIdManager().RemoveID<spu_group_t>(id);
return CELL_OK;
}

View file

@ -74,7 +74,7 @@ s32 sys_timer_destroy(u32 timer_id)
return CELL_EISCONN;
}
Emu.GetIdManager().RemoveID(timer_id);
Emu.GetIdManager().RemoveID<lv2_timer_t>(timer_id);
return CELL_OK;
}

View file

@ -15,6 +15,7 @@ struct sys_timer_information_t
be_t<u32> pad;
};
// "timer_t" conflicts with some definition
struct lv2_timer_t
{
std::weak_ptr<event_queue_t> port; // event queue