コード例 #1
0
        public KernelContext(
            ITickSource tickSource,
            Switch device,
            MemoryBlock memory,
            MemorySize memorySize,
            MemoryArrange memoryArrange)
        {
            TickSource = tickSource;
            Device     = device;
            Memory     = memory;

            Running = true;

            Syscall = new Syscall(this);

            SyscallHandler = new SyscallHandler(this);

            ResourceLimit = new KResourceLimit(this);

            KernelInit.InitializeResourceLimit(ResourceLimit, memorySize);

            MemoryManager = new KMemoryManager(memorySize, memoryArrange);

            LargeMemoryBlockSlabManager = new KMemoryBlockSlabManager(KernelConstants.MemoryBlockAllocatorSize * 2);
            SmallMemoryBlockSlabManager = new KMemoryBlockSlabManager(KernelConstants.MemoryBlockAllocatorSize);

            UserSlabHeapPages = new KSlabHeap(
                KernelConstants.UserSlabHeapBase,
                KernelConstants.UserSlabHeapItemSize,
                KernelConstants.UserSlabHeapSize);

            memory.Commit(KernelConstants.UserSlabHeapBase - DramMemoryMap.DramBase, KernelConstants.UserSlabHeapSize);

            CriticalSection  = new KCriticalSection(this);
            Schedulers       = new KScheduler[KScheduler.CpuCoresCount];
            PriorityQueue    = new KPriorityQueue();
            TimeManager      = new KTimeManager(this);
            Synchronization  = new KSynchronization(this);
            ContextIdManager = new KContextIdManager();

            for (int core = 0; core < KScheduler.CpuCoresCount; core++)
            {
                Schedulers[core] = new KScheduler(this, core);
            }

            StartPreemptionThread();

            KernelInitialized = true;

            Processes       = new ConcurrentDictionary <ulong, KProcess>();
            AutoObjectNames = new ConcurrentDictionary <string, KAutoObject>();

            _kipId     = KernelConstants.InitialKipId;
            _processId = KernelConstants.InitialProcessId;
        }
コード例 #2
0
ファイル: KernelContext.cs プロジェクト: vonchenplus/Ryujinx
        public KernelContext(Switch device, MemoryBlock memory)
        {
            Device = device;
            Memory = memory;

            Syscall = new Syscall(device, this);

            SyscallHandler = new SyscallHandler(this);

            ThreadCounter = new CountdownEvent(1);

            ResourceLimit = new KResourceLimit(this);

            KernelInit.InitializeResourceLimit(ResourceLimit);

            MemoryRegions = KernelInit.GetMemoryRegions();

            LargeMemoryBlockAllocator = new KMemoryBlockAllocator(KernelConstants.MemoryBlockAllocatorSize * 2);
            SmallMemoryBlockAllocator = new KMemoryBlockAllocator(KernelConstants.MemoryBlockAllocatorSize);

            UserSlabHeapPages = new KSlabHeap(
                KernelConstants.UserSlabHeapBase,
                KernelConstants.UserSlabHeapItemSize,
                KernelConstants.UserSlabHeapSize);

            CriticalSection  = new KCriticalSection(this);
            Scheduler        = new KScheduler(this);
            TimeManager      = new KTimeManager();
            Synchronization  = new KSynchronization(this);
            ContextIdManager = new KContextIdManager();

            Scheduler.StartAutoPreemptionThread();

            KernelInitialized = true;

            Processes       = new ConcurrentDictionary <long, KProcess>();
            AutoObjectNames = new ConcurrentDictionary <string, KAutoObject>();

            _kipId     = KernelConstants.InitialKipId;
            _processId = KernelConstants.InitialProcessId;
        }
コード例 #3
0
ファイル: KResourceLimit.cs プロジェクト: zhubaojian/Ryujinx
        public bool Reserve(LimitableResource Resource, long Amount, long Timeout)
        {
            long EndTimePoint = KTimeManager.ConvertNanosecondsToMilliseconds(Timeout);

            EndTimePoint += PerformanceCounter.ElapsedMilliseconds;

            bool Success = false;

            int Index = GetIndex(Resource);

            lock (LockObj)
            {
                long NewCurrent = Current[Index] + Amount;

                while (NewCurrent > Limit[Index] && Available[Index] + Amount <= Limit[Index])
                {
                    WaitingThreadsCount++;

                    KConditionVariable.Wait(System, WaitingThreads, LockObj, Timeout);

                    WaitingThreadsCount--;

                    NewCurrent = Current[Index] + Amount;

                    if (Timeout >= 0 && PerformanceCounter.ElapsedMilliseconds > EndTimePoint)
                    {
                        break;
                    }
                }

                if (NewCurrent <= Limit[Index])
                {
                    Current[Index] = NewCurrent;

                    Success = true;
                }
            }

            return(Success);
        }
コード例 #4
0
        public bool Reserve(LimitableResource resource, long amount, long timeout)
        {
            long endTimePoint = KTimeManager.ConvertNanosecondsToMilliseconds(timeout);

            endTimePoint += PerformanceCounter.ElapsedMilliseconds;

            bool success = false;

            int index = GetIndex(resource);

            lock (_lockObj)
            {
                long newCurrent = _current[index] + amount;

                while (newCurrent > _limit[index] && _available[index] + amount <= _limit[index])
                {
                    _waitingThreadsCount++;

                    KConditionVariable.Wait(_system, _waitingThreads, _lockObj, timeout);

                    _waitingThreadsCount--;

                    newCurrent = _current[index] + amount;

                    if (timeout >= 0 && PerformanceCounter.ElapsedMilliseconds > endTimePoint)
                    {
                        break;
                    }
                }

                if (newCurrent <= _limit[index])
                {
                    _current[index] = newCurrent;

                    success = true;
                }
            }

            return(success);
        }
コード例 #5
0
        private KernelResult GetInfo(uint id, int handle, long subId, out long value)
        {
            value = 0;

            switch (id)
            {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
            case 12:
            case 13:
            case 14:
            case 15:
            case 16:
            case 17:
            case 18:
            case 20:
            case 21:
            case 22:
            {
                if (subId != 0)
                {
                    return(KernelResult.InvalidCombination);
                }

                KProcess currentProcess = _system.Scheduler.GetCurrentProcess();

                KProcess process = currentProcess.HandleTable.GetKProcess(handle);

                if (process == null)
                {
                    return(KernelResult.InvalidHandle);
                }

                switch (id)
                {
                case 0: value = process.Capabilities.AllowedCpuCoresMask;    break;

                case 1: value = process.Capabilities.AllowedThreadPriosMask; break;

                case 2: value = (long)process.MemoryManager.AliasRegionStart; break;

                case 3: value = (long)(process.MemoryManager.AliasRegionEnd -
                                       process.MemoryManager.AliasRegionStart); break;

                case 4: value = (long)process.MemoryManager.HeapRegionStart; break;

                case 5: value = (long)(process.MemoryManager.HeapRegionEnd -
                                       process.MemoryManager.HeapRegionStart); break;

                case 6: value = (long)process.GetMemoryCapacity(); break;

                case 7: value = (long)process.GetMemoryUsage(); break;

                case 12: value = (long)process.MemoryManager.GetAddrSpaceBaseAddr(); break;

                case 13: value = (long)process.MemoryManager.GetAddrSpaceSize(); break;

                case 14: value = (long)process.MemoryManager.StackRegionStart; break;

                case 15: value = (long)(process.MemoryManager.StackRegionEnd -
                                        process.MemoryManager.StackRegionStart); break;

                case 16: value = (long)process.PersonalMmHeapPagesCount * KMemoryManager.PageSize; break;

                case 17:
                    if (process.PersonalMmHeapPagesCount != 0)
                    {
                        value = process.MemoryManager.GetMmUsedPages() * KMemoryManager.PageSize;
                    }

                    break;

                case 18: value = process.TitleId; break;

                case 20: value = (long)process.UserExceptionContextAddress; break;

                case 21: value = (long)process.GetMemoryCapacityWithoutPersonalMmHeap(); break;

                case 22: value = (long)process.GetMemoryUsageWithoutPersonalMmHeap(); break;
                }

                break;
            }

            case 8:
            {
                if (handle != 0)
                {
                    return(KernelResult.InvalidHandle);
                }

                if (subId != 0)
                {
                    return(KernelResult.InvalidCombination);
                }

                value = _system.Scheduler.GetCurrentProcess().Debug ? 1 : 0;

                break;
            }

            case 9:
            {
                if (handle != 0)
                {
                    return(KernelResult.InvalidHandle);
                }

                if (subId != 0)
                {
                    return(KernelResult.InvalidCombination);
                }

                KProcess currentProcess = _system.Scheduler.GetCurrentProcess();

                if (currentProcess.ResourceLimit != null)
                {
                    KHandleTable   handleTable   = currentProcess.HandleTable;
                    KResourceLimit resourceLimit = currentProcess.ResourceLimit;

                    KernelResult result = handleTable.GenerateHandle(resourceLimit, out int resLimHandle);

                    if (result != KernelResult.Success)
                    {
                        return(result);
                    }

                    value = (uint)resLimHandle;
                }

                break;
            }

            case 10:
            {
                if (handle != 0)
                {
                    return(KernelResult.InvalidHandle);
                }

                int currentCore = _system.Scheduler.GetCurrentThread().CurrentCore;

                if (subId != -1 && subId != currentCore)
                {
                    return(KernelResult.InvalidCombination);
                }

                value = _system.Scheduler.CoreContexts[currentCore].TotalIdleTimeTicks;

                break;
            }

            case 11:
            {
                if (handle != 0)
                {
                    return(KernelResult.InvalidHandle);
                }

                if ((ulong)subId > 3)
                {
                    return(KernelResult.InvalidCombination);
                }

                KProcess currentProcess = _system.Scheduler.GetCurrentProcess();


                value = currentProcess.RandomEntropy[subId];

                break;
            }

            case 0xf0000002u:
            {
                if (subId < -1 || subId > 3)
                {
                    return(KernelResult.InvalidCombination);
                }

                KThread thread = _system.Scheduler.GetCurrentProcess().HandleTable.GetKThread(handle);

                if (thread == null)
                {
                    return(KernelResult.InvalidHandle);
                }

                KThread currentThread = _system.Scheduler.GetCurrentThread();

                int currentCore = currentThread.CurrentCore;

                if (subId != -1 && subId != currentCore)
                {
                    return(KernelResult.Success);
                }

                KCoreContext coreContext = _system.Scheduler.CoreContexts[currentCore];

                long timeDelta = PerformanceCounter.ElapsedMilliseconds - coreContext.LastContextSwitchTime;

                if (subId != -1)
                {
                    value = KTimeManager.ConvertMillisecondsToTicks(timeDelta);
                }
                else
                {
                    long totalTimeRunning = thread.TotalTimeRunning;

                    if (thread == currentThread)
                    {
                        totalTimeRunning += timeDelta;
                    }

                    value = KTimeManager.ConvertMillisecondsToTicks(totalTimeRunning);
                }

                break;
            }

            default: return(KernelResult.InvalidEnumValue);
            }

            return(KernelResult.Success);
        }
コード例 #6
0
ファイル: KResourceLimit.cs プロジェクト: zhubaojian/Ryujinx
 public bool Reserve(LimitableResource Resource, long Amount)
 {
     return(Reserve(Resource, Amount, KTimeManager.ConvertMillisecondsToNanoseconds(Time10SecondsMs)));
 }
コード例 #7
0
ファイル: SvcSystem.cs プロジェクト: zhubaojian/Ryujinx
        private KernelResult GetInfo(uint Id, int Handle, long SubId, out long Value)
        {
            Value = 0;

            switch (Id)
            {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
            case 12:
            case 13:
            case 14:
            case 15:
            case 16:
            case 17:
            case 18:
            case 20:
            case 21:
            case 22:
            {
                if (SubId != 0)
                {
                    return(KernelResult.InvalidCombination);
                }

                KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();

                KProcess Process = CurrentProcess.HandleTable.GetKProcess(Handle);

                if (Process == null)
                {
                    return(KernelResult.InvalidHandle);
                }

                switch (Id)
                {
                case 0: Value = Process.Capabilities.AllowedCpuCoresMask;    break;

                case 1: Value = Process.Capabilities.AllowedThreadPriosMask; break;

                case 2: Value = (long)Process.MemoryManager.AliasRegionStart; break;

                case 3: Value = (long)(Process.MemoryManager.AliasRegionEnd -
                                       Process.MemoryManager.AliasRegionStart); break;

                case 4: Value = (long)Process.MemoryManager.HeapRegionStart; break;

                case 5: Value = (long)(Process.MemoryManager.HeapRegionEnd -
                                       Process.MemoryManager.HeapRegionStart); break;

                case 6: Value = (long)Process.GetMemoryCapacity(); break;

                case 7: Value = (long)Process.GetMemoryUsage(); break;

                case 12: Value = (long)Process.MemoryManager.GetAddrSpaceBaseAddr(); break;

                case 13: Value = (long)Process.MemoryManager.GetAddrSpaceSize(); break;

                case 14: Value = (long)Process.MemoryManager.StackRegionStart; break;

                case 15: Value = (long)(Process.MemoryManager.StackRegionEnd -
                                        Process.MemoryManager.StackRegionStart); break;

                case 16: Value = (long)Process.PersonalMmHeapPagesCount * KMemoryManager.PageSize; break;

                case 17:
                    if (Process.PersonalMmHeapPagesCount != 0)
                    {
                        Value = Process.MemoryManager.GetMmUsedPages() * KMemoryManager.PageSize;
                    }

                    break;

                case 18: Value = Process.TitleId; break;

                case 20: Value = (long)Process.UserExceptionContextAddress; break;

                case 21: Value = (long)Process.GetMemoryCapacityWithoutPersonalMmHeap(); break;

                case 22: Value = (long)Process.GetMemoryUsageWithoutPersonalMmHeap(); break;
                }

                break;
            }

            case 8:
            {
                if (Handle != 0)
                {
                    return(KernelResult.InvalidHandle);
                }

                if (SubId != 0)
                {
                    return(KernelResult.InvalidCombination);
                }

                Value = System.Scheduler.GetCurrentProcess().Debug ? 1 : 0;

                break;
            }

            case 9:
            {
                if (Handle != 0)
                {
                    return(KernelResult.InvalidHandle);
                }

                if (SubId != 0)
                {
                    return(KernelResult.InvalidCombination);
                }

                KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();

                if (CurrentProcess.ResourceLimit != null)
                {
                    KHandleTable   HandleTable   = CurrentProcess.HandleTable;
                    KResourceLimit ResourceLimit = CurrentProcess.ResourceLimit;

                    KernelResult Result = HandleTable.GenerateHandle(ResourceLimit, out int ResLimHandle);

                    if (Result != KernelResult.Success)
                    {
                        return(Result);
                    }

                    Value = (uint)ResLimHandle;
                }

                break;
            }

            case 10:
            {
                if (Handle != 0)
                {
                    return(KernelResult.InvalidHandle);
                }

                int CurrentCore = System.Scheduler.GetCurrentThread().CurrentCore;

                if (SubId != -1 && SubId != CurrentCore)
                {
                    return(KernelResult.InvalidCombination);
                }

                Value = System.Scheduler.CoreContexts[CurrentCore].TotalIdleTimeTicks;

                break;
            }

            case 11:
            {
                if (Handle != 0)
                {
                    return(KernelResult.InvalidHandle);
                }

                if ((ulong)SubId > 3)
                {
                    return(KernelResult.InvalidCombination);
                }

                KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();


                Value = CurrentProcess.RandomEntropy[SubId];

                break;
            }

            case 0xf0000002u:
            {
                if (SubId < -1 || SubId > 3)
                {
                    return(KernelResult.InvalidCombination);
                }

                KThread Thread = System.Scheduler.GetCurrentProcess().HandleTable.GetKThread(Handle);

                if (Thread == null)
                {
                    return(KernelResult.InvalidHandle);
                }

                KThread CurrentThread = System.Scheduler.GetCurrentThread();

                int CurrentCore = CurrentThread.CurrentCore;

                if (SubId != -1 && SubId != CurrentCore)
                {
                    return(KernelResult.Success);
                }

                KCoreContext CoreContext = System.Scheduler.CoreContexts[CurrentCore];

                long TimeDelta = PerformanceCounter.ElapsedMilliseconds - CoreContext.LastContextSwitchTime;

                if (SubId != -1)
                {
                    Value = KTimeManager.ConvertMillisecondsToTicks(TimeDelta);
                }
                else
                {
                    long TotalTimeRunning = Thread.TotalTimeRunning;

                    if (Thread == CurrentThread)
                    {
                        TotalTimeRunning += TimeDelta;
                    }

                    Value = KTimeManager.ConvertMillisecondsToTicks(TotalTimeRunning);
                }

                break;
            }

            default: return(KernelResult.InvalidEnumValue);
            }

            return(KernelResult.Success);
        }
コード例 #8
0
        private KernelResult CreateThread(
            ulong entrypoint,
            ulong argsPtr,
            ulong stackTop,
            int priority,
            int cpuCore,
            out int handle)
        {
            handle = 0;

            KProcess currentProcess = _system.Scheduler.GetCurrentProcess();

            if (cpuCore == -2)
            {
                cpuCore = currentProcess.DefaultCpuCore;
            }

            if ((uint)cpuCore >= KScheduler.CpuCoresCount || !currentProcess.IsCpuCoreAllowed(cpuCore))
            {
                return(KernelResult.InvalidCpuCore);
            }

            if ((uint)priority >= KScheduler.PrioritiesCount || !currentProcess.IsPriorityAllowed(priority))
            {
                return(KernelResult.InvalidPriority);
            }

            long timeout = KTimeManager.ConvertMillisecondsToNanoseconds(100);

            if (currentProcess.ResourceLimit != null &&
                !currentProcess.ResourceLimit.Reserve(LimitableResource.Thread, 1, timeout))
            {
                return(KernelResult.ResLimitExceeded);
            }

            KThread thread = new KThread(_system);

            KernelResult result = currentProcess.InitializeThread(
                thread,
                entrypoint,
                argsPtr,
                stackTop,
                priority,
                cpuCore);

            if (result != KernelResult.Success)
            {
                currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);

                return(result);
            }

            result = _process.HandleTable.GenerateHandle(thread, out handle);

            if (result != KernelResult.Success)
            {
                thread.Terminate();

                currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);
            }

            return(result);
        }
コード例 #9
0
ファイル: SvcThread.cs プロジェクト: zhubaojian/Ryujinx
        private KernelResult CreateThread(
            ulong Entrypoint,
            ulong ArgsPtr,
            ulong StackTop,
            int Priority,
            int CpuCore,
            out int Handle)
        {
            Handle = 0;

            KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();

            if (CpuCore == -2)
            {
                CpuCore = CurrentProcess.DefaultCpuCore;
            }

            if ((uint)CpuCore >= KScheduler.CpuCoresCount || !CurrentProcess.IsCpuCoreAllowed(CpuCore))
            {
                return(KernelResult.InvalidCpuCore);
            }

            if ((uint)Priority >= KScheduler.PrioritiesCount || !CurrentProcess.IsPriorityAllowed(Priority))
            {
                return(KernelResult.InvalidPriority);
            }

            long Timeout = KTimeManager.ConvertMillisecondsToNanoseconds(100);

            if (CurrentProcess.ResourceLimit != null &&
                !CurrentProcess.ResourceLimit.Reserve(LimitableResource.Thread, 1, Timeout))
            {
                return(KernelResult.ResLimitExceeded);
            }

            KThread Thread = new KThread(System);

            KernelResult Result = CurrentProcess.InitializeThread(
                Thread,
                Entrypoint,
                ArgsPtr,
                StackTop,
                Priority,
                CpuCore);

            if (Result != KernelResult.Success)
            {
                CurrentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);

                return(Result);
            }

            Result = Process.HandleTable.GenerateHandle(Thread, out Handle);

            if (Result != KernelResult.Success)
            {
                Thread.Terminate();

                CurrentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);
            }

            return(Result);
        }