ReactOS 0.4.17-dev-573-g8315b8c
arbiter.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Arbitrartion Library
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Generic Arbiter Library
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include <ntifs.h>
11#include <ndk/rtlfuncs.h>
12#include "arbiter.h"
13
14#define NDEBUG
15#include <debug.h>
16
17#define ARBITER_SIG 'sbrA'
18#define TAG_ARBITER 'ibrA'
19
20/*
21 * TODO: ArbTestAllocation-ArbQueryConflict have some signature rewrites
22 * that need to happen when we retarget to vista.
23 */
24CODE_SEG("PAGE")
28 _In_ PARBITER_INSTANCE Arbiter,
29 _Inout_ PLIST_ENTRY ArbitrationList)
30{
31 PAGED_CODE();
32
35}
36
37CODE_SEG("PAGE")
41 _In_ PARBITER_INSTANCE Arbiter,
42 _Inout_ PLIST_ENTRY ArbitrationList)
43{
44 PAGED_CODE();
45
48}
49
50CODE_SEG("PAGE")
54 _In_ PARBITER_INSTANCE Arbiter,
55 _Inout_ PLIST_ENTRY ArbitrationList)
56{
57 PAGED_CODE();
58
61}
62
63CODE_SEG("PAGE")
67 _In_ PARBITER_INSTANCE Arbiter,
70{
71 PAGED_CODE();
72
75}
76
77CODE_SEG("PAGE")
81 _In_ PARBITER_INSTANCE Arbiter,
83 _In_ PIO_RESOURCE_DESCRIPTOR ConflictingResource,
84 _Out_ PULONG ConflictCount,
86{
87 PAGED_CODE();
88
91}
92
93#if (NTDDI_VERSION >= NTDDI_VISTA)
94CODE_SEG("PAGE")
98 _In_ PARBITER_INSTANCE Arbiter,
101 _Inout_ PRTL_RANGE_LIST RangeList)
102{
103 PAGED_CODE();
104
107}
108#endif
109
110CODE_SEG("PAGE")
112NTAPI
114 _In_ PARBITER_INSTANCE Arbiter)
115{
116 PAGED_CODE();
117
120}
121
122CODE_SEG("PAGE")
124NTAPI
126 _In_ PARBITER_INSTANCE Arbiter)
127{
128 PAGED_CODE();
129
132}
133
134CODE_SEG("PAGE")
136NTAPI
138 _In_ PARBITER_INSTANCE Arbiter,
139 _In_ PCM_RESOURCE_LIST StartResources)
140{
141 PAGED_CODE();
142
145}
146
147CODE_SEG("PAGE")
149NTAPI
151 _In_ PARBITER_INSTANCE Arbiter,
153{
154 PAGED_CODE();
155
157 return STATUS_SUCCESS;
158}
159
160CODE_SEG("PAGE")
162NTAPI
164 _In_ PARBITER_INSTANCE Arbiter,
166{
167 PAGED_CODE();
168
171}
172
173CODE_SEG("PAGE")
175NTAPI
177 _Inout_ PLIST_ENTRY ArbitrationList)
178{
179 PAGED_CODE();
180
183}
184
185CODE_SEG("PAGE")
187NTAPI
189 _In_ PARBITER_INSTANCE Arbiter,
191{
192 PAGED_CODE();
193
195 return FALSE;
196}
197
198CODE_SEG("PAGE")
200NTAPI
202 _In_ PARBITER_INSTANCE Arbiter,
204{
205 PAGED_CODE();
206
208 return FALSE;
209}
210
211CODE_SEG("PAGE")
212VOID
213NTAPI
215 _In_ PARBITER_INSTANCE Arbiter,
217{
218 PAGED_CODE();
219
221}
222
223CODE_SEG("PAGE")
224VOID
225NTAPI
227 _In_ PARBITER_INSTANCE Arbiter,
229{
230 PAGED_CODE();
231
233}
234
235CODE_SEG("PAGE")
236VOID
237NTAPI
239 _In_ PARBITER_INSTANCE Arbiter,
241{
242 PAGED_CODE();
243
245}
246
247CODE_SEG("PAGE")
249NTAPI
251 _In_ PARBITER_INSTANCE Arbiter,
253{
254 PAGED_CODE();
255
257 return FALSE;
258}
259
260CODE_SEG("PAGE")
262NTAPI
267{
268 PAGED_CODE();
269
272}
273
274CODE_SEG("PAGE")
276NTAPI
278 _Out_ PARBITER_ORDERING_LIST OrderingList)
279{
280 PAGED_CODE();
281
284}
285
286CODE_SEG("PAGE")
287VOID
288NTAPI
290 _Inout_ PARBITER_ORDERING_LIST OrderingList)
291{
292 PAGED_CODE();
293
295}
296
297CODE_SEG("PAGE")
299NTAPI
303{
304 PAGED_CODE();
305
308}
309
310CODE_SEG("PAGE")
312NTAPI
314 _Inout_ PARBITER_ORDERING_LIST OrderingList,
316 _In_ UINT64 End)
317{
318 PAGED_CODE();
319
322}
323
324CODE_SEG("PAGE")
326NTAPI
328 _Inout_ PARBITER_ORDERING_LIST OrderingList,
330 _In_ UINT64 End)
331{
332 PAGED_CODE();
333
336}
337
338CODE_SEG("PAGE")
340NTAPI
343 _In_ PCWSTR AllocationOrderName,
344 _In_ PCWSTR ReservedResourcesName,
345 _In_opt_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
346{
347 PAGED_CODE();
348
350 return STATUS_SUCCESS;
351}
352
353CODE_SEG("PAGE")
354VOID
355NTAPI
357 _In_ PARBITER_INSTANCE Arbiter)
358{
359 PAGED_CODE();
360
361 if (Arbiter->PossibleAllocation)
362 {
363 RtlFreeRangeList(Arbiter->PossibleAllocation);
364 ExFreePoolWithTag(Arbiter->PossibleAllocation, TAG_ARBITER);
365 Arbiter->PossibleAllocation = NULL;
366 }
367
368 if (Arbiter->Allocation)
369 {
370 RtlFreeRangeList(Arbiter->Allocation);
371 ExFreePoolWithTag(Arbiter->Allocation, TAG_ARBITER);
372 Arbiter->Allocation = NULL;
373 }
374
375 if (Arbiter->AllocationStack)
376 {
377 ExFreePoolWithTag(Arbiter->AllocationStack, TAG_ARBITER);
378 Arbiter->AllocationStack = NULL;
379 Arbiter->AllocationStackMaxSize = 0;
380 }
381
382#if (NTDDI_VERSION >= NTDDI_VISTA)
383 if (Arbiter->TransactionEvent)
384 {
385 ExFreePoolWithTag(Arbiter->TransactionEvent, TAG_ARBITER);
386 Arbiter->TransactionEvent = NULL;
387 }
388#endif
389
390 if (Arbiter->MutexEvent)
391 {
392 ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
393 Arbiter->MutexEvent = NULL;
394 }
395}
396
397CODE_SEG("PAGE")
399NTAPI
402 _In_ PDEVICE_OBJECT BusDeviceObject,
403 _In_ CM_RESOURCE_TYPE ResourceType,
404 _In_ PCWSTR ArbiterName,
405 _In_ PCWSTR OrderName,
406 _In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
407{
409
410 PAGED_CODE();
411
412 DPRINT("ArbInitializeArbiterInstance: '%S'\n", ArbiterName);
413
414 ASSERT(Arbiter->UnpackRequirement != NULL);
415 ASSERT(Arbiter->PackResource != NULL);
416 ASSERT(Arbiter->UnpackResource != NULL);
417 ASSERT(Arbiter->MutexEvent == NULL);
418 ASSERT(Arbiter->Allocation == NULL);
419 ASSERT(Arbiter->PossibleAllocation == NULL);
420 ASSERT(Arbiter->AllocationStack == NULL);
421
422 Arbiter->Signature = ARBITER_SIG;
423 Arbiter->BusDeviceObject = BusDeviceObject;
424 Arbiter->Name = ArbiterName;
425 Arbiter->ResourceType = ResourceType;
426 Arbiter->TransactionInProgress = FALSE;
427#if (NTDDI_VERSION >= NTDDI_VISTA)
428 Arbiter->OrderingName = OrderName;
429#endif
430
431 /* The per-instance lock: a signaled synchronization event used as a mutex. */
432 Arbiter->MutexEvent = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_ARBITER);
433 if (!Arbiter->MutexEvent)
434 {
436 goto Failure;
437 }
438 KeInitializeEvent(Arbiter->MutexEvent, SynchronizationEvent, TRUE);
439
440#if (NTDDI_VERSION >= NTDDI_VISTA)
441 /* Vista+: a notification event exposing whether a Test is outstanding. */
442 Arbiter->TransactionEvent = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_ARBITER);
443 if (!Arbiter->TransactionEvent)
444 {
446 goto Failure;
447 }
448 KeInitializeEvent(Arbiter->TransactionEvent, NotificationEvent, TRUE);
449#endif
450
451 Arbiter->AllocationStack = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, TAG_ARBITER);
452 if (!Arbiter->AllocationStack)
453 {
455 goto Failure;
456 }
457 Arbiter->AllocationStackMaxSize = PAGE_SIZE;
458 Arbiter->Allocation = ExAllocatePoolWithTag(PagedPool, sizeof(RTL_RANGE_LIST), TAG_ARBITER);
459 if (!Arbiter->Allocation)
460 {
462 goto Failure;
463 }
464 RtlInitializeRangeList(Arbiter->Allocation);
465
466 Arbiter->PossibleAllocation = ExAllocatePoolWithTag(PagedPool, sizeof(RTL_RANGE_LIST), TAG_ARBITER);
467 if (!Arbiter->PossibleAllocation)
468 {
470 goto Failure;
471 }
472 RtlInitializeRangeList(Arbiter->PossibleAllocation);
473
474 if (!Arbiter->TestAllocation)
475 Arbiter->TestAllocation = ArbTestAllocation;
476 if (!Arbiter->RetestAllocation)
477 Arbiter->RetestAllocation = ArbRetestAllocation;
478 if (!Arbiter->CommitAllocation)
479 Arbiter->CommitAllocation = ArbCommitAllocation;
480 if (!Arbiter->RollbackAllocation)
481 Arbiter->RollbackAllocation = ArbRollbackAllocation;
482 if (!Arbiter->BootAllocation)
483 Arbiter->BootAllocation = ArbBootAllocation;
484 if (!Arbiter->AddReserved)
485 Arbiter->AddReserved = ArbAddReserved;
486 if (!Arbiter->QueryConflict)
487 Arbiter->QueryConflict = ArbQueryConflict;
488 if (!Arbiter->StartArbiter)
489 Arbiter->StartArbiter = ArbStartArbiter;
490 if (!Arbiter->PreprocessEntry)
491 Arbiter->PreprocessEntry = ArbPreprocessEntry;
492 if (!Arbiter->AllocateEntry)
493 Arbiter->AllocateEntry = ArbAllocateEntry;
494 if (!Arbiter->GetNextAllocationRange)
495 Arbiter->GetNextAllocationRange = ArbGetNextAllocationRange;
496 if (!Arbiter->FindSuitableRange)
497 Arbiter->FindSuitableRange = ArbFindSuitableRange;
498 if (!Arbiter->AddAllocation)
499 Arbiter->AddAllocation = ArbAddAllocation;
500 if (!Arbiter->BacktrackAllocation)
501 Arbiter->BacktrackAllocation = ArbBacktrackAllocation;
502 if (!Arbiter->OverrideConflict)
503 Arbiter->OverrideConflict = ArbOverrideConflict;
504#if (NTDDI_VERSION >= NTDDI_VISTA)
505 if (!Arbiter->InitializeRangeList)
506 Arbiter->InitializeRangeList = ArbInitializeRangeList;
507#endif
508
509 Status = ArbBuildAssignmentOrdering(Arbiter, OrderName, OrderName, TranslateOrderingFunction);
510 if (!NT_SUCCESS(Status))
511 {
512 DPRINT1("ArbInitializeArbiterInstance: ArbBuildAssignmentOrdering failed, Status %X\n", Status);
513 goto Failure;
514 }
515
516 return STATUS_SUCCESS;
517
518Failure:
519 DPRINT1("ArbInitializeArbiterInstance: '%S' failed, Status %X\n", ArbiterName, Status);
521 return Status;
522}
#define PAGED_CODE()
#define CODE_SEG(...)
unsigned char BOOLEAN
Definition: actypes.h:127
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
BOOLEAN NTAPI ArbGetNextAllocationRange(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:188
VOID NTAPI ArbAddAllocation(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:214
VOID NTAPI ArbConfirmAllocation(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:238
NTSTATUS NTAPI ArbArbiterHandler(_In_ PVOID Context, _In_ ARBITER_ACTION Action, _Inout_ PARBITER_PARAMETERS Parameters)
Definition: arbiter.c:263
NTSTATUS NTAPI ArbInitializeRangeList(_In_ PARBITER_INSTANCE Arbiter, _In_ ULONG ResourceCount, _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Resources, _Inout_ PRTL_RANGE_LIST RangeList)
Definition: arbiter.c:97
NTSTATUS NTAPI ArbCopyOrderingList(_Out_ PARBITER_ORDERING_LIST Destination, _In_ PARBITER_ORDERING_LIST Source)
Definition: arbiter.c:300
VOID NTAPI ArbDeleteArbiterInstance(_In_ PARBITER_INSTANCE Arbiter)
Definition: arbiter.c:356
BOOLEAN NTAPI ArbFindSuitableRange(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:201
NTSTATUS NTAPI ArbQueryConflict(_In_ PARBITER_INSTANCE Arbiter, _In_ PDEVICE_OBJECT PhysicalDeviceObject, _In_ PIO_RESOURCE_DESCRIPTOR ConflictingResource, _Out_ PULONG ConflictCount, _Out_ PARBITER_CONFLICT_INFO *Conflicts)
Definition: arbiter.c:80
NTSTATUS NTAPI ArbCommitAllocation(_In_ PARBITER_INSTANCE Arbiter)
Definition: arbiter.c:113
BOOLEAN NTAPI ArbOverrideConflict(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:250
NTSTATUS NTAPI ArbPreprocessEntry(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:150
NTSTATUS NTAPI ArbTestAllocation(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PLIST_ENTRY ArbitrationList)
Definition: arbiter.c:27
NTSTATUS NTAPI ArbInitializeOrderingList(_Out_ PARBITER_ORDERING_LIST OrderingList)
Definition: arbiter.c:277
#define TAG_ARBITER
Definition: arbiter.c:18
NTSTATUS NTAPI ArbStartArbiter(_In_ PARBITER_INSTANCE Arbiter, _In_ PCM_RESOURCE_LIST StartResources)
Definition: arbiter.c:137
NTSTATUS NTAPI ArbAddReserved(_In_ PARBITER_INSTANCE Arbiter, _In_opt_ PIO_RESOURCE_DESCRIPTOR Requirement, _In_opt_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource)
Definition: arbiter.c:66
VOID NTAPI ArbBacktrackAllocation(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:226
NTSTATUS NTAPI ArbBootAllocation(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PLIST_ENTRY ArbitrationList)
Definition: arbiter.c:53
NTSTATUS NTAPI ArbAllocateEntry(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:163
NTSTATUS NTAPI ArbRetestAllocation(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PLIST_ENTRY ArbitrationList)
Definition: arbiter.c:40
VOID NTAPI ArbFreeOrderingList(_Inout_ PARBITER_ORDERING_LIST OrderingList)
Definition: arbiter.c:289
NTSTATUS NTAPI ArbInitializeArbiterInstance(_Inout_ PARBITER_INSTANCE Arbiter, _In_ PDEVICE_OBJECT BusDeviceObject, _In_ CM_RESOURCE_TYPE ResourceType, _In_ PCWSTR ArbiterName, _In_ PCWSTR OrderName, _In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
Definition: arbiter.c:400
NTSTATUS NTAPI ArbPruneOrdering(_Inout_ PARBITER_ORDERING_LIST OrderingList, _In_ UINT64 Start, _In_ UINT64 End)
Definition: arbiter.c:327
NTSTATUS NTAPI ArbAddOrdering(_Inout_ PARBITER_ORDERING_LIST OrderingList, _In_ UINT64 Start, _In_ UINT64 End)
Definition: arbiter.c:313
NTSTATUS NTAPI ArbSortArbitrationList(_Inout_ PLIST_ENTRY ArbitrationList)
Definition: arbiter.c:176
#define ARBITER_SIG
Definition: arbiter.c:17
NTSTATUS NTAPI ArbBuildAssignmentOrdering(_Inout_ PARBITER_INSTANCE Arbiter, _In_ PCWSTR AllocationOrderName, _In_ PCWSTR ReservedResourcesName, _In_opt_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
Definition: arbiter.c:341
NTSTATUS NTAPI ArbRollbackAllocation(_In_ PARBITER_INSTANCE Arbiter)
Definition: arbiter.c:125
NTSTATUS(NTAPI * PARB_TRANSLATE_ORDERING)(_Out_ PIO_RESOURCE_DESCRIPTOR OutIoDescriptor, _In_ PIO_RESOURCE_DESCRIPTOR IoDescriptor)
Definition: arbiter.h:224
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
_Acquires_exclusive_lock_ Resource _Acquires_shared_lock_ Resource _Inout_ PERESOURCE Resource
Definition: cdprocs.h:843
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define NonPagedPool
Definition: env_spec_w32.h:307
#define PagedPool
Definition: env_spec_w32.h:308
return pTarget Start()
Status
Definition: gdiplustypes.h:24
static ULONG ResourceCount
Definition: inbv.c:50
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:3051
NTSYSAPI VOID NTAPI RtlInitializeRangeList(_Out_ PRTL_RANGE_LIST RangeList)
NTSYSAPI VOID NTAPI RtlFreeRangeList(_In_ PRTL_RANGE_LIST RangeList)
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
@ NotificationEvent
@ SynchronizationEvent
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
_In_ PVOID Context
Definition: storport.h:2269
Definition: typedefs.h:120
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:869
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:510
enum _ARBITER_ACTION ARBITER_ACTION