private bool checkEventFlag(SceKernelEventFlagInfo @event, int bits, int wait, TPointer32 outBitsAddr) { bool matched = false; if (((wait & PSP_EVENT_WAITANDOR_MASK) == PSP_EVENT_WAITAND) && ((@event.currentPattern & bits) == bits)) { matched = true; } else if (((wait & PSP_EVENT_WAITANDOR_MASK) == PSP_EVENT_WAITOR) && ((@event.currentPattern & bits) != 0)) { matched = true; } if (matched) { // Write current pattern. outBitsAddr.setValue(@event.currentPattern); if (log.DebugEnabled && outBitsAddr.NotNull) { Console.WriteLine(string.Format("checkEventFlag returning outBits=0x{0:X} at {1}", outBitsAddr.getValue(), outBitsAddr)); } if ((wait & PSP_EVENT_WAITCLEARALL) == PSP_EVENT_WAITCLEARALL) { @event.currentPattern = 0; } if ((wait & PSP_EVENT_WAITCLEAR) == PSP_EVENT_WAITCLEAR) { @event.currentPattern &= ~bits; } } return(matched); }
public virtual int sceKernelClearEventFlag(int uid, int bitsToKeep) { SceKernelEventFlagInfo @event = eventMap[uid]; @event.currentPattern &= bitsToKeep; return(0); }
public virtual int sceKernelCreateEventFlag(string name, int attr, int initPattern, TPointer option) { SceKernelEventFlagInfo @event = new SceKernelEventFlagInfo(name, attr, initPattern, initPattern); eventMap[@event.uid] = @event; return(@event.uid); }
public virtual int sceKernelSetEventFlag(int uid, int bitsToSet) { SceKernelEventFlagInfo @event = eventMap[uid]; @event.currentPattern |= bitsToSet; onEventFlagModified(@event); return(0); }
public virtual int sceKernelCancelEventFlag(int uid, int newPattern, TPointer32 numWaitThreadAddr) { SceKernelEventFlagInfo @event = eventMap[uid]; numWaitThreadAddr.setValue(@event.NumWaitThreads); @event.threadWaitingList.removeAllWaitingThreads(); @event.currentPattern = newPattern; onEventFlagCancelled(uid); return(0); }
public virtual int sceKernelReferEventFlagStatus(int uid, TPointer addr) { SceKernelEventFlagInfo @event = eventMap[uid]; //if (log.DebugEnabled) { Console.WriteLine(string.Format("sceKernelReferEventFlagStatus event={0}", @event)); } @event.write(addr); return(0); }
public virtual int sceKernelDeleteEventFlag(int uid) { SceKernelEventFlagInfo @event = eventMap.Remove(uid); if (@event.NumWaitThreads > 0) { Console.WriteLine(string.Format("sceKernelDeleteEventFlag numWaitThreads {0:D}", @event.NumWaitThreads)); } onEventFlagDeleted(uid); return(0); }
public virtual int hleKernelWaitEventFlag(int uid, int bits, int wait, TPointer32 outBitsAddr, TPointer32 timeoutAddr, bool doCallbacks) { if ((wait & ~(PSP_EVENT_WAITOR | PSP_EVENT_WAITCLEAR | PSP_EVENT_WAITCLEARALL)) != 0 || (wait & (PSP_EVENT_WAITCLEAR | PSP_EVENT_WAITCLEARALL)) == (PSP_EVENT_WAITCLEAR | PSP_EVENT_WAITCLEARALL)) { return(ERROR_KERNEL_ILLEGAL_MODE); } if (bits == 0) { return(ERROR_KERNEL_EVENT_FLAG_ILLEGAL_WAIT_PATTERN); } if (!Modules.ThreadManForUserModule.DispatchThreadEnabled) { return(ERROR_KERNEL_WAIT_CAN_NOT_WAIT); } SceKernelEventFlagInfo @event = eventMap[uid]; if (@event.NumWaitThreads >= 1 && (@event.attr & PSP_EVENT_WAITMULTIPLE) != PSP_EVENT_WAITMULTIPLE) { Console.WriteLine("hleKernelWaitEventFlag already another thread waiting on it"); return(ERROR_KERNEL_EVENT_FLAG_NO_MULTI_PERM); } if (!checkEventFlag(@event, bits, wait, outBitsAddr)) { // Failed, but it's ok, just wait a little //if (log.DebugEnabled) { Console.WriteLine(string.Format("hleKernelWaitEventFlag - {0} fast check failed", @event)); } ThreadManForUser threadMan = Modules.ThreadManForUserModule; SceKernelThreadInfo currentThread = threadMan.CurrentThread; @event.threadWaitingList.addWaitingThread(currentThread); // Wait on a specific event flag currentThread.wait.EventFlag_id = uid; currentThread.wait.EventFlag_bits = bits; currentThread.wait.EventFlag_wait = wait; currentThread.wait.EventFlag_outBits_addr = outBitsAddr; threadMan.hleKernelThreadEnterWaitState(PSP_WAIT_EVENTFLAG, uid, eventFlagWaitStateChecker, timeoutAddr.Address, doCallbacks); } else { // Success, do not reschedule the current thread. //if (log.DebugEnabled) { Console.WriteLine(string.Format("hleKernelWaitEventFlag - {0} fast check succeeded", @event)); } } return(0); }
/// <summary> /// Don't call this unless thread.waitType == PSP_WAIT_EVENTFLAG </summary> /// <returns> true if the thread was waiting on a valid event flag </returns> private bool removeWaitingThread(SceKernelThreadInfo thread) { SceKernelEventFlagInfo @event = eventMap[thread.wait.EventFlag_id]; if (@event == null) { return(false); } @event.threadWaitingList.removeWaitingThread(thread); // Store the currentPattern at the outBits address, even in case of error thread.wait.EventFlag_outBits_addr.setValue(@event.currentPattern); return(true); }
public virtual int sceKernelPollEventFlag(int uid, int bits, int wait, TPointer32 outBitsAddr) { if (bits == 0) { return(ERROR_KERNEL_EVENT_FLAG_ILLEGAL_WAIT_PATTERN); } SceKernelEventFlagInfo @event = eventMap[uid]; if (!checkEventFlag(@event, bits, wait, outBitsAddr)) { // Write the outBits, even if the poll failed outBitsAddr.setValue(@event.currentPattern); return(ERROR_KERNEL_EVENT_FLAG_POLL_FAILED); } return(0); }
public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait) { // Check if the thread has to continue its wait state or if the event flag // has been set during the callback execution. SceKernelEventFlagInfo @event = eventMap[wait.EventFlag_id]; if (@event == null) { thread.cpuContext._v0 = ERROR_KERNEL_NOT_FOUND_EVENT_FLAG; return(false); } // Check EventFlag. if (outerInstance.checkEventFlag(@event, wait.EventFlag_bits, wait.EventFlag_wait, wait.EventFlag_outBits_addr)) { @event.threadWaitingList.removeWaitingThread(thread); thread.cpuContext._v0 = 0; return(false); } return(true); }
private void onEventFlagModified(SceKernelEventFlagInfo @event) { ThreadManForUser threadMan = Modules.ThreadManForUserModule; bool reschedule = false; SceKernelThreadInfo checkedThread = null; while (@event.currentPattern != 0) { SceKernelThreadInfo thread = @event.threadWaitingList.getNextWaitingThread(checkedThread); if (thread == null) { break; } if (checkEventFlag(@event, thread.wait.EventFlag_bits, thread.wait.EventFlag_wait, thread.wait.EventFlag_outBits_addr)) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("onEventFlagModified waking thread {0}", thread)); } @event.threadWaitingList.removeWaitingThread(thread); thread.cpuContext._v0 = 0; threadMan.hleChangeThreadState(thread, PSP_THREAD_READY); reschedule = true; } else { checkedThread = thread; } } // Reschedule only if threads waked up. if (reschedule) { threadMan.hleRescheduleCurrentThread(); } }