Example #1
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;
}
Example #2
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;
}
Example #3
0
void SPUThread::StopAndSignal(u32 code)
{
	SetExitStatus(code); // exit code (not status)
	// TODO: process interrupts for RawSPU

	switch (code)
	{
	case 0x110:
	{
		/* ===== sys_spu_thread_receive_event ===== */

		u32 spuq = 0;
		if (!SPU.Out_MBox.Pop(spuq))
		{
			LOG_ERROR(Log::SPU, "sys_spu_thread_receive_event: cannot read Out_MBox");
			SPU.In_MBox.PushUncond(CELL_EINVAL); // ???
			return;
		}

		if (SPU.In_MBox.GetCount())
		{
			LOG_ERROR(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x): In_MBox is not empty", spuq);
			SPU.In_MBox.PushUncond(CELL_EBUSY); // ???
			return;
		}

		if (Ini.HLELogging.GetValue())
		{
			LOG_NOTICE(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x)", spuq);
		}

		EventQueue* eq;
		if (!SPUQs.GetEventQueue(FIX_SPUQ(spuq), eq))
		{
			SPU.In_MBox.PushUncond(CELL_EINVAL); // TODO: check error value
			return;
		}

		u32 tid = GetId();

		eq->sq.push(tid); // add thread to sleep queue

		while (true)
		{
			switch (eq->owner.trylock(tid))
			{
			case SMR_OK:
				if (!eq->events.count())
				{
					eq->owner.unlock(tid);
					break;
				}
				else
				{
					u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->sq.pop() : eq->sq.pop_prio();
					if (next != tid)
					{
						eq->owner.unlock(tid, next);
						break;
					}
				}
			case SMR_SIGNAL:
			{
				sys_event_data event;
				eq->events.pop(event);
				eq->owner.unlock(tid);
				SPU.In_MBox.PushUncond(CELL_OK);
				SPU.In_MBox.PushUncond((u32)event.data1);
				SPU.In_MBox.PushUncond((u32)event.data2);
				SPU.In_MBox.PushUncond((u32)event.data3);
				return;
			}
			case SMR_FAILED: break;
			default: eq->sq.invalidate(tid); SPU.In_MBox.PushUncond(CELL_ECANCELED); return;
			}

			std::this_thread::sleep_for(std::chrono::milliseconds(1));
			if (Emu.IsStopped())
			{
				LOG_WARNING(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x) aborted", spuq);
				eq->sq.invalidate(tid);
				return;
			}
		}
		break;
	}

	case 0x101:
	{
		/* ===== sys_spu_thread_group_exit ===== */

		if (!group)
		{
			LOG_ERROR(Log::SPU, "sys_spu_thread_group_exit(): group not set");
			break;
		}
		else if (!SPU.Out_MBox.GetCount())
		{
			LOG_ERROR(Log::SPU, "sys_spu_thread_group_exit(): Out_MBox is empty");
		}
		else if (Ini.HLELogging.GetValue())
		{
			LOG_NOTICE(Log::SPU, "sys_spu_thread_group_exit(status=0x%x)", SPU.Out_MBox.GetValue());
		}
		
		group->m_group_exit = true;
		group->m_exit_status = SPU.Out_MBox.GetValue();
		for (auto& v : group->list)
		{
			if (CPUThread* t = Emu.GetCPU().GetThread(v))
			{
				t->Stop();
			}
		}

		break;
	}

	case 0x102:
	{
		/* ===== sys_spu_thread_exit ===== */

		if (!SPU.Out_MBox.GetCount())
		{
			LOG_ERROR(Log::SPU, "sys_spu_thread_exit(): Out_MBox is empty");
		}
		else if (Ini.HLELogging.GetValue())
		{
			// the real exit status
			LOG_NOTICE(Log::SPU, "sys_spu_thread_exit(status=0x%x)", SPU.Out_MBox.GetValue());
		}
		SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP);
		Stop();
		break;
	}

	default:
	{
		if (!SPU.Out_MBox.GetCount())
		{
			LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (no message)", code);
		}
		else
		{
			LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue());
		}
		Stop();
		break;
	}
	}
}