diff --git a/rpcs3/Emu/Audio/cellAudio.h b/rpcs3/Emu/Audio/cellAudio.h index 7d492b0ba9..dc371c9c67 100644 --- a/rpcs3/Emu/Audio/cellAudio.h +++ b/rpcs3/Emu/Audio/cellAudio.h @@ -121,6 +121,7 @@ struct AudioPortConfig struct AudioConfig //custom structure { + std::mutex m_mutex; enum { AUDIO_PORT_COUNT = 8, @@ -131,15 +132,14 @@ struct AudioConfig //custom structure bool m_is_audio_initialized; bool m_is_audio_finalized; u32 m_port_in_use; - u64 event_key; u64 counter; u64 start_time; + Array m_keys; AudioConfig() : m_is_audio_initialized(false) , m_is_audio_finalized(false) , m_port_in_use(0) - , event_key(0x80004d494f323221) , counter(0) { memset(&m_ports, 0, sizeof(AudioPortConfig) * AUDIO_PORT_COUNT); diff --git a/rpcs3/Emu/Cell/MFC.h b/rpcs3/Emu/Cell/MFC.h index 6016924ae5..bef241c7b8 100644 --- a/rpcs3/Emu/Cell/MFC.h +++ b/rpcs3/Emu/Cell/MFC.h @@ -18,6 +18,7 @@ enum MFC_BARRIER_MASK = 0x01, MFC_FENCE_MASK = 0x02, + MFC_LIST_MASK = 0x04, MFC_MASK_CMD = 0xffff, }; @@ -165,7 +166,7 @@ struct DMAC //returns true if the command should be deleted from the queue if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence(); - switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) + switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK)) { case MFC_PUT_CMD: Memory.Copy(ea, ls_offset + lsa, size); @@ -176,7 +177,7 @@ struct DMAC return true; default: - ConLog.Error("Unknown DMA cmd."); + ConLog.Error("DMAC::ProcessCmd(): Unknown DMA cmd."); return true; } } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index fcaccd72c9..cfed36752e 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -1,6 +1,7 @@ #pragma once #include "PPCThread.h" #include "Emu/event.h" +#include "Emu/SysCalls/lv2/SC_SPU_Thread.h" #include "MFC.h" #include @@ -484,6 +485,22 @@ public: Channel<1> AtomicStat; } Prxy; + struct StalledList + { + u32 lsa; + u64 ea; + u16 tag; + u16 size; + u32 cmd; + MFCReg* MFCArgs; + + StalledList() + : MFCArgs(nullptr) + { + } + } StallList[32]; + Channel<1> StallStat; + struct { Channel<1> Out_MBox; @@ -505,6 +522,66 @@ public: DMAC dmac; + void ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs) + { + u32 list_addr = ea & 0x3ffff; + u32 list_size = size / 8; + lsa &= 0x3fff0; + + struct list_element + { + be_t s; // Stall-and-Notify bit (0x8000) + be_t ts; // List Transfer Size + be_t ea; // External Address Low + }; + + u32 result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR; + + for (u32 i = 0; i < list_size; i++) + { + mem_ptr_t rec(dmac.ls_offset + list_addr + i * 8); + + u32 size = rec->ts; + if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8) + { + ConLog.Error("DMA List: invalid transfer size(%d)", size); + return; + } + + u32 addr = rec->ea; + result = dmac.Cmd(cmd, tag, lsa | (addr & 0xf), addr, size); + if (result == MFC_PPU_DMA_CMD_SEQUENCE_ERROR) + { + break; + } + + if (Ini.HLELogging.GetValue() || rec->s) + ConLog.Write("*** list element(%d/%d): s = 0x%x, ts = 0x%x, low ea = 0x%x (lsa = 0x%x)", + i, list_size, (u16)rec->s, (u16)rec->ts, (u32)rec->ea, lsa | (addr & 0xf)); + + lsa += max(size, (u32)16); + + if (rec->s & se16(0x8000)) + { + StallStat.PushUncond_OR(1 << tag); + + if (StallList[tag].MFCArgs) + { + ConLog.Error("DMA List: existing stalled list found (tag=%d)", tag); + } + StallList[tag].MFCArgs = &MFCArgs; + StallList[tag].cmd = cmd; + StallList[tag].ea = (ea & ~0xffffffff) | (list_addr + (i + 1) * 8); + StallList[tag].lsa = lsa; + StallList[tag].size = (list_size - i - 1) * 8; + + return; + } + } + + MFCArgs.CMDStatus.SetValue(result); + } + void EnqMfcCmd(MFCReg& MFCArgs) { u32 cmd = MFCArgs.CMDStatus.GetValue(); @@ -528,7 +605,7 @@ public: lsa, ea, tag, size, cmd); if (op & MFC_PUT_CMD) { - SMutexLocker lock(reservation.mutex); + SMutexLocker lock(reservation.mutex); // should be removed MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size)); if ((reservation.addr + reservation.size > ea && reservation.addr <= ea + size) || (ea + size > reservation.addr && ea <= reservation.addr + reservation.size)) @@ -543,6 +620,19 @@ public: } break; + case MFC_PUTL_CMD: + case MFC_GETL_CMD: + { + if (Ini.HLELogging.GetValue()) ConLog.Write("DMA %s%s%s: lsa = 0x%x, list = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", + wxString(op & MFC_PUT_CMD ? "PUTL" : "GETL").wx_str(), + wxString(op & MFC_BARRIER_MASK ? "B" : "").wx_str(), + wxString(op & MFC_FENCE_MASK ? "F" : "").wx_str(), + lsa, ea, tag, size, cmd); + + ListCmd(lsa, ea, tag, size, cmd, MFCArgs); + } + break; + case MFC_GETLLAR_CMD: case MFC_PUTLLC_CMD: case MFC_PUTLLUC_CMD: @@ -628,6 +718,9 @@ public: case MFC_RdTagStat: return Prxy.TagStatus.GetCount(); + case MFC_RdListStallStat: + return StallStat.GetCount(); + case MFC_WrTagUpdate: return Prxy.TagStatus.GetCount(); // hack @@ -751,6 +844,24 @@ public: EnqMfcCmd(MFC1); break; + case MFC_WrListStallAck: + { + if (v >= 32) + { + ConLog.Error("MFC_WrListStallAck error: invalid tag(%d)", v); + return; + } + StalledList temp = StallList[v]; + if (!temp.MFCArgs) + { + ConLog.Error("MFC_WrListStallAck error: empty tag(%d)", v); + return; + } + StallList[v].MFCArgs = nullptr; + ListCmd(temp.lsa, temp.ea, temp.tag, temp.size, temp.cmd, *temp.MFCArgs); + } + break; + default: ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", wxString(__FUNCTION__).wx_str(), ch, wxString(spu_ch_name[ch]).wx_str()); break; @@ -790,6 +901,10 @@ public: while (!Prxy.AtomicStat.Pop(v) && !Emu.IsStopped()) Sleep(1); break; + case MFC_RdListStallStat: + while (!StallStat.Pop(v) && !Emu.IsStopped()) Sleep(1); + break; + default: ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", wxString(__FUNCTION__).wx_str(), ch, wxString(spu_ch_name[ch]).wx_str()); break; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index 1fb6dc72ff..f6ff6404b2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -60,6 +60,8 @@ int cellAudioInit() memset(buffer2, 0, sizeof(buffer2)); memset(oal_buffer.get(), 0, oal_buffer_size * sizeof(u16)); + Array keys; + if(m_audio_out) { m_audio_out->Init(); @@ -144,8 +146,16 @@ int cellAudioInit() } // send aftermix event (normal audio event) - // TODO: check event source - Emu.GetEventManager().SendEvent(m_config.event_key, 0x10103000e010e07, 0, 0, 0); + { + std::lock_guard lock(m_config.m_mutex); + keys.SetCount(m_config.m_keys.GetCount()); + memcpy(keys.GetPtr(), m_config.m_keys.GetPtr(), sizeof(u64) * keys.GetCount()); + } + for (u32 i = 0; i < keys.GetCount(); i++) + { + // TODO: check event source + Emu.GetEventManager().SendEvent(keys[i], 0x10103000e010e07, 0, 0, 0); + } oal_buffer_offset += sizeof(buffer) / sizeof(float); @@ -441,22 +451,27 @@ int cellAudioCreateNotifyEventQueue(mem32_t id, mem64_t key) { cellAudio.Warning("cellAudioCreateNotifyEventQueue(id_addr=0x%x, key_addr=0x%x)", id.GetAddr(), key.GetAddr()); - while (Emu.GetEventManager().CheckKey(m_config.event_key)) + std::lock_guard lock(m_config.m_mutex); + + u64 event_key = 0; + while (Emu.GetEventManager().CheckKey((event_key << 48) | 0x80004d494f323221)) { - m_config.event_key++; // experimental + event_key++; // experimental //return CELL_AUDIO_ERROR_EVENT_QUEUE; } + event_key = (event_key << 48) | 0x80004d494f323221; // left part: 0x8000, 0x8001, 0x8002 ... - EventQueue* eq = new EventQueue(SYS_SYNC_FIFO, SYS_PPU_QUEUE, m_config.event_key, m_config.event_key, 32); + EventQueue* eq = new EventQueue(SYS_SYNC_FIFO, SYS_PPU_QUEUE, event_key, event_key, 32); - if (!Emu.GetEventManager().RegisterKey(eq, m_config.event_key)) + if (!Emu.GetEventManager().RegisterKey(eq, event_key)) { delete eq; return CELL_AUDIO_ERROR_EVENT_QUEUE; } + m_config.m_keys.AddCpy(event_key); id = cellAudio.GetNewId(eq); - key = m_config.event_key; + key = event_key; return CELL_OK; } @@ -471,7 +486,9 @@ int cellAudioSetNotifyEventQueue(u64 key) { cellAudio.Warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key); - //m_config.event_key = key; + std::lock_guard lock(m_config.m_mutex); + + m_config.m_keys.AddCpy(key); /*EventQueue* eq; if (!Emu.GetEventManager().GetEventQueue(key, eq)) @@ -494,13 +511,30 @@ int cellAudioRemoveNotifyEventQueue(u64 key) { cellAudio.Warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key); - EventQueue* eq; - if (!Emu.GetEventManager().GetEventQueue(key, eq)) + std::lock_guard lock(m_config.m_mutex); + + bool found = false; + for (u32 i = 0; i < m_config.m_keys.GetCount(); i++) { + if (m_config.m_keys[i] == key) + { + m_config.m_keys.RemoveAt(i); + found = true; + break; + } + } + + if (!found) + { + // ??? return CELL_AUDIO_ERROR_PARAM; } - m_config.event_key = 0x80004d494f323221; + /*EventQueue* eq; + if (!Emu.GetEventManager().GetEventQueue(key, eq)) + { + return CELL_AUDIO_ERROR_PARAM; + }*/ // TODO: disconnect port diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp index 8f0785ab96..cc6a1d7c9d 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp @@ -71,48 +71,15 @@ int sys_cond_signal(u32 cond_id) } Mutex* mutex = cond->mutex; - u32 tid = GetCurrentPPUThread().GetId(); - - bool was_locked = (mutex->m_mutex.GetOwner() == tid); if (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop())) { - CPUThread* tt = Emu.GetCPU().GetThread(target); - bool valid = tt && tt->IsAlive(); - if (!valid) - { - sys_cond.Error("sys_cond_signal(%d): signal to invalid thread(%d)", cond_id, target); - return CELL_OK; - } + cond->cond.lock(target); - if (!was_locked) // mutex hasn't been locked (don't care about mutex state) + if (Emu.IsStopped()) { - if (u32 owner = mutex->m_mutex.GetOwner()) - { - tt = Emu.GetCPU().GetThread(owner); - valid = tt && tt->IsAlive(); - if (!valid) - { - sys_cond.Error("sys_cond_signal(%d): deadlock on invalid thread(%d)", cond_id, owner); - return CELL_OK; - } - } - mutex->m_mutex.lock(tid); - mutex->recursive = 1; - mutex->m_mutex.unlock(tid, target); + ConLog.Warning("sys_cond_signal(id=%d) aborted", cond_id); } - else // mutex has been locked (should preserve original mutex state) - { - mutex->recursive = 1; - mutex->m_mutex.unlock(tid, target); - mutex->m_mutex.lock(tid); - mutex->recursive = 1; - } - } - - if (Emu.IsStopped()) - { - ConLog.Warning("sys_cond_signal(id=%d) aborted", cond_id); } return CELL_OK; @@ -129,43 +96,10 @@ int sys_cond_signal_all(u32 cond_id) } Mutex* mutex = cond->mutex; - u32 tid = GetCurrentPPUThread().GetId(); - - bool was_locked = (mutex->m_mutex.GetOwner() == tid); while (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop())) { - CPUThread* tt = Emu.GetCPU().GetThread(target); - bool valid = tt && tt->IsAlive(); - if (!valid) - { - sys_cond.Error("sys_cond_signal_all(%d): signal to invalid thread(%d)", cond_id, target); - return CELL_OK; - } - - if (!was_locked) - { - if (u32 owner = mutex->m_mutex.GetOwner()) - { - tt = Emu.GetCPU().GetThread(owner); - valid = tt && tt->IsAlive(); - if (!valid) - { - sys_cond.Error("sys_cond_signal_all(%d): deadlock on invalid thread(%d)", cond_id, owner); - return CELL_OK; - } - } - mutex->m_mutex.lock(tid); - mutex->recursive = 1; - mutex->m_mutex.unlock(tid, target); - } - else - { - mutex->recursive = 1; - mutex->m_mutex.unlock(tid, target); - mutex->m_mutex.lock(tid); - mutex->recursive = 1; - } + cond->cond.lock(target); if (Emu.IsStopped()) { @@ -197,35 +131,10 @@ int sys_cond_signal_to(u32 cond_id, u32 thread_id) } Mutex* mutex = cond->mutex; - u32 tid = GetCurrentPPUThread().GetId(); - - bool was_locked = (mutex->m_mutex.GetOwner() == tid); u32 target = thread_id; { - if (!was_locked) - { - if (u32 owner = mutex->m_mutex.GetOwner()) - { - CPUThread* tt = Emu.GetCPU().GetThread(owner); - bool valid = tt && tt->IsAlive(); - if (!valid) - { - sys_cond.Error("sys_cond_signal_to(%d): deadlock on invalid thread(%d)", cond_id, owner); - return CELL_OK; - } - } - mutex->m_mutex.lock(tid); - mutex->recursive = 1; - mutex->m_mutex.unlock(tid, target); - } - else - { - mutex->recursive = 1; - mutex->m_mutex.unlock(tid, target); - mutex->m_mutex.lock(tid); - mutex->recursive = 1; - } + cond->cond.lock(target); } if (Emu.IsStopped()) @@ -264,15 +173,11 @@ int sys_cond_wait(u32 cond_id, u64 timeout) while (true) { - /* switch (mutex->m_mutex.trylock(tid)) + if (cond->cond.GetOwner() == tid) { - case SMR_OK: mutex->m_mutex.unlock(tid); break; - case SMR_SIGNAL: mutex->recursive = 1; return CELL_OK; - } */ - if (mutex->m_mutex.GetOwner() == tid) - { - _mm_mfence(); + mutex->m_mutex.lock(tid); mutex->recursive = 1; + cond->cond.unlock(tid); return CELL_OK; } @@ -281,6 +186,7 @@ int sys_cond_wait(u32 cond_id, u64 timeout) if (counter++ > max_counter) { cond->m_queue.invalidate(tid); + GetCurrentPPUThread().owned_mutexes--; return CELL_ETIMEDOUT; } if (Emu.IsStopped()) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Condition.h b/rpcs3/Emu/SysCalls/lv2/SC_Condition.h index dc849948b4..460923a504 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Condition.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Condition.h @@ -16,6 +16,7 @@ struct sys_cond_attribute struct Cond { Mutex* mutex; // associated with mutex + SMutex cond; SleepQueue m_queue; Cond(Mutex* mutex, u64 name) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp index b662ee10c5..d6ea1a26a3 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp @@ -203,7 +203,7 @@ int sys_event_queue_receive(u32 equeue_id, mem_ptr_t event, u64 eq->owner.unlock(tid); sys_event.Log(" *** event received: source=0x%llx, d1=0x%llx, d2=0x%llx, d3=0x%llx", (u64)event->source, (u64)event->data1, (u64)event->data2, (u64)event->data3); - /* HACK: passing event data in registers */ + /* passing event data in registers */ PPUThread& t = GetCurrentPPUThread(); t.GPR[4] = event->source; t.GPR[5] = event->data1; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index dfbe386ca0..c006439d1e 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -324,10 +324,15 @@ int cellFsMkdir(u32 path_addr, u32 mode) const wxString& ps3_path = Memory.ReadString(path_addr); sys_fs.Log("cellFsMkdir(path=\"%s\", mode=0x%x)", ps3_path.wx_str(), mode); - vfsDir dir; + /*vfsDir dir; if(dir.IsExists(ps3_path)) return CELL_EEXIST; if(!dir.Create(ps3_path)) + return CELL_EBUSY;*/ + + if(Emu.GetVFS().ExistsDir(ps3_path)) + return CELL_EEXIST; + if(!Emu.GetVFS().CreateDir(ps3_path)) return CELL_EBUSY; return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp index ce1b3f51d3..d0d2b3f962 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp @@ -98,8 +98,9 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout) PPUThread& t = GetCurrentPPUThread(); u32 tid = t.GetId(); - u32 owner = mutex->m_mutex.GetOwner(); + _mm_mfence(); + u32 owner = mutex->m_mutex.GetOwner(); if (owner == tid) { if (mutex->is_recursive) @@ -119,22 +120,10 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout) { if (CPUThread* tt = Emu.GetCPU().GetThread(owner)) { - if (!tt->IsAlive()) - { - if (owner == mutex->m_mutex.GetOwner()) sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner); - /*mutex->m_mutex.unlock(owner, tid); - mutex->recursive = 1; - t.owned_mutexes++; - return CELL_OK;*/ - } } else { sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner); - /*mutex->m_mutex.unlock(owner, tid); - mutex->recursive = 1; - t.owned_mutexes++; - return CELL_OK;*/ } } @@ -180,8 +169,9 @@ int sys_mutex_trylock(u32 mutex_id) PPUThread& t = GetCurrentPPUThread(); u32 tid = t.GetId(); - u32 owner = mutex->m_mutex.GetOwner(); + _mm_mfence(); + u32 owner = mutex->m_mutex.GetOwner(); if (owner == tid) { if (mutex->is_recursive) @@ -201,22 +191,10 @@ int sys_mutex_trylock(u32 mutex_id) { if (CPUThread* tt = Emu.GetCPU().GetThread(owner)) { - if (!tt->IsAlive()) - { - if (owner == mutex->m_mutex.GetOwner()) sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner); - /*mutex->m_mutex.unlock(owner, tid); - mutex->recursive = 1; - t.owned_mutexes++; - return CELL_OK;*/ - } } else { sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner); - /*mutex->m_mutex.unlock(owner, tid); - mutex->recursive = 1; - t.owned_mutexes++; - return CELL_OK;*/ } } @@ -241,6 +219,7 @@ int sys_mutex_unlock(u32 mutex_id) PPUThread& t = GetCurrentPPUThread(); u32 tid = t.GetId(); + _mm_mfence(); if (mutex->m_mutex.GetOwner() == tid) { if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive)) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index 02b898207e..170343883c 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -9,32 +9,6 @@ static SysCallBase sc_spu("sys_spu"); extern SysCallBase sys_event; -static const u32 g_spu_group_thr_max = 255; - -struct SpuGroupInfo -{ - Array list; - std::atomic lock; - wxString m_name; - int m_prio; - int m_type; - int m_ct; - - SpuGroupInfo(wxString name, u32 num, int prio, int type, u32 ct) - : m_name(name) - , m_prio(prio) - , m_type(type) - , m_ct(ct) - , lock(0) - { - list.SetCount(num); - for (u32 i = 0; i < num; i++) - { - list[i] = 0; - } - } -}; - u32 LoadSpuImage(vfsStream& stream, u32& spu_ep) { ELFLoader l(stream); @@ -114,7 +88,7 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< return CELL_EFAULT; } - if(spu_num >= g_spu_group_thr_max) + if(spu_num >= group_info->list.GetCount()) { return CELL_EINVAL; } @@ -287,7 +261,7 @@ int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_tname_addr, attr->name_len)) return CELL_EFAULT; - if (num > g_spu_group_thr_max) return CELL_EINVAL; + if (num > 256) return CELL_EINVAL; if (prio < 16 || prio > 255) return CELL_EINVAL; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h index 7d674155e4..1721b9c232 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h @@ -55,3 +55,28 @@ struct sys_spu_segment be_t size; be_t src; }; + +struct SpuGroupInfo +{ + Array list; + std::atomic lock; + wxString m_name; + int m_prio; + int m_type; + int m_ct; + + SpuGroupInfo(wxString name, u32 num, int prio, int type, u32 ct) + : m_name(name) + , m_prio(prio) + , m_type(type) + , m_ct(ct) + , lock(0) + { + num = 256; + list.SetCount(num); + for (u32 i = 0; i < num; i++) + { + list[i] = 0; + } + } +}; \ No newline at end of file