1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-21 18:22:33 +01:00

sys_spu: Fix SPU Thread Id

* Removed wrong code in sys_spu_thread_group_terminate.
* SPU Thread ID is accurate, including 5th thread id "rule".
* Fixed possible use-after-free access of spu_thread::group member.
* RawSPU ID management simplified.
This commit is contained in:
Eladash 2019-11-03 01:44:02 +02:00 committed by Ivan
parent e050dcbc52
commit 5631382623
7 changed files with 122 additions and 120 deletions

View File

@ -1319,14 +1319,15 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
{
data2 = (SYS_MEMORY_PAGE_FAULT_TYPE_PPU_THREAD << 32) | cpu->id;
}
else if (static_cast<spu_thread*>(cpu)->group)
{
data2 = (SYS_MEMORY_PAGE_FAULT_TYPE_SPU_THREAD << 32) | cpu->id;
}
else
{
// Index is the correct ID in RawSPU
data2 = (SYS_MEMORY_PAGE_FAULT_TYPE_RAW_SPU << 32) | static_cast<spu_thread*>(cpu)->index;
const auto& spu = static_cast<spu_thread&>(*cpu);
const u64 type = spu.offset < RAW_SPU_BASE_ADDR ?
SYS_MEMORY_PAGE_FAULT_TYPE_SPU_THREAD :
SYS_MEMORY_PAGE_FAULT_TYPE_RAW_SPU;
data2 = (type << 32) | spu.lv2_id;
}
u64 data3;

View File

@ -266,7 +266,7 @@ bool spu_thread::write_reg(const u32 addr, const u32 value)
void spu_load_exec(const spu_exec_object& elf)
{
auto ls0 = vm::cast(vm::falloc(RAW_SPU_BASE_ADDR, 0x80000, vm::spu));
auto spu = idm::make_ptr<named_thread<spu_thread>>("TEST_SPU", ls0, nullptr, 0, "");
auto spu = idm::make_ptr<named_thread<spu_thread>>("TEST_SPU", ls0, nullptr, 0, "", 0);
spu_thread::g_raw_spu_ctr++;
spu_thread::g_raw_spu_id[0] = spu->id;

View File

@ -991,7 +991,7 @@ spu_imm_table_t::spu_imm_table_t()
std::string spu_thread::get_name() const
{
return fmt::format("%sSPU[0x%x] Thread (%s)", offset >= RAW_SPU_BASE_ADDR ? "Raw" : "", id, spu_name.get());
return fmt::format("%sSPU[0x%07x] Thread (%s)", offset >= RAW_SPU_BASE_ADDR ? "Raw" : "", lv2_id, spu_name.get());
}
std::string spu_thread::dump() const
@ -1202,12 +1202,13 @@ spu_thread::~spu_thread()
}
}
spu_thread::spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name)
spu_thread::spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id)
: cpu_thread(idm::last_id())
, spu_name(name)
, index(index)
, offset(ls)
, group(group)
, lv2_id(lv2_id)
{
if (g_cfg.core.spu_decoder == spu_decoder_type::asmjit)
{
@ -1295,9 +1296,9 @@ void spu_thread::do_dma_transfer(const spu_mfc_cmd& args)
{
fmt::throw_exception("SPU MMIO used for RawSPU (cmd=0x%x, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x)" HERE, args.cmd, args.lsa, args.eal, args.tag, args.size);
}
else if (group && group->threads[index])
else if (group && group->threads_map[index] != -1)
{
auto& spu = static_cast<spu_thread&>(*group->threads[index]);
auto& spu = static_cast<spu_thread&>(*group->threads[group->threads_map[index]]);
if (offset + args.size - 1 < 0x40000) // LS access
{
@ -2506,7 +2507,7 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)
ch_in_mbox.set_values(1, CELL_OK);
if (!queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, id, (u64{spup} << 32) | (value & 0x00ffffff), data))
if (!queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, lv2_id, (u64{spup} << 32) | (value & 0x00ffffff), data))
{
ch_in_mbox.set_values(1, CELL_EBUSY);
}
@ -2536,7 +2537,7 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)
}
// TODO: check passing spup value
if (!queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, id, (u64{spup} << 32) | (value & 0x00ffffff), data))
if (!queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, lv2_id, (u64{spup} << 32) | (value & 0x00ffffff), data))
{
LOG_WARNING(SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x) failed (queue is full)", spup, (value & 0x00ffffff), data);
}

View File

@ -510,7 +510,7 @@ public:
static const u32 id_step = 1;
static const u32 id_count = 2048;
spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name);
spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id);
u32 pc = 0;
@ -575,7 +575,10 @@ public:
const u32 index; // SPU index
const u32 offset; // SPU LS offset
lv2_spu_group* const group; // SPU Thread Group
private:
lv2_spu_group* const group; // SPU Thread Group (only safe to access in the spu thread itself)
public:
const u32 lv2_id; // The actual id that is used by syscalls
lf_value<std::string> spu_name; // Thread name

View File

@ -141,6 +141,29 @@ void sys_spu_image::deploy(u32 loc, sys_spu_segment* segs, u32 nsegs)
LOG_NOTICE(LOADER, "Loaded SPU image: %s (<- %u)%s", hash, applied, dump);
}
// Get spu thread ptr, returns group ptr as well for refcounting
std::pair<named_thread<spu_thread>*, std::shared_ptr<lv2_spu_group>> lv2_spu_group::get_thread(u32 id)
{
if (id >= 0x06000000)
{
// thread index is out of range (5 max)
return {};
}
// Bits 0-23 contain group id (without id base)
decltype(get_thread(0)) res{nullptr, idm::get<lv2_spu_group>((id & 0xFFFFFF) | (lv2_spu_group::id_base & ~0xFFFFFF))};
// Bits 24-31 contain thread index within the group
const u32 index = id >> 24;
if (auto group = res.second.get(); group && group->init > index)
{
res.first = group->threads[index].get();
}
return res;
}
error_code sys_spu_initialize(ppu_thread& ppu, u32 max_usable_spu, u32 max_raw_spu)
{
vm::temporary_unlock(ppu);
@ -253,9 +276,7 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
return CELL_ESRCH;
}
std::lock_guard lock(group->mutex);
if (spu_num >= group->threads.size())
if (spu_num >= group->threads_map.size())
{
return CELL_EINVAL;
}
@ -265,7 +286,9 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
return CELL_EINVAL;
}
if (group->threads[spu_num] || group->run_state != SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED)
std::lock_guard lock(group->mutex);
if (group->threads_map[spu_num] != -1 || group->run_state != SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED)
{
return CELL_EBUSY;
}
@ -292,26 +315,30 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
const vm::addr_t ls_addr{verify("SPU LS" HERE, vm::alloc(0x80000, vm::main))};
const u32 tid = idm::import<named_thread<spu_thread>>([&]()
{
const u32 tid = idm::last_id();
const u32 inited = group->init;
std::string full_name = fmt::format("SPU[0x%x] Thread", tid);
const u32 tid = (inited << 24) | (group_id & 0xffffff);
verify(HERE), idm::import<named_thread<spu_thread>>([&]()
{
std::string full_name = fmt::format("SPU[0x%07x] Thread", tid);
if (!thread_name.empty())
{
fmt::append(full_name, " (%s)", thread_name);
}
group->threads[spu_num] = std::make_shared<named_thread<spu_thread>>(full_name, ls_addr, group.get(), spu_num, thread_name);
return group->threads[spu_num];
const auto spu = std::make_shared<named_thread<spu_thread>>(full_name, ls_addr, group.get(), spu_num, thread_name, tid);
group->threads[inited] = spu;
group->threads_map[spu_num] = static_cast<s8>(inited);
return spu;
});
*thread = tid;
group->args[spu_num] = {arg->arg1, arg->arg2, arg->arg3, arg->arg4};
group->imgs[spu_num] = std::make_pair(image, std::vector<sys_spu_segment>());
group->imgs[spu_num].second.assign(img->segs.get_ptr(), img->segs.get_ptr() + img->nsegs);
group->args[inited] = {arg->arg1, arg->arg2, arg->arg3, arg->arg4};
group->imgs[inited].first = image;
group->imgs[inited].second.assign(img->segs.get_ptr(), img->segs.get_ptr() + img->nsegs);
if (++group->init == group->max_num)
{
@ -320,7 +347,7 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
if (group->name.size() >= 20 && group->name.compare(group->name.size() - 20, 20, "CellSpursKernelGroup", 20) == 0)
{
// Hack: don't run more SPURS threads than specified.
group->init = g_cfg.core.max_spurs_threads;
group->max_run = g_cfg.core.max_spurs_threads;
LOG_SUCCESS(SPU, "HACK: '%s' (0x%x) limited to %u threads.", group->name, group_id, +g_cfg.core.max_spurs_threads);
}
@ -338,18 +365,16 @@ error_code sys_spu_thread_set_argument(ppu_thread& ppu, u32 id, vm::ptr<sys_spu_
sys_spu.warning("sys_spu_thread_set_argument(id=0x%x, arg=*0x%x)", id, arg);
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
if (UNLIKELY(!thread || !thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
const auto group = thread->group;
std::lock_guard lock(group->mutex);
group->args[thread->index] = {arg->arg1, arg->arg2, arg->arg3, arg->arg4};
group->args[id >> 24] = {arg->arg1, arg->arg2, arg->arg3, arg->arg4};
return CELL_OK;
}
@ -360,9 +385,9 @@ error_code sys_spu_thread_get_exit_status(ppu_thread& ppu, u32 id, vm::ptr<u32>
sys_spu.warning("sys_spu_thread_get_exit_status(id=0x%x, status=*0x%x)", id, status);
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
if (UNLIKELY(!thread || !thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -427,11 +452,11 @@ error_code sys_spu_thread_group_destroy(ppu_thread& ppu, u32 id)
return group.ret;
}
// Cleanup
for (auto& ptr : group->threads)
for (const auto& t : group->threads)
{
if (auto thread = std::move(ptr))
if (auto thread = t.get())
{
// Remove ID from IDM (destruction will occur in group destructor)
idm::remove<named_thread<spu_thread>>(thread->id);
}
}
@ -463,23 +488,17 @@ error_code sys_spu_thread_group_start(ppu_thread& ppu, u32 id)
std::lock_guard lock(group->mutex);
u32 max_threads = +group->init;
const u32 max_threads = group->max_run;
group->join_state = 0;
group->running = max_threads;
u32 run_threads = max_threads;
for (auto& thread : group->threads)
{
if (!run_threads)
if (thread)
{
break;
}
if (thread && run_threads--)
{
auto& args = group->args[thread->index];
auto& img = group->imgs[thread->index];
auto& args = group->args[thread->lv2_id >> 24];
auto& img = group->imgs[thread->lv2_id >> 24];
sys_spu_image::deploy(thread->offset, img.second.data(), img.first.nsegs);
@ -653,35 +672,13 @@ error_code sys_spu_thread_group_terminate(ppu_thread& ppu, u32 id, s32 value)
sys_spu.trace("sys_spu_thread_group_terminate(id=0x%x, value=0x%x)", id, value);
// The id can be either SPU Thread Group or SPU Thread
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto _group = idm::get<lv2_spu_group>(id);
const auto group = thread ? thread->group : _group.get();
const auto group = idm::get<lv2_spu_group>(id);
if (!group && (!thread || !thread->group))
if (!group)
{
return CELL_ESRCH;
}
if (thread)
{
for (auto& t : group->threads)
{
// find primary (?) thread and compare it with the one specified
if (t)
{
if (t == thread)
{
break;
}
else
{
return CELL_EPERM;
}
}
}
}
std::unique_lock lock(group->mutex);
if (group->run_state <= SPU_THREAD_GROUP_STATUS_INITIALIZED ||
@ -863,15 +860,13 @@ error_code sys_spu_thread_write_ls(ppu_thread& ppu, u32 id, u32 lsa, u64 value,
return CELL_EINVAL;
}
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
if (UNLIKELY(!thread || !thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
const auto group = thread->group;
std::lock_guard lock(group->mutex);
if (group->run_state < SPU_THREAD_GROUP_STATUS_WAITING || group->run_state > SPU_THREAD_GROUP_STATUS_RUNNING)
@ -902,15 +897,13 @@ error_code sys_spu_thread_read_ls(ppu_thread& ppu, u32 id, u32 lsa, vm::ptr<u64>
return CELL_EINVAL;
}
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
if (UNLIKELY(!thread || !thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
const auto group = thread->group;
std::lock_guard lock(group->mutex);
if (group->run_state < SPU_THREAD_GROUP_STATUS_WAITING || group->run_state > SPU_THREAD_GROUP_STATUS_RUNNING)
@ -936,15 +929,13 @@ error_code sys_spu_thread_write_spu_mb(ppu_thread& ppu, u32 id, u32 value)
sys_spu.warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x)", id, value);
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
if (UNLIKELY(!thread || !thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
const auto group = thread->group;
std::lock_guard lock(group->mutex);
thread->ch_in_mbox.push(*thread, value);
@ -963,9 +954,9 @@ error_code sys_spu_thread_set_spu_cfg(ppu_thread& ppu, u32 id, u64 value)
return CELL_EINVAL;
}
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
if (UNLIKELY(!thread || !thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -981,9 +972,9 @@ error_code sys_spu_thread_get_spu_cfg(ppu_thread& ppu, u32 id, vm::ptr<u64> valu
sys_spu.warning("sys_spu_thread_get_spu_cfg(id=0x%x, value=*0x%x)", id, value);
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
if (UNLIKELY(!thread || !thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -999,9 +990,9 @@ error_code sys_spu_thread_write_snr(ppu_thread& ppu, u32 id, u32 number, u32 val
sys_spu.trace("sys_spu_thread_write_snr(id=0x%x, number=%d, value=0x%x)", id, number, value);
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
if (UNLIKELY(!thread || !thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -1102,10 +1093,10 @@ error_code sys_spu_thread_connect_event(ppu_thread& ppu, u32 id, u32 eq, u32 et,
sys_spu.warning("sys_spu_thread_connect_event(id=0x%x, eq=0x%x, et=%d, spup=%d)", id, eq, et, spup);
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
const auto queue = idm::get<lv2_obj, lv2_event_queue>(eq);
if (UNLIKELY(!queue || !thread || !thread->group))
if (UNLIKELY(!queue || !thread))
{
return CELL_ESRCH;
}
@ -1116,7 +1107,7 @@ error_code sys_spu_thread_connect_event(ppu_thread& ppu, u32 id, u32 eq, u32 et,
return CELL_EINVAL;
}
std::lock_guard lock(thread->group->mutex);
std::lock_guard lock(group->mutex);
auto& port = thread->spup[spup];
@ -1136,9 +1127,9 @@ error_code sys_spu_thread_disconnect_event(ppu_thread& ppu, u32 id, u32 et, u8 s
sys_spu.warning("sys_spu_thread_disconnect_event(id=0x%x, et=%d, spup=%d)", id, et, spup);
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
if (UNLIKELY(!thread || !thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -1149,7 +1140,7 @@ error_code sys_spu_thread_disconnect_event(ppu_thread& ppu, u32 id, u32 et, u8 s
return CELL_EINVAL;
}
std::lock_guard lock(thread->group->mutex);
std::lock_guard lock(group->mutex);
auto& port = thread->spup[spup];
@ -1169,10 +1160,10 @@ error_code sys_spu_thread_bind_queue(ppu_thread& ppu, u32 id, u32 spuq, u32 spuq
sys_spu.warning("sys_spu_thread_bind_queue(id=0x%x, spuq=0x%x, spuq_num=0x%x)", id, spuq, spuq_num);
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
const auto queue = idm::get<lv2_obj, lv2_event_queue>(spuq);
if (UNLIKELY(!queue || !thread || !thread->group))
if (UNLIKELY(!queue || !thread))
{
return CELL_ESRCH;
}
@ -1182,7 +1173,7 @@ error_code sys_spu_thread_bind_queue(ppu_thread& ppu, u32 id, u32 spuq, u32 spuq
return CELL_EINVAL;
}
std::lock_guard lock(thread->group->mutex);
std::lock_guard lock(group->mutex);
decltype(std::data(thread->spuq)) q{};
@ -1223,14 +1214,14 @@ error_code sys_spu_thread_unbind_queue(ppu_thread& ppu, u32 id, u32 spuq_num)
sys_spu.warning("sys_spu_thread_unbind_queue(id=0x%x, spuq_num=0x%x)", id, spuq_num);
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
if (UNLIKELY(!thread || !thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
std::lock_guard lock(thread->group->mutex);
std::lock_guard lock(group->mutex);
for (auto& v : thread->spuq)
{
@ -1399,9 +1390,9 @@ error_code sys_spu_thread_recover_page_fault(ppu_thread& ppu, u32 id)
sys_spu.warning("sys_spu_thread_recover_page_fault(id=0x%x)", id);
const auto thread = idm::get<named_thread<spu_thread>>(id);
const auto [thread, group] = lv2_spu_group::get_thread(id);
if (UNLIKELY(!thread || !thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -1417,7 +1408,7 @@ error_code sys_raw_spu_recover_page_fault(ppu_thread& ppu, u32 id)
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (UNLIKELY(!thread || thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -1449,7 +1440,7 @@ error_code sys_raw_spu_create(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<void> at
const vm::addr_t ls_addr{verify(HERE, vm::falloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, 0x40000, vm::spu))};
const u32 tid = idm::make<named_thread<spu_thread>>(fmt::format("RawSPU[0x%x] Thread", index), ls_addr, nullptr, index, "");
const u32 tid = idm::make<named_thread<spu_thread>>(fmt::format("RawSPU[0x%x] Thread", index), ls_addr, nullptr, index, "", index);
spu_thread::g_raw_spu_id[index] = verify("RawSPU ID" HERE, tid);
@ -1466,7 +1457,7 @@ error_code sys_raw_spu_destroy(ppu_thread& ppu, u32 id)
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (UNLIKELY(!thread || thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -1538,7 +1529,7 @@ error_code sys_raw_spu_create_interrupt_tag(ppu_thread& ppu, u32 id, u32 class_i
auto thread = idm::check_unlocked<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (!thread || thread->group)
if (!thread)
{
error = CELL_ESRCH;
return result;
@ -1579,7 +1570,7 @@ error_code sys_raw_spu_set_int_mask(ppu_thread& ppu, u32 id, u32 class_id, u64 m
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (UNLIKELY(!thread || thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -1602,7 +1593,7 @@ error_code sys_raw_spu_get_int_mask(ppu_thread& ppu, u32 id, u32 class_id, vm::p
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (UNLIKELY(!thread || thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -1625,7 +1616,7 @@ error_code sys_raw_spu_set_int_stat(ppu_thread& ppu, u32 id, u32 class_id, u64 s
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (UNLIKELY(!thread || thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -1648,7 +1639,7 @@ error_code sys_raw_spu_get_int_stat(ppu_thread& ppu, u32 id, u32 class_id, vm::p
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (UNLIKELY(!thread || thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -1666,7 +1657,7 @@ error_code sys_raw_spu_read_puint_mb(ppu_thread& ppu, u32 id, vm::ptr<u32> value
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (UNLIKELY(!thread || thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -1689,7 +1680,7 @@ error_code sys_raw_spu_set_spu_cfg(ppu_thread& ppu, u32 id, u32 value)
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (UNLIKELY(!thread || thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}
@ -1707,7 +1698,7 @@ error_code sys_raw_spu_get_spu_cfg(ppu_thread& ppu, u32 id, vm::ptr<u32> value)
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (UNLIKELY(!thread || thread->group))
if (UNLIKELY(!thread))
{
return CELL_ESRCH;
}

View File

@ -241,6 +241,7 @@ struct lv2_spu_group
const u32 max_num;
const s32 type; // SPU Thread Group Type
const u32 ct; // Memory Container Id
u32 max_run;
shared_mutex mutex;
@ -254,9 +255,10 @@ struct lv2_spu_group
atomic_t<u64> stop_count;
class ppu_thread* waiter = nullptr;
std::array<std::shared_ptr<named_thread<spu_thread>>, 256> threads; // SPU Threads
std::array<std::pair<sys_spu_image, std::vector<sys_spu_segment>>, 256> imgs; // SPU Images
std::array<std::array<u64, 4>, 256> args; // SPU Thread Arguments
std::array<std::shared_ptr<named_thread<spu_thread>>, 8> threads; // SPU Threads
std::array<s8, 256> threads_map; // SPU Threads map based number
std::array<std::pair<sys_spu_image, std::vector<sys_spu_segment>>, 8> imgs; // SPU Images
std::array<std::array<u64, 4>, 8> args; // SPU Thread Arguments
std::weak_ptr<lv2_event_queue> ep_run; // port for SYS_SPU_THREAD_GROUP_EVENT_RUN events
std::weak_ptr<lv2_event_queue> ep_exception; // TODO: SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION
@ -266,6 +268,7 @@ struct lv2_spu_group
: id(idm::last_id())
, name(name)
, max_num(num)
, max_run(num)
, init(0)
, prio(prio)
, type(type)
@ -276,6 +279,7 @@ struct lv2_spu_group
, running(0)
, stop_count(0)
{
threads_map.fill(-1);
}
void send_run_event(u64 data1, u64 data2, u64 data3)
@ -301,6 +305,8 @@ struct lv2_spu_group
queue->send(SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE_KEY, data1, data2, data3);
}
}
static std::pair<named_thread<spu_thread>*, std::shared_ptr<lv2_spu_group>> get_thread(u32 id);
};
class ppu_thread;

View File

@ -281,7 +281,7 @@ void kernel_explorer::Update()
idm::select<named_thread<spu_thread>>([&](u32 id, spu_thread& spu)
{
lv2_types.back().count++;
l_addTreeChild(lv2_types.back().node, qstr(fmt::format("SPU Thread: ID = 0x%08x '%s'", id, spu.spu_name.get())));
l_addTreeChild(lv2_types.back().node, qstr(fmt::format("SPU Thread: ID = 0x%08x '%s'", spu.lv2_id, spu.spu_name.get())));
});
lv2_types.emplace_back(l_addTreeChild(root, "SPU Thread Groups"));