コード例 #1
0
        protected internal virtual int hleUmdWaitDriveStat(int wantedStat, bool doCallbacks, bool doTimeout, int timeout)
        {
            ThreadManForUser threadMan = Modules.ThreadManForUserModule;

            if (!checkDriveStat(wantedStat))
            {
                SceKernelThreadInfo currentThread = threadMan.CurrentThread;
                // Wait on a specific umdStat.
                currentThread.wait.wantedUmdStat = wantedStat;
                waitingThreads.Add(currentThread);
                threadMan.hleKernelThreadEnterWaitState(currentThread, JPCSP_WAIT_UMD, -1, umdWaitStateChecker, timeout, !doTimeout, doCallbacks);
            }
            threadMan.hleRescheduleCurrentThread(doCallbacks);

            return(0);
        }
コード例 #2
0
        public virtual int sceKernelSendMbx(int uid, TPointer msgAddr)
        {
            SceKernelMbxInfo info = mbxMap[uid];

            bool msgConsumed = false;

            // If the Mbx is empty, check if some thread is already waiting.
            // If a thread is already waiting, do not update the msg "nextMsgPacketAddr" FieldInfo.
            if (!info.hasMessage())
            {
                SceKernelThreadInfo thread = info.threadWaitingList.FirstWaitingThread;
                if (thread != null)
                {
                    //if (log.DebugEnabled)
                    {
                        Console.WriteLine(string.Format("sceKernelSendMbx waking thread {0}", thread));
                    }
                    thread.wait.Mbx_resultAddr.setValue(msgAddr.Address);
                    info.threadWaitingList.removeWaitingThread(thread);
                    thread.cpuContext._v0 = 0;

                    ThreadManForUser threadMan = Modules.ThreadManForUserModule;
                    threadMan.hleChangeThreadState(thread, PSP_THREAD_READY);
                    threadMan.hleRescheduleCurrentThread();

                    msgConsumed = true;
                }
            }

            // Add the message if it has not yet been consumed by a waiting thread
            if (!msgConsumed)
            {
                if ((info.attr & PSP_MBX_ATTR_MSG_PRIORITY) == PSP_MBX_ATTR_MSG_FIFO)
                {
                    info.addMsg(msgAddr.Memory, msgAddr.Address);
                }
                else if ((info.attr & PSP_MBX_ATTR_MSG_PRIORITY) == PSP_MBX_ATTR_MSG_PRIORITY)
                {
                    info.addMsgByPriority(msgAddr.Memory, msgAddr.Address);
                }
            }

            return(0);
        }
コード例 #3
0
        private bool tryReceiveMsgPipe(SceKernelMppInfo info, TPointer addr, int size, int waitMode, TPointer32 resultSizeAddr)
        {
            if (size > 0)
            {
                int availableSize = info.availableReadSize();
                if (availableSize == 0)
                {
                    return(false);
                }
                // Trying to receive more than available?
                if (size > availableSize)
                {
                    // Do we need to receive the complete size?
                    if (waitMode == PSP_MPP_WAIT_MODE_COMPLETE)
                    {
                        return(false);
                    }
                    // We can just receive the available size.
                    size = availableSize;
                }
                info.consume(addr.Memory, addr.Address, size);

                if (info.bufSize == 0 && info.availableReadSize() == 0 && info.NumSendWaitThreads > 0)
                {
                    SceKernelThreadInfo thread = info.sendThreadWaitingList.FirstWaitingThread;
                    if (thread.wait.MsgPipe_isSend)
                    {
                        //if (log.DebugEnabled)
                        {
                            Console.WriteLine(string.Format("tryReceiveMsgPipe waking thread {0}", thread));
                        }
                        ThreadManForUser threadMan = Modules.ThreadManForUserModule;
                        info.sendThreadWaitingList.removeWaitingThread(thread);
                        thread.cpuContext._v0 = 0;
                        threadMan.hleChangeThreadState(thread, PSP_THREAD_READY);
                        threadMan.hleRescheduleCurrentThread();
                    }
                }
            }
            resultSizeAddr.setValue(size);

            return(true);
        }
コード例 #4
0
        private void onFplFree(SceKernelFplInfo info)
        {
            ThreadManForUser threadMan  = Modules.ThreadManForUserModule;
            bool             reschedule = false;

            SceKernelThreadInfo checkedThread = null;

            while (info.freeBlocks > 0)
            {
                SceKernelThreadInfo thread = info.threadWaitingList.getNextWaitingThread(checkedThread);
                if (thread == null)
                {
                    break;
                }
                int addr = tryAllocateFpl(info);
                if (addr != 0)
                {
                    //if (log.DebugEnabled)
                    {
                        Console.WriteLine(string.Format("onFplFree waking thread {0}", thread));
                    }
                    // Return the allocated address
                    thread.wait.Fpl_dataAddr.setValue(addr);

                    info.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();
            }
        }
コード例 #5
0
        private void onMbxDeletedCancelled(int mbxid, int result)
        {
            ThreadManForUser threadMan  = Modules.ThreadManForUserModule;
            bool             reschedule = false;

            for (IEnumerator <SceKernelThreadInfo> it = threadMan.GetEnumerator(); it.MoveNext();)
            {
                SceKernelThreadInfo thread = it.Current;
                if (thread.isWaitingFor(PSP_WAIT_MBX, mbxid))
                {
                    thread.cpuContext._v0 = result;
                    threadMan.hleChangeThreadState(thread, PSP_THREAD_READY);
                    reschedule = true;
                }
            }
            // Reschedule only if threads waked up.
            if (reschedule)
            {
                threadMan.hleRescheduleCurrentThread();
            }
        }
コード例 #6
0
        private void onLwMutexDeleted(int lwmid)
        {
            ThreadManForUser threadMan  = Modules.ThreadManForUserModule;
            bool             reschedule = false;

            for (IEnumerator <SceKernelThreadInfo> it = threadMan.GetEnumerator(); it.MoveNext();)
            {
                SceKernelThreadInfo thread = it.Current;
                if (thread.isWaitingFor(PSP_WAIT_LWMUTEX, lwmid))
                {
                    thread.cpuContext._v0 = ERROR_KERNEL_WAIT_DELETE;
                    threadMan.hleChangeThreadState(thread, PSP_THREAD_READY);
                    reschedule = true;
                }
            }
            // Reschedule only if threads waked up.
            if (reschedule)
            {
                threadMan.hleRescheduleCurrentThread();
            }
        }
コード例 #7
0
        private void onMsgPipeReceiveModified(SceKernelMppInfo info)
        {
            ThreadManForUser threadMan  = Modules.ThreadManForUserModule;
            bool             reschedule = false;

            SceKernelThreadInfo checkedThread = null;

            while (true)
            {
                SceKernelThreadInfo thread = info.receiveThreadWaitingList.getNextWaitingThread(checkedThread);
                if (thread == null)
                {
                    break;
                }
                if (!thread.wait.MsgPipe_isSend && tryReceiveMsgPipe(info, thread.wait.MsgPipe_address, thread.wait.MsgPipe_size, thread.wait.MsgPipe_waitMode, thread.wait.MsgPipe_resultSize_addr))
                {
                    //if (log.DebugEnabled)
                    {
                        Console.WriteLine(string.Format("onMsgPipeReceiveModified waking thread {0}", thread));
                    }
                    info.receiveThreadWaitingList.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();
            }
        }
コード例 #8
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();
            }
        }
コード例 #9
0
        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();
            }
        }