mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
Bugfix, sys_spu_thread_group_connect_event implemented
This commit is contained in:
parent
8c046429cc
commit
5d768bd3cf
8 changed files with 190 additions and 53 deletions
|
@ -55,7 +55,7 @@ bool RawSPUThread::ReadReg(const u32 addr, u32& value)
|
|||
|
||||
case SPU_MBox_Status_offs:
|
||||
{
|
||||
value = (ch_out_mbox.get_count() & 0xff) | ((4 - ch_in_mbox.get_count()) << 8 & 0xff) | (ch_out_intr_mbox.get_count() << 16 & 0xff);
|
||||
value = (ch_out_mbox.get_count() & 0xff) | ((4 - ch_in_mbox.get_count()) << 8 & 0xff00) | (ch_out_intr_mbox.get_count() << 16 & 0xff0000);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -307,7 +307,7 @@ void SPUThread::process_mfc_cmd(u32 cmd)
|
|||
{
|
||||
if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
LOG_NOTICE(SPU, "DMA %s: cmd=0x%x, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x", get_mfc_cmd_name(cmd), ch_mfc_args.lsa, ch_mfc_args.ea, ch_mfc_args.tag, ch_mfc_args.size, cmd);
|
||||
LOG_NOTICE(SPU, "DMA %s: cmd=0x%x, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x", get_mfc_cmd_name(cmd), cmd, ch_mfc_args.lsa, ch_mfc_args.ea, ch_mfc_args.tag, ch_mfc_args.size);
|
||||
}
|
||||
|
||||
switch (cmd)
|
||||
|
@ -398,11 +398,11 @@ void SPUThread::process_mfc_cmd(u32 cmd)
|
|||
// tag may be used here
|
||||
}
|
||||
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR(SPU, "Unknown DMA %s: cmd=0x%x, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x", get_mfc_cmd_name(cmd), ch_mfc_args.lsa, ch_mfc_args.ea, ch_mfc_args.tag, ch_mfc_args.size, cmd);
|
||||
LOG_ERROR(SPU, "Unknown DMA %s: cmd=0x%x, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x", get_mfc_cmd_name(cmd), cmd, ch_mfc_args.lsa, ch_mfc_args.ea, ch_mfc_args.tag, ch_mfc_args.size);
|
||||
throw __FUNCTION__;
|
||||
}
|
||||
|
||||
|
@ -614,9 +614,8 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
|
|||
return;
|
||||
}
|
||||
|
||||
queue->events.emplace_back(SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (value & 0x00ffffff), data);
|
||||
queue->push(SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (value & 0x00ffffff), data);
|
||||
ch_in_mbox.push_uncond(CELL_OK);
|
||||
queue->cv.notify_one();
|
||||
return;
|
||||
}
|
||||
else if (code < 128)
|
||||
|
@ -654,8 +653,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
|
|||
return;
|
||||
}
|
||||
|
||||
queue->events.emplace_back(SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (value & 0x00ffffff), data);
|
||||
queue->cv.notify_one();
|
||||
queue->push(SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (value & 0x00ffffff), data);
|
||||
return;
|
||||
}
|
||||
else if (code == 128)
|
||||
|
@ -968,14 +966,26 @@ void SPUThread::stop_and_signal(u32 code)
|
|||
|
||||
LV2_LOCK;
|
||||
|
||||
auto found = this->spuq.find(spuq);
|
||||
if (found == this->spuq.end())
|
||||
std::shared_ptr<event_queue_t> queue;
|
||||
|
||||
for (auto& v : this->spuq)
|
||||
{
|
||||
if (spuq == v.first)
|
||||
{
|
||||
queue = v.second.lock();
|
||||
|
||||
if (queue)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!queue)
|
||||
{
|
||||
ch_in_mbox.push_uncond(CELL_EINVAL); // TODO: check error value
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<event_queue_t> queue = found->second;
|
||||
|
||||
// protocol is ignored in current implementation
|
||||
queue->waiters++;
|
||||
|
@ -1046,7 +1056,7 @@ void SPUThread::stop_and_signal(u32 code)
|
|||
|
||||
group->state = SPU_THREAD_GROUP_STATUS_INITIALIZED;
|
||||
group->exit_status = value;
|
||||
group->join_state |= STGJSF_GROUP_EXIT;
|
||||
group->join_state |= SPU_TGJSF_GROUP_EXIT;
|
||||
group->join_cv.notify_one();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -504,9 +504,9 @@ public:
|
|||
spu_interrupt_tag_t int0; // SPU Class 0 Interrupt Management
|
||||
spu_interrupt_tag_t int2; // SPU Class 2 Interrupt Management
|
||||
|
||||
std::weak_ptr<spu_group_t> tg; // SPU Thread Group Id
|
||||
std::weak_ptr<spu_group_t> tg; // SPU Thread Group
|
||||
|
||||
std::unordered_map<u32, std::shared_ptr<event_queue_t>> spuq; // Event Queue Keys for SPU Thread
|
||||
std::array<std::pair<u32, std::weak_ptr<event_queue_t>>, 32> spuq; // Event Queue Keys for SPU Thread
|
||||
std::weak_ptr<event_queue_t> spup[64]; // SPU Ports
|
||||
|
||||
void write_snr(bool number, u32 value)
|
||||
|
|
|
@ -393,19 +393,18 @@ s32 cellAudioInit()
|
|||
keys.resize(g_audio.keys.size());
|
||||
memcpy(keys.data(), g_audio.keys.data(), sizeof(u64) * keys.size());
|
||||
}
|
||||
for (u32 i = 0; i < keys.size(); i++)
|
||||
{
|
||||
auto eq = Emu.GetEventManager().GetEventQueue(keys[i]);
|
||||
LV2_LOCK;
|
||||
|
||||
if (eq)
|
||||
for (u32 i = 0; i < keys.size(); i++)
|
||||
{
|
||||
LV2_LOCK;
|
||||
|
||||
// TODO: check event source
|
||||
eq->events.emplace_back(0x10103000e010e07, 0, 0, 0);
|
||||
eq->cv.notify_one();
|
||||
if (std::shared_ptr<event_queue_t> queue = Emu.GetEventManager().GetEventQueue(keys[i]))
|
||||
{
|
||||
queue->push(0, 0, 0, 0); // TODO: check arguments
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//const u64 stamp3 = get_system_time();
|
||||
|
||||
|
|
|
@ -314,6 +314,7 @@ s32 sys_event_port_disconnect(u32 eport_id)
|
|||
//}
|
||||
|
||||
port->queue.reset();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -343,7 +344,7 @@ s32 sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3)
|
|||
|
||||
const u64 source = port->name ? port->name : ((u64)process_getpid() << 32) | (u64)eport_id;
|
||||
|
||||
queue->events.emplace_back(source, data1, data2, data3);
|
||||
queue->cv.notify_one();
|
||||
queue->push(source, data1, data2, data3);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -92,6 +92,12 @@ struct event_queue_t
|
|||
, waiters(0)
|
||||
{
|
||||
}
|
||||
|
||||
void push(u64 source, u64 data1, u64 data2, u64 data3)
|
||||
{
|
||||
events.emplace_back(source, data1, data2, data3);
|
||||
cv.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
struct event_port_t
|
||||
|
|
|
@ -320,6 +320,13 @@ s32 sys_spu_thread_group_start(u32 id)
|
|||
}
|
||||
}
|
||||
|
||||
// because SPU_THREAD_GROUP_STATUS_READY is not possible, run event is delivered immediately
|
||||
|
||||
if (std::shared_ptr<event_queue_t> queue = group->ep_run.lock())
|
||||
{
|
||||
queue->push(SYS_SPU_THREAD_GROUP_EVENT_RUN_KEY, id, 0, 0); // TODO: check data2 and data3
|
||||
}
|
||||
|
||||
for (auto& t : group->threads)
|
||||
{
|
||||
if (t)
|
||||
|
@ -485,7 +492,7 @@ s32 sys_spu_thread_group_terminate(u32 id, s32 value)
|
|||
|
||||
group->state = SPU_THREAD_GROUP_STATUS_INITIALIZED;
|
||||
group->exit_status = value;
|
||||
group->join_state |= STGJSF_TERMINATED;
|
||||
group->join_state |= SPU_TGJSF_TERMINATED;
|
||||
group->join_cv.notify_one();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -507,13 +514,13 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr<u32> cause, vm::ptr<u32> status)
|
|||
return CELL_ESTAT;
|
||||
}
|
||||
|
||||
if (group->join_state.fetch_or(STGJSF_IS_JOINING) & STGJSF_IS_JOINING)
|
||||
if (group->join_state.fetch_or(SPU_TGJSF_IS_JOINING) & SPU_TGJSF_IS_JOINING)
|
||||
{
|
||||
// another PPU thread is joining this thread group
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
while ((group->join_state & ~STGJSF_IS_JOINING) == 0)
|
||||
while ((group->join_state & ~SPU_TGJSF_IS_JOINING) == 0)
|
||||
{
|
||||
bool stopped = true;
|
||||
|
||||
|
@ -545,19 +552,19 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr<u32> cause, vm::ptr<u32> status)
|
|||
group->join_cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
switch (group->join_state & ~STGJSF_IS_JOINING)
|
||||
switch (group->join_state & ~SPU_TGJSF_IS_JOINING)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (cause) *cause = SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT;
|
||||
break;
|
||||
}
|
||||
case STGJSF_GROUP_EXIT:
|
||||
case SPU_TGJSF_GROUP_EXIT:
|
||||
{
|
||||
if (cause) *cause = SYS_SPU_THREAD_GROUP_JOIN_GROUP_EXIT;
|
||||
break;
|
||||
}
|
||||
case STGJSF_TERMINATED:
|
||||
case SPU_TGJSF_TERMINATED:
|
||||
{
|
||||
if (cause) *cause = SYS_SPU_THREAD_GROUP_JOIN_TERMINATED;
|
||||
break;
|
||||
|
@ -570,7 +577,7 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr<u32> cause, vm::ptr<u32> status)
|
|||
*status = group->exit_status;
|
||||
}
|
||||
|
||||
group->join_state &= ~STGJSF_IS_JOINING;
|
||||
group->join_state &= ~SPU_TGJSF_IS_JOINING;
|
||||
group->state = SPU_THREAD_GROUP_STATUS_INITIALIZED; // hack
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -729,14 +736,111 @@ s32 sys_spu_thread_write_snr(u32 id, u32 number, u32 value)
|
|||
|
||||
s32 sys_spu_thread_group_connect_event(u32 id, u32 eq, u32 et)
|
||||
{
|
||||
sys_spu.Todo("sys_spu_thread_group_connect_event(id=%d, eq=%d, et=0x%x)", id, eq, et);
|
||||
sys_spu.Warning("sys_spu_thread_group_connect_event(id=%d, eq=%d, et=%d)", id, eq, et);
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<spu_group_t> group;
|
||||
std::shared_ptr<event_queue_t> queue;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(id, group) || !Emu.GetIdManager().GetIDData(eq, queue))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
switch (et)
|
||||
{
|
||||
case SYS_SPU_THREAD_GROUP_EVENT_RUN:
|
||||
{
|
||||
if (!group->ep_run.expired())
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
group->ep_run = queue;
|
||||
break;
|
||||
}
|
||||
case SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION:
|
||||
{
|
||||
if (!group->ep_exception.expired())
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
group->ep_exception = queue;
|
||||
break;
|
||||
}
|
||||
case SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE:
|
||||
{
|
||||
if (!group->ep_sysmodule.expired())
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
group->ep_sysmodule = queue;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
sys_spu.Error("sys_spu_thread_group_connect_event(): unknown event type (%d)", et);
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_spu_thread_group_disconnect_event(u32 id, u32 et)
|
||||
{
|
||||
sys_spu.Todo("sys_spu_thread_group_disconnect_event(id=%d, et=0x%x)", id, et);
|
||||
sys_spu.Warning("sys_spu_thread_group_disconnect_event(id=%d, et=%d)", id, et);
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
std::shared_ptr<spu_group_t> group;
|
||||
|
||||
if (!Emu.GetIdManager().GetIDData(id, group))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
switch (et)
|
||||
{
|
||||
case SYS_SPU_THREAD_GROUP_EVENT_RUN:
|
||||
{
|
||||
if (group->ep_run.expired())
|
||||
{
|
||||
return CELL_ENOTCONN;
|
||||
}
|
||||
|
||||
group->ep_run.reset();
|
||||
break;
|
||||
}
|
||||
case SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION:
|
||||
{
|
||||
if (group->ep_exception.expired())
|
||||
{
|
||||
return CELL_ENOTCONN;
|
||||
}
|
||||
|
||||
group->ep_exception.reset();
|
||||
break;
|
||||
}
|
||||
case SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE:
|
||||
{
|
||||
if (group->ep_sysmodule.expired())
|
||||
{
|
||||
return CELL_ENOTCONN;
|
||||
}
|
||||
|
||||
group->ep_sysmodule.reset();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
sys_spu.Error("sys_spu_thread_group_disconnect_event(): unknown event type (%d)", et);
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -839,20 +943,29 @@ s32 sys_spu_thread_bind_queue(u32 id, u32 spuq, u32 spuq_num)
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (spu.spuq.size() >= 32)
|
||||
for (auto& v : spu.spuq)
|
||||
{
|
||||
return CELL_EAGAIN;
|
||||
if (auto q = v.second.lock())
|
||||
{
|
||||
if (v.first == spuq_num || q == queue)
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto found = spu.spuq.find(spuq_num);
|
||||
if (found != spu.spuq.end())
|
||||
for (auto& v : spu.spuq)
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
if (v.second.expired())
|
||||
{
|
||||
v.first = spuq_num;
|
||||
v.second = queue;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
spu.spuq[spuq_num] = queue;
|
||||
|
||||
return CELL_OK;
|
||||
return CELL_EAGAIN;
|
||||
}
|
||||
|
||||
s32 sys_spu_thread_unbind_queue(u32 id, u32 spuq_num)
|
||||
|
@ -870,15 +983,17 @@ s32 sys_spu_thread_unbind_queue(u32 id, u32 spuq_num)
|
|||
|
||||
auto& spu = static_cast<SPUThread&>(*t);
|
||||
|
||||
auto found = spu.spuq.find(spuq_num);
|
||||
if (found == spu.spuq.end())
|
||||
for (auto& v : spu.spuq)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
if (v.first == spuq_num && !v.second.expired())
|
||||
{
|
||||
v.second.reset();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
spu.spuq.erase(found);
|
||||
|
||||
return CELL_OK;
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, vm::ptr<u8> spup)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
struct event_queue_t;
|
||||
|
||||
enum : s32
|
||||
{
|
||||
SYS_SPU_THREAD_GROUP_TYPE_NORMAL = 0x00,
|
||||
|
@ -132,9 +134,9 @@ struct spu_arg_t
|
|||
// SPU Thread Group Join State Flag
|
||||
enum : u32
|
||||
{
|
||||
STGJSF_IS_JOINING = (1 << 0),
|
||||
STGJSF_TERMINATED = (1 << 1), // set if SPU Thread Group is terminated by sys_spu_thread_group_terminate
|
||||
STGJSF_GROUP_EXIT = (1 << 2), // set if SPU Thread Group is terminated by sys_spu_thread_group_exit
|
||||
SPU_TGJSF_IS_JOINING = (1 << 0),
|
||||
SPU_TGJSF_TERMINATED = (1 << 1), // set if SPU Thread Group is terminated by sys_spu_thread_group_terminate
|
||||
SPU_TGJSF_GROUP_EXIT = (1 << 2), // set if SPU Thread Group is terminated by sys_spu_thread_group_exit
|
||||
};
|
||||
|
||||
struct spu_group_t
|
||||
|
@ -144,9 +146,9 @@ struct spu_group_t
|
|||
const s32 type; // SPU Thread Group Type
|
||||
const u32 ct; // Memory Container Id
|
||||
|
||||
std::array<std::shared_ptr<CPUThread>, 256> threads;
|
||||
std::array<std::shared_ptr<CPUThread>, 256> threads; // SPU Threads
|
||||
std::array<vm::ptr<sys_spu_image>, 256> images; // SPU Images
|
||||
std::array<spu_arg_t, 256> args; // SPU Thread Arguments
|
||||
std::array<vm::ptr<sys_spu_image>, 256> images; // SPU Thread Images
|
||||
|
||||
s32 prio; // SPU Thread Group Priority
|
||||
u32 state; // SPU Thread Group State
|
||||
|
@ -155,6 +157,10 @@ struct spu_group_t
|
|||
std::atomic<u32> join_state; // flags used to detect exit cause
|
||||
std::condition_variable join_cv; // used to signal waiting PPU thread
|
||||
|
||||
std::weak_ptr<event_queue_t> ep_run; // port for SYS_SPU_THREAD_GROUP_EVENT_RUN events
|
||||
std::weak_ptr<event_queue_t> ep_exception; // TODO: SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION
|
||||
std::weak_ptr<event_queue_t> ep_sysmodule; // TODO: SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE
|
||||
|
||||
spu_group_t(std::string name, u32 num, s32 prio, s32 type, u32 ct)
|
||||
: name(name)
|
||||
, num(num)
|
||||
|
|
Loading…
Add table
Reference in a new issue