示例#1
0
bool __KernelUnlockEventFlagForThread(EventFlag *e, EventFlagTh &th, u32 &error, int result, bool &wokeThreads)
{
	SceUID waitID = __KernelGetWaitID(th.tid, WAITTYPE_EVENTFLAG, error);
	u32 timeoutPtr = __KernelGetWaitTimeoutPtr(th.tid, error);

	// The waitID may be different after a timeout.
	if (waitID != e->GetUID())
		return true;

	// If result is an error code, we're just letting it go.
	if (result == 0)
	{
		if (!__KernelEventFlagMatches(&e->nef.currentPattern, th.bits, th.wait, th.outAddr))
			return false;

		e->nef.numWaitThreads--;
	}
	else
	{
		// Otherwise, we set the current result since we're bailing.
		if (Memory::IsValidAddress(th.outAddr))
			Memory::Write_U32(e->nef.currentPattern, th.outAddr);
	}

	if (timeoutPtr != 0 && eventFlagWaitTimer != 0)
	{
		// Remove any event for this thread.
		u64 cyclesLeft = CoreTiming::UnscheduleEvent(eventFlagWaitTimer, th.tid);
		Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr);
	}

	__KernelResumeThreadFromWait(th.tid, result);
	wokeThreads = true;
	return true;
}
示例#2
0
//int sceKernelPollEventFlag(int evid, u32 bits, u32 wait, u32 *outBits);
void sceKernelPollEventFlag()
{
	SceUID id = PARAM(0);
	u32 bits = PARAM(1);
	u32 wait = PARAM(2);
	u32 outBitsPtr = PARAM(3);
	u32 timeoutPtr = PARAM(4);

	DEBUG_LOG(HLE,"sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr);

	u32 error;
	EventFlag *e = kernelObjects.Get<EventFlag>(id, error);
	if (e)
	{
		if (!__KernelEventFlagMatches(&e->nef.currentPattern, bits, wait, outBitsPtr))
		{
			if (Memory::IsValidAddress(outBitsPtr))
				Memory::Write_U32(e->nef.currentPattern, outBitsPtr);
			// No match - return that, this is polling, not waiting.
			RETURN(SCE_KERNEL_ERROR_EVF_COND);
		}
		else
		{
			RETURN(0);
		}
	}
	else
	{
		RETURN(error);
	}
}
示例#3
0
//int sceKernelSetEventFlag(SceUID evid, u32 bits);
void sceKernelSetEventFlag()
{
	SceUID id = PARAM(0);
	u32 bitsToSet = PARAM(1);
	u32 error;
	DEBUG_LOG(HLE,"sceKernelSetEventFlag(%i, %08x)", id, bitsToSet);
	EventFlag *e = kernelObjects.Get<EventFlag>(id, error);
	if (e)
	{
		bool wokeThreads = false;

		e->nef.currentPattern |= bitsToSet;

retry:
		for (size_t i = 0; i < e->waitingThreads.size(); i++)
		{
			EventFlagTh *t = &e->waitingThreads[i];
			if (__KernelEventFlagMatches(&e->nef.currentPattern, t->bits, t->wait, t->outAddr))
			{
				__KernelResumeThread(t->tid);
				wokeThreads = true;
				e->nef.numWaitThreads--;
				e->waitingThreads.erase(e->waitingThreads.begin() + i);
				goto retry;
			}
		}
		RETURN(0);
	}
	else
	{
		RETURN(error);
	}
}
示例#4
0
int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeoutPtr)
{
	DEBUG_LOG(HLE, "sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr);

	if ((wait & ~PSP_EVENT_WAITKNOWN) != 0)
	{
		WARN_LOG(HLE, "sceKernelWaitEventFlagCB(%i) invalid mode parameter: %08x", id, wait);
		return SCE_KERNEL_ERROR_ILLEGAL_MODE;
	}
	// Can't wait on 0, that's guaranteed to wait forever.
	if (bits == 0)
		return SCE_KERNEL_ERROR_EVF_ILPAT;

	u32 error;
	EventFlag *e = kernelObjects.Get<EventFlag>(id, error);
	if (e)
	{
		EventFlagTh th;
		if (!__KernelEventFlagMatches(&e->nef.currentPattern, bits, wait, outBitsPtr))
		{
			// If this thread was left in waitingThreads after a timeout, remove it.
			// Otherwise we might write the outBitsPtr in the wrong place.
			__KernelEventFlagRemoveThread(e, __KernelGetCurThread());

			u32 timeout = 0xFFFFFFFF;
			if (Memory::IsValidAddress(timeoutPtr))
				timeout = Memory::Read_U32(timeoutPtr);

			// Do we allow more than one thread to wait?
			if (e->nef.numWaitThreads > 0 && (e->nef.attr & PSP_EVENT_WAITMULTIPLE) == 0)
				return SCE_KERNEL_ERROR_EVF_MULTI;

			// No match - must wait.
			e->nef.numWaitThreads++;
			th.tid = __KernelGetCurThread();
			th.bits = bits;
			th.wait = wait;
			// If < 5ms, sometimes hardware doesn't write this, but it's unpredictable.
			th.outAddr = timeout == 0 ? 0 : outBitsPtr;
			e->waitingThreads.push_back(th);

			__KernelSetEventFlagTimeout(e, timeoutPtr);
			__KernelWaitCurThread(WAITTYPE_EVENTFLAG, id, 0, timeoutPtr, true);
		}
		else
			hleCheckCurrentCallbacks();

		return 0;
	}
	else
	{
		return error;
	}
}
示例#5
0
int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr)
{
	if ((wait & ~PSP_EVENT_WAITKNOWN) != 0)
	{
		WARN_LOG_REPORT(HLE, "sceKernelPollEventFlag(%i) invalid mode parameter: %08x", id, wait);
		return SCE_KERNEL_ERROR_ILLEGAL_MODE;
	}
	// Poll seems to also fail when CLEAR and CLEARALL are used together, but not wait.
	if ((wait & PSP_EVENT_WAITCLEAR) != 0 && (wait & PSP_EVENT_WAITCLEARALL) != 0)
	{
		WARN_LOG_REPORT(HLE, "sceKernelPollEventFlag(%i) invalid mode parameter: %08x", id, wait);
		return SCE_KERNEL_ERROR_ILLEGAL_MODE;
	}
	// Can't wait on 0, it never matches.
	if (bits == 0)
	{
		DEBUG_LOG(HLE, "sceKernelPollEventFlag(%i, %08x, %i, %08x): bad pattern", id, bits, wait, outBitsPtr);
		return SCE_KERNEL_ERROR_EVF_ILPAT;
	}

	u32 error;
	EventFlag *e = kernelObjects.Get<EventFlag>(id, error);
	if (e)
	{
		if (!__KernelEventFlagMatches(&e->nef.currentPattern, bits, wait, outBitsPtr))
		{
			if (Memory::IsValidAddress(outBitsPtr))
				Memory::Write_U32(e->nef.currentPattern, outBitsPtr);

			if (e->waitingThreads.size() > 0 && (e->nef.attr & PSP_EVENT_WAITMULTIPLE) == 0)
			{
				DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_EVF_MULTI=sceKernelPollEventFlag(%i, %08x, %i, %08x)", id, bits, wait, outBitsPtr);
				return SCE_KERNEL_ERROR_EVF_MULTI;
			}

			// No match - return that, this is polling, not waiting.
			DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_EVF_COND=sceKernelPollEventFlag(%i, %08x, %i, %08x)", id, bits, wait, outBitsPtr);
			return SCE_KERNEL_ERROR_EVF_COND;
		}
		else
		{
			DEBUG_LOG(HLE, "0=sceKernelPollEventFlag(%i, %08x, %i, %08x)", id, bits, wait, outBitsPtr);
			return 0;
		}
	}
	else
	{
		DEBUG_LOG(HLE, "sceKernelPollEventFlag(%i, %08x, %i, %08x): invalid event flag", id, bits, wait, outBitsPtr);
		return error;
	}
}
示例#6
0
//int sceKernelWaitEventFlagCB(SceUID evid, u32 bits, u32 wait, u32 *outBits, SceUInt *timeout);
void sceKernelWaitEventFlagCB()
{
	SceUID id = PARAM(0);
	u32 bits = PARAM(1);
	u32 wait = PARAM(2);
	u32 outBitsPtr = PARAM(3);
	u32 timeoutPtr = PARAM(4);

	DEBUG_LOG(HLE,"sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr);

	u32 error;
	EventFlag *e = kernelObjects.Get<EventFlag>(id, error);
	if (e)
	{
		EventFlagTh th;
		if (!__KernelEventFlagMatches(&e->nef.currentPattern, bits, wait, outBitsPtr))
		{
			// No match - must wait.
			e->nef.numWaitThreads++;
			th.tid = __KernelGetCurThread();
			th.bits = bits;
			th.wait = wait;
			th.outAddr = outBitsPtr;
			e->waitingThreads.push_back(th);
			u32 timeout;
			if (Memory::IsValidAddress(timeoutPtr))
				timeout = Memory::Read_U32(timeoutPtr);

			__KernelWaitCurThread(WAITTYPE_EVENTFLAG, id, 0, 0, true);
		}
		RETURN(0);
	}
	else
	{
		RETURN(error);
	}
}
示例#7
0
int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeoutPtr)
{
	if ((wait & ~PSP_EVENT_WAITKNOWN) != 0)
	{
		WARN_LOG_REPORT(SCEKERNEL, "sceKernelWaitEventFlagCB(%i) invalid mode parameter: %08x", id, wait);
		return SCE_KERNEL_ERROR_ILLEGAL_MODE;
	}
	// Can't wait on 0, that's guaranteed to wait forever.
	if (bits == 0)
	{
		DEBUG_LOG(SCEKERNEL, "sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x): bad pattern", id, bits, wait, outBitsPtr, timeoutPtr);
		return SCE_KERNEL_ERROR_EVF_ILPAT;
	}

	if (!__KernelIsDispatchEnabled())
	{
		DEBUG_LOG(SCEKERNEL, "sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x): dispatch disabled", id, bits, wait, outBitsPtr, timeoutPtr);
		return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
	}

	u32 error;
	EventFlag *e = kernelObjects.Get<EventFlag>(id, error);
	if (e)
	{
		EventFlagTh th;
		bool doWait = !__KernelEventFlagMatches(&e->nef.currentPattern, bits, wait, outBitsPtr);
		bool doCallbackWait = false;
		if (__KernelCurHasReadyCallbacks())
		{
			doWait = true;
			doCallbackWait = true;
		}

		if (doWait)
		{
			// If this thread was left in waitingThreads after a timeout, remove it.
			// Otherwise we might write the outBitsPtr in the wrong place.
			HLEKernel::RemoveWaitingThread(e->waitingThreads, __KernelGetCurThread());

			u32 timeout = 0xFFFFFFFF;
			if (Memory::IsValidAddress(timeoutPtr))
				timeout = Memory::Read_U32(timeoutPtr);

			// Do we allow more than one thread to wait?
			if (e->waitingThreads.size() > 0 && (e->nef.attr & PSP_EVENT_WAITMULTIPLE) == 0)
			{
				DEBUG_LOG(SCEKERNEL, "SCE_KERNEL_ERROR_EVF_MULTI=sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr);
				return SCE_KERNEL_ERROR_EVF_MULTI;
			}

			DEBUG_LOG(SCEKERNEL, "sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x): waiting", id, bits, wait, outBitsPtr, timeoutPtr);

			// No match - must wait.
			th.threadID = __KernelGetCurThread();
			th.bits = bits;
			th.wait = wait;
			// If < 5ms, sometimes hardware doesn't write this, but it's unpredictable.
			th.outAddr = timeout == 0 ? 0 : outBitsPtr;
			e->waitingThreads.push_back(th);

			__KernelSetEventFlagTimeout(e, timeoutPtr);
			if (doCallbackWait)
				__KernelWaitCallbacksCurThread(WAITTYPE_EVENTFLAG, id, 0, timeoutPtr);
			else
				__KernelWaitCurThread(WAITTYPE_EVENTFLAG, id, 0, timeoutPtr, true, "event flag waited");
		}
		else
		{
			DEBUG_LOG(SCEKERNEL, "0=sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr);
			hleCheckCurrentCallbacks();
		}

		return 0;
	}
	else
	{
		DEBUG_LOG(SCEKERNEL, "sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x): invalid event flag", id, bits, wait, outBitsPtr, timeoutPtr);
		return error;
	}
}