Exemple #1
0
        public void Signal()
        {
            // Try to wake threads
            bool wokeThreads = false;

            LinkedListEntry <KThread> entry = WaitingThreads.HeadEntry;

            while (entry != null)
            {
                if (this.Messages.Count > 0)
                {
                    this.GetMessage((int)entry.Value.WaitAddress);
                    entry.Value.Wake(0);
                    wokeThreads = true;
                }
                else
                {
                    break;
                }
            }

            if (wokeThreads == true)
            {
                Kernel.Schedule();
            }
        }
Exemple #2
0
        public void Signal(int count)
        {
            CurrentCount += count;

            // Try to wake threads
            bool wokeThreads            = false;
            LinkedListEntry <KThread> e = WaitingThreads.HeadEntry;

            while (e != null)
            {
                int needed = ( int )e.Value.WaitArgument;
                if (CurrentCount >= needed)
                {
                    e.Value.Wake(0);
                    CurrentCount -= needed;
                    wokeThreads   = true;
                }
                else
                {
                    break;
                }
            }
            if (wokeThreads == true)
            {
                Kernel.Schedule();
            }
        }
        public static void InsertHeadList <T>(LinkedListEntry <T> listHead, LinkedListEntry <T> entry)
        {
            LinkedListEntry <T> flink;

            flink          = listHead.Flink;
            entry.Flink    = flink;
            entry.Blink    = listHead;
            flink.Blink    = entry;
            listHead.Flink = entry;
        }
        public static void InsertTailList <T>(LinkedListEntry <T> listHead, LinkedListEntry <T> entry)
        {
            LinkedListEntry <T> blink;

            blink          = listHead.Blink;
            entry.Flink    = listHead;
            entry.Blink    = blink;
            blink.Flink    = entry;
            listHead.Blink = entry;
        }
Exemple #5
0
        /// <summary>
        /// Creates a new instance of the Provider class, specifying a
        /// custom <seealso cref="System.Collections.Generic.IDictionary&lt;TKey, TValue&gt;"/> instance.
        /// </summary>
        public Provider(IDictionary <TKey, TValue> dictionary)
        {
            if (dictionary == null)
            {
                throw new ArgumentNullException("dictionary");
            }

            _dictionary      = dictionary;
            _listEntry       = new LinkedListEntry <IProvider>();
            _listEntry.Value = this;
        }
 public IEnumerator <IProvider> GetEnumerator()
 {
     for (
         LinkedListEntry <IProvider> entry = _listHead.Flink;
         entry != _listHead;
         entry = entry.Flink
         )
     {
         yield return(entry.Value);
     }
 }
        public static LinkedListEntry <T> RemoveTailList <T>(LinkedListEntry <T> listHead)
        {
            LinkedListEntry <T> blink;
            LinkedListEntry <T> entry;

            entry          = listHead.Blink;
            blink          = entry.Blink;
            listHead.Blink = blink;
            blink.Flink    = listHead;

            return(entry);
        }
        public static LinkedListEntry <T> RemoveHeadList <T>(LinkedListEntry <T> listHead)
        {
            LinkedListEntry <T> flink;
            LinkedListEntry <T> entry;

            entry          = listHead.Flink;
            flink          = entry.Flink;
            listHead.Flink = flink;
            flink.Blink    = listHead;

            return(entry);
        }
        public static bool RemoveEntryList <T>(LinkedListEntry <T> entry)
        {
            LinkedListEntry <T> blink;
            LinkedListEntry <T> flink;

            flink       = entry.Flink;
            blink       = entry.Blink;
            blink.Flink = flink;
            flink.Blink = blink;

            return(flink == blink);
        }
        // SDK location: /user/pspthreadman.h:390
        // SDK declaration: int sceKernelRotateThreadReadyQueue(int priority);
        public int sceKernelRotateThreadReadyQueue(int priority)
        {
            // At the given priority, move the head thread to the tail
            // This is tricky - we need to find the first and last thread at a given priority
            // then move the first one after the last one

            // Find first thread
            LinkedListEntry <KThread> first = null;
            LinkedListEntry <KThread> e     = _kernel.SchedulableThreads.HeadEntry;

            while (e != null)
            {
                if (e.Value.Priority == priority)
                {
                    first = e;
                    break;
                }
                e = e.Next;
            }
            //Debug.Assert( first != null );
            if (first == null)
            {
                // No threads of the given priority found
                return(0);
            }

            // Find last thread
            LinkedListEntry <KThread> last = first;

            while (e != null)
            {
                if (e.Value.Priority != priority)
                {
                    break;
                }
                last = e;
                e    = e.Next;
            }
            if (first == last)
            {
                // No change - only one schedulable thread had this priority
                _kernel.Schedule();
                return(0);
            }

            // Perform the move
            _kernel.SchedulableThreads.Remove(first);
            _kernel.SchedulableThreads.InsertAfter(first.Value, last);

            _kernel.Schedule();
            return(0);
        }
        // SDK location: /user/pspsysmem.h:88
        // SDK declaration: SceSize sceKernelMaxFreeMemSize();
        public int sceKernelMaxFreeMemSize()
        {
            uint maxSize = 0;
            LinkedListEntry <KMemoryBlock> e = _kernel.Partitions[2].FreeList.HeadEntry;

            while (e != null)
            {
                maxSize = Math.Max(maxSize, e.Value.Size);
                e       = e.Next;
            }
            // HACK: return a bit less, so that a stupid game can't use it all then try to launch threads
            return(( int )maxSize - 1024 * 1024);
        }
        public void Clear()
        {
            List <int> textureIds          = new List <int>();
            LinkedListEntry <MGLTexture> e = _values.HeadEntry;

            while (e != null)
            {
                textureIds.Add(e.Value.TextureID);
                e = e.Next;
            }
            _values.Clear();
            Gl.glDeleteTextures(textureIds.Count, textureIds.ToArray());
        }
Exemple #13
0
        public void Dispose()
        {
            GC.SuppressFinalize(this);

            LinkedListEntry <KMemoryBlock> e = Blocks.HeadEntry;

            while (e != null)
            {
                Partition.Free(e.Value);
                e = e.Next;
            }
            Blocks.Clear();
        }
Exemple #14
0
        /// <summary>
        /// Creates a new instance of the Provider class, specifying a
        /// custom <seealso cref="System.Collections.Generic.IDictionary&lt;TKey, TValue&gt;"/> instance.
        /// </summary>
        protected Provider(IDictionary <TKey, TValue> dictionary)
        {
            if (dictionary == null)
            {
                throw new ArgumentNullException("dictionary");
            }

            _dictionary = dictionary;
            _listEntry  = new LinkedListEntry <IProvider>
            {
                Value = this
            };
        }
Exemple #15
0
        public void Free(KMemoryBlock block)
        {
            Debug.Assert(block != null);
            Debug.Assert(block.IsFree == false);

            block.UID    = 0;
            block.IsFree = true;
            FreeSize    += block.Size;

            LinkedListEntry <KMemoryBlock> entry = Blocks.Find(block);

            Debug.Assert(entry != null);

            // Attempt to coalesce in to previous and or next blocks
            KMemoryBlock merged = null;
            LinkedListEntry <KMemoryBlock> prev = entry.Previous;
            LinkedListEntry <KMemoryBlock> next = entry.Next;

            if ((prev != null) &&
                (prev.Value.IsFree == true))
            {
                // Merge in to previous (kill us)
                Blocks.Remove(entry);
                prev.Value.Size += block.Size;
                merged           = prev.Value;
            }
            if ((next != null) &&
                (next.Value.IsFree == true))
            {
                // Merge next in to us (kill them)
                // This takes in to account whether or not we already merged
                KMemoryBlock nextBlock = next.Value;
                Blocks.Remove(next);
                FreeList.Remove(nextBlock);
                if (merged == null)
                {
                    block.Size += nextBlock.Size;
                }
                else
                {
                    merged.Size += nextBlock.Size;
                }
            }

            if (merged == null)
            {
                // Didn't merge - put back in free list
                this.AddToFreeList(block);
            }
        }
Exemple #16
0
        public bool Free(int address)
        {
            LinkedListEntry <KMemoryBlock> e = UsedBlocks.HeadEntry;

            while (e != null)
            {
                if (e.Value.Address == address)
                {
                    UsedBlocks.Remove(e);
                    FreeBlocks.Enqueue(e.Value);
                    return(this.WakeWaiter());
                }
                e = e.Next;
            }
            return(false);
        }
        public MGLTexture Find(MGLTextureInfo info, out uint checksum)
        {
            checksum = 0;
            LinkedListEntry <MGLTexture> e = _values.HeadEntry;

            while (e != null)
            {
                if (e.Value.Address == info.Address)
                {
                    // Check to make sure it's right
                    bool match =
                        (e.Value.Width == info.Width) &&
                        (e.Value.Height == info.Height) &&
                        (e.Value.LineWidth == info.LineWidth) &&
                        (e.Value.PixelStorage == info.PixelStorage) &&
                        (((( int )e.Value.PixelStorage & 0x4) == 0x4) ? (e.Value.ClutChecksum == _ctx.Clut.Checksum) : true);
                    if (match == true)
                    {
                        // Cookie check
                        //uint cookie = *((uint*)

                        if (match == true)
                        {
                            byte *textureAddress = _driver.MemorySystem.Translate(info.Address);
                            checksum = MGLTexture.CalculateChecksum(textureAddress, info.Width, info.Height, info.PixelStorage);
                            match    = (checksum == e.Value.Checksum);
                        }
                    }
                    if (match == true)
                    {
                        // Match - move to head
                        _values.MoveToHead(e);
                        return(e.Value);
                    }
                    else
                    {
                        // Mismatch - free
                        Gl.glDeleteTextures(1, ref e.Value.TextureID);
                        _driver.InvalidateCurrentTexture();
                        _values.Remove(e);
                        return(null);
                    }
                }
                e = e.Next;
            }
            return(null);
        }
Exemple #18
0
        public bool Free(KMemoryBlock block)
        {
            Debug.Assert(block != null);

            LinkedListEntry <KMemoryBlock> e = UsedBlocks.Find(block);

            Debug.Assert(e != null);
            if (e != null)
            {
                UsedBlocks.Remove(e);
                FreeBlocks.Enqueue(block);
                return(this.WakeWaiter());
            }
            else
            {
                return(false);
            }
        }
Exemple #19
0
        private void HandleCompletedTimers()
        {
            LinkedListEntry <TimerCompletionEntry> e = null;

            lock ( _timerSyncRoot )
            {
                if (_timerCompletionQueue.Count == 0)
                {
                    return;
                }
                e = _timerCompletionQueue.HeadEntry;
                _timerCompletionQueue.Clear();
            }
            while (e != null)
            {
                e.Value.Callback(e.Value.Timer, e.Value.State);
                e = e.Next;
            }
        }
Exemple #20
0
        public bool Signal()
        {
            bool needsSwitch = false;

            LinkedListEntry <KThread> e = WaitingThreads.HeadEntry;

            while (e != null)
            {
                LinkedListEntry <KThread> next = e.Next;

                KThread thread = e.Value;
                Debug.Assert(thread != null);
                Debug.Assert(thread.WaitingOn == KThreadWait.Event);
                Debug.Assert(thread.WaitHandle == this);

                bool matches = this.Matches(thread.WaitArgument, thread.WaitEventMode);
                if (matches == true)
                {
                    // Finish wait
                    if (thread.WaitAddress != 0x0)
                    {
                        unsafe
                        {
                            uint *poutBits = ( uint * )Kernel.MemorySystem.Translate(thread.WaitAddress);
                            *     poutBits = this.Value;
                        }
                    }

                    this.Clear(thread.WaitArgument, thread.WaitEventMode);

                    WaitingThreads.Remove(e);

                    // Wake thread
                    thread.Wake(0);

                    needsSwitch = true;
                }

                e = next;
            }

            return(needsSwitch);
        }
Exemple #21
0
        private void AddToSchedule()
        {
            // This can happen sometimes (race conditions)
            bool alreadyScheduled = (Kernel.SchedulableThreads.Find(this) != null);

            if (alreadyScheduled == true)
            {
                Log.WriteLine(Verbosity.Critical, Feature.Bios, "KThread: AddToSchedule found thread already scheduled - your game is dead!");
                return;
            }

            // Find the right place by walking the thread list and inserting before a thread of higher priority
            LinkedListEntry <KThread> e = Kernel.SchedulableThreads.HeadEntry;

            if (e == null)
            {
                // Special case
                Kernel.SchedulableThreads.Enqueue(this);
            }
            else
            {
                do
                {
                    if (e.Value.Priority >= this.Priority)
                    {
                        // Insert here (this will be before any threads with the same priority)
                        Kernel.SchedulableThreads.InsertBefore(this, e);
                        break;
                    }

                    if (e.Next == null)
                    {
                        // Append
                        Kernel.SchedulableThreads.Enqueue(this);
                        break;
                    }

                    e = e.Next;
                } while(e != null);
            }
        }
Exemple #22
0
        public void Signal()
        {
            // Try to wake threads
            bool wokeThreads = false;

            LinkedListEntry <KThread> entry = WaitingThreads.HeadEntry;

            while (entry != null)
            {
                int needed = ( int )entry.Value.WaitArgument;
                if (this.Stream.Length >= needed)
                {
                    this.Stream.Seek(0, SeekOrigin.Begin);
                    this.Kernel.Memory.WriteStream(( int )entry.Value.WaitAddress, this.Stream, ( int )entry.Value.WaitArgument);
                    this.Stream.SetLength(0);

                    if (entry.Value.WaitAddressResult != 0)
                    {
                        unsafe
                        {
                            uint *poutSize = (uint *)Kernel.MemorySystem.Translate(entry.Value.WaitAddressResult);
                            *     poutSize = entry.Value.WaitArgument;
                        }
                    }

                    entry.Value.Wake(0);
                    wokeThreads = true;
                }
                else
                {
                    break;
                }
            }

            if (wokeThreads == true)
            {
                Kernel.Schedule();
            }
        }
Exemple #23
0
        // manual add
        public void sceKernelExitGameWithStatus(int status)
        {
            Log.WriteLine(Verbosity.Normal, Feature.Bios, "sceKernelExitGameWithStatus: exiting with status code {0}", status);

            // Call exit callbacks
            FastLinkedList <KCallback> cbll = _kernel.Callbacks[Kernel.CallbackTypes.Exit];

            if (cbll.Count > 0)
            {
                LinkedListEntry <KCallback> cbs = cbll.HeadEntry;
                while (cbs != null)
                {
                    _kernel.NotifyCallback(cbs.Value, ( uint )status);
                    cbs = cbs.Next;
                }
            }
            else
            {
                // Do the callbacks kill the game for us?
                _kernel.StopGame(status);
            }
        }
Exemple #24
0
        internal void PrintMemoryInfo()
        {
            // Partition 2 and 6 are what we care about
            StringBuilder sb = new StringBuilder();

            sb.Append("=== Memory Info ===");
            sb.Append(Environment.NewLine);
            int[] partitions = new int[] { 2, 6 };
            for (int n = 0; n < partitions.Length; n++)
            {
                KPartition partition = this.Partitions[partitions[n]];
                sb.AppendFormat("-- [{0}] -- {1:X8}-{2:X8} - {3}b/{4}b ({5}b free)", partitions[n], partition.BaseAddress, partition.UpperBound, partition.Size - partition.FreeSize, partition.Size, partition.FreeSize);
                sb.Append(Environment.NewLine);
                LinkedListEntry <KMemoryBlock> e = partition.Blocks.HeadEntry;
                while (e != null)
                {
                    KMemoryBlock block = e.Value;
                    sb.AppendFormat("   {0:X8}-{1:X8} - {2,10}b taken: {3} - {4}", block.Address, block.UpperBound, block.Size, !block.IsFree ? 1 : 0, block.Name);
                    sb.Append(Environment.NewLine);
                    e = e.Next;
                }
            }
            Debug.WriteLine(sb.ToString());
        }
Exemple #25
0
 private void AddToFreeList(KMemoryBlock block)
 {
     // Inserts in to free list at the right place
     if (FreeList.Count == 0)
     {
         FreeList.Enqueue(block);
     }
     else
     {
         LinkedListEntry <KMemoryBlock> e = FreeList.HeadEntry;
         while (e != null)
         {
             if (e.Value.Address > block.Address)
             {
                 // Found next block - insert before
                 FreeList.InsertBefore(block, e);
                 return;
             }
             e = e.Next;
         }
         // Didn't find - add to tail
         FreeList.Enqueue(block);
     }
 }
        private void Update()
        {
            LinkedListEntry <IProvider> tempListHead = new LinkedListEntry <IProvider>();
            LinkedListEntry <IProvider> listEntry;
            NtStatus status = NtStatus.Success;

            _threadHandle = ThreadHandle.OpenCurrent(
                ThreadAccess.Alert | (ThreadAccess)StandardRights.Synchronize
                );
            _initializedEvent.Set();

            while (!_terminating)
            {
                LinkedList.InitializeListHead(tempListHead);

                Monitor.Enter(_listHead);

                // Main loop.

                while (true)
                {
                    if (status == NtStatus.Alerted)
                    {
                        // Check if we have any more providers to boost.
                        if (_boostCount == 0)
                        {
                            break;
                        }
                    }

                    listEntry = LinkedList.RemoveHeadList(_listHead);

                    if (listEntry == _listHead)
                    {
                        break;
                    }

                    // Add the provider to the temp list.
                    LinkedList.InsertTailList(tempListHead, listEntry);

                    if (status != NtStatus.Alerted)
                    {
                        if (!listEntry.Value.Enabled || listEntry.Value.Unregistering)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (listEntry.Value.Unregistering)
                        {
                            // Give the unregistering thread a chance to fix
                            // the boost count.
                            Monitor.Exit(_listHead);
                            Monitor.Enter(_listHead);

                            continue;
                        }
                    }

                    if (status == NtStatus.Alerted)
                    {
                        listEntry.Value.Boosting = false;
                        _boostCount--;
                    }

                    Monitor.Exit(_listHead);

                    try
                    {
                        listEntry.Value.Run();
                    }
                    finally
                    {
                        Monitor.Enter(_listHead);
                    }
                }

                // Re-add the items in the temp list to the main list.

                while ((listEntry = LinkedList.RemoveHeadList(tempListHead)) != tempListHead)
                {
                    LinkedList.InsertTailList(_listHead, listEntry);
                }

                Monitor.Exit(_listHead);

                // Wait for the interval. We may get alerted.
                status = _timerHandle.Wait(true);
            }
        }
Exemple #27
0
        private KMemoryBlock SplitBlock(KMemoryBlock block, uint address, uint size)
        {
            Debug.Assert(size > 0);

            KMemoryBlock newBlock = new KMemoryBlock(this, address, size, false);

            LinkedListEntry <KMemoryBlock> blockEntry = Blocks.Find(block);

            Debug.Assert(blockEntry != null);

            if (address == block.Address)
            {
                // Bottom up - put right before free and shift free up
                block.Address += size;
                block.Size    -= size;

                Blocks.InsertBefore(newBlock, blockEntry);
            }
            else if (address == block.UpperBound - size)
            {
                // Top down - put right after and free shift free down
                block.Size -= size;

                Blocks.InsertAfter(newBlock, blockEntry);
            }
            else
            {
                // Middle - need a real split
                uint originalSize = block.Size;
                block.Size = newBlock.Address - block.Address;
                if (block.Size == 0)
                {
                    // Special case of block replacing block
                    Blocks.InsertAfter(newBlock, blockEntry);
                    // block will be removed below
                }
                else
                {
                    uint freeAddress = newBlock.Address + newBlock.Size;
                    uint freeSize    = originalSize - block.Size - newBlock.Size;

                    KMemoryBlock freeBlock = new KMemoryBlock(this, freeAddress, freeSize, true);

                    // Add free space after start block if needed
                    if (freeSize > 0)
                    {
                        LinkedListEntry <KMemoryBlock> blockEntryFree = FreeList.Find(block);
                        Blocks.InsertAfter(freeBlock, blockEntry);
                        FreeList.InsertAfter(freeBlock, blockEntryFree);
                    }

                    // Add after the block (but before the freeBlock if there was one)
                    Blocks.InsertAfter(newBlock, blockEntry);
                }
            }

            Debug.Assert(block.Size >= 0);

            // Remove old block if dead
            if (block.Size == 0)
            {
                Blocks.Remove(blockEntry);
                FreeList.Remove(block);
            }

            return(newBlock);
        }
Exemple #28
0
        public KMemoryBlock Allocate(string name, KAllocType type, uint address, uint size)
        {
            KMemoryBlock newBlock = null;

            // Round size up to the next word
            //if( ( size & 0x3 ) != 0 )
            //    size += 4 - ( size & 0x3 );

            if ((type == KAllocType.LowAligned) ||
                (type == KAllocType.HighAligned))
            {
                // TODO: align at 'address' (like 4096, etc)
                address = 0;

                // Other logic is the same
                if (type == KAllocType.LowAligned)
                {
                    type = KAllocType.Low;
                }
                else if (type == KAllocType.HighAligned)
                {
                    type = KAllocType.High;
                }
            }

            // Quick check to see if we have the space free
            Debug.Assert(FreeSize >= size);
            if (FreeSize < size)
            {
                return(null);
            }

            switch (type)
            {
            case KAllocType.Specific:
            {
                Debug.Assert(address != 0);
                LinkedListEntry <KMemoryBlock> e = FreeList.HeadEntry;
                while (e != null)
                {
                    if ((address >= e.Value.Address) &&
                        (address < e.Value.UpperBound))
                    {
                        newBlock = this.SplitBlock(e.Value, address, size);
                        break;
                    }
                    e = e.Next;
                }
            }
            break;

            case KAllocType.Low:
            {
                KMemoryBlock targetBlock = null;
                uint         maxContig   = 0;
                if (address != 0)
                {
                    // Specified lower limit, find the first block that fits
                    LinkedListEntry <KMemoryBlock> e = FreeList.HeadEntry;
                    while (e != null)
                    {
                        if ((address >= e.Value.Address) &&
                            (address < e.Value.UpperBound))
                        {
                            targetBlock = e.Value;
                            break;
                        }
                        maxContig = Math.Max(maxContig, e.Value.Size);
                        e         = e.Next;
                    }
                }
                else
                {
                    // No lower limit - pick first free block that fits
                    LinkedListEntry <KMemoryBlock> e = FreeList.HeadEntry;
                    while (e != null)
                    {
                        if (e.Value.Size >= size)
                        {
                            targetBlock = e.Value;
                            break;
                        }
                        maxContig = Math.Max(maxContig, e.Value.Size);
                        e         = e.Next;
                    }
                }
                Debug.Assert(targetBlock != null);
                if (targetBlock == null)
                {
                    // Try again with a smaller size
                    Log.WriteLine(Verbosity.Critical, Feature.Bios, "KPartition::Allocate could not find enough space");
                    //return this.Allocate( KAllocType.Maximum, 0, maxContig );
                    return(null);
                }
                Debug.Assert(targetBlock.Size >= size);
                if (targetBlock.Size < size)
                {
                    return(null);
                }
                newBlock = this.SplitBlock(targetBlock,
                                           (address != 0) ? address : targetBlock.Address,
                                           size);
            }
            break;

            case KAllocType.High:
            {
                Debug.Assert(address == 0);
                KMemoryBlock targetBlock         = null;
                LinkedListEntry <KMemoryBlock> e = FreeList.TailEntry;
                while (e != null)
                {
                    if (e.Value.Size >= size)
                    {
                        targetBlock = e.Value;
                        break;
                    }
                    e = e.Previous;
                }
                Debug.Assert(targetBlock != null);
                if (targetBlock == null)
                {
                    // Try again with a smaller size
                    Log.WriteLine(Verbosity.Critical, Feature.Bios, "KPartition::Allocate could not find enough space");
                    //return this.Allocate( KAllocType.Maximum, 0, maxContig );
                    return(null);
                }
                Debug.Assert(( int )targetBlock.UpperBound - ( int )size >= 0);
                newBlock = this.SplitBlock(targetBlock, targetBlock.UpperBound - size, size);
            }
            break;
            }

            if (newBlock != null)
            {
                newBlock.Name   = name;
                newBlock.IsFree = false;
                FreeSize       -= size;
            }
            this.Kernel.PrintMemoryInfo();
            return(newBlock);
        }
Exemple #29
0
        private bool FixupDelayedImports(Kernel kernel, LoadResults results)
        {
            int fixupCount = 0;

            foreach (KModule previous in kernel.UserModules)
            {
                if (previous.LoadResults.MissingImports.Count == 0)
                {
                    continue;
                }

                LinkedListEntry <DelayedImport> e = previous.LoadResults.MissingImports.HeadEntry;
                while (e != null)
                {
                    LinkedListEntry <DelayedImport> next = e.Next;
                    DelayedImport import = e.Value;
                    if (results.ExportNames.Contains(import.StubImport.ModuleName) == true)
                    {
                        // Find export
                        StubExport myExport = null;
                        foreach (StubExport export in results.Exports)
                        {
                            if (export.NID == import.StubImport.NID)
                            {
                                myExport = export;
                                break;
                            }
                        }
                        if (myExport != null)
                        {
                            previous.LoadResults.MissingImports.Remove(e);
                            fixupCount++;

                            // Fixup
                            Log.WriteLine(Verbosity.Verbose, Feature.Loader, "Fixing up module {0} delayed import 0x{1:X8}; value={2:X8}", previous.Name, import.StubImport.NID, myExport.Address);

                            Debug.Assert(myExport.Type == import.StubImport.Type);
                            if (myExport.Type == StubType.Function)
                            {
                                BiosFunction function = import.StubImport.Function;
                                // TODO: Change function module, etc?

                                // Perform fixup
                                uint *pcode = ( uint * )kernel.MemorySystem.Translate(function.StubAddress);
                                {
                                    // j {target}
                                    // nop
                                    *(pcode + 0) = ( uint )((2 << 26) | ((myExport.Address >> 2) & 0x03FFFFFF));
                                    *(pcode + 1) = ( uint )0;
                                }
                            }
                            else
                            {
                                throw new NotImplementedException("Cannot handle fixups of variable imports");
                            }
                        }
                    }
                    e = next;
                }
            }
            return(true);
        }
 public static void InitializeListHead <T>(LinkedListEntry <T> listHead)
 {
     listHead.Flink = listHead.Blink = listHead;
 }