mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-28 13:28:01 +03:00
sys_spu: Fix HW schedular limits
This commit is contained in:
parent
f38a61bdb3
commit
19d01835d3
1 changed files with 90 additions and 16 deletions
|
@ -388,19 +388,43 @@ struct spu_limits_t
|
||||||
|
|
||||||
SAVESTATE_INIT_POS(47);
|
SAVESTATE_INIT_POS(47);
|
||||||
|
|
||||||
bool check(const limits_data& init) const
|
bool check_valid(const limits_data& init) const
|
||||||
|
{
|
||||||
|
const u32 physical_spus_count = init.physical;
|
||||||
|
const u32 controllable_spu_count = init.controllable;
|
||||||
|
|
||||||
|
const u32 spu_limit = init.spu_limit != umax ? init.spu_limit : max_spu;
|
||||||
|
const u32 raw_limit = init.raw_limit != umax ? init.raw_limit : max_raw;
|
||||||
|
|
||||||
|
if (spu_limit + raw_limit > 6 || physical_spus_count > spu_limit || controllable_spu_count > spu_limit)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_busy(const limits_data& init) const
|
||||||
{
|
{
|
||||||
u32 physical_spus_count = init.physical;
|
u32 physical_spus_count = init.physical;
|
||||||
u32 raw_spu_count = init.raw_spu;
|
u32 raw_spu_count = init.raw_spu;
|
||||||
u32 controllable_spu_count = init.controllable;
|
u32 controllable_spu_count = init.controllable;
|
||||||
|
u32 system_coop = init.controllable != 0 && init.physical != 0 ? 1 : 0;
|
||||||
|
|
||||||
const u32 spu_limit = init.spu_limit != umax ? init.spu_limit : max_spu;
|
const u32 spu_limit = init.spu_limit != umax ? init.spu_limit : max_spu;
|
||||||
const u32 raw_limit = init.raw_limit != umax ? init.raw_limit : max_raw;
|
const u32 raw_limit = init.raw_limit != umax ? init.raw_limit : max_raw;
|
||||||
|
|
||||||
idm::select<lv2_spu_group>([&](u32, lv2_spu_group& group)
|
idm::select<lv2_spu_group>([&](u32, lv2_spu_group& group)
|
||||||
{
|
{
|
||||||
if (group.has_scheduler_context)
|
if (group.type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
|
||||||
{
|
{
|
||||||
controllable_spu_count = std::max(controllable_spu_count, group.max_num);
|
system_coop++;
|
||||||
|
controllable_spu_count = std::max<u32>(controllable_spu_count, 1);
|
||||||
|
physical_spus_count += group.max_num - 1;
|
||||||
|
}
|
||||||
|
else if (group.has_scheduler_context)
|
||||||
|
{
|
||||||
|
controllable_spu_count = std::max<u32>(controllable_spu_count, group.max_num);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -410,11 +434,18 @@ struct spu_limits_t
|
||||||
|
|
||||||
raw_spu_count += spu_thread::g_raw_spu_ctr;
|
raw_spu_count += spu_thread::g_raw_spu_ctr;
|
||||||
|
|
||||||
if (spu_limit + raw_limit > 6 || raw_spu_count > raw_limit || physical_spus_count >= spu_limit || physical_spus_count + controllable_spu_count > spu_limit)
|
// physical_spus_count >= spu_limit returns EBUSY, not EINVAL!
|
||||||
|
if (spu_limit + raw_limit > 6 || raw_spu_count > raw_limit || physical_spus_count >= spu_limit || physical_spus_count > spu_limit || controllable_spu_count > spu_limit)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (system_coop > 1)
|
||||||
|
{
|
||||||
|
// Cannot have more than one SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM group at a time
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -437,7 +468,7 @@ error_code sys_spu_initialize(ppu_thread& ppu, u32 max_usable_spu, u32 max_raw_s
|
||||||
|
|
||||||
std::lock_guard lock(limits.mutex);
|
std::lock_guard lock(limits.mutex);
|
||||||
|
|
||||||
if (!limits.check(limits_data{.spu_limit = max_usable_spu - max_raw_spu, .raw_limit = max_raw_spu}))
|
if (!limits.check_busy(limits_data{.spu_limit = max_usable_spu - max_raw_spu, .raw_limit = max_raw_spu}))
|
||||||
{
|
{
|
||||||
return CELL_EBUSY;
|
return CELL_EBUSY;
|
||||||
}
|
}
|
||||||
|
@ -845,23 +876,24 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 0x0:
|
case 0x0:
|
||||||
case 0x4:
|
case SYS_SPU_THREAD_GROUP_TYPE_MEMORY_FROM_CONTAINER:
|
||||||
case 0x18:
|
case SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x20:
|
case SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM:
|
||||||
case 0x22:
|
case (SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM | 0x2):
|
||||||
case 0x24:
|
case (SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM | 0x4):
|
||||||
case 0x26:
|
case (SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM | 0x6):
|
||||||
{
|
{
|
||||||
if (type == 0x22 || type == 0x26)
|
if (type == 0x22 || type == 0x26)
|
||||||
{
|
{
|
||||||
needs_root = true;
|
needs_root = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
min_threads = 2; // That's what appears from reversing
|
// For a single thread that is being shared with system (the cooperative victim)
|
||||||
|
min_threads = 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -901,7 +933,7 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
|
||||||
|
|
||||||
if (is_system_coop)
|
if (is_system_coop)
|
||||||
{
|
{
|
||||||
// Constant size, unknown what it means
|
// For a single thread that is being shared with system (the cooperative victim)
|
||||||
mem_size = SPU_LS_SIZE;
|
mem_size = SPU_LS_SIZE;
|
||||||
}
|
}
|
||||||
else if (type & SYS_SPU_THREAD_GROUP_TYPE_NON_CONTEXT)
|
else if (type & SYS_SPU_THREAD_GROUP_TYPE_NON_CONTEXT)
|
||||||
|
@ -952,7 +984,29 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
|
||||||
|
|
||||||
std::unique_lock lock(limits.mutex);
|
std::unique_lock lock(limits.mutex);
|
||||||
|
|
||||||
if (!limits.check(use_scheduler ? limits_data{.controllable = num} : limits_data{.physical = num}))
|
limits_data group_limits{};
|
||||||
|
|
||||||
|
if (is_system_coop)
|
||||||
|
{
|
||||||
|
group_limits.controllable = 1;
|
||||||
|
group_limits.physical = num - 1;
|
||||||
|
}
|
||||||
|
else if (use_scheduler)
|
||||||
|
{
|
||||||
|
group_limits.controllable = num;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
group_limits.physical = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!limits.check_valid(group_limits))
|
||||||
|
{
|
||||||
|
ct->free(mem_size);
|
||||||
|
return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!limits.check_busy(group_limits))
|
||||||
{
|
{
|
||||||
ct->free(mem_size);
|
ct->free(mem_size);
|
||||||
return CELL_EBUSY;
|
return CELL_EBUSY;
|
||||||
|
@ -1135,6 +1189,11 @@ error_code sys_spu_thread_group_suspend(ppu_thread& ppu, u32 id)
|
||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (group->type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
|
||||||
|
{
|
||||||
|
return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
std::lock_guard lock(group->mutex);
|
std::lock_guard lock(group->mutex);
|
||||||
|
|
||||||
CellError error;
|
CellError error;
|
||||||
|
@ -1218,6 +1277,11 @@ error_code sys_spu_thread_group_resume(ppu_thread& ppu, u32 id)
|
||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (group->type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
|
||||||
|
{
|
||||||
|
return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
struct notify_on_exit
|
struct notify_on_exit
|
||||||
{
|
{
|
||||||
usz index = umax;
|
usz index = umax;
|
||||||
|
@ -1565,6 +1629,11 @@ error_code sys_spu_thread_group_set_priority(ppu_thread& ppu, u32 id, s32 priori
|
||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (group->type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
|
||||||
|
{
|
||||||
|
return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
group->prio.atomic_op([&](std::common_type_t<decltype(lv2_spu_group::prio)>& prio)
|
group->prio.atomic_op([&](std::common_type_t<decltype(lv2_spu_group::prio)>& prio)
|
||||||
{
|
{
|
||||||
prio.prio = priority;
|
prio.prio = priority;
|
||||||
|
@ -1592,6 +1661,11 @@ error_code sys_spu_thread_group_get_priority(ppu_thread& ppu, u32 id, vm::ptr<s3
|
||||||
{
|
{
|
||||||
*priority = 0;
|
*priority = 0;
|
||||||
}
|
}
|
||||||
|
else if (group->type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
|
||||||
|
{
|
||||||
|
// Regardless of the value being set in group creation
|
||||||
|
*priority = 15;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*priority = group->prio.load().prio;
|
*priority = group->prio.load().prio;
|
||||||
|
@ -2275,7 +2349,7 @@ error_code sys_raw_spu_create(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<void> at
|
||||||
|
|
||||||
std::lock_guard lock(limits.mutex);
|
std::lock_guard lock(limits.mutex);
|
||||||
|
|
||||||
if (!limits.check(limits_data{.raw_spu = 1}))
|
if (!limits.check_busy(limits_data{.raw_spu = 1}))
|
||||||
{
|
{
|
||||||
return CELL_EAGAIN;
|
return CELL_EAGAIN;
|
||||||
}
|
}
|
||||||
|
@ -2331,7 +2405,7 @@ error_code sys_isolated_spu_create(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<voi
|
||||||
|
|
||||||
std::lock_guard lock(limits.mutex);
|
std::lock_guard lock(limits.mutex);
|
||||||
|
|
||||||
if (!limits.check(limits_data{.raw_spu = 1}))
|
if (!limits.check_busy(limits_data{.raw_spu = 1}))
|
||||||
{
|
{
|
||||||
return CELL_EAGAIN;
|
return CELL_EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue