예제 #1
0
파일: himem.c 프로젝트: GYGit/reactos
static UCHAR XmsAlloc(WORD Size, PWORD Handle)
{
    BYTE i;
    PXMS_HANDLE HandleEntry;
    DWORD CurrentIndex = 0;
    ULONG RunStart;
    ULONG RunSize;

    if (Size > FreeBlocks) return XMS_STATUS_OUT_OF_MEMORY;

    for (i = 0; i < XMS_MAX_HANDLES; i++)
    {
        HandleEntry = &HandleTable[i];
        if (HandleEntry->Handle == 0)
        {
            *Handle = i + 1;
            break;
        }
    }

    if (i == XMS_MAX_HANDLES) return XMS_STATUS_OUT_OF_HANDLES;

    /* Optimize blocks */
    for (i = 0; i < XMS_MAX_HANDLES; i++)
    {
        /* Skip free and locked blocks */
        if (HandleEntry->Handle == 0 || HandleEntry->LockCount > 0) continue;

        CurrentIndex = (HandleEntry->Address - XMS_ADDRESS) / XMS_BLOCK_SIZE;

        /* Check if there is any free space before this block */
        RunSize = RtlFindLastBackwardRunClear(&AllocBitmap, CurrentIndex, &RunStart);
        if (RunSize == 0) break;

        /* Move this block back */
        RtlMoveMemory((PVOID)REAL_TO_PHYS(HandleEntry->Address - RunSize * XMS_BLOCK_SIZE),
                      (PVOID)REAL_TO_PHYS(HandleEntry->Address),
                      RunSize * XMS_BLOCK_SIZE);

        /* Update the address */
        HandleEntry->Address -= RunSize * XMS_BLOCK_SIZE;
    }

    while (CurrentIndex < XMS_BLOCKS)
    {
        RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart);
        if (RunSize == 0) break;

        if (RunSize >= HandleEntry->Size)
        {
            /* Allocate it here */
            HandleEntry->Handle = i + 1;
            HandleEntry->LockCount = 0;
            HandleEntry->Size = Size;
            HandleEntry->Address = XMS_ADDRESS + RunStart * XMS_BLOCK_SIZE;

            FreeBlocks -= Size;
            RtlSetBits(&AllocBitmap, RunStart, HandleEntry->Size);

            return XMS_STATUS_SUCCESS;
        }

        /* Keep searching */
        CurrentIndex = RunStart + RunSize;
    }

    return XMS_STATUS_OUT_OF_MEMORY;
}
예제 #2
0
파일: bitmap_class.cpp 프로젝트: 0cch/misc
ULONG NtdllBitmap::FindLastBackwardRunClear( ULONG from_index, PULONG starting_run_index )
{
	assert(RtlFindLastBackwardRunClear != NULL);
	return RtlFindLastBackwardRunClear(this, from_index, starting_run_index);
}