Small fixes

This commit is contained in:
Nekotekina 2015-07-08 18:01:59 +03:00
parent c0f13f7084
commit 82781e620a
22 changed files with 201 additions and 194 deletions

View file

@ -1012,10 +1012,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
switch (d_size) switch (d_size)
{ {
case 1: reg_value = vm::priv_ref<atomic<u8>>(addr).exchange((u8)reg_value); break; case 1: reg_value = vm::priv_ref<atomic_t<u8>>(addr).exchange((u8)reg_value); break;
case 2: reg_value = vm::priv_ref<atomic<u16>>(addr).exchange((u16)reg_value); break; case 2: reg_value = vm::priv_ref<atomic_t<u16>>(addr).exchange((u16)reg_value); break;
case 4: reg_value = vm::priv_ref<atomic<u32>>(addr).exchange((u32)reg_value); break; case 4: reg_value = vm::priv_ref<atomic_t<u32>>(addr).exchange((u32)reg_value); break;
case 8: reg_value = vm::priv_ref<atomic<u64>>(addr).exchange((u64)reg_value); break; case 8: reg_value = vm::priv_ref<atomic_t<u64>>(addr).exchange((u64)reg_value); break;
default: return false; default: return false;
} }
@ -1035,10 +1035,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
switch (d_size) switch (d_size)
{ {
case 1: old_value = vm::priv_ref<atomic<u8>>(addr).compare_and_swap((u8)cmp_value, (u8)reg_value); break; case 1: old_value = vm::priv_ref<atomic_t<u8>>(addr).compare_and_swap((u8)cmp_value, (u8)reg_value); break;
case 2: old_value = vm::priv_ref<atomic<u16>>(addr).compare_and_swap((u16)cmp_value, (u16)reg_value); break; case 2: old_value = vm::priv_ref<atomic_t<u16>>(addr).compare_and_swap((u16)cmp_value, (u16)reg_value); break;
case 4: old_value = vm::priv_ref<atomic<u32>>(addr).compare_and_swap((u32)cmp_value, (u32)reg_value); break; case 4: old_value = vm::priv_ref<atomic_t<u32>>(addr).compare_and_swap((u32)cmp_value, (u32)reg_value); break;
case 8: old_value = vm::priv_ref<atomic<u64>>(addr).compare_and_swap((u64)cmp_value, (u64)reg_value); break; case 8: old_value = vm::priv_ref<atomic_t<u64>>(addr).compare_and_swap((u64)cmp_value, (u64)reg_value); break;
default: return false; default: return false;
} }
@ -1058,10 +1058,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
switch (d_size) switch (d_size)
{ {
case 1: value = vm::priv_ref<atomic<u8>>(addr) &= static_cast<u8>(value); break; case 1: value = vm::priv_ref<atomic_t<u8>>(addr) &= (u8)value; break;
case 2: value = vm::priv_ref<atomic<u16>>(addr) &= static_cast<u16>(value); break; case 2: value = vm::priv_ref<atomic_t<u16>>(addr) &= (u16)value; break;
case 4: value = vm::priv_ref<atomic<u32>>(addr) &= static_cast<u32>(value); break; case 4: value = vm::priv_ref<atomic_t<u32>>(addr) &= (u32)value; break;
case 8: value = vm::priv_ref<atomic<u64>>(addr) &= value; break; case 8: value = vm::priv_ref<atomic_t<u64>>(addr) &= value; break;
default: return false; default: return false;
} }

View file

@ -13,10 +13,10 @@ class thread_ctrl_t final
// name getter // name getter
const std::function<std::string()> name; const std::function<std::string()> name;
// true if TLS of some thread points to owner // true if assigned somewhere in TLS
std::atomic<bool> assigned{ false }; std::atomic<bool> assigned{ false };
// assign TLS // assign TLS (must be assigned only once)
void set_current(); void set_current();
public: public:
@ -174,7 +174,7 @@ class squeue_t
}; };
}; };
atomic<squeue_sync_var_t> m_sync; atomic_t<squeue_sync_var_t> m_sync;
mutable std::mutex m_rcv_mutex; mutable std::mutex m_rcv_mutex;
mutable std::mutex m_wcv_mutex; mutable std::mutex m_wcv_mutex;

View file

@ -37,6 +37,7 @@ CPUThread::CPUThread(CPUThreadType type, const std::string& name, std::function<
} }
catch (CPUThreadReturn) catch (CPUThreadReturn)
{ {
;
} }
catch (CPUThreadStop) catch (CPUThreadStop)
{ {
@ -47,12 +48,21 @@ CPUThread::CPUThread(CPUThreadType type, const std::string& name, std::function<
m_state |= CPU_STATE_DEAD; m_state |= CPU_STATE_DEAD;
break; break;
} }
catch (const fmt::exception&)
{
DumpInformation();
throw;
}
m_state &= ~CPU_STATE_RETURN; m_state &= ~CPU_STATE_RETURN;
continue; continue;
} }
if (!lock) lock.lock(); if (!lock)
{
lock.lock();
continue;
}
cv.wait(lock); cv.wait(lock);
} }

View file

@ -38,7 +38,7 @@ class CPUDecoder;
class CPUThread : protected thread_t, public std::enable_shared_from_this<CPUThread> class CPUThread : protected thread_t, public std::enable_shared_from_this<CPUThread>
{ {
protected: protected:
atomic<u64> m_state; // thread state flags atomic_t<u64> m_state; // thread state flags
std::unique_ptr<CPUDecoder> m_dec; std::unique_ptr<CPUDecoder> m_dec;

View file

@ -28,43 +28,43 @@ void CPUThreadManager::Close()
} }
} }
std::vector<std::shared_ptr<CPUThread>> CPUThreadManager::GetAllThreads() const std::vector<std::shared_ptr<CPUThread>> CPUThreadManager::GetAllThreads()
{ {
std::vector<std::shared_ptr<CPUThread>> result; std::vector<std::shared_ptr<CPUThread>> result;
for (auto& v : Emu.GetIdManager().get_data<PPUThread>()) for (auto& t : Emu.GetIdManager().get_all<PPUThread>())
{ {
result.emplace_back(std::static_pointer_cast<CPUThread>(v.data)); result.emplace_back(t);
} }
for (auto& v : Emu.GetIdManager().get_data<SPUThread>()) for (auto& t : Emu.GetIdManager().get_all<SPUThread>())
{ {
result.emplace_back(std::static_pointer_cast<CPUThread>(v.data)); result.emplace_back(t);
} }
for (auto& v : Emu.GetIdManager().get_data<RawSPUThread>()) for (auto& t : Emu.GetIdManager().get_all<RawSPUThread>())
{ {
result.emplace_back(std::static_pointer_cast<CPUThread>(v.data)); result.emplace_back(t);
} }
for (auto& v : Emu.GetIdManager().get_data<ARMv7Thread>()) for (auto& t : Emu.GetIdManager().get_all<ARMv7Thread>())
{ {
result.emplace_back(std::static_pointer_cast<CPUThread>(v.data)); result.emplace_back(t);
} }
return result; return result;
} }
void CPUThreadManager::Exec() const void CPUThreadManager::Exec()
{ {
for (auto& v : Emu.GetIdManager().get_data<PPUThread>()) for (auto& t : Emu.GetIdManager().get_all<PPUThread>())
{ {
static_cast<CPUThread*>(v.data.get())->Exec(); t->Exec();
} }
for (auto& v : Emu.GetIdManager().get_data<ARMv7Thread>()) for (auto& t : Emu.GetIdManager().get_all<ARMv7Thread>())
{ {
static_cast<CPUThread*>(v.data.get())->Exec(); t->Exec();
} }
} }

View file

@ -15,9 +15,9 @@ public:
void Close(); void Close();
std::vector<std::shared_ptr<CPUThread>> GetAllThreads() const; static std::vector<std::shared_ptr<CPUThread>> GetAllThreads();
void Exec() const; static void Exec();
std::shared_ptr<RawSPUThread> NewRawSPUThread(); std::shared_ptr<RawSPUThread> NewRawSPUThread();

View file

@ -507,10 +507,9 @@ void PPUThread::DumpInformation() const
{ {
if (~hle_code < 1024) if (~hle_code < 1024)
{ {
LOG_SUCCESS(HLE, "Last function: syscall %lld (%s)", ~hle_code, SysCalls::GetFuncName(hle_code)); LOG_SUCCESS(HLE, "Last syscall: %lld (%s)", ~hle_code, SysCalls::GetFuncName(hle_code));
} }
else if (hle_code)
if (hle_code > 0)
{ {
LOG_SUCCESS(HLE, "Last function: %s (0x%llx)", SysCalls::GetFuncName(hle_code), hle_code); LOG_SUCCESS(HLE, "Last function: %s (0x%llx)", SysCalls::GetFuncName(hle_code), hle_code);
} }

View file

@ -137,7 +137,7 @@ union spu_channel_t
u32 value; u32 value;
}; };
atomic<sync_var_t> sync_var; // atomic variable atomic_t<sync_var_t> sync_var; // atomic variable
public: public:
bool try_push(u32 value) bool try_push(u32 value)
@ -223,8 +223,8 @@ struct spu_channel_4_t
u32 value2; u32 value2;
}; };
atomic<sync_var_t> sync_var; atomic_t<sync_var_t> sync_var;
atomic<u32> value3; atomic_t<u32> value3;
public: public:
void clear() void clear()
@ -280,10 +280,10 @@ public:
struct spu_interrupt_tag_t struct spu_interrupt_tag_t
{ {
atomic<u64> mask; atomic_t<u64> mask;
atomic<u64> stat; atomic_t<u64> stat;
atomic<s32> assigned; atomic_t<s32> assigned;
std::mutex handler_mutex; std::mutex handler_mutex;
std::condition_variable cond; std::condition_variable cond;
@ -526,14 +526,14 @@ public:
spu_channel_t ch_snr2; // SPU Signal Notification Register 2 spu_channel_t ch_snr2; // SPU Signal Notification Register 2
u32 ch_event_mask; u32 ch_event_mask;
atomic<u32> ch_event_stat; atomic_t<u32> ch_event_stat;
u64 ch_dec_start_timestamp; // timestamp of writing decrementer value u64 ch_dec_start_timestamp; // timestamp of writing decrementer value
u32 ch_dec_value; // written decrementer value u32 ch_dec_value; // written decrementer value
atomic<u32> run_ctrl; // SPU Run Control register (only provided to get latest data written) atomic_t<u32> run_ctrl; // SPU Run Control register (only provided to get latest data written)
atomic<u32> status; // SPU Status register atomic_t<u32> status; // SPU Status register
atomic<u32> npc; // SPU Next Program Counter register atomic_t<u32> npc; // SPU Next Program Counter register
spu_interrupt_tag_t int0; // SPU Class 0 Interrupt Management spu_interrupt_tag_t int0; // SPU Class 0 Interrupt Management
spu_interrupt_tag_t int2; // SPU Class 2 Interrupt Management spu_interrupt_tag_t int2; // SPU Class 2 Interrupt Management

View file

@ -20,13 +20,13 @@ class ID_data_t final
{ {
public: public:
const std::shared_ptr<void> data; const std::shared_ptr<void> data;
const std::type_info& info; const std::size_t info;
const u32 type; const u32 type;
const u32 id; const u32 id;
template<typename T> force_inline ID_data_t(std::shared_ptr<T> data, u32 type, u32 id) template<typename T> force_inline ID_data_t(std::shared_ptr<T> data, u32 type, u32 id)
: data(std::move(data)) : data(std::move(data))
, info(typeid(T)) , info(typeid(T).hash_code())
, type(type) , type(type)
, id(id) , id(id)
{ {
@ -62,13 +62,23 @@ class ID_manager
public: public:
// check if ID exists and has specified type // check if ID exists and has specified type
template<typename T> bool check_id(const u32 id) template<typename T> bool check_id(u32 id)
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
auto f = m_id_map.find(id); auto f = m_id_map.find(id);
return f != m_id_map.end() && f->second.info == typeid(T); return f != m_id_map.end() && f->second.info == typeid(T).hash_code();
}
// check if ID exists and has specified type
bool check_id(u32 id, u32 type)
{
std::lock_guard<std::mutex> lock(m_mutex);
auto f = m_id_map.find(id);
return f != m_id_map.end() && f->second.type == type;
} }
// must be called from the constructor called through make() to get further ID of current object // must be called from the constructor called through make() to get further ID of current object
@ -122,14 +132,14 @@ public:
return m_cur_id++; return m_cur_id++;
} }
// load ID created with type Original, optionally static_cast to T // load ID created with type Orig, optionally static_cast to T
template<typename T, typename Orig = T> auto get(u32 id) -> decltype(std::shared_ptr<T>(static_cast<T*>(std::declval<Orig*>()))) template<typename T, typename Orig = T> auto get(u32 id) -> decltype(std::shared_ptr<T>(static_cast<T*>(std::declval<Orig*>())))
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
auto f = m_id_map.find(id); auto f = m_id_map.find(id);
if (f == m_id_map.end() || f->second.info != typeid(Orig)) if (f == m_id_map.end() || f->second.info != typeid(Orig).hash_code())
{ {
return nullptr; return nullptr;
} }
@ -137,13 +147,33 @@ public:
return std::static_pointer_cast<T>(f->second.data); return std::static_pointer_cast<T>(f->second.data);
} }
// load all IDs created with type Orig, optionally static_cast to T
template<typename T, typename Orig = T> auto get_all() -> std::vector<decltype(std::shared_ptr<T>(static_cast<T*>(std::declval<Orig*>())))>
{
std::lock_guard<std::mutex> lock(m_mutex);
std::vector<std::shared_ptr<T>> result;
const std::size_t hash = typeid(Orig).hash_code();
for (auto& v : m_id_map)
{
if (v.second.info == hash)
{
result.emplace_back(std::static_pointer_cast<T>(v.second.data));
}
}
return result;
}
template<typename T> bool remove(u32 id) template<typename T> bool remove(u32 id)
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
auto item = m_id_map.find(id); auto item = m_id_map.find(id);
if (item == m_id_map.end() || item->second.info != typeid(T)) if (item == m_id_map.end() || item->second.info != typeid(T).hash_code())
{ {
return false; return false;
} }
@ -159,9 +189,11 @@ public:
u32 result = 0; u32 result = 0;
const std::size_t hash = typeid(T).hash_code();
for (auto& v : m_id_map) for (auto& v : m_id_map)
{ {
if (v.second.info == typeid(T)) if (v.second.info == hash)
{ {
result++; result++;
} }
@ -187,15 +219,18 @@ public:
return result; return result;
} }
// get sorted ID list
template<typename T> std::set<u32> get_IDs() template<typename T> std::set<u32> get_IDs()
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
std::set<u32> result; std::set<u32> result;
const std::size_t hash = typeid(T).hash_code();
for (auto& v : m_id_map) for (auto& v : m_id_map)
{ {
if (v.second.info == typeid(T)) if (v.second.info == hash)
{ {
result.insert(v.first); result.insert(v.first);
} }
@ -204,6 +239,7 @@ public:
return result; return result;
} }
// get sorted ID list
std::set<u32> get_IDs(u32 type) std::set<u32> get_IDs(u32 type)
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
@ -227,9 +263,11 @@ public:
std::vector<ID_data_t> result; std::vector<ID_data_t> result;
const std::size_t hash = typeid(T).hash_code();
for (auto& v : m_id_map) for (auto& v : m_id_map)
{ {
if (v.second.info == typeid(T)) if (v.second.info == hash)
{ {
result.emplace_back(v.second); result.emplace_back(v.second);
} }

View file

@ -318,7 +318,7 @@ template<typename T, typename T2, typename = if_integral_t<T>> inline auto opera
}); });
} }
template<typename T> using atomic = _atomic_base<T>; // Atomic Type with native endianness (for emulator memory) template<typename T> using atomic_t = _atomic_base<T>; // Atomic Type with native endianness (for emulator memory)
template<typename T> using atomic_be_t = _atomic_base<to_be_t<T>>; // Atomic BE Type (for PS3 virtual memory) template<typename T> using atomic_be_t = _atomic_base<to_be_t<T>>; // Atomic BE Type (for PS3 virtual memory)

View file

@ -74,11 +74,11 @@ namespace vm
void* g_base_addr = (atexit(finalize), initialize()); void* g_base_addr = (atexit(finalize), initialize());
void* g_priv_addr; void* g_priv_addr;
std::array<atomic<u8>, 0x100000000ull / 4096> g_page_info = {}; // information about every page std::array<atomic_t<u8>, 0x100000000ull / 4096> g_page_info = {}; // information about every page
class reservation_mutex_t class reservation_mutex_t
{ {
atomic<const thread_ctrl_t*> m_owner{}; atomic_t<const thread_ctrl_t*> m_owner{};
std::condition_variable m_cv; std::condition_variable m_cv;
std::mutex m_mutex; std::mutex m_mutex;

View file

@ -100,7 +100,7 @@ enum AudioPortState : u32
struct AudioPortConfig struct AudioPortConfig
{ {
std::mutex mutex; std::mutex mutex;
atomic<AudioPortState> state; atomic_t<AudioPortState> state;
u32 channel; u32 channel;
u32 block; u32 block;
@ -118,12 +118,12 @@ struct AudioPortConfig
}; };
float level; float level;
atomic<level_set_t> level_set; atomic_t<level_set_t> level_set;
}; };
struct AudioConfig final // custom structure struct AudioConfig final // custom structure
{ {
atomic<AudioState> state; atomic_t<AudioState> state;
thread_t thread; thread_t thread;
AudioPortConfig ports[AUDIO_PORT_COUNT]; AudioPortConfig ports[AUDIO_PORT_COUNT];

View file

@ -34,14 +34,19 @@
#include "SysCalls.h" #include "SysCalls.h"
void null_func(PPUThread& CPU); void null_func(PPUThread& ppu)
{
const auto code = ppu.GPR[11];
LOG_ERROR(HLE, "Unimplemented syscall %lld: %s -> CELL_OK", code, SysCalls::GetFuncName(~code));
ppu.GPR[3] = 0;
}
// UNS = Unused // UNS = Unused
// ROOT = Root // ROOT = Root
// DBG = Debug // DBG = Debug
// PM = Product Mode // PM = Product Mode
// AuthID = Authentication ID // AuthID = Authentication ID
const ppu_func_caller sc_table[1024] = const ppu_func_caller g_sc_table[1024] =
{ {
null_func, null_func,
bind_func(sys_process_getpid), //1 (0x001) bind_func(sys_process_getpid), //1 (0x001)
@ -886,13 +891,6 @@ const ppu_func_caller sc_table[1024] =
null_func, null_func, null_func, bind_func(cellGcmCallback), //1023 UNS null_func, null_func, null_func, bind_func(cellGcmCallback), //1023 UNS
}; };
void null_func(PPUThread& CPU)
{
const auto code = CPU.GPR[11];
LOG_ERROR(HLE, "Unimplemented syscall %lld: %s -> CELL_OK", code, SysCalls::GetFuncName(~code));
CPU.GPR[3] = 0;
}
void SysCalls::DoSyscall(PPUThread& CPU, u64 code) void SysCalls::DoSyscall(PPUThread& CPU, u64 code)
{ {
if (code >= 1024) if (code >= 1024)
@ -908,7 +906,7 @@ void SysCalls::DoSyscall(PPUThread& CPU, u64 code)
LOG_NOTICE(PPU, "Syscall %lld called: %s", code, SysCalls::GetFuncName(~code)); LOG_NOTICE(PPU, "Syscall %lld called: %s", code, SysCalls::GetFuncName(~code));
} }
sc_table[code](CPU); g_sc_table[code](CPU);
if (Ini.HLELogging.GetValue()) if (Ini.HLELogging.GetValue())
{ {

View file

@ -87,14 +87,6 @@ s32 sys_cond_signal(u32 cond_id)
// signal one waiting thread; protocol is ignored in current implementation // signal one waiting thread; protocol is ignored in current implementation
if (thread->Signal()) if (thread->Signal())
{ {
cond->sent++;
if (!cond->mutex->owner)
{
// set the appropriate mutex owner if free; protocol is ignored in current implementation
cond->mutex->owner = thread;
}
return CELL_OK; return CELL_OK;
} }
} }
@ -120,13 +112,7 @@ s32 sys_cond_signal_all(u32 cond_id)
// signal all waiting threads; protocol is ignored in current implementation // signal all waiting threads; protocol is ignored in current implementation
if (thread->Signal()) if (thread->Signal())
{ {
cond->sent++; ;
if (!cond->mutex->owner)
{
// set the appropriate mutex owner if free; protocol is ignored in current implementation
cond->mutex->owner = thread;
}
} }
} }
@ -153,14 +139,6 @@ s32 sys_cond_signal_to(u32 cond_id, u32 thread_id)
// signal specified thread // signal specified thread
if (thread->GetId() == thread_id && thread->Signal()) if (thread->GetId() == thread_id && thread->Signal())
{ {
cond->sent++;
if (!cond->mutex->owner)
{
// set the appropriate mutex owner if free; protocol is ignored in current implementation
cond->mutex->owner = thread;
}
return CELL_OK; return CELL_OK;
} }
} }
@ -228,8 +206,6 @@ s32 sys_cond_wait(PPUThread& ppu, u32 cond_id, u64 timeout)
CHECK_EMU_STATUS; CHECK_EMU_STATUS;
} }
cond->recv++;
} }
// reown the mutex (could be set when notified) // reown the mutex (could be set when notified)

View file

@ -26,9 +26,6 @@ struct lv2_cond_t
sleep_queue_t sq; sleep_queue_t sq;
std::atomic<u32> sent{ 0 };
std::atomic<u32> recv{ 0 };
lv2_cond_t(const std::shared_ptr<lv2_mutex_t>& mutex, u64 name) lv2_cond_t(const std::shared_ptr<lv2_mutex_t>& mutex, u64 name)
: mutex(mutex) : mutex(mutex)
, name(name) , name(name)

View file

@ -177,7 +177,7 @@ struct lv2_file_t
std::mutex mutex; std::mutex mutex;
std::condition_variable cv; std::condition_variable cv;
atomic<u32> st_status; atomic_t<u32> st_status;
u64 st_ringbuf_size; u64 st_ringbuf_size;
u64 st_block_size; u64 st_block_size;
@ -191,7 +191,7 @@ struct lv2_file_t
std::atomic<u64> st_total_read; std::atomic<u64> st_total_read;
std::atomic<u64> st_copied; std::atomic<u64> st_copied;
atomic<fs_st_cb_rec_t> st_callback; atomic_t<fs_st_cb_rec_t> st_callback;
lv2_file_t(std::shared_ptr<vfsStream> file, s32 mode, s32 flags) lv2_file_t(std::shared_ptr<vfsStream> file, s32 mode, s32 flags)
: file(std::move(file)) : file(std::move(file))

View file

@ -98,10 +98,10 @@ s32 sys_interrupt_thread_establish(vm::ptr<u32> ih, u32 intrtag, u32 intrthread,
it->custom_task = [thread, &tag, arg](PPUThread& CPU) it->custom_task = [thread, &tag, arg](PPUThread& CPU)
{ {
const auto pc = CPU.PC; const u32 pc = CPU.PC;
const auto rtoc = CPU.GPR[2]; const u32 rtoc = CPU.GPR[2];
std::unique_lock<std::mutex> cond_lock(tag.handler_mutex); std::unique_lock<std::mutex> lock(tag.handler_mutex);
while (!CPU.IsStopped()) while (!CPU.IsStopped())
{ {
@ -114,7 +114,7 @@ s32 sys_interrupt_thread_establish(vm::ptr<u32> ih, u32 intrtag, u32 intrthread,
CPU.FastCall2(pc, rtoc); CPU.FastCall2(pc, rtoc);
} }
tag.cond.wait_for(cond_lock, std::chrono::milliseconds(1)); tag.cond.wait_for(lock, std::chrono::milliseconds(1));
} }
}; };
} }
@ -149,7 +149,7 @@ void sys_interrupt_thread_eoi(PPUThread& CPU)
// TODO: maybe it should actually unwind the stack of PPU thread? // TODO: maybe it should actually unwind the stack of PPU thread?
CPU.GPR[1] = align(CPU.stack_addr + CPU.stack_size, 0x200) - 0x200; // supercrutch to avoid stack check CPU.GPR[1] = align(CPU.stack_addr + CPU.stack_size, 0x200) - 0x200; // supercrutch to bypass stack check
CPU.FastStop(); CPU.FastStop();
} }

View file

@ -11,6 +11,24 @@ SysCallBase sys_mutex("sys_mutex");
extern u64 get_system_time(); extern u64 get_system_time();
void lv2_mutex_t::unlock(lv2_lock_type& lv2_lock)
{
CHECK_LV2_LOCK(lv2_lock);
owner.reset();
if (sq.size())
{
// pick new owner; protocol is ignored in current implementation
owner = sq.front();
if (!owner->Signal())
{
throw EXCEPTION("Mutex owner not signaled");
}
}
}
s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t> attr) s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t> attr)
{ {
sys_mutex.Warning("sys_mutex_create(mutex_id=*0x%x, attr=*0x%x)", mutex_id, attr); sys_mutex.Warning("sys_mutex_create(mutex_id=*0x%x, attr=*0x%x)", mutex_id, attr);
@ -217,19 +235,7 @@ s32 sys_mutex_unlock(PPUThread& ppu, u32 mutex_id)
} }
else else
{ {
// free the mutex mutex->unlock(lv2_lock);
mutex->owner.reset();
if (mutex->sq.size())
{
// pick another owner; protocol is ignored in current implementation
mutex->owner = mutex->sq.front();
if (!mutex->owner->Signal())
{
throw EXCEPTION("Mutex owner not signaled");
}
}
} }
return CELL_OK; return CELL_OK;

View file

@ -39,6 +39,8 @@ struct lv2_mutex_t
, name(name) , name(name)
{ {
} }
void unlock(lv2_lock_type& lv2_lock);
}; };
REG_ID_TYPE(lv2_mutex_t, 0x85); // SYS_MUTEX_OBJECT REG_ID_TYPE(lv2_mutex_t, 0x85); // SYS_MUTEX_OBJECT

View file

@ -18,23 +18,17 @@ void _sys_ppu_thread_exit(PPUThread& ppu, u64 errorcode)
LV2_LOCK; LV2_LOCK;
// get all sys_mutex objects // get all sys_mutex objects
for (auto& _id : Emu.GetIdManager().get_data<lv2_mutex_t>()) for (auto& mutex : Emu.GetIdManager().get_all<lv2_mutex_t>())
{ {
const auto mutex = std::static_pointer_cast<lv2_mutex_t>(_id.data);
// unlock mutex if locked by this thread // unlock mutex if locked by this thread
if (mutex->owner.get() == &ppu) if (mutex->owner.get() == &ppu)
{ {
mutex->owner.reset(); mutex->unlock(lv2_lock);
if (mutex->sq.size())
{
mutex->owner = mutex->sq.front();
mutex->owner->Signal();
}
} }
} }
const auto thread = ppu.shared_from_this();
if (!ppu.is_joinable) if (!ppu.is_joinable)
{ {
const u32 id = ppu.GetId(); const u32 id = ppu.GetId();
@ -260,8 +254,8 @@ s32 _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_param_t> p
return CELL_EINVAL; return CELL_EINVAL;
} }
const bool is_joinable = flags & SYS_PPU_THREAD_CREATE_JOINABLE; const bool is_joinable = (flags & SYS_PPU_THREAD_CREATE_JOINABLE) != 0;
const bool is_interrupt = flags & SYS_PPU_THREAD_CREATE_INTERRUPT; const bool is_interrupt = (flags & SYS_PPU_THREAD_CREATE_INTERRUPT) != 0;
if (is_joinable && is_interrupt) if (is_joinable && is_interrupt)
{ {

View file

@ -4,8 +4,9 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/CPU/CPUThreadManager.h" #include "Emu/Cell/PPUThread.h"
#include "Emu/CPU/CPUThread.h" #include "Emu/Cell/SPUThread.h"
#include "Emu/Cell/RawSPUThread.h"
#include "Emu/SysCalls/lv2/sleep_queue.h" #include "Emu/SysCalls/lv2/sleep_queue.h"
#include "Emu/SysCalls/lv2/sys_lwmutex.h" #include "Emu/SysCalls/lv2/sys_lwmutex.h"
#include "Emu/SysCalls/lv2/sys_lwcond.h" #include "Emu/SysCalls/lv2/sys_lwcond.h"
@ -81,6 +82,7 @@ void KernelExplorer::Update()
{ {
sprintf(name, "Semaphores (%d)", count); sprintf(name, "Semaphores (%d)", count);
const auto& node = m_tree->AppendItem(root, name); const auto& node = m_tree->AppendItem(root, name);
for (const auto id : Emu.GetIdManager().get_IDs(SYS_SEMAPHORE_OBJECT)) for (const auto id : Emu.GetIdManager().get_IDs(SYS_SEMAPHORE_OBJECT))
{ {
const auto sem = Emu.GetIdManager().get<lv2_sema_t>(id); const auto sem = Emu.GetIdManager().get<lv2_sema_t>(id);
@ -94,6 +96,7 @@ void KernelExplorer::Update()
{ {
sprintf(name, "Mutexes (%d)", count); sprintf(name, "Mutexes (%d)", count);
const auto& node = m_tree->AppendItem(root, name); const auto& node = m_tree->AppendItem(root, name);
for (const auto id : Emu.GetIdManager().get_IDs(SYS_MUTEX_OBJECT)) for (const auto id : Emu.GetIdManager().get_IDs(SYS_MUTEX_OBJECT))
{ {
const auto mutex = Emu.GetIdManager().get<lv2_mutex_t>(id); const auto mutex = Emu.GetIdManager().get<lv2_mutex_t>(id);
@ -107,6 +110,7 @@ void KernelExplorer::Update()
{ {
sprintf(name, "Lightweight Mutexes (%d)", count); sprintf(name, "Lightweight Mutexes (%d)", count);
const auto& node = m_tree->AppendItem(root, name); const auto& node = m_tree->AppendItem(root, name);
for (const auto id : Emu.GetIdManager().get_IDs(SYS_LWMUTEX_OBJECT)) for (const auto id : Emu.GetIdManager().get_IDs(SYS_LWMUTEX_OBJECT))
{ {
const auto lwm = Emu.GetIdManager().get<lv2_lwmutex_t>(id); const auto lwm = Emu.GetIdManager().get<lv2_lwmutex_t>(id);
@ -120,6 +124,7 @@ void KernelExplorer::Update()
{ {
sprintf(name, "Condition Variables (%d)", count); sprintf(name, "Condition Variables (%d)", count);
const auto& node = m_tree->AppendItem(root, name); const auto& node = m_tree->AppendItem(root, name);
for (const auto id : Emu.GetIdManager().get_IDs(SYS_COND_OBJECT)) for (const auto id : Emu.GetIdManager().get_IDs(SYS_COND_OBJECT))
{ {
const auto cond = Emu.GetIdManager().get<lv2_cond_t>(id); const auto cond = Emu.GetIdManager().get<lv2_cond_t>(id);
@ -133,6 +138,7 @@ void KernelExplorer::Update()
{ {
sprintf(name, "Lightweight Condition Variables (%d)", count); sprintf(name, "Lightweight Condition Variables (%d)", count);
const auto& node = m_tree->AppendItem(root, name); const auto& node = m_tree->AppendItem(root, name);
for (const auto id : Emu.GetIdManager().get_IDs(SYS_LWCOND_OBJECT)) for (const auto id : Emu.GetIdManager().get_IDs(SYS_LWCOND_OBJECT))
{ {
const auto lwc = Emu.GetIdManager().get<lv2_lwcond_t>(id); const auto lwc = Emu.GetIdManager().get<lv2_lwcond_t>(id);
@ -146,6 +152,7 @@ void KernelExplorer::Update()
{ {
sprintf(name, "Event Queues (%d)", count); sprintf(name, "Event Queues (%d)", count);
const auto& node = m_tree->AppendItem(root, name); const auto& node = m_tree->AppendItem(root, name);
for (const auto id : Emu.GetIdManager().get_IDs(SYS_EVENT_QUEUE_OBJECT)) for (const auto id : Emu.GetIdManager().get_IDs(SYS_EVENT_QUEUE_OBJECT))
{ {
const auto queue = Emu.GetIdManager().get<lv2_event_queue_t>(id); const auto queue = Emu.GetIdManager().get<lv2_event_queue_t>(id);
@ -159,6 +166,7 @@ void KernelExplorer::Update()
{ {
sprintf(name, "Event Ports (%d)", count); sprintf(name, "Event Ports (%d)", count);
const auto& node = m_tree->AppendItem(root, name); const auto& node = m_tree->AppendItem(root, name);
for (const auto id : Emu.GetIdManager().get_IDs(SYS_EVENT_PORT_OBJECT)) for (const auto id : Emu.GetIdManager().get_IDs(SYS_EVENT_PORT_OBJECT))
{ {
const auto port = Emu.GetIdManager().get<lv2_event_port_t>(id); const auto port = Emu.GetIdManager().get<lv2_event_port_t>(id);
@ -174,6 +182,7 @@ void KernelExplorer::Update()
const auto& node = m_tree->AppendItem(root, name); const auto& node = m_tree->AppendItem(root, name);
//sprintf(name, "Segment List (%l)", 2 * objects.size()); // TODO: Assuming 2 segments per PRX file is not good //sprintf(name, "Segment List (%l)", 2 * objects.size()); // TODO: Assuming 2 segments per PRX file is not good
//m_tree->AppendItem(node, name); //m_tree->AppendItem(node, name);
for (const auto& id : Emu.GetIdManager().get_IDs(SYS_PRX_OBJECT)) for (const auto& id : Emu.GetIdManager().get_IDs(SYS_PRX_OBJECT))
{ {
sprintf(name, "PRX: ID = 0x%x", id); sprintf(name, "PRX: ID = 0x%x", id);
@ -186,6 +195,7 @@ void KernelExplorer::Update()
{ {
sprintf(name, "Memory Containers (%d)", count); sprintf(name, "Memory Containers (%d)", count);
const auto& node = m_tree->AppendItem(root, name); const auto& node = m_tree->AppendItem(root, name);
for (const auto& id : Emu.GetIdManager().get_IDs(SYS_MEM_OBJECT)) for (const auto& id : Emu.GetIdManager().get_IDs(SYS_MEM_OBJECT))
{ {
sprintf(name, "Memory Container: ID = 0x%x", id); sprintf(name, "Memory Container: ID = 0x%x", id);
@ -198,6 +208,7 @@ void KernelExplorer::Update()
{ {
sprintf(name, "Event Flags (%d)", count); sprintf(name, "Event Flags (%d)", count);
const auto& node = m_tree->AppendItem(root, name); const auto& node = m_tree->AppendItem(root, name);
for (const auto& id : Emu.GetIdManager().get_IDs(SYS_EVENT_FLAG_OBJECT)) for (const auto& id : Emu.GetIdManager().get_IDs(SYS_EVENT_FLAG_OBJECT))
{ {
sprintf(name, "Event Flag: ID = 0x%x", id); sprintf(name, "Event Flag: ID = 0x%x", id);
@ -205,71 +216,47 @@ void KernelExplorer::Update()
} }
} }
// PPU / SPU / RawSPU threads // PPU Threads
if (u32 count = Emu.GetIdManager().get_count<PPUThread>())
{ {
// TODO: add mutexes owners sprintf(name, "PPU Threads (%d)", count);
const auto& node = m_tree->AppendItem(root, name);
//const auto& objects = Emu.GetCPU().GetThreads(); for (const auto& thread : Emu.GetIdManager().get_all<PPUThread>())
u32 ppu_threads_count = 0; {
u32 spu_threads_count = 0; sprintf(name, "Thread: ID = 0x%08x '%s', - %s", thread->GetId(), thread->GetName().c_str(), thread->ThreadStatusToString());
u32 raw_spu_threads_count = 0; m_tree->AppendItem(node, name);
//for (const auto& thread : objects) }
//{ }
// if (thread->GetType() == CPU_THREAD_PPU)
// ppu_threads_count++;
// if (thread->GetType() == CPU_THREAD_SPU) if (u32 count = Emu.GetIdManager().get_count<SPUThread>())
// spu_threads_count++; {
sprintf(name, "SPU Threads (%d)", count);
const auto& node = m_tree->AppendItem(root, name);
// if (thread->GetType() == CPU_THREAD_RAW_SPU) for (const auto& thread : Emu.GetIdManager().get_all<SPUThread>())
// raw_spu_threads_count++; {
//} if (thread->GetType() == CPU_THREAD_SPU)
{
sprintf(name, "Thread: ID = 0x%08x '%s', - %s", thread->GetId(), thread->GetName().c_str(), thread->ThreadStatusToString());
m_tree->AppendItem(node, name);
}
}
}
//if (ppu_threads_count) if (u32 count = Emu.GetIdManager().get_count<RawSPUThread>())
//{ {
// sprintf(name, "PPU Threads (%d)", ppu_threads_count); sprintf(name, "RawSPU Threads (%d)", count);
// const auto& node = m_tree->AppendItem(root, name); const auto& node = m_tree->AppendItem(root, name);
// for (const auto& thread : objects)
// {
// if (thread->GetType() == CPU_THREAD_PPU)
// {
// sprintf(name, "Thread: ID = 0x%08x '%s', - %s", thread->GetId(), thread->GetName().c_str(), thread->ThreadStatusToString().c_str());
// m_tree->AppendItem(node, name);
// }
// }
//}
//if (spu_threads_count)
//{
// sprintf(name, "SPU Threads (%d)", spu_threads_count);
// const auto& node = m_tree->AppendItem(root, name);
// for (const auto& thread : objects)
// {
// if (thread->GetType() == CPU_THREAD_SPU)
// {
// sprintf(name, "Thread: ID = 0x%08x '%s', - %s", thread->GetId(), thread->GetName().c_str(), thread->ThreadStatusToString().c_str());
// m_tree->AppendItem(node, name);
// }
// }
//}
//if (raw_spu_threads_count)
//{
// sprintf(name, "RawSPU Threads (%d)", raw_spu_threads_count);
// const auto& node = m_tree->AppendItem(root, name);
// for (const auto& thread : objects)
// {
// if (thread->GetType() == CPU_THREAD_RAW_SPU)
// {
// sprintf(name, "Thread: ID = 0x%08x '%s', - %s", thread->GetId(), thread->GetName().c_str(), thread->ThreadStatusToString().c_str());
// m_tree->AppendItem(node, name);
// }
// }
//}
for (const auto& thread : Emu.GetIdManager().get_all<RawSPUThread>())
{
if (thread->GetType() == CPU_THREAD_RAW_SPU)
{
sprintf(name, "Thread: ID = 0x%08x '%s', - %s", thread->GetId(), thread->GetName().c_str(), thread->ThreadStatusToString());
m_tree->AppendItem(node, name);
}
}
} }
m_tree->Expand(root); m_tree->Expand(root);

View file

@ -424,7 +424,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
wxCheckBox* chbox_gs_3dmonitor = new wxCheckBox(p_graphics, wxID_ANY, "3D Monitor"); wxCheckBox* chbox_gs_3dmonitor = new wxCheckBox(p_graphics, wxID_ANY, "3D Monitor");
wxCheckBox* chbox_audio_dump = new wxCheckBox(p_audio, wxID_ANY, "Dump to file"); wxCheckBox* chbox_audio_dump = new wxCheckBox(p_audio, wxID_ANY, "Dump to file");
wxCheckBox* chbox_audio_conv = new wxCheckBox(p_audio, wxID_ANY, "Convert to 16 bit"); wxCheckBox* chbox_audio_conv = new wxCheckBox(p_audio, wxID_ANY, "Convert to 16 bit");
wxCheckBox* chbox_hle_logging = new wxCheckBox(p_hle, wxID_ANY, "Log all SysCalls"); wxCheckBox* chbox_hle_logging = new wxCheckBox(p_hle, wxID_ANY, "Log everything");
wxCheckBox* chbox_rsx_logging = new wxCheckBox(p_hle, wxID_ANY, "RSX Logging"); wxCheckBox* chbox_rsx_logging = new wxCheckBox(p_hle, wxID_ANY, "RSX Logging");
wxCheckBox* chbox_hle_hook_stfunc = new wxCheckBox(p_hle, wxID_ANY, "Hook static functions"); wxCheckBox* chbox_hle_hook_stfunc = new wxCheckBox(p_hle, wxID_ANY, "Hook static functions");
wxCheckBox* chbox_hle_savetty = new wxCheckBox(p_hle, wxID_ANY, "Save TTY output to file"); wxCheckBox* chbox_hle_savetty = new wxCheckBox(p_hle, wxID_ANY, "Save TTY output to file");