示例#1
0
        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);
        }
示例#2
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);
        }
示例#3
0
        private bool tryWaitSemaphore(SceKernelSemaInfo sema, int signal)
        {
            bool success = false;

            if (sema.currentCount >= signal)
            {
                sema.currentCount -= signal;
                success            = true;
            }
            return(success);
        }
示例#4
0
        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);
        }
示例#5
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));
        }
示例#6
0
        /// <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);
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#9
0
        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);
        }
示例#10
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);
        }
示例#11
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));
        }
示例#12
0
            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);
            }
示例#13
0
        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();
            }
        }
示例#14
0
        public virtual int sceKernelSignalSema(int semaid, int signal)
        {
            SceKernelSemaInfo sema = semaMap[semaid];

            return(hleKernelSignalSema(sema, signal));
        }