mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-15 13:21:14 +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/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/IPC.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
@ -12,18 +13,14 @@ namespace vm { using namespace ps3; }
|
||||
|
||||
logs::channel sys_cond("sys_cond");
|
||||
|
||||
template<> DECLARE(ipc_manager<lv2_cond, u64>::g_ipc) {};
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 CELL_OK;
|
||||
return std::make_shared<lv2_cond>(
|
||||
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)
|
||||
@ -51,7 +56,6 @@ error_code sys_cond_destroy(u32 cond_id)
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
cond.mutex->cond_count--;
|
||||
return {};
|
||||
});
|
||||
|
||||
|
@ -30,15 +30,20 @@ struct lv2_cond final : lv2_obj
|
||||
atomic_t<u32> waiters{0};
|
||||
std::deque<cpu_thread*> sq;
|
||||
|
||||
lv2_cond(u64 name, std::shared_ptr<lv2_mutex> mutex)
|
||||
: shared(0)
|
||||
, key(0)
|
||||
, flags(0)
|
||||
lv2_cond(u32 shared, s32 flags, u64 key, u64 name, std::shared_ptr<lv2_mutex> mutex)
|
||||
: shared(shared)
|
||||
, key(key)
|
||||
, flags(flags)
|
||||
, name(name)
|
||||
, mutex(std::move(mutex))
|
||||
{
|
||||
this->mutex->cond_count++;
|
||||
}
|
||||
|
||||
~lv2_cond()
|
||||
{
|
||||
this->mutex->cond_count--;
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
|
||||
std::shared_ptr<lv2_event_queue> result;
|
||||
|
||||
// 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);
|
||||
return result;
|
||||
if (const u32 _id = idm::import_existing<lv2_obj, lv2_event_queue>(queue))
|
||||
{
|
||||
*equeue_id = _id;
|
||||
return std::move(queue);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}))
|
||||
{
|
||||
return CELL_EEXIST;
|
||||
}
|
||||
|
||||
if (result)
|
||||
if (queue)
|
||||
{
|
||||
*equeue_id = idm::last_id();
|
||||
return CELL_OK;
|
||||
return CELL_EAGAIN;
|
||||
}
|
||||
|
||||
return CELL_EAGAIN;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
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/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/IPC.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
@ -13,6 +14,8 @@ namespace vm { using namespace ps3; }
|
||||
|
||||
logs::channel sys_event_flag("sys_event_flag");
|
||||
|
||||
template<> DECLARE(ipc_manager<lv2_event_flag, u64>::g_ipc) {};
|
||||
|
||||
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)
|
||||
@ -37,12 +40,6 @@ error_code sys_event_flag_create(vm::ptr<u32> id, vm::ptr<sys_event_flag_attribu
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 CELL_OK;
|
||||
return std::make_shared<lv2_event_flag>(
|
||||
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)
|
||||
|
@ -45,11 +45,11 @@ struct lv2_event_flag final : lv2_obj
|
||||
atomic_t<u64> pattern;
|
||||
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)
|
||||
, shared(0)
|
||||
, key(0)
|
||||
, flags(0)
|
||||
, shared(shared)
|
||||
, key(key)
|
||||
, flags(flags)
|
||||
, type(type)
|
||||
, name(name)
|
||||
, pattern(pattern)
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/IPC.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
@ -11,6 +12,8 @@ namespace vm { using namespace ps3; }
|
||||
|
||||
logs::channel sys_mutex("sys_mutex");
|
||||
|
||||
template<> DECLARE(ipc_manager<lv2_mutex, u64>::g_ipc) {};
|
||||
|
||||
extern u64 get_system_time();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const u32 protocol = attr->protocol;
|
||||
|
||||
switch (protocol)
|
||||
switch (attr->protocol)
|
||||
{
|
||||
case SYS_SYNC_FIFO: break;
|
||||
case SYS_SYNC_PRIORITY: break;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
const u32 recursive = attr->recursive;
|
||||
|
||||
switch (recursive)
|
||||
switch (attr->recursive)
|
||||
{
|
||||
case SYS_SYNC_RECURSIVE: break;
|
||||
case SYS_SYNC_NOT_RECURSIVE: break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
return CELL_EINVAL;
|
||||
sys_mutex.todo("sys_mutex_create(): unexpected adaptive (0x%x)", attr->adaptive);
|
||||
}
|
||||
|
||||
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 CELL_OK;
|
||||
return std::make_shared<lv2_mutex>(
|
||||
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)
|
||||
|
@ -37,13 +37,13 @@ struct lv2_mutex final : lv2_obj
|
||||
atomic_t<u32> cond_count{0}; // Condition Variables
|
||||
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)
|
||||
, recursive(recursive)
|
||||
, shared(0)
|
||||
, adaptive(0)
|
||||
, key(0)
|
||||
, flags(0)
|
||||
, shared(shared)
|
||||
, adaptive(adaptive)
|
||||
, key(key)
|
||||
, flags(flags)
|
||||
, name(name)
|
||||
{
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/IPC.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
@ -11,6 +12,8 @@ namespace vm { using namespace ps3; }
|
||||
|
||||
logs::channel sys_rwlock("sys_rwlock");
|
||||
|
||||
template<> DECLARE(ipc_manager<lv2_rwlock, u64>::g_ipc) {};
|
||||
|
||||
extern u64 get_system_time();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 CELL_EINVAL;
|
||||
return std::make_shared<lv2_rwlock>(protocol, attr->pshared, attr->ipc_key, attr->flags, attr->name_u64);
|
||||
}))
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
if (const u32 id = idm::make<lv2_obj, lv2_rwlock>(protocol, attr->name_u64))
|
||||
{
|
||||
*rw_lock_id = id;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return CELL_EAGAIN;
|
||||
*rw_lock_id = idm::last_id();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
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*> wq;
|
||||
|
||||
lv2_rwlock(u32 protocol, u64 name)
|
||||
lv2_rwlock(u32 protocol, u32 shared, u64 key, s32 flags, u64 name)
|
||||
: protocol(protocol)
|
||||
, shared(0)
|
||||
, key(0)
|
||||
, flags(0)
|
||||
, shared(shared)
|
||||
, key(key)
|
||||
, flags(flags)
|
||||
, name(name)
|
||||
{
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/IPC.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
@ -11,6 +12,8 @@ namespace vm { using namespace ps3; }
|
||||
|
||||
logs::channel sys_semaphore("sys_semaphore");
|
||||
|
||||
template<> DECLARE(ipc_manager<lv2_sema, u64>::g_ipc) {};
|
||||
|
||||
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)
|
||||
@ -39,19 +42,16 @@ error_code sys_semaphore_create(vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attri
|
||||
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 CELL_EINVAL;
|
||||
return std::make_shared<lv2_sema>(protocol, attr->pshared, attr->ipc_key, attr->flags, attr->name_u64, max_val, initial_val);
|
||||
}))
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
if (const u32 id = idm::make<lv2_obj, lv2_sema>(protocol, attr->name_u64, max_val, initial_val))
|
||||
{
|
||||
*sem_id = id;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return CELL_EAGAIN;
|
||||
*sem_id = idm::last_id();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_semaphore_destroy(u32 sem_id)
|
||||
|
@ -32,11 +32,11 @@ struct lv2_sema final : lv2_obj
|
||||
atomic_t<s32> val;
|
||||
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)
|
||||
, shared(0)
|
||||
, key(0)
|
||||
, flags(0)
|
||||
, shared(shared)
|
||||
, key(key)
|
||||
, flags(flags)
|
||||
, name(name)
|
||||
, max(max)
|
||||
, val(value)
|
||||
|
@ -7,46 +7,52 @@
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/IPC.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
// attr_protocol (waiting scheduling policy)
|
||||
enum
|
||||
{
|
||||
// First In, First Out
|
||||
SYS_SYNC_FIFO = 1,
|
||||
// Priority Order
|
||||
SYS_SYNC_PRIORITY = 2,
|
||||
// Basic Priority Inheritance Protocol (probably not implemented)
|
||||
SYS_SYNC_PRIORITY_INHERIT = 3,
|
||||
// Not selected while unlocking
|
||||
SYS_SYNC_RETRY = 4,
|
||||
//
|
||||
SYS_SYNC_ATTR_PROTOCOL_MASK = 0xF,
|
||||
SYS_SYNC_FIFO = 0x1, // First In, First Out Order
|
||||
SYS_SYNC_PRIORITY = 0x2, // Priority Order
|
||||
SYS_SYNC_PRIORITY_INHERIT = 0x3, // Basic Priority Inheritance Protocol
|
||||
SYS_SYNC_RETRY = 0x4, // Not selected while unlocking
|
||||
SYS_SYNC_ATTR_PROTOCOL_MASK = 0xf,
|
||||
};
|
||||
|
||||
// attr_recursive (recursive locks policy)
|
||||
enum
|
||||
{
|
||||
// Recursive locks are allowed
|
||||
SYS_SYNC_RECURSIVE = 0x10,
|
||||
// Recursive locks are NOT allowed
|
||||
SYS_SYNC_NOT_RECURSIVE = 0x20,
|
||||
//
|
||||
SYS_SYNC_ATTR_RECURSIVE_MASK = 0xF0, //???
|
||||
SYS_SYNC_RECURSIVE = 0x10,
|
||||
SYS_SYNC_NOT_RECURSIVE = 0x20,
|
||||
SYS_SYNC_ATTR_RECURSIVE_MASK = 0xf0,
|
||||
};
|
||||
|
||||
// attr_pshared
|
||||
// attr_pshared (sharing among processes policy)
|
||||
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
|
||||
enum
|
||||
{
|
||||
SYS_SYNC_ADAPTIVE = 0x1000,
|
||||
SYS_SYNC_NOT_ADAPTIVE = 0x2000,
|
||||
SYS_SYNC_ADAPTIVE = 0x1000,
|
||||
SYS_SYNC_NOT_ADAPTIVE = 0x2000,
|
||||
SYS_SYNC_ATTR_ADAPTIVE_MASK = 0xf000,
|
||||
};
|
||||
|
||||
// Base class for some kernel objects (shared set of 8192 objects).
|
||||
@ -126,6 +132,81 @@ struct lv2_obj
|
||||
|
||||
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:
|
||||
// Scheduler mutex
|
||||
static semaphore<> g_mutex;
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
// IPC manager for objects of type T and IPC keys of type K.
|
||||
// External declaration of g_ipc is required.
|
||||
template<typename T, typename K>
|
||||
template <typename T, typename K>
|
||||
class ipc_manager final
|
||||
{
|
||||
std::unordered_map<K, std::weak_ptr<T>> m_map;
|
||||
@ -18,18 +18,27 @@ class ipc_manager final
|
||||
|
||||
public:
|
||||
// Add new object if specified ipc_key is not used
|
||||
template<typename F>
|
||||
static bool add(const K& ipc_key, F&& provider)
|
||||
template <typename F>
|
||||
static bool add(const K& ipc_key, F&& provider, std::shared_ptr<T>* out = nullptr)
|
||||
{
|
||||
writer_lock lock(g_ipc.m_mutex);
|
||||
|
||||
// Get object location
|
||||
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
|
||||
wptr = provider();
|
||||
if (out)
|
||||
{
|
||||
*out = provider();
|
||||
wptr = *out;
|
||||
}
|
||||
else
|
||||
{
|
||||
wptr = provider();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user