ReactOS 0.4.17-dev-683-g0dafdc5
arbiter.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Arbitration 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
19CODE_SEG("PAGE")
22#if (NTDDI_VERSION >= NTDDI_VISTA)
24 _In_ PARBITER_INSTANCE Arbiter,
26#else
28 _In_ PARBITER_INSTANCE Arbiter,
29 _Inout_ PLIST_ENTRY ArbitrationList)
30#endif
31{
32 PAGED_CODE();
33
36}
37
38CODE_SEG("PAGE")
41#if (NTDDI_VERSION >= NTDDI_VISTA)
43 _In_ PARBITER_INSTANCE Arbiter,
45#else
47 _In_ PARBITER_INSTANCE Arbiter,
48 _Inout_ PLIST_ENTRY ArbitrationList)
49#endif
50{
51 PAGED_CODE();
52
55}
56
57CODE_SEG("PAGE")
60#if (NTDDI_VERSION >= NTDDI_VISTA)
62 _In_ PARBITER_INSTANCE Arbiter,
64#else
66 _In_ PARBITER_INSTANCE Arbiter,
67 _Inout_ PLIST_ENTRY ArbitrationList)
68#endif
69{
70 PAGED_CODE();
71
74}
75
76CODE_SEG("PAGE")
79#if (NTDDI_VERSION >= NTDDI_VISTA)
81 _In_ PARBITER_INSTANCE Arbiter,
83#else
85 _In_ PARBITER_INSTANCE Arbiter,
88#endif
89{
90 PAGED_CODE();
91
94}
95
96CODE_SEG("PAGE")
99#if (NTDDI_VERSION >= NTDDI_VISTA)
101 _In_ PARBITER_INSTANCE Arbiter,
103#else
105 _In_ PARBITER_INSTANCE Arbiter,
107 _In_ PIO_RESOURCE_DESCRIPTOR ConflictingResource,
108 _Out_ PULONG ConflictCount,
109 _Out_ PARBITER_CONFLICT_INFO *Conflicts)
110#endif
111{
112 PAGED_CODE();
113
116}
117
118#if (NTDDI_VERSION >= NTDDI_VISTA)
119CODE_SEG("PAGE")
121NTAPI
123 _In_ PARBITER_INSTANCE Arbiter,
126 _Inout_ PRTL_RANGE_LIST RangeList)
127{
128 PAGED_CODE();
129
132}
133#endif
134
135CODE_SEG("PAGE")
137NTAPI
139 _In_ PARBITER_INSTANCE Arbiter)
140{
141 PAGED_CODE();
142
145}
146
147CODE_SEG("PAGE")
149NTAPI
151 _In_ PARBITER_INSTANCE Arbiter)
152{
153 PAGED_CODE();
154
157}
158
159CODE_SEG("PAGE")
161NTAPI
163 _In_ PARBITER_INSTANCE Arbiter,
164 _In_ PCM_RESOURCE_LIST StartResources)
165{
166 PAGED_CODE();
167
170}
171
172CODE_SEG("PAGE")
174NTAPI
176 _In_ PARBITER_INSTANCE Arbiter,
178{
179 PAGED_CODE();
180
182 return STATUS_SUCCESS;
183}
184
185CODE_SEG("PAGE")
187NTAPI
189 _In_ PARBITER_INSTANCE Arbiter,
191{
192 PAGED_CODE();
193
196}
197
198CODE_SEG("PAGE")
200NTAPI
202 _Inout_ PLIST_ENTRY ArbitrationList)
203{
204 PAGED_CODE();
205
208}
209
210CODE_SEG("PAGE")
212NTAPI
214 _In_ PARBITER_INSTANCE Arbiter,
216{
217 PAGED_CODE();
218
220 return FALSE;
221}
222
223CODE_SEG("PAGE")
225NTAPI
227 _In_ PARBITER_INSTANCE Arbiter,
229{
230 PAGED_CODE();
231
233 return FALSE;
234}
235
236CODE_SEG("PAGE")
237VOID
238NTAPI
240 _In_ PARBITER_INSTANCE Arbiter,
242{
243 PAGED_CODE();
244
246}
247
248CODE_SEG("PAGE")
249VOID
250NTAPI
252 _In_ PARBITER_INSTANCE Arbiter,
254{
255 PAGED_CODE();
256
258}
259
260CODE_SEG("PAGE")
261VOID
262NTAPI
264 _In_ PARBITER_INSTANCE Arbiter,
266{
267 PAGED_CODE();
268
270}
271
272CODE_SEG("PAGE")
274NTAPI
276 _In_ PARBITER_INSTANCE Arbiter,
278{
279 PAGED_CODE();
280
282 return FALSE;
283}
284
285CODE_SEG("PAGE")
287NTAPI
292{
293 PAGED_CODE();
294
297}
298
299CODE_SEG("PAGE")
300VOID
301NTAPI
303 _In_ PARBITER_INSTANCE Arbiter)
304{
305 PAGED_CODE();
306
307 if (Arbiter->PossibleAllocation)
308 {
309 RtlFreeRangeList(Arbiter->PossibleAllocation);
310 ExFreePoolWithTag(Arbiter->PossibleAllocation, TAG_ARBITER);
311 Arbiter->PossibleAllocation = NULL;
312 }
313
314 if (Arbiter->Allocation)
315 {
316 RtlFreeRangeList(Arbiter->Allocation);
317 ExFreePoolWithTag(Arbiter->Allocation, TAG_ARBITER);
318 Arbiter->Allocation = NULL;
319 }
320
321 if (Arbiter->AllocationStack)
322 {
323 ExFreePoolWithTag(Arbiter->AllocationStack, TAG_ARBITER);
324 Arbiter->AllocationStack = NULL;
325 Arbiter->AllocationStackMaxSize = 0;
326 }
327
328 ArbiterLibFreeOrderingList(&Arbiter->OrderingList);
329 ArbiterLibFreeOrderingList(&Arbiter->ReservedList);
330
331#if (NTDDI_VERSION >= NTDDI_VISTA)
332 if (Arbiter->TransactionEvent)
333 {
334 ExFreePoolWithTag(Arbiter->TransactionEvent, TAG_ARBITER);
335 Arbiter->TransactionEvent = NULL;
336 }
337#endif
338
339 if (Arbiter->MutexEvent)
340 {
341 ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
342 Arbiter->MutexEvent = NULL;
343 }
344}
345
346CODE_SEG("PAGE")
348NTAPI
351 _In_ PDEVICE_OBJECT BusDeviceObject,
352 _In_ CM_RESOURCE_TYPE ResourceType,
353 _In_ PCWSTR ArbiterName,
354 _In_ PCWSTR OrderName,
355 _In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
356{
358
359 PAGED_CODE();
360
361 DPRINT("ArbiterLibInitializeInstance: '%S'\n", ArbiterName);
362
363 ASSERT(Arbiter->UnpackRequirement != NULL);
364 ASSERT(Arbiter->PackResource != NULL);
365 ASSERT(Arbiter->UnpackResource != NULL);
366 ASSERT(Arbiter->MutexEvent == NULL);
367 ASSERT(Arbiter->Allocation == NULL);
368 ASSERT(Arbiter->PossibleAllocation == NULL);
369 ASSERT(Arbiter->AllocationStack == NULL);
370
371 Arbiter->Signature = ARBITER_SIG;
372 Arbiter->BusDeviceObject = BusDeviceObject;
373 Arbiter->Name = ArbiterName;
374 Arbiter->ResourceType = ResourceType;
375 Arbiter->TransactionInProgress = FALSE;
376#if (NTDDI_VERSION >= NTDDI_VISTA)
377 Arbiter->OrderingName = OrderName;
378#endif
379
380 /* The per-instance lock: a signaled synchronization event used as a mutex. */
381 Arbiter->MutexEvent = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_ARBITER);
382 if (!Arbiter->MutexEvent)
383 {
385 goto Failure;
386 }
387 KeInitializeEvent(Arbiter->MutexEvent, SynchronizationEvent, TRUE);
388
389#if (NTDDI_VERSION >= NTDDI_VISTA)
390 /* Vista+: a notification event exposing whether a Test is outstanding. */
391 Arbiter->TransactionEvent = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_ARBITER);
392 if (!Arbiter->TransactionEvent)
393 {
395 goto Failure;
396 }
397 KeInitializeEvent(Arbiter->TransactionEvent, NotificationEvent, TRUE);
398#endif
399
400 Arbiter->AllocationStack = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, TAG_ARBITER);
401 if (!Arbiter->AllocationStack)
402 {
404 goto Failure;
405 }
406 Arbiter->AllocationStackMaxSize = PAGE_SIZE;
407 Arbiter->Allocation = ExAllocatePoolWithTag(PagedPool, sizeof(RTL_RANGE_LIST), TAG_ARBITER);
408 if (!Arbiter->Allocation)
409 {
411 goto Failure;
412 }
413 RtlInitializeRangeList(Arbiter->Allocation);
414
415 Arbiter->PossibleAllocation = ExAllocatePoolWithTag(PagedPool, sizeof(RTL_RANGE_LIST), TAG_ARBITER);
416 if (!Arbiter->PossibleAllocation)
417 {
419 goto Failure;
420 }
421 RtlInitializeRangeList(Arbiter->PossibleAllocation);
422
423 if (!Arbiter->TestAllocation)
424 Arbiter->TestAllocation = ArbiterLibTestAllocation;
425 if (!Arbiter->RetestAllocation)
426 Arbiter->RetestAllocation = ArbiterLibRetestAllocation;
427 if (!Arbiter->CommitAllocation)
428 Arbiter->CommitAllocation = ArbiterLibCommitAllocation;
429 if (!Arbiter->RollbackAllocation)
430 Arbiter->RollbackAllocation = ArbiterLibRollbackAllocation;
431 if (!Arbiter->BootAllocation)
432 Arbiter->BootAllocation = ArbiterLibBootAllocation;
433 if (!Arbiter->AddReserved)
434 Arbiter->AddReserved = ArbiterLibAddReserved;
435 if (!Arbiter->QueryConflict)
436 Arbiter->QueryConflict = ArbiterLibQueryConflict;
437 if (!Arbiter->StartArbiter)
438 Arbiter->StartArbiter = ArbiterLibStartArbiter;
439 if (!Arbiter->PreprocessEntry)
440 Arbiter->PreprocessEntry = ArbiterLibPreprocessEntry;
441 if (!Arbiter->AllocateEntry)
442 Arbiter->AllocateEntry = ArbiterLibAllocateEntry;
443 if (!Arbiter->GetNextAllocationRange)
444 Arbiter->GetNextAllocationRange = ArbiterLibGetNextAllocationRange;
445 if (!Arbiter->FindSuitableRange)
446 Arbiter->FindSuitableRange = ArbiterLibFindSuitableRange;
447 if (!Arbiter->AddAllocation)
448 Arbiter->AddAllocation = ArbiterLibAddAllocation;
449 if (!Arbiter->BacktrackAllocation)
450 Arbiter->BacktrackAllocation = ArbiterLibBacktrackAllocation;
451 if (!Arbiter->OverrideConflict)
452 Arbiter->OverrideConflict = ArbiterLibOverrideConflict;
453#if (NTDDI_VERSION >= NTDDI_VISTA)
454 if (!Arbiter->InitializeRangeList)
455 Arbiter->InitializeRangeList = ArbiterLibInitializeRangeList;
456#endif
457
458 Status = ArbiterLibDefaultAssignmentOrdering(Arbiter, OrderName, OrderName, TranslateOrderingFunction);
459 if (!NT_SUCCESS(Status))
460 {
461 DPRINT1("ArbiterLibInitializeInstance: ArbiterLibDefaultAssignmentOrdering failed, Status %X\n", Status);
462 goto Failure;
463 }
464
465 return STATUS_SUCCESS;
466
467Failure:
468 DPRINT1("ArbiterLibInitializeInstance: '%S' failed, Status %X\n", ArbiterName, Status);
470 return Status;
471}
#define PAGED_CODE()
#define CODE_SEG(...)
unsigned char BOOLEAN
Definition: actypes.h:127
NTSTATUS NTAPI ArbiterLibBootAllocation(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_BOOT_ALLOCATION_PARAMETERS Parameters)
Definition: arbiter.c:61
BOOLEAN NTAPI ArbiterLibGetNextAllocationRange(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:213
NTSTATUS NTAPI ArbiterLibInitializeRangeList(_In_ PARBITER_INSTANCE Arbiter, _In_ ULONG ResourceCount, _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Resources, _Inout_ PRTL_RANGE_LIST RangeList)
Definition: arbiter.c:122
NTSTATUS NTAPI ArbiterLibAllocateEntry(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:188
VOID NTAPI ArbiterLibConfirmAllocation(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:263
NTSTATUS NTAPI ArbiterLibRetestAllocation(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_RETEST_ALLOCATION_PARAMETERS Parameters)
Definition: arbiter.c:42
NTSTATUS NTAPI ArbiterLibTestAllocation(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_TEST_ALLOCATION_PARAMETERS Parameters)
Definition: arbiter.c:23
NTSTATUS NTAPI ArbiterLibAddReserved(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ADD_RESERVED_PARAMETERS Parameters)
Definition: arbiter.c:80
VOID NTAPI ArbiterLibBacktrackAllocation(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:251
BOOLEAN NTAPI ArbiterLibFindSuitableRange(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:226
NTSTATUS NTAPI ArbiterLibCommitAllocation(_In_ PARBITER_INSTANCE Arbiter)
Definition: arbiter.c:138
VOID NTAPI ArbiterLibDeleteInstance(_In_ PARBITER_INSTANCE Arbiter)
Definition: arbiter.c:302
NTSTATUS NTAPI ArbiterLibRollbackAllocation(_In_ PARBITER_INSTANCE Arbiter)
Definition: arbiter.c:150
NTSTATUS NTAPI ArbiterLibSortArbitrationList(_Inout_ PLIST_ENTRY ArbitrationList)
Definition: arbiter.c:201
NTSTATUS NTAPI ArbiterLibPreprocessEntry(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:175
NTSTATUS NTAPI ArbiterLibStartArbiter(_In_ PARBITER_INSTANCE Arbiter, _In_ PCM_RESOURCE_LIST StartResources)
Definition: arbiter.c:162
BOOLEAN NTAPI ArbiterLibOverrideConflict(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:275
NTSTATUS NTAPI ArbiterLibHandler(_In_ PVOID Context, _In_ ARBITER_ACTION Action, _Inout_ PARBITER_PARAMETERS Parameters)
Definition: arbiter.c:288
#define ARBITER_SIG
Definition: arbiter.c:17
VOID NTAPI ArbiterLibAddAllocation(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Definition: arbiter.c:239
NTSTATUS NTAPI ArbiterLibInitializeInstance(_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:349
NTSTATUS NTAPI ArbiterLibQueryConflict(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_QUERY_CONFLICT_PARAMETERS Parameters)
Definition: arbiter.c:100
NTSTATUS(NTAPI * PARB_TRANSLATE_ORDERING)(_Out_ PIO_RESOURCE_DESCRIPTOR OutIoDescriptor, _In_ PIO_RESOURCE_DESCRIPTOR IoDescriptor)
Definition: arbiter.h:226
#define TAG_ARBITER
Definition: arbiter.h:10
NTSTATUS NTAPI ArbiterLibDefaultAssignmentOrdering(_Inout_ PARBITER_INSTANCE Arbiter, _In_ PCWSTR AllocationOrderName, _In_ PCWSTR ReservedResourcesName, _In_opt_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
Definition: ordering.c:328
VOID NTAPI ArbiterLibFreeOrderingList(_Inout_ PARBITER_ORDERING_LIST OrderingList)
Definition: ordering.c:52
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
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
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