mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-16 07:20:59 +00:00
IPC support for lv2 sync objects
This commit is contained in:
parent
60c6bb9865
commit
bf53035e3f
@ -2,6 +2,7 @@
|
|||||||
#include "Emu/Memory/Memory.h"
|
#include "Emu/Memory/Memory.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
|
#include "Emu/IPC.h"
|
||||||
|
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
#include "Emu/Cell/PPUThread.h"
|
#include "Emu/Cell/PPUThread.h"
|
||||||
@ -12,18 +13,14 @@ namespace vm { using namespace ps3; }
|
|||||||
|
|
||||||
logs::channel sys_cond("sys_cond");
|
logs::channel sys_cond("sys_cond");
|
||||||
|
|
||||||
|
template<> DECLARE(ipc_manager<lv2_cond, u64>::g_ipc) {};
|
||||||
|
|
||||||
extern u64 get_system_time();
|
extern u64 get_system_time();
|
||||||
|
|
||||||
error_code sys_cond_create(vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribute_t> attr)
|
error_code sys_cond_create(vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribute_t> attr)
|
||||||
{
|
{
|
||||||
sys_cond.warning("sys_cond_create(cond_id=*0x%x, mutex_id=0x%x, attr=*0x%x)", cond_id, mutex_id, attr);
|
sys_cond.warning("sys_cond_create(cond_id=*0x%x, mutex_id=0x%x, attr=*0x%x)", cond_id, mutex_id, attr);
|
||||||
|
|
||||||
if (attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->ipc_key || attr->flags)
|
|
||||||
{
|
|
||||||
sys_cond.error("sys_cond_create(): unknown attributes (pshared=0x%x, ipc_key=0x%llx, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags);
|
|
||||||
return CELL_EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto mutex = idm::get<lv2_obj, lv2_mutex>(mutex_id);
|
auto mutex = idm::get<lv2_obj, lv2_mutex>(mutex_id);
|
||||||
|
|
||||||
if (!mutex)
|
if (!mutex)
|
||||||
@ -31,13 +28,21 @@ error_code sys_cond_create(vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_
|
|||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const u32 id = idm::make<lv2_obj, lv2_cond>(attr->name_u64, std::move(mutex)))
|
if (auto error = lv2_obj::create<lv2_cond>(attr->pshared, attr->ipc_key, attr->flags, [&]
|
||||||
{
|
{
|
||||||
*cond_id = id;
|
return std::make_shared<lv2_cond>(
|
||||||
return CELL_OK;
|
attr->pshared,
|
||||||
|
attr->flags,
|
||||||
|
attr->ipc_key,
|
||||||
|
attr->name_u64,
|
||||||
|
std::move(mutex));
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CELL_EAGAIN;
|
*cond_id = idm::last_id();
|
||||||
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sys_cond_destroy(u32 cond_id)
|
error_code sys_cond_destroy(u32 cond_id)
|
||||||
@ -51,7 +56,6 @@ error_code sys_cond_destroy(u32 cond_id)
|
|||||||
return CELL_EBUSY;
|
return CELL_EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
cond.mutex->cond_count--;
|
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -30,15 +30,20 @@ struct lv2_cond final : lv2_obj
|
|||||||
atomic_t<u32> waiters{0};
|
atomic_t<u32> waiters{0};
|
||||||
std::deque<cpu_thread*> sq;
|
std::deque<cpu_thread*> sq;
|
||||||
|
|
||||||
lv2_cond(u64 name, std::shared_ptr<lv2_mutex> mutex)
|
lv2_cond(u32 shared, s32 flags, u64 key, u64 name, std::shared_ptr<lv2_mutex> mutex)
|
||||||
: shared(0)
|
: shared(shared)
|
||||||
, key(0)
|
, key(key)
|
||||||
, flags(0)
|
, flags(flags)
|
||||||
, name(name)
|
, name(name)
|
||||||
, mutex(std::move(mutex))
|
, mutex(std::move(mutex))
|
||||||
{
|
{
|
||||||
this->mutex->cond_count++;
|
this->mutex->cond_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~lv2_cond()
|
||||||
|
{
|
||||||
|
this->mutex->cond_count--;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ppu_thread;
|
class ppu_thread;
|
||||||
|
@ -99,10 +99,12 @@ error_code sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queu
|
|||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto queue = std::make_shared<lv2_event_queue>(protocol, type, attr->name_u64, event_queue_key, size);
|
||||||
|
|
||||||
if (event_queue_key == SYS_EVENT_QUEUE_LOCAL)
|
if (event_queue_key == SYS_EVENT_QUEUE_LOCAL)
|
||||||
{
|
{
|
||||||
// Not an IPC queue
|
// Not an IPC queue
|
||||||
if (const u32 _id = idm::make<lv2_obj, lv2_event_queue>(protocol, type, attr->name_u64, event_queue_key, size))
|
if (const u32 _id = idm::import_existing<lv2_obj, lv2_event_queue>(std::move(queue)))
|
||||||
{
|
{
|
||||||
*equeue_id = _id;
|
*equeue_id = _id;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
@ -111,25 +113,27 @@ error_code sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queu
|
|||||||
return CELL_EAGAIN;
|
return CELL_EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<lv2_event_queue> result;
|
|
||||||
|
|
||||||
// Create IPC queue
|
// Create IPC queue
|
||||||
if (!ipc_manager<lv2_event_queue, u64>::add(event_queue_key, [&]() -> const std::shared_ptr<lv2_event_queue>&
|
if (!ipc_manager<lv2_event_queue, u64>::add(event_queue_key, [&]() -> std::shared_ptr<lv2_event_queue>
|
||||||
{
|
{
|
||||||
result = idm::make_ptr<lv2_obj, lv2_event_queue>(protocol, type, attr->name_u64, event_queue_key, size);
|
if (const u32 _id = idm::import_existing<lv2_obj, lv2_event_queue>(queue))
|
||||||
return result;
|
{
|
||||||
|
*equeue_id = _id;
|
||||||
|
return std::move(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
return CELL_EEXIST;
|
return CELL_EEXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
if (queue)
|
||||||
{
|
{
|
||||||
*equeue_id = idm::last_id();
|
return CELL_EAGAIN;
|
||||||
return CELL_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return CELL_EAGAIN;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
|
error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "Emu/Memory/Memory.h"
|
#include "Emu/Memory/Memory.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
|
#include "Emu/IPC.h"
|
||||||
|
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
#include "Emu/Cell/PPUThread.h"
|
#include "Emu/Cell/PPUThread.h"
|
||||||
@ -13,6 +14,8 @@ namespace vm { using namespace ps3; }
|
|||||||
|
|
||||||
logs::channel sys_event_flag("sys_event_flag");
|
logs::channel sys_event_flag("sys_event_flag");
|
||||||
|
|
||||||
|
template<> DECLARE(ipc_manager<lv2_event_flag, u64>::g_ipc) {};
|
||||||
|
|
||||||
extern u64 get_system_time();
|
extern u64 get_system_time();
|
||||||
|
|
||||||
error_code sys_event_flag_create(vm::ptr<u32> id, vm::ptr<sys_event_flag_attribute_t> attr, u64 init)
|
error_code sys_event_flag_create(vm::ptr<u32> id, vm::ptr<sys_event_flag_attribute_t> attr, u64 init)
|
||||||
@ -37,12 +40,6 @@ error_code sys_event_flag_create(vm::ptr<u32> id, vm::ptr<sys_event_flag_attribu
|
|||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->ipc_key || attr->flags)
|
|
||||||
{
|
|
||||||
sys_event_flag.error("sys_event_flag_create(): unknown attributes (pshared=0x%x, ipc_key=0x%llx, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags);
|
|
||||||
return CELL_EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 type = attr->type;
|
const u32 type = attr->type;
|
||||||
|
|
||||||
if (type != SYS_SYNC_WAITER_SINGLE && type != SYS_SYNC_WAITER_MULTIPLE)
|
if (type != SYS_SYNC_WAITER_SINGLE && type != SYS_SYNC_WAITER_MULTIPLE)
|
||||||
@ -51,13 +48,23 @@ error_code sys_event_flag_create(vm::ptr<u32> id, vm::ptr<sys_event_flag_attribu
|
|||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const u32 _id = idm::make<lv2_obj, lv2_event_flag>(protocol, type, attr->name_u64, init))
|
if (auto error = lv2_obj::create<lv2_event_flag>(attr->pshared, attr->ipc_key, attr->flags, [&]
|
||||||
{
|
{
|
||||||
*id = _id;
|
return std::make_shared<lv2_event_flag>(
|
||||||
return CELL_OK;
|
attr->protocol,
|
||||||
|
attr->pshared,
|
||||||
|
attr->ipc_key,
|
||||||
|
attr->flags,
|
||||||
|
attr->type,
|
||||||
|
attr->name_u64,
|
||||||
|
init);
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CELL_EAGAIN;
|
*id = idm::last_id();
|
||||||
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sys_event_flag_destroy(u32 id)
|
error_code sys_event_flag_destroy(u32 id)
|
||||||
|
@ -45,11 +45,11 @@ struct lv2_event_flag final : lv2_obj
|
|||||||
atomic_t<u64> pattern;
|
atomic_t<u64> pattern;
|
||||||
std::deque<cpu_thread*> sq;
|
std::deque<cpu_thread*> sq;
|
||||||
|
|
||||||
lv2_event_flag(u32 protocol, s32 type, u64 name, u64 pattern)
|
lv2_event_flag(u32 protocol, u32 shared, u64 key, s32 flags, s32 type, u64 name, u64 pattern)
|
||||||
: protocol(protocol)
|
: protocol(protocol)
|
||||||
, shared(0)
|
, shared(shared)
|
||||||
, key(0)
|
, key(key)
|
||||||
, flags(0)
|
, flags(flags)
|
||||||
, type(type)
|
, type(type)
|
||||||
, name(name)
|
, name(name)
|
||||||
, pattern(pattern)
|
, pattern(pattern)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "Emu/Memory/Memory.h"
|
#include "Emu/Memory/Memory.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
|
#include "Emu/IPC.h"
|
||||||
|
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
#include "Emu/Cell/PPUThread.h"
|
#include "Emu/Cell/PPUThread.h"
|
||||||
@ -11,6 +12,8 @@ namespace vm { using namespace ps3; }
|
|||||||
|
|
||||||
logs::channel sys_mutex("sys_mutex");
|
logs::channel sys_mutex("sys_mutex");
|
||||||
|
|
||||||
|
template<> DECLARE(ipc_manager<lv2_mutex, u64>::g_ipc) {};
|
||||||
|
|
||||||
extern u64 get_system_time();
|
extern u64 get_system_time();
|
||||||
|
|
||||||
error_code sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t> attr)
|
error_code sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t> attr)
|
||||||
@ -22,48 +25,53 @@ error_code sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t
|
|||||||
return CELL_EFAULT;
|
return CELL_EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 protocol = attr->protocol;
|
switch (attr->protocol)
|
||||||
|
|
||||||
switch (protocol)
|
|
||||||
{
|
{
|
||||||
case SYS_SYNC_FIFO: break;
|
case SYS_SYNC_FIFO: break;
|
||||||
case SYS_SYNC_PRIORITY: break;
|
case SYS_SYNC_PRIORITY: break;
|
||||||
case SYS_SYNC_PRIORITY_INHERIT:
|
case SYS_SYNC_PRIORITY_INHERIT:
|
||||||
sys_mutex.todo("sys_mutex_create(): SYS_SYNC_PRIORITY_INHERIT");
|
sys_mutex.fatal("sys_mutex_create(): SYS_SYNC_PRIORITY_INHERIT");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
sys_mutex.error("sys_mutex_create(): unknown protocol (0x%x)", protocol);
|
sys_mutex.error("sys_mutex_create(): unknown protocol (0x%x)", attr->protocol);
|
||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 recursive = attr->recursive;
|
switch (attr->recursive)
|
||||||
|
|
||||||
switch (recursive)
|
|
||||||
{
|
{
|
||||||
case SYS_SYNC_RECURSIVE: break;
|
case SYS_SYNC_RECURSIVE: break;
|
||||||
case SYS_SYNC_NOT_RECURSIVE: break;
|
case SYS_SYNC_NOT_RECURSIVE: break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
sys_mutex.error("sys_mutex_create(): unknown recursive (0x%x)", recursive);
|
sys_mutex.error("sys_mutex_create(): unknown recursive (0x%x)", attr->recursive);
|
||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->adaptive != SYS_SYNC_NOT_ADAPTIVE || attr->ipc_key || attr->flags)
|
if (attr->adaptive != SYS_SYNC_NOT_ADAPTIVE)
|
||||||
{
|
{
|
||||||
sys_mutex.error("sys_mutex_create(): unknown attributes (pshared=0x%x, adaptive=0x%x, ipc_key=0x%llx, flags=0x%x)", attr->pshared, attr->adaptive, attr->ipc_key, attr->flags);
|
sys_mutex.todo("sys_mutex_create(): unexpected adaptive (0x%x)", attr->adaptive);
|
||||||
return CELL_EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const u32 id = idm::make<lv2_obj, lv2_mutex>(protocol, recursive, attr->name_u64))
|
if (auto error = lv2_obj::create<lv2_mutex>(attr->pshared, attr->ipc_key, attr->flags, [&]()
|
||||||
{
|
{
|
||||||
*mutex_id = id;
|
return std::make_shared<lv2_mutex>(
|
||||||
return CELL_OK;
|
attr->protocol,
|
||||||
|
attr->recursive,
|
||||||
|
attr->pshared,
|
||||||
|
attr->adaptive,
|
||||||
|
attr->ipc_key,
|
||||||
|
attr->flags,
|
||||||
|
attr->name_u64);
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CELL_EAGAIN;
|
*mutex_id = idm::last_id();
|
||||||
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sys_mutex_destroy(u32 mutex_id)
|
error_code sys_mutex_destroy(u32 mutex_id)
|
||||||
|
@ -37,13 +37,13 @@ struct lv2_mutex final : lv2_obj
|
|||||||
atomic_t<u32> cond_count{0}; // Condition Variables
|
atomic_t<u32> cond_count{0}; // Condition Variables
|
||||||
std::deque<cpu_thread*> sq;
|
std::deque<cpu_thread*> sq;
|
||||||
|
|
||||||
lv2_mutex(u32 protocol, u32 recursive, u64 name)
|
lv2_mutex(u32 protocol, u32 recursive, u32 shared, u32 adaptive, u64 key, s32 flags, u64 name)
|
||||||
: protocol(protocol)
|
: protocol(protocol)
|
||||||
, recursive(recursive)
|
, recursive(recursive)
|
||||||
, shared(0)
|
, shared(shared)
|
||||||
, adaptive(0)
|
, adaptive(adaptive)
|
||||||
, key(0)
|
, key(key)
|
||||||
, flags(0)
|
, flags(flags)
|
||||||
, name(name)
|
, name(name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "Emu/Memory/Memory.h"
|
#include "Emu/Memory/Memory.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
|
#include "Emu/IPC.h"
|
||||||
|
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
#include "Emu/Cell/PPUThread.h"
|
#include "Emu/Cell/PPUThread.h"
|
||||||
@ -11,6 +12,8 @@ namespace vm { using namespace ps3; }
|
|||||||
|
|
||||||
logs::channel sys_rwlock("sys_rwlock");
|
logs::channel sys_rwlock("sys_rwlock");
|
||||||
|
|
||||||
|
template<> DECLARE(ipc_manager<lv2_rwlock, u64>::g_ipc) {};
|
||||||
|
|
||||||
extern u64 get_system_time();
|
extern u64 get_system_time();
|
||||||
|
|
||||||
error_code sys_rwlock_create(vm::ptr<u32> rw_lock_id, vm::ptr<sys_rwlock_attribute_t> attr)
|
error_code sys_rwlock_create(vm::ptr<u32> rw_lock_id, vm::ptr<sys_rwlock_attribute_t> attr)
|
||||||
@ -33,19 +36,16 @@ error_code sys_rwlock_create(vm::ptr<u32> rw_lock_id, vm::ptr<sys_rwlock_attribu
|
|||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->ipc_key || attr->flags)
|
if (auto error = lv2_obj::create<lv2_rwlock>(attr->pshared, attr->ipc_key, attr->flags, [&]
|
||||||
{
|
{
|
||||||
sys_rwlock.error("sys_rwlock_create(): unknown attributes (pshared=0x%x, ipc_key=0x%llx, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags);
|
return std::make_shared<lv2_rwlock>(protocol, attr->pshared, attr->ipc_key, attr->flags, attr->name_u64);
|
||||||
return CELL_EINVAL;
|
}))
|
||||||
|
{
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const u32 id = idm::make<lv2_obj, lv2_rwlock>(protocol, attr->name_u64))
|
*rw_lock_id = idm::last_id();
|
||||||
{
|
return CELL_OK;
|
||||||
*rw_lock_id = id;
|
|
||||||
return CELL_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CELL_EAGAIN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sys_rwlock_destroy(u32 rw_lock_id)
|
error_code sys_rwlock_destroy(u32 rw_lock_id)
|
||||||
|
@ -32,11 +32,11 @@ struct lv2_rwlock final : lv2_obj
|
|||||||
std::deque<cpu_thread*> rq;
|
std::deque<cpu_thread*> rq;
|
||||||
std::deque<cpu_thread*> wq;
|
std::deque<cpu_thread*> wq;
|
||||||
|
|
||||||
lv2_rwlock(u32 protocol, u64 name)
|
lv2_rwlock(u32 protocol, u32 shared, u64 key, s32 flags, u64 name)
|
||||||
: protocol(protocol)
|
: protocol(protocol)
|
||||||
, shared(0)
|
, shared(shared)
|
||||||
, key(0)
|
, key(key)
|
||||||
, flags(0)
|
, flags(flags)
|
||||||
, name(name)
|
, name(name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "Emu/Memory/Memory.h"
|
#include "Emu/Memory/Memory.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
|
#include "Emu/IPC.h"
|
||||||
|
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
#include "Emu/Cell/PPUThread.h"
|
#include "Emu/Cell/PPUThread.h"
|
||||||
@ -11,6 +12,8 @@ namespace vm { using namespace ps3; }
|
|||||||
|
|
||||||
logs::channel sys_semaphore("sys_semaphore");
|
logs::channel sys_semaphore("sys_semaphore");
|
||||||
|
|
||||||
|
template<> DECLARE(ipc_manager<lv2_sema, u64>::g_ipc) {};
|
||||||
|
|
||||||
extern u64 get_system_time();
|
extern u64 get_system_time();
|
||||||
|
|
||||||
error_code sys_semaphore_create(vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val)
|
error_code sys_semaphore_create(vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val)
|
||||||
@ -39,19 +42,16 @@ error_code sys_semaphore_create(vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attri
|
|||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->ipc_key || attr->flags)
|
if (auto error = lv2_obj::create<lv2_sema>(attr->pshared, attr->ipc_key, attr->flags, [&]
|
||||||
{
|
{
|
||||||
sys_semaphore.error("sys_semaphore_create(): unknown attributes (pshared=0x%x, ipc_key=0x%x, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags);
|
return std::make_shared<lv2_sema>(protocol, attr->pshared, attr->ipc_key, attr->flags, attr->name_u64, max_val, initial_val);
|
||||||
return CELL_EINVAL;
|
}))
|
||||||
|
{
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const u32 id = idm::make<lv2_obj, lv2_sema>(protocol, attr->name_u64, max_val, initial_val))
|
*sem_id = idm::last_id();
|
||||||
{
|
return CELL_OK;
|
||||||
*sem_id = id;
|
|
||||||
return CELL_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CELL_EAGAIN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sys_semaphore_destroy(u32 sem_id)
|
error_code sys_semaphore_destroy(u32 sem_id)
|
||||||
|
@ -32,11 +32,11 @@ struct lv2_sema final : lv2_obj
|
|||||||
atomic_t<s32> val;
|
atomic_t<s32> val;
|
||||||
std::deque<cpu_thread*> sq;
|
std::deque<cpu_thread*> sq;
|
||||||
|
|
||||||
lv2_sema(u32 protocol, u64 name, s32 max, s32 value)
|
lv2_sema(u32 protocol, u32 shared, u64 key, s32 flags, u64 name, s32 max, s32 value)
|
||||||
: protocol(protocol)
|
: protocol(protocol)
|
||||||
, shared(0)
|
, shared(shared)
|
||||||
, key(0)
|
, key(key)
|
||||||
, flags(0)
|
, flags(flags)
|
||||||
, name(name)
|
, name(name)
|
||||||
, max(max)
|
, max(max)
|
||||||
, val(value)
|
, val(value)
|
||||||
|
@ -7,46 +7,52 @@
|
|||||||
#include "Emu/Memory/vm.h"
|
#include "Emu/Memory/vm.h"
|
||||||
#include "Emu/CPU/CPUThread.h"
|
#include "Emu/CPU/CPUThread.h"
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
|
#include "Emu/IdManager.h"
|
||||||
|
#include "Emu/IPC.h"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
// attr_protocol (waiting scheduling policy)
|
// attr_protocol (waiting scheduling policy)
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
// First In, First Out
|
SYS_SYNC_FIFO = 0x1, // First In, First Out Order
|
||||||
SYS_SYNC_FIFO = 1,
|
SYS_SYNC_PRIORITY = 0x2, // Priority Order
|
||||||
// Priority Order
|
SYS_SYNC_PRIORITY_INHERIT = 0x3, // Basic Priority Inheritance Protocol
|
||||||
SYS_SYNC_PRIORITY = 2,
|
SYS_SYNC_RETRY = 0x4, // Not selected while unlocking
|
||||||
// Basic Priority Inheritance Protocol (probably not implemented)
|
SYS_SYNC_ATTR_PROTOCOL_MASK = 0xf,
|
||||||
SYS_SYNC_PRIORITY_INHERIT = 3,
|
|
||||||
// Not selected while unlocking
|
|
||||||
SYS_SYNC_RETRY = 4,
|
|
||||||
//
|
|
||||||
SYS_SYNC_ATTR_PROTOCOL_MASK = 0xF,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// attr_recursive (recursive locks policy)
|
// attr_recursive (recursive locks policy)
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
// Recursive locks are allowed
|
SYS_SYNC_RECURSIVE = 0x10,
|
||||||
SYS_SYNC_RECURSIVE = 0x10,
|
SYS_SYNC_NOT_RECURSIVE = 0x20,
|
||||||
// Recursive locks are NOT allowed
|
SYS_SYNC_ATTR_RECURSIVE_MASK = 0xf0,
|
||||||
SYS_SYNC_NOT_RECURSIVE = 0x20,
|
|
||||||
//
|
|
||||||
SYS_SYNC_ATTR_RECURSIVE_MASK = 0xF0, //???
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// attr_pshared
|
// attr_pshared (sharing among processes policy)
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SYS_SYNC_NOT_PROCESS_SHARED = 0x200,
|
SYS_SYNC_PROCESS_SHARED = 0x100,
|
||||||
|
SYS_SYNC_NOT_PROCESS_SHARED = 0x200,
|
||||||
|
SYS_SYNC_ATTR_PSHARED_MASK = 0xf00,
|
||||||
|
};
|
||||||
|
|
||||||
|
// attr_flags (creation policy)
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SYS_SYNC_NEWLY_CREATED = 0x1, // Create new object, fails if specified IPC key exists
|
||||||
|
SYS_SYNC_NOT_CREATE = 0x2, // Reference existing object, fails if IPC key not found
|
||||||
|
SYS_SYNC_NOT_CARE = 0x3, // Reference existing object, create new one if IPC key not found
|
||||||
|
SYS_SYNC_ATTR_FLAGS_MASK = 0xf,
|
||||||
};
|
};
|
||||||
|
|
||||||
// attr_adaptive
|
// attr_adaptive
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SYS_SYNC_ADAPTIVE = 0x1000,
|
SYS_SYNC_ADAPTIVE = 0x1000,
|
||||||
SYS_SYNC_NOT_ADAPTIVE = 0x2000,
|
SYS_SYNC_NOT_ADAPTIVE = 0x2000,
|
||||||
|
SYS_SYNC_ATTR_ADAPTIVE_MASK = 0xf000,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base class for some kernel objects (shared set of 8192 objects).
|
// Base class for some kernel objects (shared set of 8192 objects).
|
||||||
@ -126,6 +132,81 @@ struct lv2_obj
|
|||||||
|
|
||||||
static void cleanup();
|
static void cleanup();
|
||||||
|
|
||||||
|
template <typename T, typename F>
|
||||||
|
static error_code create(u32 pshared, u64 ipc_key, s32 flags, F&& make)
|
||||||
|
{
|
||||||
|
switch (pshared)
|
||||||
|
{
|
||||||
|
case SYS_SYNC_PROCESS_SHARED:
|
||||||
|
{
|
||||||
|
switch (flags)
|
||||||
|
{
|
||||||
|
case SYS_SYNC_NEWLY_CREATED:
|
||||||
|
case SYS_SYNC_NOT_CARE:
|
||||||
|
{
|
||||||
|
std::shared_ptr<T> result = make();
|
||||||
|
|
||||||
|
if (!ipc_manager<T, u64>::add(ipc_key, [&] { if (!idm::import_existing<lv2_obj, T>(result)) result.reset(); return result; }, &result))
|
||||||
|
{
|
||||||
|
if (flags == SYS_SYNC_NEWLY_CREATED)
|
||||||
|
{
|
||||||
|
return CELL_EEXIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!idm::import_existing<lv2_obj, T>(result))
|
||||||
|
{
|
||||||
|
return CELL_EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
else if (!result)
|
||||||
|
{
|
||||||
|
return CELL_EAGAIN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case SYS_SYNC_NOT_CREATE:
|
||||||
|
{
|
||||||
|
auto result = ipc_manager<T, u64>::get(ipc_key);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return CELL_ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!idm::import_existing<lv2_obj, T>(result))
|
||||||
|
{
|
||||||
|
return CELL_EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case SYS_SYNC_NOT_PROCESS_SHARED:
|
||||||
|
{
|
||||||
|
if (!idm::import<lv2_obj, T>(std::forward<F>(make)))
|
||||||
|
{
|
||||||
|
return CELL_EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Scheduler mutex
|
// Scheduler mutex
|
||||||
static semaphore<> g_mutex;
|
static semaphore<> g_mutex;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// IPC manager for objects of type T and IPC keys of type K.
|
// IPC manager for objects of type T and IPC keys of type K.
|
||||||
// External declaration of g_ipc is required.
|
// External declaration of g_ipc is required.
|
||||||
template<typename T, typename K>
|
template <typename T, typename K>
|
||||||
class ipc_manager final
|
class ipc_manager final
|
||||||
{
|
{
|
||||||
std::unordered_map<K, std::weak_ptr<T>> m_map;
|
std::unordered_map<K, std::weak_ptr<T>> m_map;
|
||||||
@ -18,18 +18,27 @@ class ipc_manager final
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Add new object if specified ipc_key is not used
|
// Add new object if specified ipc_key is not used
|
||||||
template<typename F>
|
template <typename F>
|
||||||
static bool add(const K& ipc_key, F&& provider)
|
static bool add(const K& ipc_key, F&& provider, std::shared_ptr<T>* out = nullptr)
|
||||||
{
|
{
|
||||||
writer_lock lock(g_ipc.m_mutex);
|
writer_lock lock(g_ipc.m_mutex);
|
||||||
|
|
||||||
// Get object location
|
// Get object location
|
||||||
std::weak_ptr<T>& wptr = g_ipc.m_map[ipc_key];
|
std::weak_ptr<T>& wptr = g_ipc.m_map[ipc_key];
|
||||||
|
|
||||||
if (wptr.expired())
|
if ((out && !(*out = wptr.lock())) || wptr.expired())
|
||||||
{
|
{
|
||||||
// Call a function which must return the object
|
// Call a function which must return the object
|
||||||
wptr = provider();
|
if (out)
|
||||||
|
{
|
||||||
|
*out = provider();
|
||||||
|
wptr = *out;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wptr = provider();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user