Author: aandrejevic Date: Sat Jul 20 06:14:13 2013 New Revision: 59530
URL: http://svn.reactos.org/svn/reactos?rev=59530&view=rev Log: [NTVDM] Implement multiple allocation strategies.
Modified: branches/ntvdm/subsystems/ntvdm/dos.c branches/ntvdm/subsystems/ntvdm/dos.h
Modified: branches/ntvdm/subsystems/ntvdm/dos.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/dos.c?rev... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/dos.c [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/dos.c [iso-8859-1] Sat Jul 20 06:14:13 2013 @@ -15,9 +15,11 @@ /* PRIVATE VARIABLES **********************************************************/
static WORD CurrentPsp = SYSTEM_PSP; +static WORD DosLastError = 0; static DWORD DiskTransferArea; static HANDLE DosSystemFileTable[DOS_SFT_SIZE]; static WORD DosSftRefCount[DOS_SFT_SIZE]; +static BYTE DosAllocStrategy = DOS_ALLOC_BEST_FIT; static BOOLEAN DosUmbLinked = FALSE;
/* PRIVATE FUNCTIONS **********************************************************/ @@ -225,6 +227,14 @@ { WORD Result = 0, Segment = FIRST_MCB_SEGMENT, MaxSize = 0; PDOS_MCB CurrentMcb, NextMcb; + BOOLEAN SearchUmb = FALSE; + + if (DosUmbLinked && (DosAllocStrategy & (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW))) + { + /* Search UMB first */ + Segment = UMB_START_SEGMENT; + SearchUmb = TRUE; + }
while (TRUE) { @@ -234,6 +244,7 @@ /* Make sure it's valid */ if (CurrentMcb->BlockType != 'M' && CurrentMcb->BlockType != 'Z') { + DosLastError = ERROR_ARENA_TRASHED; return 0; }
@@ -249,23 +260,59 @@ /* Check if this block is big enough */ if (CurrentMcb->Size < Size) goto Next;
- /* It is, update the smallest found so far */ - if ((Result == 0) || (CurrentMcb->Size < SEGMENT_TO_MCB(Result)->Size)) - { - Result = Segment; + switch (DosAllocStrategy & 0x3F) + { + case DOS_ALLOC_FIRST_FIT: + { + /* For first fit, stop immediately */ + Result = Segment; + goto Done; + } + + case DOS_ALLOC_BEST_FIT: + { + /* For best fit, update the smallest block found so far */ + if ((Result == 0) || (CurrentMcb->Size < SEGMENT_TO_MCB(Result)->Size)) + { + Result = Segment; + } + + break; + } + + case DOS_ALLOC_LAST_FIT: + { + /* For last fit, make the current block the result, but keep searching */ + Result = Segment; + break; + } }
Next: /* If this was the last MCB in the chain, quit */ - if (CurrentMcb->BlockType == 'Z') break; + if (CurrentMcb->BlockType == 'Z') + { + /* Check if nothing was found while searching through UMBs */ + if ((Result == 0) && SearchUmb && (DosAllocStrategy & DOS_ALLOC_HIGH_LOW)) + { + /* Search low memory */ + Segment = FIRST_MCB_SEGMENT; + continue; + } + + break; + }
/* Otherwise, update the segment and continue */ Segment += CurrentMcb->Size + 1; }
+Done: + /* If we didn't find a free block, return 0 */ if (Result == 0) { + DosLastError = ERROR_NOT_ENOUGH_MEMORY; if (MaxAvailable) *MaxAvailable = MaxSize; return 0; } @@ -306,6 +353,7 @@ if ((Mcb->BlockType != 'M' && Mcb->BlockType != 'Z') || Mcb->OwnerPsp == 0) { Success = FALSE; + DosLastError = ERROR_INVALID_PARAMETER; goto Done; }
@@ -328,6 +376,7 @@ /* Make sure the next segment is free */ if (NextMcb->OwnerPsp != 0) { + DosLastError = ERROR_NOT_ENOUGH_MEMORY; Success = FALSE; goto Done; } @@ -1457,7 +1506,7 @@ } else { - EmulatorSetRegister(EMULATOR_REG_AX, ERROR_NOT_ENOUGH_MEMORY); + EmulatorSetRegister(EMULATOR_REG_AX, DosLastError); EmulatorSetRegister(EMULATOR_REG_BX, MaxAvailable); EmulatorSetFlag(EMULATOR_FLAG_CF); } @@ -1492,6 +1541,7 @@ } else { + EmulatorSetRegister(EMULATOR_REG_AX, DosLastError); EmulatorSetFlag(EMULATOR_FLAG_CF); EmulatorSetRegister(EMULATOR_REG_BX, Size); } @@ -1509,13 +1559,45 @@ /* Get/Set Memory Management Options */ case 0x58: { - if (LOBYTE(Eax) == 0x02) + if (LOBYTE(Eax) == 0x00) + { + /* Get allocation strategy */ + + EmulatorSetRegister(EMULATOR_REG_AX, DosAllocStrategy); + EmulatorClearFlag(EMULATOR_FLAG_CF); + } + else if (LOBYTE(Eax) == 0x01) + { + /* Set allocation strategy */ + + if ((LOBYTE(Ebx) & (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) + == (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) + { + /* Can't set both */ + EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_PARAMETER); + EmulatorSetFlag(EMULATOR_FLAG_CF); + break; + } + + if ((LOBYTE(Ebx) & 0x3F) > DOS_ALLOC_LAST_FIT) + { + /* Invalid allocation strategy */ + EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_PARAMETER); + EmulatorSetFlag(EMULATOR_FLAG_CF); + break; + } + + DosAllocStrategy = LOBYTE(Ebx); + EmulatorClearFlag(EMULATOR_FLAG_CF); + } + else if (LOBYTE(Eax) == 0x02) { /* Get UMB link state */
Eax &= 0xFFFFFF00; if (DosUmbLinked) Eax |= 1; EmulatorSetRegister(EMULATOR_REG_AX, Eax); + EmulatorClearFlag(EMULATOR_FLAG_CF); } else if (LOBYTE(Eax) == 0x03) { @@ -1523,6 +1605,7 @@
if (Ebx) DosLinkUmb(); else DosUnlinkUmb(); + EmulatorClearFlag(EMULATOR_FLAG_CF); } else {
Modified: branches/ntvdm/subsystems/ntvdm/dos.h URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/dos.h?rev... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/dos.h [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/dos.h [iso-8859-1] Sat Jul 20 06:14:13 2013 @@ -31,6 +31,15 @@ #define SEGMENT_TO_PSP(seg) ((PDOS_PSP)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0))) #define UMB_START_SEGMENT 0xC000 #define UMB_END_SEGMENT 0xDFFF +#define DOS_ALLOC_HIGH 0x40 +#define DOS_ALLOC_HIGH_LOW 0x80 + +enum DOS_ALLOC_STRATEGY +{ + DOS_ALLOC_FIRST_FIT, + DOS_ALLOC_BEST_FIT, + DOS_ALLOC_LAST_FIT +};
#pragma pack(push, 1)