public virtual int hleKernelWaitSema(SceKernelSemaInfo sema, int signal, TPointer32 timeoutAddr, bool doCallbacks) { if (!tryWaitSemaphore(sema, signal)) { // Failed, but it's ok, just wait a little //if (log.DebugEnabled) { Console.WriteLine(string.Format("hleKernelWaitSema {0} fast check failed", sema)); } ThreadManForUser threadMan = Modules.ThreadManForUserModule; SceKernelThreadInfo currentThread = threadMan.CurrentThread; sema.threadWaitingList.addWaitingThread(currentThread); // Wait on a specific semaphore currentThread.wait.Semaphore_id = sema.uid; currentThread.wait.Semaphore_signal = signal; threadMan.hleKernelThreadEnterWaitState(PSP_WAIT_SEMA, sema.uid, semaWaitStateChecker, timeoutAddr.Address, doCallbacks); } else { // Success, do not reschedule the current thread. //if (log.DebugEnabled) { Console.WriteLine(string.Format("hleKernelWaitSema {0} fast check succeeded", sema)); } } return(0); }
public virtual int sceKernelCancelSema(int semaid, int newcount, TPointer32 numWaitThreadAddr) { SceKernelSemaInfo sema = semaMap[semaid]; if (newcount > sema.maxCount) { return(ERROR_KERNEL_ILLEGAL_COUNT); } // Write previous numWaitThreads count. numWaitThreadAddr.setValue(sema.NumWaitThreads); sema.threadWaitingList.removeAllWaitingThreads(); // Reset this semaphore's count based on newcount. // Note: If newcount is negative, the count becomes this semaphore's initCount. if (newcount < 0) { sema.currentCount = sema.initCount; } else { sema.currentCount = newcount; } onSemaphoreCancelled(semaid); return(0); }
private bool tryWaitSemaphore(SceKernelSemaInfo sema, int signal) { bool success = false; if (sema.currentCount >= signal) { sema.currentCount -= signal; success = true; } return(success); }
public virtual int sceKernelReferSemaStatus(int semaid, TPointer addr) { SceKernelSemaInfo sema = semaMap[semaid]; sema.write(addr); //if (log.DebugEnabled) { Console.WriteLine(string.Format("sceKernelReferSemaStatus returning {0}", sema)); } return(0); }
/// <summary> /// This is attempt to signal the sema and always return immediately </summary> public virtual int sceKernelPollSema(int semaid, int signal) { if (signal <= 0) { Console.WriteLine(string.Format("sceKernelPollSema id=0x{0:X}, signal={1:D}: bad signal", semaid, signal)); return(ERROR_KERNEL_ILLEGAL_COUNT); } SceKernelSemaInfo sema = semaMap[semaid]; return(hleKernelPollSema(sema, signal)); }
/// <summary> /// Don't call this unless thread.wait.waitingOnSemaphore == true </summary> /// <returns> true if the thread was waiting on a valid sema </returns> private bool removeWaitingThread(SceKernelThreadInfo thread) { SceKernelSemaInfo sema = semaMap[thread.wait.Semaphore_id]; if (sema == null) { return(false); } sema.threadWaitingList.removeWaitingThread(thread); return(true); }
public virtual int sceKernelCreateSema(string name, int attr, int initVal, int maxVal, TPointer option) { if (string.ReferenceEquals(name, null)) { return(SceKernelErrors.ERROR_KERNEL_ERROR); } SceKernelSemaInfo sema = hleKernelCreateSema(name, attr, initVal, maxVal, option); //if (log.DebugEnabled) { Console.WriteLine(string.Format("sceKernelCreateSema {0}", sema)); } return(sema.uid); }
public virtual SceKernelSemaInfo hleKernelCreateSema(string name, int attr, int initVal, int maxVal, TPointer option) { if (option.NotNull) { // The first int does not seem to be the size of the struct, found values: // SSX On Tour: 0, 0x08B0F9E4, 0x0892E664, 0x08AF7257 (some values are used in more than one semaphore) int optionSize = option.getValue32(); Console.WriteLine(string.Format("sceKernelCreateSema option at {0}, size={1:D}", option, optionSize)); } SceKernelSemaInfo sema = new SceKernelSemaInfo(name, attr, initVal, maxVal); semaMap[sema.uid] = sema; return(sema); }
public virtual int hleKernelSignalSema(SceKernelSemaInfo sema, int signal) { // Check that currentCount will not exceed the maxCount // after releasing all the threads waiting on this sema. int newCount = sema.currentCount + signal; if (newCount > sema.maxCount) { for (IEnumerator <SceKernelThreadInfo> it = Modules.ThreadManForUserModule.GetEnumerator(); it.MoveNext();) { SceKernelThreadInfo thread = it.Current; if (thread.isWaitingForType(PSP_WAIT_SEMA) && thread.wait.Semaphore_id == sema.uid) { newCount -= thread.wait.Semaphore_signal; } } if (newCount > sema.maxCount) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("hleKernelSignalSema returning 0x{0:X8}(ERROR_KERNEL_SEMA_OVERFLOW)", ERROR_KERNEL_SEMA_OVERFLOW)); } return(ERROR_KERNEL_SEMA_OVERFLOW); } } sema.currentCount += signal; onSemaphoreModified(sema); // Sanity check... if (sema.currentCount > sema.maxCount) { // This situation should never happen, otherwise something went wrong // in the overflow check above. Console.WriteLine(string.Format("hleKernelSignalSema currentCount {0:D} exceeding maxCount {1:D}", sema.currentCount, sema.maxCount)); } //if (log.DebugEnabled) { Console.WriteLine(string.Format("hleKernelSignalSema returning 0, {0}", sema)); } return(0); }
public virtual int hleKernelPollSema(SceKernelSemaInfo sema, int signal) { if (signal > sema.currentCount) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("hleKernelPollSema returning 0x{0:X8}(ERROR_KERNEL_SEMA_ZERO)", ERROR_KERNEL_SEMA_ZERO)); } return(ERROR_KERNEL_SEMA_ZERO); } sema.currentCount -= signal; //if (log.DebugEnabled) { Console.WriteLine(string.Format("hleKernelPollSema returning 0, {0}", sema)); } return(0); }
private int hleKernelWaitSema(int semaid, int signal, TPointer32 timeoutAddr, bool doCallbacks) { if (signal <= 0) { Console.WriteLine(string.Format("hleKernelWaitSema - bad signal {0:D}", signal)); return(ERROR_KERNEL_ILLEGAL_COUNT); } SceKernelSemaInfo sema = semaMap[semaid]; if (signal > sema.maxCount) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("hleKernelWaitSema returning 0x{0:X8}(ERROR_KERNEL_ILLEGAL_COUNT)", ERROR_KERNEL_ILLEGAL_COUNT)); } return(ERROR_KERNEL_ILLEGAL_COUNT); } return(hleKernelWaitSema(sema, signal, timeoutAddr, doCallbacks)); }
public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait) { // Check if the thread has to continue its wait state or if the sema // has been signaled during the callback execution. SceKernelSemaInfo sema = outerInstance.semaMap[wait.Semaphore_id]; if (sema == null) { thread.cpuContext._v0 = ERROR_KERNEL_NOT_FOUND_SEMAPHORE; return(false); } // Check the sema. if (outerInstance.tryWaitSemaphore(sema, wait.Semaphore_signal)) { sema.threadWaitingList.removeWaitingThread(thread); thread.cpuContext._v0 = 0; return(false); } return(true); }
private void onSemaphoreModified(SceKernelSemaInfo sema) { ThreadManForUser threadMan = Modules.ThreadManForUserModule; bool reschedule = false; SceKernelThreadInfo checkedThread = null; while (sema.currentCount > 0) { SceKernelThreadInfo thread = sema.threadWaitingList.getNextWaitingThread(checkedThread); if (thread == null) { break; } if (tryWaitSemaphore(sema, thread.wait.Semaphore_signal)) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("onSemaphoreModified waking thread {0}", thread)); } sema.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(); } }
public virtual int sceKernelSignalSema(int semaid, int signal) { SceKernelSemaInfo sema = semaMap[semaid]; return(hleKernelSignalSema(sema, signal)); }