idm::check extended

idm::check_unlocked
idm::find_unlocked
idm::get_unlocked
This commit is contained in:
Nekotekina 2017-02-02 20:32:49 +03:00
parent a809f33418
commit 0674a58502
4 changed files with 72 additions and 37 deletions

View file

@ -102,9 +102,9 @@ error_code sys_memory_allocate_from_container(u32 size, u32 cid, u64 flags, vm::
return CELL_ESRCH; return CELL_ESRCH;
} }
if (ct.value) if (ct.ret)
{ {
return ct.value; return ct.ret;
} }
// Allocate memory, write back the start address of the allocated area, use cid as the supplementary info // Allocate memory, write back the start address of the allocated area, use cid as the supplementary info
@ -219,9 +219,9 @@ error_code sys_memory_container_destroy(u32 cid)
return CELL_ESRCH; return CELL_ESRCH;
} }
if (ct.value) if (ct.ret)
{ {
return ct.value; return ct.ret;
} }
// Return "physical memory" to the default container // Return "physical memory" to the default container

View file

@ -157,9 +157,9 @@ error_code sys_mmapper_allocate_shared_memory_from_container(u64 unk, u32 size,
return CELL_ESRCH; return CELL_ESRCH;
} }
if (ct.value) if (ct.ret)
{ {
return ct.value; return ct.ret;
} }
// Generate a new mem ID // Generate a new mem ID
@ -215,9 +215,9 @@ error_code sys_mmapper_free_shared_memory(u32 mem_id)
return CELL_ESRCH; return CELL_ESRCH;
} }
if (mem.value) if (mem.ret)
{ {
return mem.value; return mem.ret;
} }
// Return "physical memory" to the memory container // Return "physical memory" to the memory container

View file

@ -70,9 +70,9 @@ error_code sys_semaphore_destroy(u32 sem_id)
return CELL_ESRCH; return CELL_ESRCH;
} }
if (sem.value) if (sem.ret)
{ {
return sem.value; return sem.ret;
} }
return CELL_OK; return CELL_OK;
@ -112,7 +112,7 @@ error_code sys_semaphore_wait(ppu_thread& ppu, u32 sem_id, u64 timeout)
return CELL_ESRCH; return CELL_ESRCH;
} }
if (sem.value) if (sem.ret)
{ {
return CELL_OK; return CELL_OK;
} }
@ -182,7 +182,7 @@ error_code sys_semaphore_trywait(u32 sem_id)
return CELL_ESRCH; return CELL_ESRCH;
} }
if (!sem.value) if (!sem.ret)
{ {
return not_an_error(CELL_EBUSY); return not_an_error(CELL_EBUSY);
} }
@ -219,7 +219,7 @@ error_code sys_semaphore_post(u32 sem_id, s32 count)
return CELL_ESRCH; return CELL_ESRCH;
} }
if (sem.value) if (sem.ret)
{ {
return CELL_OK; return CELL_OK;
} }

View file

@ -227,33 +227,39 @@ class idm
using void_type = void; using void_type = void;
}; };
// Helper // Helper type: pointer + return value propagated
template <typename T, typename RT> template <typename T, typename RT>
struct return_pair struct return_pair
{ {
std::shared_ptr<T> ptr; std::shared_ptr<T> ptr;
RT value; RT ret;
explicit operator bool() const explicit operator bool() const
{ {
return ptr.operator bool(); return ptr.operator bool();
} }
auto operator->() const T* operator->() const
{ {
return ptr.get(); return ptr.get();
} }
}; };
template <typename RT> // Unsafe specialization (not refcounted)
struct return_pair<bool, RT> template <typename T, typename RT>
struct return_pair<T*, RT>
{ {
bool result; T* ptr;
RT value; RT ret;
explicit operator bool() const explicit operator bool() const
{ {
return result; return ptr != nullptr;
}
T* operator->() const
{
return ptr;
} }
}; };
@ -382,46 +388,75 @@ public:
return id_manager::id_traits<Made>::invalid; return id_manager::id_traits<Made>::invalid;
} }
// Access the ID record without locking (unsafe)
template <typename T, typename Get = T>
static inline id_manager::id_map::pointer find_unlocked(u32 id)
{
return find_id<T, Get>(id);
}
// Check the ID without locking (can be called from other method)
template <typename T, typename Get = T>
static inline Get* check_unlocked(u32 id)
{
if (const auto found = find_id<T, Get>(id))
{
return static_cast<Get*>(found->second.get());
}
return nullptr;
}
// Check the ID // Check the ID
template <typename T, typename Get = T> template <typename T, typename Get = T>
static inline explicit_bool_t check(u32 id) static inline Get* check(u32 id)
{ {
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
return find_id<T, Get>(id) != nullptr; return check_unlocked<T, Get>(id);
} }
// Check the ID, access object under shared lock // Check the ID, access object under shared lock
template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(Get&)>, typename = std::enable_if_t<std::is_void<FRT>::value>> template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(Get&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
static inline explicit_bool_t check(u32 id, F&& func, int = 0) static inline Get* check(u32 id, F&& func, int = 0)
{ {
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
const auto found = find_id<T, Get>(id); if (const auto ptr = check_unlocked<T, Get>(id))
if (UNLIKELY(found == nullptr))
{ {
return false; func(*ptr);
return ptr;
} }
func(*static_cast<Get*>(found->second.get())); return nullptr;
return true;
} }
// Check the ID, access object under reader lock, propagate return value // Check the ID, access object under reader lock, propagate return value
template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(Get&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>> template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(Get&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline return_pair<bool, FRT> check(u32 id, F&& func) static inline return_pair<Get*, FRT> check(u32 id, F&& func)
{ {
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
if (const auto ptr = check_unlocked<T, Get>(id))
{
return {ptr, func(*ptr)};
}
return {nullptr};
}
// Get the object without locking (can be called from other method)
template <typename T, typename Get = T>
static inline std::shared_ptr<Get> get_unlocked(u32 id)
{
const auto found = find_id<T, Get>(id); const auto found = find_id<T, Get>(id);
if (UNLIKELY(found == nullptr)) if (UNLIKELY(found == nullptr))
{ {
return {false}; return nullptr;
} }
return {true, func(*static_cast<Get*>(found->second.get()))}; return {found->second, static_cast<Get*>(found->second.get())};
} }
// Get the object // Get the object
@ -807,12 +842,12 @@ public:
} }
// Check whether the object exists // Check whether the object exists
template <typename T, typename Get = T> template <typename T>
static inline explicit_bool_t check() static inline T* check()
{ {
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
return g_vec[get_type<T>()].second != nullptr; return static_cast<T*>(g_vec[get_type<T>()].second.get());
} }
// Get the object (returns nullptr if it doesn't exist) // Get the object (returns nullptr if it doesn't exist)