public static void Main() { ExceptionMethods.AddExceptionHandlerInfo(null, null); UART.Init(); BasicConsole.Init(); BasicConsole.WriteLine("Kernel executing..."); try { ManagedMain(); } catch { BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Startup error! " + ExceptionMethods.CurrentException.Message); BasicConsole.WriteLine("FlingOS forced to halt!"); BasicConsole.SetTextColour(BasicConsole.default_colour); } bool OK2 = true; while (OK2) { ; } }
public static unsafe void Throw(Testing2.Exception ex) { Testing2.GC.IncrementRefCount(ex); BasicConsole.WriteLine("Exception thrown:"); BasicConsole.WriteLine(ex.Message); if (State->CurrentHandlerPtr->Ex != null) { //GC ref count remains consistent because the Ex pointer below is going to be replaced but // same pointer stored in InnerException. // Result is ref count goes: +1 here, -1 below ex.InnerException = (Testing2.Exception)Utilities.ObjectUtilities.GetObject(State->CurrentHandlerPtr->Ex); } if (ex.InstructionAddress == 0) { ex.InstructionAddress = *((uint *)BasePointer + 1); } State->CurrentHandlerPtr->Ex = Utilities.ObjectUtilities.GetHandle(ex); State->CurrentHandlerPtr->ExPending = 1; HandleException(); // We never expect to get here... HaltReason = "HandleException returned!"; BasicConsole.WriteLine(HaltReason); // Try to cause fault *((byte *)0xDEADBEEF) = 0; }
public static unsafe void AddExceptionHandlerInfo( void *handlerPtr, void *filterPtr) { if (State == null) { BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! ExceptionMethods.State is null."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); } AddExceptionHandlerInfo_EntryStackState *BasePtr = (AddExceptionHandlerInfo_EntryStackState *)BasePointer; uint LocalsSize = (uint)BasePtr - (uint)StackPointer; // Create space for setting up handler info StackPointer -= sizeof(ExceptionHandlerInfo); // Setup handler info ExceptionHandlerInfo *ExHndlrPtr = (ExceptionHandlerInfo *)StackPointer; ExHndlrPtr->EBP = BasePtr->EBP; // EBP + 8 (for ret addr, ebp) + 8 (for args) - sizeof(ExceptionHandlerInfo) ExHndlrPtr->ESP = (uint)BasePtr + 8 + 8 - (uint)sizeof(ExceptionHandlerInfo); ExHndlrPtr->FilterAddress = (byte *)filterPtr; ExHndlrPtr->HandlerAddress = (byte *)handlerPtr; ExHndlrPtr->PrevHandlerPtr = State->CurrentHandlerPtr; ExHndlrPtr->InHandler = 0; ExHndlrPtr->ExPending = 0; ExHndlrPtr->Ex = null; State->CurrentHandlerPtr = (ExceptionHandlerInfo *)((byte *)ExHndlrPtr + (LocalsSize + 12)); StackPointer -= 8; // For duplicate (empty) args StackPointer -= 8; // For duplicate ebp, ret addr // Setup the duplicate stack data // - Nothing to do for args - duplicate values don't matter // - Copy over ebp and return address uint *DuplicateValsStackPointer = (uint *)StackPointer; *DuplicateValsStackPointer = BasePtr->EBP; *(DuplicateValsStackPointer + 1) = BasePtr->RetAddr; ShiftStack((byte *)ExHndlrPtr + sizeof(ExceptionHandlerInfo) - 4, LocalsSize + 12); // Shift stack pointer to correct position - eliminates "empty space" of duplicates StackPointer += 16; // MethodEnd will: // - Add size of locals to esp // - Pop EBP // - Ret to ret address // Caller will: // - Add size of args to esp // Which should leave the stack at the bottom of the (shifted up) ex handler info }
public static void *NewObj(Testing2.Type theType) { if (!Enabled) { BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("Warning! GC returning null pointer because GC not enabled."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } //try //{ InsideGC = true; //Alloc space for GC header that prefixes object data //Alloc space for new object uint totalSize = theType.Size; totalSize += (uint)sizeof(GCHeader); GCHeader *newObjPtr = (GCHeader *)Heap.AllocZeroed(totalSize, "GC : NewObject"); if ((UInt32)newObjPtr == 0) { InsideGC = false; BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't create a new object because the heap returned a null pointer."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } NumObjs++; //Initialise the GCHeader SetSignature(newObjPtr); newObjPtr->RefCount = 1; //Initialise the object _Type field Testing2.ObjectWithType newObj = (Testing2.ObjectWithType)Utilities.ObjectUtilities.GetObject(newObjPtr + 1); newObj._Type = theType; //Move past GCHeader byte *newObjBytePtr = (byte *)(newObjPtr + 1); InsideGC = false; return(newObjBytePtr); //} //finally //{ //} }
public static void MemSet(byte val, byte *to, uint length) { BasicConsole.WriteLine(((Testing2.String) "Setting ") + (uint)to + " to " + val + ", size: " + length); //BasicConsole.DumpMemory(to, (int)length); uint tempLength = length; while (tempLength-- > 0) { *to++ = val; } //BasicConsole.DumpMemory(to - length, (int)length); }
public static unsafe void HandleException() { if (State != null) { if (State->CurrentHandlerPtr != null) { if (State->CurrentHandlerPtr->InHandler != 0) { State->CurrentHandlerPtr->InHandler = 0; if (State->CurrentHandlerPtr->PrevHandlerPtr != null) { State->CurrentHandlerPtr->PrevHandlerPtr->Ex = State->CurrentHandlerPtr->Ex; State->CurrentHandlerPtr->PrevHandlerPtr->ExPending = State->CurrentHandlerPtr->ExPending; } State->CurrentHandlerPtr = State->CurrentHandlerPtr->PrevHandlerPtr; } } ExceptionHandlerInfo *CurrHandlerPtr = State->CurrentHandlerPtr; if (CurrHandlerPtr != null) { if ((uint)CurrHandlerPtr->HandlerAddress != 0x00000000u) { if ((uint)CurrHandlerPtr->FilterAddress != 0x00000000u) { //Catch handler CurrHandlerPtr->ExPending = 0; } CurrHandlerPtr->InHandler = 1; ArbitaryReturn(CurrHandlerPtr->EBP, CurrHandlerPtr->ESP, CurrHandlerPtr->HandlerAddress); } } } // If we get to here, it's an unhandled exception HaltReason = "Unhandled / improperly handled exception!"; BasicConsole.WriteLine(HaltReason); // Try to cause fault *((byte *)0xDEADBEEF) = 0; }
public static unsafe void HandleEndFinally() { if (State == null || State->CurrentHandlerPtr == null) { // If we get to here, it's an unhandled exception HaltReason = "Cannot end finally on null handler!"; BasicConsole.WriteLine(HaltReason); BasicConsole.DelayOutput(5); // Try to cause fault *((byte *)0xDEADBEEF) = 0; } // Leaving a "finally" critical section cleanly // We need to handle 2 cases: // Case 1 : Pending exception // Case 2 : No pending exception if (State->CurrentHandlerPtr->ExPending != 0) { // Case 1 : Pending exception HandleException(); } else { // Case 2 : No pending exception State->CurrentHandlerPtr->InHandler = 0; uint EBP = State->CurrentHandlerPtr->EBP; uint ESP = State->CurrentHandlerPtr->ESP; State->CurrentHandlerPtr = State->CurrentHandlerPtr->PrevHandlerPtr; ArbitaryReturn(EBP, ESP + (uint)sizeof(ExceptionHandlerInfo), (byte *)*((uint *)(BasePointer + 4))); } }
public static void _IncrementRefCount(byte *objPtr) { if ((uint)objPtr < (uint)sizeof(GCHeader)) { BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't increment ref count of an object in low memory."); BasicConsole.DelayOutput(5); BasicConsole.SetTextColour(BasicConsole.default_colour); } objPtr -= sizeof(GCHeader); GCHeader *gcHeaderPtr = (GCHeader *)objPtr; if (CheckSignature(gcHeaderPtr)) { gcHeaderPtr->RefCount++; if (gcHeaderPtr->RefCount > 0) { RemoveObjectToCleanup(gcHeaderPtr); } } }
public static void ManagedMain() { InitialiseInterrupts(); EnableInterrupts(); BasicConsole.WriteLine("Interrupts enabled"); #region Struct Tests //int size = sizeof(AStruct); //if (size != 15) //{ // UART.Write("Bad size\n"); //} //else //{ // UART.Write("Good size\n"); //} //AStruct Inst = new AStruct(); //Inst.a = 1; //Inst.b = 2; //Inst.c = 4; //Inst.d = 8; //if (Inst.a != 1) //{ // UART.Write("Inst.a wrong\n"); //} //else //{ // UART.Write("Inst.a right\n"); //} //if (Inst.b != 2) //{ // UART.Write("Inst.b wrong\n"); //} //else //{ // UART.Write("Inst.b right\n"); //} //if (Inst.c != 4) //{ // UART.Write("Inst.c wrong\n"); //} //else //{ // UART.Write("Inst.c right\n"); //} //if (Inst.d != 8) //{ // UART.Write("Inst.d wrong\n"); //} //else //{ // UART.Write("Inst.d right\n"); //} //AStruct* HeapInst = (AStruct*)Heap.AllocZeroed((uint)sizeof(AStruct), "Kernel:Main"); //if (HeapInst == null) //{ // UART.Write("HeapInst null\n"); //} //else //{ // UART.Write("HeapInst not null\n"); //} //HeapInst->a = 1; //HeapInst->b = 2; //HeapInst->c = 4; //HeapInst->d = 8; //if (HeapInst->a != 1) //{ // UART.Write("HeapInst->a wrong\n"); //} //else //{ // UART.Write("HeapInst->a right\n"); //} //if (HeapInst->b != 2) //{ // UART.Write("HeapInst->b wrong\n"); //} //else //{ // UART.Write("HeapInst->b right\n"); //} //if (HeapInst->c != 4) //{ // UART.Write("HeapInst->c wrong\n"); //} //else //{ // UART.Write("HeapInst->c right\n"); //} //if (HeapInst->d != 8) //{ // UART.Write("HeapInst->d wrong\n"); //} //else //{ // UART.Write("HeapInst->d right\n"); //} #endregion #region Array Tests Value Types //int[] array = new int[4]; //int len = array.Length; //if (len != 4) //{ // UART.Write("Array length wrong\n"); //} //else //{ // UART.Write("Array length right\n"); //} //array[0] = 5; //array[1] = 10; //array[2] = 15; //array[3] = 20; //if (array[0] != 5) //{ // UART.Write("array[0] wrong\n"); //} //else //{ // UART.Write("array[0] right\n"); //} //if (array[1] != 10) //{ // UART.Write("array[1] wrong\n"); //} //else //{ // UART.Write("array[1] right\n"); //} //if (array[2] != 15) //{ // UART.Write("array[2] wrong\n"); //} //else //{ // UART.Write("array[2] right\n"); //} //if (array[3] != 20) //{ // UART.Write("array[3] wrong\n"); //} //else //{ // UART.Write("array[3] right\n"); //} #endregion #region Array Tests Using Structs //AStruct[] arr = new AStruct[3]; //int length = arr.Length; //if (length != 3) //{ // UART.Write("Struct array length wrong\n"); //} //else //{ // UART.Write("Struct array length right\n"); //} //arr[0].a = 255; //arr[0].b = 32767; //arr[0].c = 2147483647; //arr[0].d = 9223372036854775807; //if (arr[0].a != 255) //{ // UART.Write("arr[0].a wrong\n"); //} //else //{ // UART.Write("arr[0].a right\n"); //} //if (arr[0].b != 32767) //{ // UART.Write("arr[0].b wrong\n"); //} //else //{ // UART.Write("arr[0].b right\n"); //} //if (arr[0].c != 2147483647) //{ // UART.Write("arr[0].c wrong\n"); //} //else //{ // UART.Write("arr[0].c right\n"); //} //if (arr[0].d != 9223372036854775807) //{ // UART.Write("arr[0].d wrong\n"); //} //else //{ // UART.Write("arr[0].d right\n"); //} //arr[1].a = 0; //arr[1].b = 1; //arr[1].c = 2; //arr[1].d = 3; //if (arr[1].a != 0) //{ // UART.Write("arr[1].a wrong\n"); //} //else //{ // UART.Write("arr[1].a right\n"); //} //if (arr[1].b != 1) //{ // UART.Write("arr[1].b wrong\n"); //} //else //{ // UART.Write("arr[1].b right\n"); //} //if (arr[1].c != 2) //{ // UART.Write("arr[1].c wrong\n"); //} //else //{ // UART.Write("arr[1].c right\n"); //} //if (arr[1].d != 3) //{ // UART.Write("arr[1].d wrong\n"); //} //else //{ // UART.Write("arr[1].d right\n"); //} //arr[2].a = 100; //arr[2].b = 3000; //arr[2].c = 5777; //arr[2].d = 99876; //if (arr[2].a != 100) //{ // UART.Write("arr[2].a wrong\n"); //} //else //{ // UART.Write("arr[2].a right\n"); //} //if (arr[2].b != 3000) //{ // UART.Write("arr[2].b wrong\n"); //} //else //{ // UART.Write("arr[2].b right\n"); //} //if (arr[2].c != 5777) //{ // UART.Write("arr[2].c wrong\n"); //} //else //{ // UART.Write("arr[2].c right\n"); //} //if (arr[2].d != 99876) //{ // UART.Write("arr[2].d wrong\n"); //} //else //{ // UART.Write("arr[2].d right\n"); //} #endregion #region String Tests //BasicConsole.WriteLine("Test BasicConsole write line!"); //int testNum = 5; //Testing2.String ATestString = "Hello, world!"; //BasicConsole.WriteLine(ATestString); //if (ATestString != "Hello, world!") //{ // BasicConsole.WriteLine("String equality does not work!"); //} //else //{ // BasicConsole.WriteLine("String equality works."); //} //ATestString += " But wait! There's more..."; //BasicConsole.WriteLine(ATestString); //ATestString += " We can even append numbers: " + (Testing2.String)testNum; //BasicConsole.WriteLine(ATestString); //BasicConsole.DumpMemory((byte*)Utilities.ObjectUtilities.GetHandle(ATestString) - sizeof(GCHeader), (int)(ATestString.length + Testing2.String.FieldsBytesSize + sizeof(GCHeader))); #endregion #region Objects //TestClass aClass = new TestClass(); //BasicConsole.WriteLine("Object created!"); //int fld = aClass.aField; //if (fld != 9) //{ // UART.Write("Class field wrong\n"); //} //else //{ // UART.Write("Class field right\n"); //} //int arg = 10; //int arg1 = aClass.aMethodInt(arg); //if (arg1 != 30) //{ // UART.Write("Class method int wrong\n"); //} //else //{ // UART.Write("Class method int right\n"); //} //aClass.aMethodVoid(); //int arg2 = aClass.aMethodField(arg); //if (arg2 != 90) //{ // UART.Write("Class method field wrong\n"); //} //else //{ // UART.Write("Class method field right\n"); //} #endregion Timer.Init(); BasicConsole.WriteLine("Okay"); bool OK = true; uint lastCount = count; while (OK) { if (count > lastCount) { BasicConsole.WriteLine(count); lastCount = count + 0; } } }
public static void _DecrementRefCount(byte *objPtr) { if ((uint)objPtr < (uint)sizeof(GCHeader)) { BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't decrement ref count of an object in low memory."); BasicConsole.DelayOutput(5); BasicConsole.SetTextColour(BasicConsole.default_colour); } GCHeader *gcHeaderPtr = (GCHeader *)(objPtr - sizeof(GCHeader)); if (CheckSignature(gcHeaderPtr)) { gcHeaderPtr->RefCount--; //If the ref count goes below 0 then there was a circular reference somewhere. // In actuality we don't care we can just only do cleanup when the ref count is // exactly 0. if (gcHeaderPtr->RefCount == 0) { #if GC_TRACE BasicConsole.WriteLine("Cleaned up object."); #endif Testing2.Object obj = (Testing2.Object)Utilities.ObjectUtilities.GetObject(objPtr); if (obj is Testing2.Array) { //Decrement ref count of elements Testing2.Array arr = (Testing2.Array)obj; if (!arr.elemType.IsValueType) { Testing2.Object[] objArr = (Testing2.Object[])Utilities.ObjectUtilities.GetObject(objPtr); for (int i = 0; i < arr.length; i++) { DecrementRefCount(objArr[i], true); } } } //Cleanup fields FieldInfo *FieldInfoPtr = obj._Type.FieldTablePtr; //Loop through all fields. The if-block at the end handles moving to parent // fields. while (FieldInfoPtr != null) { if (FieldInfoPtr->Size > 0) { Testing2.Type fieldType = (Testing2.Type)Utilities.ObjectUtilities.GetObject(FieldInfoPtr->FieldType); if (!fieldType.IsValueType && !fieldType.IsPointer) { byte * fieldPtr = objPtr + FieldInfoPtr->Offset; Testing2.Object theFieldObj = (Testing2.Object)Utilities.ObjectUtilities.GetObject(fieldPtr); DecrementRefCount(theFieldObj, true); #if GC_TRACE BasicConsole.WriteLine("Cleaned up field."); #endif } FieldInfoPtr++; } if (FieldInfoPtr->Size == 0) { FieldInfoPtr = (FieldInfo *)FieldInfoPtr->FieldType; } } AddObjectToCleanup(gcHeaderPtr, objPtr); } } }
public static void *NewString(int length) { if (!Enabled) { BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("Warning! GC returning null pointer because GC not enabled."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } //try { if (length < 0) { BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't create a new string because \"length\" is less than 0."); BasicConsole.DelayOutput(5); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); //ExceptionMethods.Throw_OverflowException(); } InsideGC = true; //Alloc space for GC header that prefixes object data //Alloc space for new string object //Alloc space for new string chars uint totalSize = ((Testing2.Type) typeof(Testing2.String)).Size; totalSize += /*char size in bytes*/ 2 * (uint)length; totalSize += (uint)sizeof(GCHeader); GCHeader *newObjPtr = (GCHeader *)Heap.AllocZeroed(totalSize, "GC : NewString"); if ((UInt32)newObjPtr == 0) { InsideGC = false; BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't create a new string because the heap returned a null pointer."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } NumObjs++; NumStrings++; //Initialise the GCHeader SetSignature(newObjPtr); //RefCount to 0 initially because of Testing2.String.New should be used // - In theory, New should be called, creates new string and passes it back to caller // Caller is then required to store the string in a variable resulting in inc. // ref count so ref count = 1 in only stored location. // Caller is not allowed to just "discard" (i.e. use Pop IL op or C# that generates // Pop IL op) so ref count will always at some point be incremented and later // decremented by managed code. OR the variable will stay in a static var until // the OS exits... newObjPtr->RefCount = 0; Testing2.String newStr = (Testing2.String)Utilities.ObjectUtilities.GetObject(newObjPtr + 1); newStr._Type = (Testing2.Type) typeof(Testing2.String); newStr.length = length; //Move past GCHeader byte *newObjBytePtr = (byte *)(newObjPtr + 1); InsideGC = false; return(newObjBytePtr); } //finally { //ExitCritical(); } }
public static void *NewArr(int length, Testing2.Type elemType) { if (!Enabled) { BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("Warning! GC returning null pointer because GC not enabled."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } //try { if (length < 0) { UART.Write("length < 0. Overflow exception."); return(null); //ExceptionMethods.Throw_OverflowException(); } InsideGC = true; //Alloc space for GC header that prefixes object data //Alloc space for new array object //Alloc space for new array elems uint totalSize = ((Testing2.Type) typeof(Testing2.Array)).Size; if (elemType.IsValueType) { totalSize += elemType.Size * (uint)length; } else { totalSize += elemType.StackSize * (uint)length; } totalSize += (uint)sizeof(GCHeader); GCHeader *newObjPtr = (GCHeader *)Heap.AllocZeroed(totalSize, "GC : NewArray"); if ((UInt32)newObjPtr == 0) { InsideGC = false; BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't create a new array because the heap returned a null pointer."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } NumObjs++; //Initialise the GCHeader SetSignature(newObjPtr); newObjPtr->RefCount = 1; Testing2.Array newArr = (Testing2.Array)Utilities.ObjectUtilities.GetObject(newObjPtr + 1); newArr._Type = (Testing2.Type) typeof(Testing2.Array); newArr.length = length; newArr.elemType = elemType; //Move past GCHeader byte *newObjBytePtr = (byte *)(newObjPtr + 1); InsideGC = false; return(newObjBytePtr); } //finally { } }
public static unsafe void HandleLeave(void *continuePtr) { if (State == null || State->CurrentHandlerPtr == null) { // If we get to here, it's an unhandled exception HaltReason = "Cannot leave on null handler! Address: 0x "; uint y = *((uint *)(BasePointer + 4)); int offset = 48; #region Address while (offset > 40) { uint rem = y & 0xFu; switch (rem) { case 0: HaltReason[offset] = '0'; break; case 1: HaltReason[offset] = '1'; break; case 2: HaltReason[offset] = '2'; break; case 3: HaltReason[offset] = '3'; break; case 4: HaltReason[offset] = '4'; break; case 5: HaltReason[offset] = '5'; break; case 6: HaltReason[offset] = '6'; break; case 7: HaltReason[offset] = '7'; break; case 8: HaltReason[offset] = '8'; break; case 9: HaltReason[offset] = '9'; break; case 10: HaltReason[offset] = 'A'; break; case 11: HaltReason[offset] = 'B'; break; case 12: HaltReason[offset] = 'C'; break; case 13: HaltReason[offset] = 'D'; break; case 14: HaltReason[offset] = 'E'; break; case 15: HaltReason[offset] = 'F'; break; } y >>= 4; offset--; } #endregion BasicConsole.WriteLine(HaltReason); BasicConsole.DelayOutput(5); // Try to cause fault *((byte *)0xDEADBEEF) = 0; } // Leaving a critical section cleanly // We need to handle 2 cases: // Case 1 : Leaving "try" or "catch" of a try-catch // Case 2 : Leaving the "try" of a try-finally if ((uint)State->CurrentHandlerPtr->FilterAddress != 0x0u) { // Case 1 : Leaving "try" or "catch" of a try-catch if (State->CurrentHandlerPtr->Ex != null) { Testing2.GC.DecrementRefCount((Testing2.Object)Utilities.ObjectUtilities.GetObject(State->CurrentHandlerPtr->Ex)); State->CurrentHandlerPtr->Ex = null; } State->CurrentHandlerPtr->InHandler = 0; uint EBP = State->CurrentHandlerPtr->EBP; uint ESP = State->CurrentHandlerPtr->ESP; State->CurrentHandlerPtr = State->CurrentHandlerPtr->PrevHandlerPtr; ArbitaryReturn(EBP, ESP + (uint)sizeof(ExceptionHandlerInfo), (byte *)continuePtr); } else { // Case 2 : Leaving the "try" of a try-finally State->CurrentHandlerPtr->InHandler = 1; ArbitaryReturn(State->CurrentHandlerPtr->EBP, State->CurrentHandlerPtr->ESP, State->CurrentHandlerPtr->HandlerAddress); } }
public static void *Alloc(UInt32 size, UInt32 boundary, Testing2.String caller) { #if HEAP_TRACE BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("Attempt to alloc mem...."); BasicConsole.SetTextColour(BasicConsole.default_colour); #endif HeapBlock *b; byte * bm; UInt32 bcnt; UInt32 x, y, z; UInt32 bneed; byte nid; if (boundary > 1) { size += (boundary - 1); } /* iterate blocks */ for (b = fblock; (UInt32)b != 0; b = b->next) { /* check if block has enough room */ if (b->size - (b->used * b->bsize) >= size) { bcnt = b->size / b->bsize; bneed = (size / b->bsize) * b->bsize < size ? size / b->bsize + 1 : size / b->bsize; bm = (byte *)&b[1]; for (x = (b->lfb + 1 >= bcnt ? 0 : b->lfb + 1); x != b->lfb; ++x) { /* just wrap around */ if (x >= bcnt) { x = 0; } if (bm[x] == 0) { /* count free blocks */ for (y = 0; bm[x + y] == 0 && y < bneed && (x + y) < bcnt; ++y) { ; } /* we have enough, now allocate them */ if (y == bneed) { /* find ID that does not match left or right */ nid = GetNID(bm[x - 1], bm[x + y]); /* allocate by setting id */ for (z = 0; z < y; ++z) { bm[x + z] = nid; } /* optimization */ b->lfb = (x + bneed) - 2; /* count used blocks NOT bytes */ b->used += y; void *result = (void *)(x * b->bsize + (UInt32)(&b[1])); if (boundary > 1) { result = (void *)((((UInt32)result) + (boundary - 1)) & ~(boundary - 1)); #if HEAP_TRACE ExitCritical(); BasicConsole.WriteLine(((Testing2.String) "Allocated address ") + (uint)result + " on boundary " + boundary + " for " + caller); EnterCritical("Alloc:Boundary condition"); #endif } return(result); } /* x will be incremented by one ONCE more in our FOR loop */ x += (y - 1); continue; } } } } #if HEAP_TRACE BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("!!Heap out of memory!!"); BasicConsole.SetTextColour(BasicConsole.default_colour); BasicConsole.DelayOutput(2); #endif return(null); }