示例#1
0
        public virtual int sceKernelCreateMsgPipe(string name, int partitionid, int attr, int size, TPointer option)
        {
            if (option.NotNull)
            {
                int optionSize = option.getValue32();
                Console.WriteLine(string.Format("sceKernelCreateMsgPipe option at {0}, size={1:D}", option, optionSize));
            }

            int memType = PSP_SMEM_Low;

            if ((attr & PSP_MPP_ATTR_ADDR_HIGH) == PSP_MPP_ATTR_ADDR_HIGH)
            {
                memType = PSP_SMEM_High;
            }

            SceKernelMppInfo info = new SceKernelMppInfo(name, partitionid, attr, size, memType);

            if (!info.MemoryAllocated)
            {
                Console.WriteLine(string.Format("sceKernelCreateMsgPipe name='{0}', partitionId={1:D}, attr=0x{2:X}, size=0x{3:X}, option={4} not enough memory", name, partitionid, attr, size, option));
                info.delete();
                return(SceKernelErrors.ERROR_KERNEL_NO_MEMORY);
            }

            //if (log.DebugEnabled)
            {
                Console.WriteLine(string.Format("sceKernelCreateMsgPipe returning {0}", info));
            }
            msgMap[info.uid] = info;

            return(info.uid);
        }
示例#2
0
        public virtual int sceKernelReferMsgPipeStatus(int uid, TPointer infoAddr)
        {
            SceKernelMppInfo info = msgMap[uid];

            info.write(infoAddr);

            return(0);
        }
示例#3
0
        public virtual int sceKernelDeleteMsgPipe(int uid)
        {
            SceKernelMppInfo info = msgMap.Remove(uid);

            info.delete();
            onMsgPipeDeleted(uid);

            return(0);
        }
示例#4
0
        public virtual int sceKernelCancelMsgPipe(int uid, TPointer32 sendAddr, TPointer32 recvAddr)
        {
            SceKernelMppInfo info = msgMap[uid];

            sendAddr.setValue(info.NumSendWaitThreads);
            recvAddr.setValue(info.NumReceiveWaitThreads);
            info.sendThreadWaitingList.removeAllWaitingThreads();
            info.receiveThreadWaitingList.removeAllWaitingThreads();
            onMsgPipeCancelled(uid);

            return(0);
        }
示例#5
0
        private int hleKernelReceiveMsgPipe(int uid, TPointer msgAddr, int size, int waitMode, TPointer32 resultSizeAddr, TPointer32 timeoutAddr, bool doCallbacks, bool poll)
        {
            SceKernelMppInfo info = msgMap[uid];

            if (info.bufSize != 0 && size > info.bufSize)
            {
                Console.WriteLine(string.Format("hleKernelReceiveMsgPipe illegal size 0x{0:X}, max 0x{1:X}", size, info.bufSize));
                return(ERROR_KERNEL_ILLEGAL_SIZE);
            }

            ThreadManForUser threadMan = Modules.ThreadManForUserModule;

            if (!tryReceiveMsgPipe(info, msgAddr, size, waitMode, resultSizeAddr))
            {
                if (!poll)
                {
                    // Failed, but it's ok, just wait a little
                    //if (log.DebugEnabled)
                    {
                        Console.WriteLine(string.Format("hleKernelReceiveMsgPipe {0} waiting for 0x{1:X} bytes to become available", info, size));
                    }
                    SceKernelThreadInfo currentThread = threadMan.CurrentThread;
                    info.receiveThreadWaitingList.addWaitingThread(currentThread);
                    // Wait on a specific MsgPipe.
                    currentThread.wait.MsgPipe_isSend          = false;
                    currentThread.wait.MsgPipe_id              = uid;
                    currentThread.wait.MsgPipe_address         = msgAddr;
                    currentThread.wait.MsgPipe_size            = size;
                    currentThread.wait.MsgPipe_resultSize_addr = resultSizeAddr;
                    threadMan.hleKernelThreadEnterWaitState(PSP_WAIT_MSGPIPE, uid, msgPipeReceiveWaitStateChecker, timeoutAddr.Address, doCallbacks);
                }
                else
                {
                    //if (log.DebugEnabled)
                    {
                        Console.WriteLine(string.Format("hleKernelReceiveMsgPipe trying to read more than is available size 0x{0:X}, available 0x{1:X}", size, info.bufSize - info.freeSize));
                    }
                    return(ERROR_KERNEL_MESSAGE_PIPE_EMPTY);
                }
            }
            else
            {
                // Success, do not reschedule the current thread.
                //if (log.DebugEnabled)
                {
                    Console.WriteLine(string.Format("hleKernelReceiveMsgPipe {0} fast check succeeded", info));
                }
                onMsgPipeSendModified(info);
            }

            return(0);
        }
示例#6
0
        private bool trySendMsgPipe(SceKernelMppInfo info, TPointer addr, int size, int waitMode, TPointer32 resultSizeAddr)
        {
            if (size > 0)
            {
                // When the bufSize is 0, the data is transfered directly
                // from the sender to the receiver without being buffered.
                if (info.bufSize == 0)
                {
                    info.setUserData(addr.Address, size);
                    onMsgPipeReceiveModified(info);
                    if (info.UserSize > 0)
                    {
                        // wait if nothing has been sent or
                        // if we have to wait to send everything
                        if (size == info.UserSize || waitMode == PSP_MPP_WAIT_MODE_COMPLETE)
                        {
                            return(false);
                        }
                    }
                }
                else
                {
                    int availableSize = info.availableWriteSize();
                    if (availableSize == 0)
                    {
                        return(false);
                    }
                    // Trying to send more than available?
                    if (size > availableSize)
                    {
                        // Do we need to send the complete size?
                        if (waitMode == PSP_MPP_WAIT_MODE_COMPLETE)
                        {
                            return(false);
                        }
                        // We can just send the available size.
                        size = availableSize;
                    }
                    info.append(addr.Memory, addr.Address, size);
                }
            }
            resultSizeAddr.setValue(size);

            return(true);
        }
示例#7
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);
        }
示例#8
0
        private bool removeWaitingThread(SceKernelThreadInfo thread)
        {
            SceKernelMppInfo info = msgMap[thread.wait.MsgPipe_id];

            if (info == null)
            {
                return(false);
            }

            if (thread.wait.MsgPipe_isSend)
            {
                info.sendThreadWaitingList.removeWaitingThread(thread);
            }
            else
            {
                info.receiveThreadWaitingList.removeWaitingThread(thread);
            }

            return(true);
        }
示例#9
0
            public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait)
            {
                // Check if the thread has to continue its wait state or if the msgpipe
                // has been sent a new message during the callback execution.
                SceKernelMppInfo info = outerInstance.msgMap[wait.MsgPipe_id];

                if (info == null)
                {
                    thread.cpuContext._v0 = ERROR_KERNEL_NOT_FOUND_MESSAGE_PIPE;
                    return(false);
                }

                if (outerInstance.tryReceiveMsgPipe(info, wait.MsgPipe_address, wait.MsgPipe_size, wait.MsgPipe_waitMode, wait.MsgPipe_resultSize_addr))
                {
                    info.receiveThreadWaitingList.removeWaitingThread(thread);
                    thread.cpuContext._v0 = 0;
                    return(false);
                }

                return(true);
            }
示例#10
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();
            }
        }