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?re…
==============================================================================
--- 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?re…
==============================================================================
--- 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)