kernel_explorer: More Improvements

This commit is contained in:
Eladash 2020-06-09 18:35:14 +03:00 committed by Megamouse
parent 22b1cc765a
commit 6892399699
18 changed files with 150 additions and 60 deletions

View File

@ -54,6 +54,23 @@ void fmt_class_string<ppu_syscall_code>::format(std::string& out, u64 arg)
out += ppu_get_syscall_name(arg);
}
template <>
void fmt_class_string<lv2_protocol>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto value)
{
switch (value)
{
case SYS_SYNC_FIFO: return "FIFO";
case SYS_SYNC_PRIORITY: return "PRIO";
case SYS_SYNC_PRIORITY_INHERIT: return "PRIO-INHER";
case SYS_SYNC_RETRY: return "RETRY";
}
return unknown;
});
}
static bool null_func(ppu_thread& ppu)
{
ppu_log.todo("Unimplemented syscall %s -> CELL_OK (r3=0x%llx, r4=0x%llx, r5=0x%llx, r6=0x%llx, r7=0x%llx, r8=0x%llx, r9=0x%llx, r10=0x%llx)", ppu_syscall_code(ppu.gpr[11]),

View File

@ -33,6 +33,7 @@ error_code sys_cond_create(ppu_thread& ppu, vm::ptr<u32> cond_id, u32 mutex_id,
_attr.flags,
_attr.ipc_key,
_attr.name_u64,
mutex_id,
std::move(mutex));
}))
{

View File

@ -26,16 +26,18 @@ struct lv2_cond final : lv2_obj
const s32 flags;
const u64 key;
const u64 name;
const u32 mtx_id;
std::shared_ptr<lv2_mutex> mutex; // Associated Mutex
atomic_t<u32> waiters{0};
std::deque<cpu_thread*> sq;
lv2_cond(u32 shared, s32 flags, u64 key, u64 name, std::shared_ptr<lv2_mutex> mutex)
lv2_cond(u32 shared, s32 flags, u64 key, u64 name, u32 mtx_id, std::shared_ptr<lv2_mutex> mutex)
: shared(shared)
, flags(flags)
, key(key)
, name(name)
, mtx_id(mtx_id)
, mutex(std::move(mutex))
{
this->mutex->cond_count++;

View File

@ -79,7 +79,7 @@ struct lv2_event_queue final : public lv2_obj
{
static const u32 id_base = 0x8d000000;
const u32 protocol;
const lv2_protocol protocol;
const s32 type;
const u64 name;
const u64 key;
@ -91,7 +91,7 @@ struct lv2_event_queue final : public lv2_obj
std::deque<cpu_thread*> sq;
lv2_event_queue(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size)
: protocol(protocol)
: protocol{protocol}
, type(type)
, name(name)
, key(ipc_key)

View File

@ -35,7 +35,7 @@ struct lv2_event_flag final : lv2_obj
{
static const u32 id_base = 0x98000000;
const u32 protocol;
const lv2_protocol protocol;
const u32 shared;
const u64 key;
const s32 flags;
@ -48,7 +48,7 @@ struct lv2_event_flag final : lv2_obj
std::deque<cpu_thread*> sq;
lv2_event_flag(u32 protocol, u32 shared, u64 key, s32 flags, s32 type, u64 name, u64 pattern)
: protocol(protocol)
: protocol{protocol}
, shared(shared)
, key(key)
, flags(flags)

View File

@ -27,7 +27,7 @@ struct lv2_lwcond final : lv2_obj
const be_t<u64> name;
const u32 lwid;
const u32 protocol;
const lv2_protocol protocol;
vm::ptr<sys_lwcond_t> control;
shared_mutex mutex;
@ -37,7 +37,7 @@ struct lv2_lwcond final : lv2_obj
lv2_lwcond(u64 name, u32 lwid, u32 protocol, vm::ptr<sys_lwcond_t> control)
: name(std::bit_cast<be_t<u64>>(name))
, lwid(lwid)
, protocol(protocol)
, protocol{protocol}
, control(control)
{
}

View File

@ -55,7 +55,7 @@ struct lv2_lwmutex final : lv2_obj
{
static const u32 id_base = 0x95000000;
const u32 protocol;
const lv2_protocol protocol;
const vm::ptr<sys_lwmutex_t> control;
const be_t<u64> name;
@ -65,7 +65,7 @@ struct lv2_lwmutex final : lv2_obj
atomic_t<s32> lwcond_waiters{0};
lv2_lwmutex(u32 protocol, vm::ptr<sys_lwmutex_t> control, u64 name)
: protocol(protocol)
: protocol{protocol}
, control(control)
, name(std::bit_cast<be_t<u64>>(name))
{

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "sys_sync.h"
@ -25,7 +25,7 @@ struct lv2_mutex final : lv2_obj
{
static const u32 id_base = 0x85000000;
const u32 protocol;
const lv2_protocol protocol;
const u32 recursive;
const u32 shared;
const u32 adaptive;
@ -40,7 +40,7 @@ struct lv2_mutex final : lv2_obj
std::deque<cpu_thread*> sq;
lv2_mutex(u32 protocol, u32 recursive, u32 shared, u32 adaptive, u64 key, s32 flags, u64 name)
: protocol(protocol)
: protocol{protocol}
, recursive(recursive)
, shared(shared)
, adaptive(adaptive)

View File

@ -80,6 +80,42 @@ void fmt_class_string<sys_net_error>::format(std::string& out, u64 arg)
});
}
template <>
void fmt_class_string<lv2_socket_type>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto value)
{
switch (value)
{
case SYS_NET_SOCK_STREAM: return "STREAM";
case SYS_NET_SOCK_DGRAM: return "DGRAM";
case SYS_NET_SOCK_RAW: return "RAW";
case SYS_NET_SOCK_DGRAM_P2P: return "DGRAM-P2P";
case SYS_NET_SOCK_STREAM_P2P: return "STREAM-P2P";
}
return unknown;
});
}
template <>
void fmt_class_string<lv2_socket_family>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto value)
{
switch (value)
{
case SYS_NET_AF_UNSPEC: return "UNSPEC";
case SYS_NET_AF_LOCAL: return "LOCAL";
case SYS_NET_AF_INET: return "INET";
case SYS_NET_AF_INET6: return "INET6";
}
return unknown;
});
}
template <>
void fmt_class_string<struct in_addr>::format(std::string& out, u64 arg)
{
@ -346,8 +382,8 @@ struct network_thread
using network_context = named_thread<network_thread>;
lv2_socket::lv2_socket(lv2_socket::socket_type s, s32 s_type)
: socket(s), type(s_type)
lv2_socket::lv2_socket(lv2_socket::socket_type s, s32 s_type, s32 family)
: socket(s), type{s_type}, family{family}
{
// Set non-blocking
#ifdef _WIN32
@ -470,7 +506,7 @@ error_code sys_net_bnet_accept(ppu_thread& ppu, s32 s, vm::ptr<sys_net_sockaddr>
return 0;
}
auto newsock = std::make_shared<lv2_socket>(native_socket, 0);
auto newsock = std::make_shared<lv2_socket>(native_socket, 0, 0);
result = idm::import_existing<lv2_socket>(newsock);
@ -1823,7 +1859,7 @@ error_code sys_net_bnet_socket(ppu_thread& ppu, s32 family, s32 type, s32 protoc
return -get_last_error(false);
}
const s32 s = idm::import_existing<lv2_socket>(std::make_shared<lv2_socket>(native_socket, type));
const s32 s = idm::import_existing<lv2_socket>(std::make_shared<lv2_socket>(native_socket, type, family));
if (s == id_manager::id_traits<lv2_socket>::invalid)
{

View File

@ -58,7 +58,7 @@ static constexpr sys_net_error operator-(sys_net_error v)
}
// Socket types (prefixed with SYS_NET_)
enum
enum lv2_socket_type : s32
{
SYS_NET_SOCK_STREAM = 1,
SYS_NET_SOCK_DGRAM = 2,
@ -95,7 +95,7 @@ enum
};
// Family (prefixed with SYS_NET_)
enum
enum lv2_socket_family : s32
{
SYS_NET_AF_UNSPEC = 0,
SYS_NET_AF_LOCAL = 1,
@ -328,7 +328,7 @@ struct lv2_socket final
__bitset_enum_max
};
lv2_socket(socket_type s, s32 s_type);
lv2_socket(socket_type s, s32 s_type, s32 family);
~lv2_socket();
shared_mutex mutex;
@ -353,7 +353,8 @@ struct lv2_socket final
// Unsupported option
s32 so_tcp_maxseg = 1500;
s32 type = 0;
const lv2_socket_type type;
const lv2_socket_family family;
// Value keepers
#ifdef _WIN32

View File

@ -23,7 +23,7 @@ struct lv2_rwlock final : lv2_obj
{
static const u32 id_base = 0x88000000;
const u32 protocol;
const lv2_protocol protocol;
const u32 shared;
const u64 key;
const u64 name;
@ -35,7 +35,7 @@ struct lv2_rwlock final : lv2_obj
std::deque<cpu_thread*> wq;
lv2_rwlock(u32 protocol, u32 shared, u64 key, s32 flags, u64 name)
: protocol(protocol)
: protocol{protocol}
, shared(shared)
, key(key)
, name(name)

View File

@ -23,7 +23,7 @@ struct lv2_sema final : lv2_obj
{
static const u32 id_base = 0x96000000;
const u32 protocol;
const lv2_protocol protocol;
const u32 shared;
const u64 key;
const u64 name;
@ -35,7 +35,7 @@ struct lv2_sema final : lv2_obj
std::deque<cpu_thread*> sq;
lv2_sema(u32 protocol, u32 shared, u64 key, s32 flags, u64 name, s32 max, s32 value)
: protocol(protocol)
: protocol{protocol}
, shared(shared)
, key(key)
, name(name)

View File

@ -17,7 +17,7 @@
#include <string_view>
// attr_protocol (waiting scheduling policy)
enum
enum lv2_protocol : u32
{
SYS_SYNC_FIFO = 0x1, // First In, First Out Order
SYS_SYNC_PRIORITY = 0x2, // Priority Order

View File

@ -110,22 +110,11 @@ error_code sys_timer_get_information(ppu_thread& ppu, u32 timer_id, vm::ptr<sys_
sys_timer.trace("sys_timer_get_information(timer_id=0x%x, info=*0x%x)", timer_id, info);
sys_timer_information_t _info{};
const auto timer = idm::check<lv2_obj, lv2_timer>(timer_id, [&](lv2_timer& timer)
{
std::shared_lock lock(timer.mutex);
if (timer.state == SYS_TIMER_STATE_RUN)
{
info->timer_state = SYS_TIMER_STATE_RUN;
info->next_expire = timer.expire;
info->period = timer.period;
}
else
{
info->timer_state = SYS_TIMER_STATE_STOP;
info->next_expire = 0;
info->period = 0;
}
timer.get_information(_info);
});
if (!timer)
@ -133,6 +122,7 @@ error_code sys_timer_get_information(ppu_thread& ppu, u32 timer_id, vm::ptr<sys_
return CELL_ESRCH;
}
std::memcpy(info.get_ptr(), &_info, info.size());
return CELL_OK;
}

View File

@ -37,6 +37,24 @@ struct lv2_timer_context : lv2_obj
atomic_t<u64> expire{0}; // Next expiration time
atomic_t<u64> period{0}; // Period (oneshot if 0)
void get_information(sys_timer_information_t& info)
{
std::shared_lock lock(mutex);
if (state == SYS_TIMER_STATE_RUN)
{
info.timer_state = SYS_TIMER_STATE_RUN;
info.next_expire = expire;
info.period = period;
}
else
{
info.timer_state = SYS_TIMER_STATE_STOP;
info.next_expire = 0;
info.period = 0;
}
}
};
using lv2_timer = named_thread<lv2_timer_context>;

View File

@ -24,7 +24,10 @@
#include "Emu/Cell/lv2/sys_mmapper.h"
#include "Emu/Cell/lv2/sys_spu.h"
#include "Emu/Cell/lv2/sys_process.h"
#include "Emu/Cell/lv2/sys_timer.h"
#include "Emu/Cell/lv2/sys_rsx.h"
#include "Emu/Cell/lv2/sys_vm.h"
#include "Emu/Cell/lv2/sys_net.h"
#include "Emu/Cell/lv2/sys_fs.h"
#include "Emu/RSX/RSXThread.h"
@ -169,6 +172,7 @@ void kernel_explorer::Update()
if (!dct)
{
m_tree->clear();
return;
}
@ -176,7 +180,8 @@ void kernel_explorer::Update()
const std::unordered_map<u32, QString> tree_item_names =
{
{ SYS_MEM_OBJECT , tr("Memory")},
{ SYS_MEM_OBJECT , tr("Shared Memory")},
{ virtual_memory , tr("Virtual Memory")},
{ SYS_MUTEX_OBJECT , tr("Mutexes")},
{ SYS_COND_OBJECT , tr("Condition Variables")},
{ SYS_RWLOCK_OBJECT , tr("Reader Writer Locks")},
@ -201,6 +206,7 @@ void kernel_explorer::Update()
{ spu_threads , tr("SPU Threads")},
{ spu_thread_groups , tr("SPU Thread Groups")},
{ rsx_contexts , tr("RSX Contexts")},
{ sockets , tr("Sockets")},
{ file_descriptors , tr("File Descriptors")},
};
@ -279,27 +285,27 @@ void kernel_explorer::Update()
case SYS_MEM_OBJECT:
{
auto& mem = static_cast<lv2_memory&>(obj);
add_leaf(node, qstr(fmt::format("Memory 0x%08x: Size: 0x%x (%0.2f MB), Granularity: %s, Mappings: %u", id, mem.size, mem.size * 1. / (1024 * 1024), mem.align == 0x10000u ? "64K" : "1MB", +mem.counter)));
add_leaf(node, qstr(fmt::format("Shared Mem 0x%08x: Size: 0x%x (%0.2f MB), Granularity: %s, Mappings: %u", id, mem.size, mem.size * 1. / (1024 * 1024), mem.align == 0x10000u ? "64K" : "1MB", +mem.counter)));
break;
}
case SYS_MUTEX_OBJECT:
{
auto& mutex = static_cast<lv2_mutex&>(obj);
add_leaf(node, qstr(fmt::format(u8"Mutex 0x%08x: “%s”,%s Owner: %#x, Locks: %u, Key: %#llx, Conds: %u, Wq: %zu", id, lv2_obj::name64(mutex.name),
add_leaf(node, qstr(fmt::format(u8"Mutex 0x%08x: “%s”, %s,%s Owner: %#x, Locks: %u, Key: %#llx, Conds: %u, Wq: %zu", id, lv2_obj::name64(mutex.name), mutex.protocol,
mutex.recursive == SYS_SYNC_RECURSIVE ? " Recursive," : "", mutex.owner >> 1, +mutex.lock_count, mutex.key, +mutex.cond_count, mutex.sq.size())));
break;
}
case SYS_COND_OBJECT:
{
auto& cond = static_cast<lv2_cond&>(obj);
add_leaf(node, qstr(fmt::format(u8"Cond 0x%08x: “%s”, Key: %#llx, Wq: %u", id, lv2_obj::name64(cond.name), cond.key, +cond.waiters)));
add_leaf(node, qstr(fmt::format(u8"Cond 0x%08x: “%s”, %s, Mutex: 0x%08x, Key: %#llx, Wq: %u", id, lv2_obj::name64(cond.name), cond.mutex->protocol, cond.mtx_id, cond.key, +cond.waiters)));
break;
}
case SYS_RWLOCK_OBJECT:
{
auto& rw = static_cast<lv2_rwlock&>(obj);
const s64 val = rw.owner;
add_leaf(node, qstr(fmt::format(u8"RW Lock 0x%08x: “%s”, Owner: %#x(%d), Key: %#llx, Rq: %zu, Wq: %zu", id, lv2_obj::name64(rw.name),
add_leaf(node, qstr(fmt::format(u8"RW Lock 0x%08x: “%s”, %s, Owner: %#x(%d), Key: %#llx, Rq: %zu, Wq: %zu", id, lv2_obj::name64(rw.name), rw.protocol,
std::max<s64>(0, val >> 1), -std::min<s64>(0, val >> 1), rw.key, rw.rq.size(), rw.wq.size())));
break;
}
@ -318,7 +324,7 @@ void kernel_explorer::Update()
case SYS_EVENT_QUEUE_OBJECT:
{
auto& eq = static_cast<lv2_event_queue&>(obj);
add_leaf(node, qstr(fmt::format(u8"Event Queue 0x%08x: “%s”, %s, Key: %#llx, Events: %zu/%d, Wq: %zu", id, lv2_obj::name64(eq.name),
add_leaf(node, qstr(fmt::format(u8"Event Queue 0x%08x: “%s”, %s, %s, Key: %#llx, Events: %zu/%d, Wq: %zu", id, lv2_obj::name64(eq.name), eq.protocol,
eq.type == SYS_SPU_QUEUE ? "SPU" : "PPU", eq.key, eq.events.size(), eq.size, eq.sq.size())));
break;
}
@ -391,38 +397,43 @@ void kernel_explorer::Update()
}
else
{
add_leaf(node, qstr(fmt::format(u8"LWMutex 0x%08x: “%s”, Wq: %zu (Couldn't extract control data)", id, lv2_obj::name64(lwm.name), lwm.sq.size())));
add_leaf(node, qstr(fmt::format(u8"LWMutex 0x%08x: “%s”, %s, Wq: %zu (Couldn't extract control data)", id, lv2_obj::name64(lwm.name), lwm.protocol, lwm.sq.size())));
break;
}
add_leaf(node, qstr(fmt::format(u8"LWMutex 0x%08x: “%s”,%s Owner: %s, Locks: %u, Wq: %zu", id, lv2_obj::name64(lwm.name),
add_leaf(node, qstr(fmt::format(u8"LWMutex 0x%08x: “%s”, %s,%s Owner: %s, Locks: %u, Wq: %zu", id, lv2_obj::name64(lwm.name), lwm.protocol,
(lwm_data.attribute & SYS_SYNC_RECURSIVE) ? " Recursive," : "", owner_str, lwm_data.recursive_count, lwm.sq.size())));
break;
}
case SYS_TIMER_OBJECT:
{
// auto& timer = static_cast<lv2_timer&>(obj);
add_leaf(node, qstr(fmt::format("Timer 0x%08x", id)));
auto& timer = static_cast<lv2_timer&>(obj);
sys_timer_information_t info;
timer.get_information(info);
add_leaf(node, qstr(fmt::format("Timer 0x%08x: State: %s, Period: 0x%llx, Next Expire: 0x%llx", id, info.timer_state ? "Running" : "Stopped"
, info.period, info.next_expire)));
break;
}
case SYS_SEMAPHORE_OBJECT:
{
auto& sema = static_cast<lv2_sema&>(obj);
const auto val = +sema.val;
add_leaf(node, qstr(fmt::format(u8"Sema 0x%08x: “%s”, Count: %d/%d, Wq: %zu", id, lv2_obj::name64(sema.name),
std::max<s32>(val, 0), sema.max, -std::min<s32>(val, 0))));
add_leaf(node, qstr(fmt::format(u8"Sema 0x%08x: “%s”, %s, Count: %d/%d, Key: %#llx, Wq: %zu", id, lv2_obj::name64(sema.name), sema.protocol,
std::max<s32>(val, 0), sema.max, sema.key, -std::min<s32>(val, 0))));
break;
}
case SYS_LWCOND_OBJECT:
{
auto& lwc = static_cast<lv2_lwcond&>(obj);
add_leaf(node, qstr(fmt::format(u8"LWCond 0x%08x: “%s”, Wq: %zu", id, lv2_obj::name64(lwc.name), +lwc.waiters)));
add_leaf(node, qstr(fmt::format(u8"LWCond 0x%08x: “%s”, %s, OG LWMutex: 0x%08x, Wq: %zu", id, lv2_obj::name64(lwc.name), lwc.protocol, lwc.lwid, +lwc.waiters)));
break;
}
case SYS_EVENT_FLAG_OBJECT:
{
auto& ef = static_cast<lv2_event_flag&>(obj);
add_leaf(node, qstr(fmt::format(u8"Event Flag 0x%08x: “%s”, Type: 0x%x, Key: %#llx, Pattern: 0x%llx, Wq: %zu", id, lv2_obj::name64(ef.name),
add_leaf(node, qstr(fmt::format(u8"Event Flag 0x%08x: “%s”, %s, Type: 0x%x, Key: %#llx, Pattern: 0x%llx, Wq: %zu", id, lv2_obj::name64(ef.name), ef.protocol,
ef.type, ef.key, ef.pattern.load(), +ef.waiters)));
break;
}
@ -433,6 +444,18 @@ void kernel_explorer::Update()
}
});
idm::select<sys_vm_t>([&](u32 /*id*/, sys_vm_t& vmo)
{
const u32 psize = vmo.psize;
add_leaf(find_node(m_tree, additional_nodes::virtual_memory), qstr(fmt::format("Virtual Mem 0x%08x: Virtual Size: 0x%x (%0.2f MB), Physical Size: 0x%x (%0.2f MB)", vmo.addr
, vmo.size, vmo.size * 1. / (1024 * 1024), psize, psize * 1. / (1024 * 1024))));
});
idm::select<lv2_socket>([&](u32 id, lv2_socket& sock)
{
add_leaf(find_node(m_tree, additional_nodes::sockets), qstr(fmt::format("Socket %u: Type: %s, Family: %s, Wq: %zu", id, sock.type, sock.family, sock.queue.size())));
});
idm::select<lv2_memory_container>([&](u32 id, lv2_memory_container& container)
{
const u32 used = container.used;

View File

@ -13,12 +13,14 @@ class kernel_explorer : public QDialog
enum additional_nodes
{
memory_containers = sys_size + 0,
ppu_threads = sys_size + 1,
spu_threads = sys_size + 2,
spu_thread_groups = sys_size + 3,
rsx_contexts = sys_size + 4,
file_descriptors = sys_size + 5,
memory_containers = sys_size,
virtual_memory,
sockets,
ppu_threads,
spu_threads,
spu_thread_groups,
rsx_contexts,
file_descriptors,
};
public:

View File

@ -334,7 +334,7 @@ namespace gui
if (parent)
{
QTreeWidgetItem *tree_item = new QTreeWidgetItem();
tree_item->setText(0, text);
tree_item->setText(column, text);
parent->addChild(tree_item);
return tree_item;
}