mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-19 19:15:26 +00:00
Merge branch 'RPCS3:master' into uruntime
This commit is contained in:
commit
c5a63d5cf8
3 changed files with 104 additions and 20 deletions
|
@ -502,7 +502,7 @@ error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
|
|||
|
||||
if (!cond || !mutex)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
return { CELL_ESRCH, fmt::format("lwmutex_id: 0x%x, lwcond_id: 0x%x", lwmutex_id, lwcond_id) };
|
||||
}
|
||||
|
||||
if (ppu.state & cpu_flag::again)
|
||||
|
|
|
@ -183,7 +183,12 @@ error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout)
|
|||
|
||||
if (!mutex)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
if (lwmutex_id >> 24 == lv2_lwmutex::id_base >> 24)
|
||||
{
|
||||
return { CELL_ESRCH, lwmutex_id };
|
||||
}
|
||||
|
||||
return { CELL_ESRCH, "Invalid ID" };
|
||||
}
|
||||
|
||||
if (mutex.ret)
|
||||
|
@ -313,7 +318,12 @@ error_code _sys_lwmutex_trylock(ppu_thread& ppu, u32 lwmutex_id)
|
|||
|
||||
if (!mutex)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
if (lwmutex_id >> 24 == lv2_lwmutex::id_base >> 24)
|
||||
{
|
||||
return { CELL_ESRCH, lwmutex_id };
|
||||
}
|
||||
|
||||
return { CELL_ESRCH, "Invalid ID" };
|
||||
}
|
||||
|
||||
if (!mutex.ret)
|
||||
|
|
|
@ -388,19 +388,43 @@ struct spu_limits_t
|
|||
|
||||
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 raw_spu_count = init.raw_spu;
|
||||
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 raw_limit = init.raw_limit != umax ? init.raw_limit : max_raw;
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -410,11 +434,18 @@ struct spu_limits_t
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -845,23 +876,24 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
|
|||
switch (type)
|
||||
{
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
case 0x18:
|
||||
case SYS_SPU_THREAD_GROUP_TYPE_MEMORY_FROM_CONTAINER:
|
||||
case SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x20:
|
||||
case 0x22:
|
||||
case 0x24:
|
||||
case 0x26:
|
||||
case SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM:
|
||||
case (SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM | 0x2):
|
||||
case (SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM | 0x4):
|
||||
case (SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM | 0x6):
|
||||
{
|
||||
if (type == 0x22 || type == 0x26)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -901,7 +933,7 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
|
|||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
|
||||
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);
|
||||
return CELL_EBUSY;
|
||||
|
@ -1135,6 +1189,11 @@ error_code sys_spu_thread_group_suspend(ppu_thread& ppu, u32 id)
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (group->type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
std::lock_guard lock(group->mutex);
|
||||
|
||||
CellError error;
|
||||
|
@ -1218,6 +1277,11 @@ error_code sys_spu_thread_group_resume(ppu_thread& ppu, u32 id)
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (group->type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
struct notify_on_exit
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
else if (group->type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
|
||||
{
|
||||
// Regardless of the value being set in group creation
|
||||
*priority = 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
*priority = group->prio.load().prio;
|
||||
|
@ -1751,7 +1825,7 @@ error_code sys_spu_thread_write_spu_mb(ppu_thread& ppu, u32 id, u32 value)
|
|||
{
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
sys_spu.warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x)", id, value);
|
||||
sys_spu.trace("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x)", id, value);
|
||||
|
||||
const auto [thread, group] = lv2_spu_group::get_thread(id);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
if (!limits.check(limits_data{.raw_spu = 1}))
|
||||
if (!limits.check_busy(limits_data{.raw_spu = 1}))
|
||||
{
|
||||
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);
|
||||
|
||||
if (!limits.check(limits_data{.raw_spu = 1}))
|
||||
if (!limits.check_busy(limits_data{.raw_spu = 1}))
|
||||
{
|
||||
return CELL_EAGAIN;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue