LV2: Move memory unlocking outside of mutex ownership and make it conditional

This commit is contained in:
Eladash 2022-07-26 09:26:25 +03:00 committed by Ivan
parent 122c6256ca
commit a17a6527f6
10 changed files with 49 additions and 13 deletions

View File

@ -1207,8 +1207,12 @@ namespace cpu_counter
void lv2_obj::sleep(cpu_thread& cpu, const u64 timeout, bool notify_later) void lv2_obj::sleep(cpu_thread& cpu, const u64 timeout, bool notify_later)
{ {
vm::temporary_unlock(cpu); // Should already be performed when using this flag
cpu_counter::remove(&cpu); if (!notify_later)
{
vm::temporary_unlock(cpu);
cpu_counter::remove(&cpu);
}
{ {
std::lock_guard lock{g_mutex}; std::lock_guard lock{g_mutex};
sleep_unlocked(cpu, timeout, notify_later); sleep_unlocked(cpu, timeout, notify_later);
@ -1218,7 +1222,12 @@ void lv2_obj::sleep(cpu_thread& cpu, const u64 timeout, bool notify_later)
bool lv2_obj::awake(cpu_thread* const thread, bool notify_later, s32 prio) bool lv2_obj::awake(cpu_thread* const thread, bool notify_later, s32 prio)
{ {
vm::temporary_unlock(); // Too risky to postpone it in case the notified thread may wait for this thread to free its passive lock
if (!notify_later)
{
vm::temporary_unlock();
}
std::lock_guard lock(g_mutex); std::lock_guard lock(g_mutex);
return awake_unlocked(thread, notify_later, prio); return awake_unlocked(thread, notify_later, prio);
} }

View File

@ -300,7 +300,7 @@ error_code sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout)
return -1; return -1;
} }
lv2_obj::notify_all_t notify; lv2_obj::notify_all_t notify(ppu);
std::lock_guard lock(cond.mutex->mutex); std::lock_guard lock(cond.mutex->mutex);

View File

@ -421,7 +421,7 @@ error_code sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sys_e
return CELL_EINVAL; return CELL_EINVAL;
} }
lv2_obj::notify_all_t notify; lv2_obj::notify_all_t notify(ppu);
std::lock_guard lock(queue.mutex); std::lock_guard lock(queue.mutex);

View File

@ -152,7 +152,7 @@ error_code sys_event_flag_wait(ppu_thread& ppu, u32 id, u64 bitptn, u32 mode, vm
return {}; return {};
} }
lv2_obj::notify_all_t notify; lv2_obj::notify_all_t notify(ppu);
std::lock_guard lock(flag.mutex); std::lock_guard lock(flag.mutex);

View File

@ -1,4 +1,4 @@
#include "stdafx.h" #include "stdafx.h"
#include "sys_lwcond.h" #include "sys_lwcond.h"
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
@ -343,7 +343,7 @@ error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
// Increment lwmutex's lwcond's waiters count // Increment lwmutex's lwcond's waiters count
mutex->lwcond_waiters++; mutex->lwcond_waiters++;
lv2_obj::notify_all_t notify; lv2_obj::notify_all_t notify(ppu);
std::lock_guard lock(cond.mutex); std::lock_guard lock(cond.mutex);

View File

@ -146,7 +146,7 @@ error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout)
return true; return true;
} }
lv2_obj::notify_all_t notify; lv2_obj::notify_all_t notify(ppu);
std::lock_guard lock(mutex.mutex); std::lock_guard lock(mutex.mutex);

View File

@ -141,7 +141,7 @@ error_code sys_mutex_lock(ppu_thread& ppu, u32 mutex_id, u64 timeout)
if (result == CELL_EBUSY) if (result == CELL_EBUSY)
{ {
lv2_obj::notify_all_t notify; lv2_obj::notify_all_t notify(ppu);
std::lock_guard lock(mutex.mutex); std::lock_guard lock(mutex.mutex);

View File

@ -114,7 +114,7 @@ error_code sys_rwlock_rlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout)
} }
} }
lv2_obj::notify_all_t notify; lv2_obj::notify_all_t notify(ppu);
std::lock_guard lock(rwlock.mutex); std::lock_guard lock(rwlock.mutex);
@ -346,7 +346,7 @@ error_code sys_rwlock_wlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout)
return val; return val;
} }
lv2_obj::notify_all_t notify; lv2_obj::notify_all_t notify(ppu);
std::lock_guard lock(rwlock.mutex); std::lock_guard lock(rwlock.mutex);

View File

@ -123,7 +123,7 @@ error_code sys_semaphore_wait(ppu_thread& ppu, u32 sem_id, u64 timeout)
} }
} }
lv2_obj::notify_all_t notify; lv2_obj::notify_all_t notify(ppu);
std::lock_guard lock(sema.mutex); std::lock_guard lock(sema.mutex);

View File

@ -61,6 +61,16 @@ enum
enum ppu_thread_status : u32; enum ppu_thread_status : u32;
namespace vm
{
void temporary_unlock(cpu_thread& cpu) noexcept;
}
namespace cpu_counter
{
void remove(cpu_thread*) noexcept;
}
// Base class for some kernel objects (shared set of 8192 objects). // Base class for some kernel objects (shared set of 8192 objects).
struct lv2_obj struct lv2_obj
{ {
@ -495,10 +505,27 @@ public:
} }
} }
template <typename T = int>
struct notify_all_t struct notify_all_t
{ {
notify_all_t() noexcept = default;
notify_all_t(T& cpu) noexcept
{
vm::temporary_unlock(cpu);
cpu_counter::remove(&cpu);
}
~notify_all_t() noexcept ~notify_all_t() noexcept
{ {
if constexpr (!std::is_base_of_v<cpu_thread, T>)
{
if (auto cpu = cpu_thread::get_current(); cpu && cpu->is_paused())
{
vm::temporary_unlock(*cpu);
}
}
lv2_obj::notify_all(); lv2_obj::notify_all();
} }
}; };