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:
parent
e050dcbc52
commit
5631382623
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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"));
|
||||
|
Loading…
Reference in New Issue
Block a user