* One bit for each page in the kmalloc region
* If set then the page is used by a kmalloc block
*/
-static ULONG AllocMap[ALLOC_MAP_SIZE/32]={0,};
+static UCHAR AllocMapBuffer[ROUND_UP(ALLOC_MAP_SIZE, 8) / 8];
+static RTL_BITMAP AllocMap;
static KSPIN_LOCK AllocMapLock;
-static ULONG AllocMapHint = 1;
+static ULONG AllocMapHint = 0;
static PVOID NonPagedPoolBase;
ExUnmapPage(PVOID Addr)
{
KIRQL oldIrql;
- ULONG i = (Addr - NonPagedPoolBase) / PAGE_SIZE;
+ ULONG Base = (Addr - NonPagedPoolBase) / PAGE_SIZE;
DPRINT("ExUnmapPage(Addr %x)\n",Addr);
- DPRINT("i %x\n",i);
MmDeleteVirtualMapping(NULL, (PVOID)Addr, FALSE, NULL, NULL);
KeAcquireSpinLock(&AllocMapLock, &oldIrql);
- AllocMap[i / 32] &= (~(1 << (i % 32)));
- AllocMapHint = min(AllocMapHint, i);
+ RtlClearBits(&AllocMap, Base, 1);
+ AllocMapHint = min(AllocMapHint, Base);
KeReleaseSpinLock(&AllocMapLock, oldIrql);
}
ExAllocatePageWithPhysPage(PHYSICAL_ADDRESS PhysPage)
{
KIRQL oldlvl;
- ULONG addr;
- ULONG i;
+ PVOID Addr;
+ ULONG Base;
NTSTATUS Status;
KeAcquireSpinLock(&AllocMapLock, &oldlvl);
- for (i = AllocMapHint; i < ALLOC_MAP_SIZE; i++)
- {
- if (!(AllocMap[i / 32] & (1 << (i % 32))))
- {
- DPRINT("i %x\n",i);
- AllocMap[i / 32] |= (1 << (i % 32));
- AllocMapHint = i + 1;
- addr = (ULONG)(NonPagedPoolBase + (i*PAGE_SIZE));
- Status = MmCreateVirtualMapping(NULL,
- (PVOID)addr,
- PAGE_READWRITE | PAGE_SYSTEM,
- PhysPage,
- FALSE);
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("Unable to create virtual mapping\n");
- KeBugCheck(0);
- }
- KeReleaseSpinLock(&AllocMapLock, oldlvl);
- return((PVOID)addr);
- }
- }
+ Base = RtlFindClearBitsAndSet(&AllocMap, 1, AllocMapHint);
+ if (Base != 0xFFFFFFFF)
+ {
+ AllocMapHint = Base + 1;
+ KeReleaseSpinLock(&AllocMapLock, oldlvl);
+ Addr = NonPagedPoolBase + Base * PAGE_SIZE;
+ Status = MmCreateVirtualMapping(NULL,
+ Addr,
+ PAGE_READWRITE | PAGE_SYSTEM,
+ PhysPage,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("Unable to create virtual mapping\n");
+ KeBugCheck(0);
+ }
+ return Addr;
+ }
KeReleaseSpinLock(&AllocMapLock, oldlvl);
- return(NULL);
+ return NULL;
}
VOID
{
NonPagedPoolBase = BaseAddress;
KeInitializeSpinLock(&AllocMapLock);
+ RtlInitializeBitMap(&AllocMap, (PVOID)&AllocMapBuffer, ALLOC_MAP_SIZE);
+ RtlClearAllBits(&AllocMap);
}
VOID
{
ULONG i;
ULONG Base = (Addr - NonPagedPoolBase) / PAGE_SIZE;
- ULONG Offset;
KIRQL oldlvl;
- KeAcquireSpinLock(&AllocMapLock, &oldlvl);
- AllocMapHint = min(AllocMapHint, Base);
for (i = 0; i < Count; i++)
- {
- Offset = Base + i;
- AllocMap[Offset / 32] &= (~(1 << (Offset % 32)));
+ {
MmDeleteVirtualMapping(NULL,
Addr + (i * PAGE_SIZE),
Free,
NULL,
NULL);
- }
+ }
+ KeAcquireSpinLock(&AllocMapLock, &oldlvl);
+ RtlClearBits(&AllocMap, Base, Count);
+ AllocMapHint = min(AllocMapHint, Base);
KeReleaseSpinLock(&AllocMapLock, oldlvl);
}
* FUNCTION: Allocates a region of pages within the nonpaged pool area
*/
{
- unsigned int start = 0;
- unsigned int length = 0;
- unsigned int i,j;
+ ULONG Base;
KIRQL oldlvl;
KeAcquireSpinLock(&AllocMapLock, &oldlvl);
- for (i=AllocMapHint; i<ALLOC_MAP_SIZE;i++)
- {
- if (!(AllocMap[i/32] & (1 << (i % 32))))
- {
- if (length == 0)
- {
- start=i;
- length = 1;
- }
- else
- {
- length++;
- }
- if (length==nr_pages)
- {
- AllocMapHint = start + length;
- for (j=start;j<(start+length);j++)
- {
- AllocMap[j / 32] |= (1 << (j % 32));
- }
- DPRINT("returning %x\n",((start*PAGE_SIZE)+NonPagedPoolBase));
- KeReleaseSpinLock(&AllocMapLock, oldlvl);
- return(((start*PAGE_SIZE)+NonPagedPoolBase));
- }
- }
- else
- {
- start=0;
- length=0;
- }
- }
- DbgPrint("CRITICAL: Out of non-paged pool space\n");
- KeBugCheck(0);
- return(0);
+ Base = RtlFindClearBitsAndSet(&AllocMap, nr_pages, AllocMapHint);
+ if (Base == 0xFFFFFFFF)
+ {
+ DbgPrint("CRITICAL: Out of non-paged pool space\n");
+ KeBugCheck(0);
+ }
+ if (AllocMapHint == Base)
+ {
+ AllocMapHint += nr_pages;
+ }
+ KeReleaseSpinLock(&AllocMapLock, oldlvl);
+ DPRINT("returning %x\n",NonPagedPoolBase + Base * PAGE_SIZE);
+ return NonPagedPoolBase + Base * PAGE_SIZE;
}