Exemple #1
0
//165
s32 sys_spu_thread_get_exit_status(u32 id, mem32_t status)
{
	sc_spu.Warning("sys_spu_thread_get_exit_status(id=%d, status_addr=0x%x)", id, status.GetAddr());

	if (!status.IsGood())
	{
		return CELL_EFAULT;
	}

	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	u32 res;
	if (!(*(SPUThread*)thr).SPU.Out_MBox.Pop(res) || !thr->IsStopped())
	{
		return CELL_ESTAT;
	}

	status = res;
	return CELL_OK;
}
int sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup)
{
	sc_spu.Warning("sys_spu_thread_connect_event(id=0x%x,eq=0x%x,et=0x%x,spup=0x%x)", id, eq, et, spup);

	EventQueue* equeue;
	if(!sys_event.CheckId(eq, equeue))
	{
		return CELL_ESRCH;
	}

	if(spup > 63)
	{
		return CELL_EINVAL;
	}

	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	for(int j=0; j<equeue->pos; ++j)
	{
		if(!equeue->ports[j]->thread)
		{
			equeue->ports[j]->thread = thr;
			return CELL_OK;
		}
	}

	return CELL_EISCONN;
}
Exemple #3
0
s32 sys_spu_thread_bind_queue(u32 id, u32 eq_id, u32 spuq_num)
{
	sc_spu.Warning("sys_spu_thread_bind_queue(id=%d, equeue_id=%d, spuq_num=0x%x)", id, eq_id, spuq_num);

	EventQueue* eq;
	if (!Emu.GetIdManager().GetIDData(eq_id, eq))
	{
		return CELL_ESRCH;
	}

	if (eq->type != SYS_SPU_QUEUE)
	{
		return CELL_EINVAL;
	}

	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	if (!(*(SPUThread*)thr).SPUQs.RegisterKey(eq, FIX_SPUQ(spuq_num)))
	{
		return CELL_EBUSY;
	}

	return CELL_OK;
}
Exemple #4
0
//181
s32 sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type)
{
	sc_spu.Log("sys_spu_thread_write_ls(id=%d, address=0x%x, value=0x%llx, type=0x%x)",
		id, address, value, type);

	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	if (!thr->IsRunning())
	{
		return CELL_ESTAT;
	}

	if (!(*(SPUThread*)thr).IsGoodLSA(address) || (address % type)) // +check alignment
	{
		return CELL_EINVAL;
	}

	switch (type)
	{
	case 1: (*(SPUThread*)thr).WriteLS8(address, value); return CELL_OK;
	case 2: (*(SPUThread*)thr).WriteLS16(address, value); return CELL_OK;
	case 4: (*(SPUThread*)thr).WriteLS32(address, value); return CELL_OK;
	case 8: (*(SPUThread*)thr).WriteLS64(address, value); return CELL_OK;
	default: return CELL_EINVAL;
	}
}
Exemple #5
0
void CPUThreadManager::RemoveThread(const u32 id)
{
	std::lock_guard<std::mutex> lock(m_mtx_thread);

	for(u32 i=0; i<m_threads.GetCount(); ++i)
	{
		if(m_threads[i].m_wait_thread_id == id)
		{
			m_threads[i].Wait(false);
			m_threads[i].m_wait_thread_id = -1;
		}

		if(m_threads[i].GetId() != id) continue;

		CPUThread* thr = &m_threads[i];
#ifndef QT_UI
		wxGetApp().SendDbgCommand(DID_REMOVE_THREAD, thr);
#endif
		thr->Close();

		m_threads.RemoveFAt(i);
		break;
	}

	Emu.GetIdManager().RemoveID(id);
	Emu.CheckStatus();
}
//184
int sys_spu_thread_write_snr(u32 id, u32 number, u32 value)
{
	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	if (number > 1)
	{
		return CELL_EINVAL;
	}

	if ((*(SPUThread*)thr).cfg.value & ((u64)1<<number))
	{ //logical OR
		(*(SPUThread*)thr).SPU.SNR[number].PushUncond_OR(value);
	}
	else
	{ //overwrite
		(*(SPUThread*)thr).SPU.SNR[number].PushUncond(value);
	}

	return CELL_OK;
}
Exemple #7
0
void CPUThreadManager::RemoveThread(const u32 id)
{
	std::lock_guard<std::mutex> lock(m_mtx_thread);

	CPUThread* thr = nullptr;
	u32 thread_index = 0;

	for (u32 i = 0; i < m_threads.size(); ++i)
	{
		if (m_threads[i]->m_wait_thread_id == id)
		{
			m_threads[i]->Wait(false);
			m_threads[i]->m_wait_thread_id = -1;
		}

		if (m_threads[i]->GetId() != id) continue;

		thr = m_threads[i];
		thread_index = i;
	}

	if (thr)
	{
#ifndef QT_UI
		wxGetApp().SendDbgCommand(DID_REMOVE_THREAD, thr);
#endif
		thr->Close();

		m_threads.erase(m_threads.begin() + thread_index);
	}

	// Removing the ID should trigger the actual deletion of the thread
	Emu.GetIdManager().RemoveID(id);
	Emu.CheckStatus();
}
Exemple #8
0
s32 sys_ppu_thread_get_priority(u64 thread_id, u32 prio_addr)
{
	sys_ppu_thread.Log("sys_ppu_thread_get_priority(thread_id=%lld, prio_addr=0x%x)", thread_id, prio_addr);

	CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
	if(!thr) return CELL_ESRCH;

	Memory.Write32(prio_addr, (s32)thr->GetPrio());

	return CELL_OK;
}
Exemple #9
0
PPCThread* GetCurrentPPCThread()
{
	CPUThread* thread = GetCurrentCPUThread();

	if(!thread || (thread->GetType() != CPU_THREAD_PPU && thread->GetType() != CPU_THREAD_SPU && thread->GetType() != CPU_THREAD_RAW_SPU))
	{
		throw wxString("GetCurrentPPCThread: bad thread");
	}

	return (PPCThread*)thread;
}
Exemple #10
0
int sys_ppu_thread_set_priority(u32 thread_id, int prio)
{
    sysPrxForUser.Warning("sys_ppu_thread_set_priority(thread_id=%d, prio=%d)", thread_id, prio);

    CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
    if(!thr) return CELL_ESRCH;

    thr->SetPrio(prio);

    return CELL_OK;
}
Exemple #11
0
s32 sys_ppu_thread_stop(u64 thread_id)
{
	sysPrxForUser->Warning("sys_ppu_thread_stop(thread_id=%lld)", thread_id);

	CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
	if(!thr) return CELL_ESRCH;

	thr->Stop();

	return CELL_OK;
}
Exemple #12
0
s32 sys_ppu_thread_set_priority(u64 thread_id, s32 prio)
{
	sysPrxForUser->Log("sys_ppu_thread_set_priority(thread_id=%lld, prio=%d)", thread_id, prio);

	CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
	if(!thr) return CELL_ESRCH;

	thr->SetPrio(prio);

	return CELL_OK;
}
Exemple #13
0
s32 sys_ppu_thread_rename(u64 thread_id, vm::ptr<const char> name)
{
	sys_ppu_thread.Log("sys_ppu_thread_rename(thread_id=%d, name_addr=0x%x('%s'))", thread_id, name.addr(), name.get_ptr());

	CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
	if (!thr) {
		return CELL_ESRCH;
	}

	thr->SetThreadName(name.get_ptr());
	return CELL_OK;
}
Exemple #14
0
s32 sys_ppu_thread_restart(u64 thread_id)
{
	sys_ppu_thread.Warning("sys_ppu_thread_restart(thread_id=%lld)", thread_id);

	CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
	if(!thr) return CELL_ESRCH;

	thr->Stop();
	thr->Run();

	return CELL_OK;
}
Exemple #15
0
int sys_ppu_thread_restart(u32 thread_id)
{
    sysPrxForUser.Warning("sys_ppu_thread_restart(thread_id=%d)", thread_id);

    CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
    if(!thr) return CELL_ESRCH;

    thr->Stop();
    thr->Run();

    return CELL_OK;
}
Exemple #16
0
s32 sys_ppu_thread_get_priority(u64 thread_id, u32 prio_addr)
{
	sysPrxForUser->Log("sys_ppu_thread_get_priority(thread_id=%lld, prio_addr=0x%x)", thread_id, prio_addr);

	CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
	if(!thr) return CELL_ESRCH;
	if(!Memory.IsGoodAddr(prio_addr)) return CELL_EFAULT;

	Memory.Write32(prio_addr, thr->GetPrio());

	return CELL_OK;
}
Exemple #17
0
s32 sys_ppu_thread_detach(u64 thread_id)
{
	sysPrxForUser->Error("sys_ppu_thread_detach(thread_id=%lld)", thread_id);

	CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
	if(!thr) return CELL_ESRCH;

	if(!thr->IsJoinable())
		return CELL_EINVAL;
	thr->SetJoinable(false);

	return CELL_OK;
}
Exemple #18
0
//190
s32 sys_spu_thread_write_spu_mb(u32 id, u32 value)
{
	sc_spu.Log("sys_spu_thread_write_spu_mb(id=%d, value=0x%x)", id, value);

	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	(*(SPUThread*)thr).SPU.In_MBox.PushUncond(value);

	return CELL_OK;
}
Exemple #19
0
//188
s32 sys_spu_thread_get_spu_cfg(u32 id, mem64_t value)
{
	sc_spu.Warning("sys_spu_thread_get_spu_cfg(id=%d, value_addr=0x%x)", id, value.GetAddr());

	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	value = (*(SPUThread*)thr).cfg.value;

	return CELL_OK;
}
Exemple #20
0
void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
{
	const u64 addr = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr();
	CPUThread* t = GetCurrentCPUThread();
	if (u == EXCEPTION_ACCESS_VIOLATION && addr < 0x100000000 && t)
	{
		// TODO: allow recovering from a page fault
		throw fmt::Format("Access violation: addr = 0x%x (is_alive=%d, last_syscall=0x%llx (%s))",
			(u32)addr, t->IsAlive() ? 1 : 0, t->m_last_syscall, SysCalls::GetHLEFuncName((u32)t->m_last_syscall).c_str());
	}
	else
	{
		// some fatal error (should crash)
		return;
	}
}
Exemple #21
0
//181
int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type)
{
	sc_spu.Warning("sys_spu_thread_write_ls(id=0x%x, address=0x%x, value=0x%llx, type=0x%x)",
		id, address, value, type);

	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	(*(SPUThread*)thr).WriteLS64(address, value);

	return CELL_OK;
}
Exemple #22
0
sleep_queue_entry_t::sleep_queue_entry_t(CPUThread& cpu, sleep_queue_t& queue)
	: m_thread(cpu)
	, m_queue(queue)
{
	add_entry();
	cpu.sleep();
}
Exemple #23
0
s32 sys_spu_thread_connect_event(u32 id, u32 eq_id, u32 et, u8 spup)
{
	sc_spu.Warning("sys_spu_thread_connect_event(id=%d, eq_id=%d, event_type=0x%x, spup=%d)", id, eq_id, et, spup);

	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	EventQueue* eq;
	if (!Emu.GetIdManager().GetIDData(eq_id, eq))
	{
		return CELL_ESRCH;
	}

	if (spup > 63)
	{
		sc_spu.Error("sys_spu_thread_connect_event: invalid spup (%d)", spup);
		return CELL_EINVAL;
	}

	if (et != SYS_SPU_THREAD_EVENT_USER)
	{
		sc_spu.Error("sys_spu_thread_connect_event: unsupported event type (0x%x)", et);
		return CELL_EINVAL;
	}

	// TODO: check if can receive these events

	SPUThread& spu = *(SPUThread*)thr;

	EventPort& port = spu.SPUPs[spup];

	std::lock_guard<std::mutex> lock(port.m_mutex);

	if (port.eq)
	{
		return CELL_EISCONN;
	}

	eq->ports.add(&port);
	port.eq = eq;

	return CELL_OK;
}
Exemple #24
0
//182
int sys_spu_thread_read_ls(u32 id, u32 address, mem64_t value, u32 type)
{
    sc_spu.Log("sys_spu_thread_read_ls(id=%d, address=0x%x, value_addr=0x%x, type=0x%x)",
               id, address, value.GetAddr(), type);

    CPUThread* thr = Emu.GetCPU().GetThread(id);

    if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
    {
        return CELL_ESRCH;
    }

    if (!thr->IsRunning())
    {
        return CELL_ESTAT;
    }

    if(!value.IsGood())
    {
        return CELL_EFAULT;
    }

    if (!(*(SPUThread*)thr).IsGoodLSA(address) || (address % type)) // +check alignment
    {
        return CELL_EINVAL;
    }

    switch (type)
    {
    case 1:
        value = (*(SPUThread*)thr).ReadLS8(address);
        return CELL_OK;
    case 2:
        value = (*(SPUThread*)thr).ReadLS16(address);
        return CELL_OK;
    case 4:
        value = (*(SPUThread*)thr).ReadLS32(address);
        return CELL_OK;
    case 8:
        value = (*(SPUThread*)thr).ReadLS64(address);
        return CELL_OK;
    default:
        return CELL_EINVAL;
    }
}
Exemple #25
0
s32 sys_spu_thread_unbind_queue(u32 id, u32 spuq_num)
{
	sc_spu.Warning("sys_spu_thread_unbind_queue(id=0x%x, spuq_num=0x%x)", id, spuq_num);

	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	if (!(*(SPUThread*)thr).SPUQs.UnregisterKey(FIX_SPUQ(spuq_num)))
	{
		return CELL_ESRCH; // may be CELL_EINVAL
	}

	return CELL_OK;
}
Exemple #26
0
//190
int sys_spu_thread_write_spu_mb(u32 id, u32 value)
{
	sc_spu.Warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x)", id, value);

	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	if(!(*(SPUThread*)thr).SPU.In_MBox.Push(value))
	{
		ConLog.Warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x): used all mbox items.");
		return CELL_EBUSY; //?
	}

	return CELL_OK;
}
Exemple #27
0
//184
s32 sys_spu_thread_write_snr(u32 id, u32 number, u32 value)
{
	sc_spu.Log("sys_spu_thread_write_snr(id=%d, number=%d, value=0x%x)", id, number, value);
	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	if (number > 1)
	{
		return CELL_EINVAL;
	}

	(*(SPUThread*)thr).WriteSNR(number, value);

	return CELL_OK;
}
Exemple #28
0
s32 sys_ppu_thread_join(u64 thread_id, mem64_t vptr)
{
	sysPrxForUser->Warning("sys_ppu_thread_join(thread_id=%lld, vptr_addr=0x%x)", thread_id, vptr.GetAddr());

	CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
	if(!thr) return CELL_ESRCH;

	while (thr->IsAlive())
	{
		if (Emu.IsStopped())
		{
			LOG_WARNING(PPU, "sys_ppu_thread_join(%d) aborted", thread_id);
			return CELL_OK;
		}
		std::this_thread::sleep_for(std::chrono::milliseconds(1));
	}

	vptr = thr->GetExitStatus();
	return CELL_OK;
}
Exemple #29
0
s32 sys_ppu_thread_join(u64 thread_id, vm::ptr<be_t<u64>> vptr)
{
	sys_ppu_thread.Warning("sys_ppu_thread_join(thread_id=%lld, vptr_addr=0x%x)", thread_id, vptr.addr());

	CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
	if(!thr) return CELL_ESRCH;

	while (thr->IsAlive())
	{
		if (Emu.IsStopped())
		{
			sys_ppu_thread.Warning("sys_ppu_thread_join(%d) aborted", thread_id);
			return CELL_OK;
		}
		std::this_thread::sleep_for(std::chrono::milliseconds(1));
	}

	*vptr = thr->GetExitStatus();
	return CELL_OK;
}
Exemple #30
0
//187
s32 sys_spu_thread_set_spu_cfg(u32 id, u64 value)
{
	sc_spu.Warning("sys_spu_thread_set_spu_cfg(id=%d, value=0x%x)", id, value);

	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	if (value > 3)
	{
		return CELL_EINVAL;
	}

	(*(SPUThread*)thr).cfg.value = value;

	return CELL_OK;
}