LONG ProcessorCount;
SYNC_REQUEST Request;
LONG CompletionCount;
+ PKDPC Dpcs;
KDPC Dpc[1];
} SYNC_CONTEXT, *PSYNC_CONTEXT;
static PSYNC_CONTEXT SyncContext = (PVOID)__Section;
static LONG SyncOwner = -1;
+#define MAX_DPCS_PER_PAGE ((PAGE_SIZE - sizeof(SYNC_CONTEXT)) / sizeof(KDPC))
+#define SYNC_POOL_TAG 'CNYS'
+
+static FORCEINLINE PVOID
+__SyncAllocate(
+ IN ULONG Size
+ )
+{
+ PVOID Buffer;
+
+ if (Size == 0)
+ return NULL;
+
+ Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ Size,
+ SYNC_POOL_TAG);
+ if (Buffer != NULL)
+ RtlZeroMemory(Buffer, Size);
+
+ return Buffer;
+}
+
+static FORCEINLINE VOID
+__SyncFree(
+ IN PVOID Buffer
+ )
+{
+ ExFreePoolWithTag(Buffer, SYNC_POOL_TAG);
+}
+
static FORCEINLINE VOID
__SyncAcquire(
IN LONG Index
Context->Late = Late;
Context->CompletionCount = 0;
- KeMemoryBarrier();
+
+ Context->Dpcs = &Context->Dpc[0];
Context->ProcessorCount = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
+ if (Context->ProcessorCount >= MAX_DPCS_PER_PAGE) {
+ Context->Dpcs = __SyncAllocate(Context->ProcessorCount * sizeof(KDPC));
+ ASSERT(Context->Dpcs != NULL);
+ }
+
+ KeMemoryBarrier();
for (Index = 0; Index < Context->ProcessorCount; Index++) {
- PKDPC Dpc = &Context->Dpc[Index];
+ PKDPC Dpc = &Context->Dpcs[Index];
NTSTATUS status;
- ASSERT3U((ULONG_PTR)(Dpc + 1), <, (ULONG_PTR)__Section + PAGE_SIZE);
+ // Imply Context->Dpcs == &Context->Dpc[0] ->
+ // ASSERT3U((ULONG_PTR)(Dpc + 1), <, (ULONG_PTR)__Section + PAGE_SIZE);
status = KeGetProcessorNumberFromIndex(Index, &ProcNumber);
ASSERT(NT_SUCCESS(status));
__SyncWait();
+ if (Context->ProcessorCount >= MAX_DPCS_PER_PAGE) {
+ ASSERT3P(Context->Dpcs, !=, &Context->Dpc[0]);
+ __SyncFree(Context->Dpcs);
+ }
+
RtlZeroMemory(Context, PAGE_SIZE);
__SyncRelease();