mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-12 13:13:43 +00:00
sys_spu: Implement proper SPU group flags (#7320)
* sys_spu: Implement proper SPU group flags
This commit is contained in:
parent
3cc42c1bf8
commit
f8b3c48af7
@ -2868,8 +2868,9 @@ bool spu_thread::stop_and_signal(u32 code)
|
||||
|
||||
spu_log.trace("sys_spu_thread_receive_event(spuq=0x%x)", spuq);
|
||||
|
||||
if (group->type & SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT) // this check may be inaccurate
|
||||
if (!group->has_scheduler_context /*|| group->type & 0xf00*/)
|
||||
{
|
||||
spu_log.error("sys_spu_thread_receive_event(): Incompatible group type = 0x%x", group->type);
|
||||
return ch_in_mbox.set_values(1, CELL_EINVAL), true;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "Emu/Cell/RawSPUThread.h"
|
||||
#include "sys_interrupt.h"
|
||||
#include "sys_process.h"
|
||||
#include "sys_memory.h"
|
||||
#include "sys_mmapper.h"
|
||||
#include "sys_event.h"
|
||||
|
||||
@ -414,23 +415,138 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
|
||||
|
||||
sys_spu.warning("sys_spu_thread_group_create(id=*0x%x, num=%d, prio=%d, attr=*0x%x)", id, num, prio, attr);
|
||||
|
||||
// TODO: max num value should be affected by sys_spu_initialize() settings
|
||||
|
||||
const s32 min_prio = g_ps3_process_info.has_root_perm() ? 0 : 16;
|
||||
if (attr->nsize > 0x80 || !num || num > 6 || ((prio < min_prio || prio > 255) && (attr->type != SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT && attr->type != SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)))
|
||||
|
||||
if (attr->nsize > 0x80 || !num)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (attr->type)
|
||||
const s32 type = attr->type;
|
||||
|
||||
bool use_scheduler = true;
|
||||
bool use_memct = !!(type & SYS_SPU_THREAD_GROUP_TYPE_MEMORY_FROM_CONTAINER);
|
||||
bool needs_root = false;
|
||||
u32 max_threads = 6; // TODO: max num value should be affected by sys_spu_initialize() settings
|
||||
u32 min_threads = 1;
|
||||
u32 mem_size = 0;
|
||||
lv2_memory_container* ct{};
|
||||
|
||||
if (type)
|
||||
{
|
||||
sys_spu.warning("sys_spu_thread_group_create(): SPU Thread Group type (0x%x)", attr->type);
|
||||
sys_spu.warning("sys_spu_thread_group_create(): SPU Thread Group type (0x%x)", type);
|
||||
}
|
||||
|
||||
const auto group = idm::make_ptr<lv2_spu_group>(std::string(attr->name.get_ptr(), std::max<u32>(attr->nsize, 1) - 1), num, prio, attr->type, attr->ct);
|
||||
switch (type)
|
||||
{
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
case 0x18:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x20:
|
||||
case 0x22:
|
||||
case 0x24:
|
||||
case 0x26:
|
||||
{
|
||||
if (type == 0x22 || type == 0x26)
|
||||
{
|
||||
needs_root = true;
|
||||
}
|
||||
|
||||
min_threads = 2; // That's what appears from reversing
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2:
|
||||
case 0x6:
|
||||
case 0xA:
|
||||
|
||||
case 0x102:
|
||||
case 0x106:
|
||||
case 0x10A:
|
||||
|
||||
case 0x202:
|
||||
case 0x206:
|
||||
case 0x20A:
|
||||
|
||||
case 0x902:
|
||||
case 0x906:
|
||||
|
||||
case 0xA02:
|
||||
case 0xA06:
|
||||
|
||||
case 0xC02:
|
||||
case 0xC06:
|
||||
{
|
||||
if (type & 0x700)
|
||||
{
|
||||
max_threads = 1;
|
||||
}
|
||||
|
||||
needs_root = true;
|
||||
break;
|
||||
}
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
|
||||
{
|
||||
// Constant size, unknown what it means but it's definitely not for each spu thread alone
|
||||
mem_size = 0x40000;
|
||||
use_scheduler = false;
|
||||
}
|
||||
else if (type & SYS_SPU_THREAD_GROUP_TYPE_NON_CONTEXT)
|
||||
{
|
||||
// No memory consumed
|
||||
mem_size = 0;
|
||||
use_scheduler = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 256kb for each spu thread, probably for saving and restoring SPU LS (used by scheduler?)
|
||||
mem_size = 0x40000 * num;
|
||||
}
|
||||
|
||||
if (num < min_threads || num > max_threads ||
|
||||
(needs_root && min_prio == 0x10) || (use_scheduler && (prio > 255 || prio < min_prio)))
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (use_memct && mem_size)
|
||||
{
|
||||
const auto sct = idm::get<lv2_memory_container>(attr->ct);
|
||||
|
||||
if (!sct)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (sct->take(mem_size) != mem_size)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
ct = sct.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
ct = g_fxo->get<lv2_memory_container>();
|
||||
|
||||
if (ct->take(mem_size) != mem_size)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
const auto group = idm::make_ptr<lv2_spu_group>(std::string(attr->name.get_ptr(), std::max<u32>(attr->nsize, 1) - 1), num, prio, type, ct, use_scheduler, mem_size);
|
||||
|
||||
if (!group)
|
||||
{
|
||||
ct->used -= mem_size;
|
||||
return CELL_EAGAIN;
|
||||
}
|
||||
|
||||
@ -454,6 +570,7 @@ error_code sys_spu_thread_group_destroy(ppu_thread& ppu, u32 id)
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
group.ct->used -= group.mem_size;
|
||||
return {};
|
||||
});
|
||||
|
||||
@ -564,7 +681,7 @@ error_code sys_spu_thread_group_suspend(ppu_thread& ppu, u32 id)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (group->type & SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT) // this check may be inaccurate
|
||||
if (!group->has_scheduler_context || group->type & 0xf00)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
@ -619,7 +736,7 @@ error_code sys_spu_thread_group_resume(ppu_thread& ppu, u32 id)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (group->type & SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT) // this check may be inaccurate
|
||||
if (!group->has_scheduler_context || group->type & 0xf00)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
@ -666,7 +783,8 @@ error_code sys_spu_thread_group_yield(ppu_thread& ppu, u32 id)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (group->type & SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT) // this check may be inaccurate
|
||||
// No effect on these group types
|
||||
if (!group->has_scheduler_context || group->type & 0xf00)
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -830,12 +948,7 @@ error_code sys_spu_thread_group_set_priority(ppu_thread& ppu, u32 id, s32 priori
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (priority < (g_ps3_process_info.has_root_perm() ? 0 : 16) || priority > 255)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (group->type == SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT)
|
||||
if (!group->has_scheduler_context || priority < (g_ps3_process_info.has_root_perm() ? 0 : 16) || priority > 255)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
@ -858,7 +971,7 @@ error_code sys_spu_thread_group_get_priority(ppu_thread& ppu, u32 id, vm::ptr<s3
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (group->type == SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT)
|
||||
if (!group->has_scheduler_context)
|
||||
{
|
||||
*priority = 0;
|
||||
}
|
||||
|
@ -7,10 +7,12 @@
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
#include "Utilities/File.h"
|
||||
|
||||
struct lv2_memory_container;
|
||||
|
||||
enum : s32
|
||||
{
|
||||
SYS_SPU_THREAD_GROUP_TYPE_NORMAL = 0x00,
|
||||
SYS_SPU_THREAD_GROUP_TYPE_SEQUENTIAL = 0x01,
|
||||
//SYS_SPU_THREAD_GROUP_TYPE_SEQUENTIAL = 0x01, doesn't exist
|
||||
SYS_SPU_THREAD_GROUP_TYPE_SYSTEM = 0x02,
|
||||
SYS_SPU_THREAD_GROUP_TYPE_MEMORY_FROM_CONTAINER = 0x04,
|
||||
SYS_SPU_THREAD_GROUP_TYPE_NON_CONTEXT = 0x08,
|
||||
@ -239,8 +241,10 @@ struct lv2_spu_group
|
||||
const std::string name;
|
||||
const u32 id;
|
||||
const u32 max_num;
|
||||
const u32 mem_size;
|
||||
const s32 type; // SPU Thread Group Type
|
||||
const u32 ct; // Memory Container Id
|
||||
lv2_memory_container* const ct; // Memory Container
|
||||
const bool has_scheduler_context;
|
||||
u32 max_run;
|
||||
|
||||
shared_mutex mutex;
|
||||
@ -264,15 +268,17 @@ struct lv2_spu_group
|
||||
std::weak_ptr<lv2_event_queue> ep_exception; // TODO: SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION
|
||||
std::weak_ptr<lv2_event_queue> ep_sysmodule; // TODO: SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE
|
||||
|
||||
lv2_spu_group(std::string name, u32 num, s32 prio, s32 type, u32 ct)
|
||||
lv2_spu_group(std::string name, u32 num, s32 prio, s32 type, lv2_memory_container* ct, bool uses_scheduler, u32 mem_size)
|
||||
: id(idm::last_id())
|
||||
, name(name)
|
||||
, max_num(num)
|
||||
, max_run(num)
|
||||
, mem_size(mem_size)
|
||||
, init(0)
|
||||
, prio(prio)
|
||||
, type(type)
|
||||
, ct(ct)
|
||||
, has_scheduler_context(uses_scheduler)
|
||||
, run_state(SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED)
|
||||
, exit_status(0)
|
||||
, join_state(0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user