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(); } }
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; }
/// <summary> /// Creates a new instance of the Provider class, specifying a /// custom <seealso cref="System.Collections.Generic.IDictionary<TKey, TValue>"/> 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()); }
public void Dispose() { GC.SuppressFinalize(this); LinkedListEntry <KMemoryBlock> e = Blocks.HeadEntry; while (e != null) { Partition.Free(e.Value); e = e.Next; } Blocks.Clear(); }
/// <summary> /// Creates a new instance of the Provider class, specifying a /// custom <seealso cref="System.Collections.Generic.IDictionary<TKey, TValue>"/> instance. /// </summary> protected Provider(IDictionary <TKey, TValue> dictionary) { if (dictionary == null) { throw new ArgumentNullException("dictionary"); } _dictionary = dictionary; _listEntry = new LinkedListEntry <IProvider> { Value = this }; }
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); } }
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); }
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); } }
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; } }
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); }
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); } }
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(); } }
// 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); } }
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()); }
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); } }
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); }
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); }
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; }