ReactOS  0.4.13-dev-235-g7373cb3
resource.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: ntoskrnl/ex/resource.c
5  * PURPOSE: Executive Resource Implementation
6  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 /* Macros for reading resource flags */
16 #define IsExclusiveWaiting(r) (r->NumberOfExclusiveWaiters > 0)
17 #define IsSharedWaiting(r) (r->NumberOfSharedWaiters > 0)
18 #define IsOwnedExclusive(r) (r->Flag & ResourceOwnedExclusive)
19 #define IsBoostAllowed(r) (!(r->Flag & ResourceHasDisabledPriorityBoost))
20 
21 #if (!(defined(CONFIG_SMP)) && !(DBG))
22 
24 VOID
27 {
30 
31  /* Simply disable interrupts */
32  _disable();
33 }
34 
36 VOID
39 {
42 
43  /* Simply enable interrupts */
44  _enable();
45 }
46 
47 #else
48 
50 VOID
53 {
54  /* Acquire the lock */
56 }
57 
59 VOID
62 {
64 
65  /* Release the lock */
67 }
68 #endif
69 
70 /* DATA***********************************************************************/
71 
72 LARGE_INTEGER ExShortTime = {{-100000, -1}};
78 
79 /* PRIVATE FUNCTIONS *********************************************************/
80 
81 #if DBG
82 /*++
83  * @name ExpVerifyResource
84  *
85  * The ExpVerifyResource routine verifies the correctness of an ERESOURCE
86  *
87  * @param Resource
88  * Pointer to the resource being verified.
89  *
90  * @return None.
91  *
92  * @remarks Only present on DBG builds.
93  *
94  *--*/
95 VOID
96 NTAPI
98 {
99  /* Verify the resource data */
100  ASSERT((((ULONG_PTR)Resource) & (sizeof(ULONG_PTR) - 1)) == 0);
101  ASSERT(!Resource->SharedWaiters ||
102  Resource->SharedWaiters->Header.Type == SemaphoreObject);
103  ASSERT(!Resource->SharedWaiters ||
104  Resource->SharedWaiters->Header.Size == (sizeof(KSEMAPHORE) / sizeof(ULONG)));
105  ASSERT(!Resource->ExclusiveWaiters ||
106  Resource->ExclusiveWaiters->Header.Type == SynchronizationEvent);
107  ASSERT(!Resource->ExclusiveWaiters ||
108  Resource->ExclusiveWaiters->Header.Size == (sizeof(KEVENT) / sizeof(ULONG)));
109 }
110 
111 /*++
112  * @name ExpCheckForApcsDisabled
113  *
114  * The ExpCheckForApcsDisabled routine checks if Kernel APCs are still
115  * enabled when they should be disabled, and optionally breakpoints.
116  *
117  * @param Irql
118  * Specifies the IRQL during the acquire attempt.
119  *
120  * @param Resource
121  * Pointer to the resource being checked.
122  *
123  * @param Thread
124  * Pointer to the thread being checked.
125  *
126  * @return None.
127  *
128  * @remarks Only present on DBG builds. Depends on ExResourceStrict value.
129  *
130  *--*/
131 VOID
132 NTAPI
136 {
137  /* Check if we should care and check if we should break */
138  if ((ExResourceStrict) &&
139  (Irql < APC_LEVEL) &&
140  !(((PETHREAD)Thread)->SystemThread) &&
141  !(Thread->CombinedApcDisable))
142  {
143  /* Bad! */
144  DPRINT1("EX: resource: APCs still enabled before resource %p acquire/release "
145  "!!!\n", Resource);
146  DbgBreakPoint();
147  }
148 }
149 #else
150 #define ExpVerifyResource(r)
151 #define ExpCheckForApcsDisabled(b,r,t)
152 #endif
153 
154 /*++
155  * @name ExpResourceInitialization
156  *
157  * The ExpResourceInitialization routine initializes resources for use.
158  *
159  * @param None.
160  *
161  * @return None.
162  *
163  * @remarks This routine should only be called once, during system startup.
164  *
165  *--*/
166 INIT_FUNCTION
167 VOID
168 NTAPI
170 {
171  /* Setup the timeout */
172  ExpTimeout.QuadPart = Int32x32To64(4, -10000000);
175 }
176 
177 /*++
178  * @name ExpAllocateExclusiveWaiterEvent
179  *
180  * The ExpAllocateExclusiveWaiterEvent routine creates the event that will
181  * be used by exclusive waiters on the resource.
182  *
183  * @param Resource
184  * Pointer to the resource.
185  *
186  * @param LockHandle
187  * Pointer to in-stack queued spinlock.
188  *
189  * @return None.
190  *
191  * @remarks The pointer to the event must be atomically set.
192  *
193  *--*/
194 VOID
195 NTAPI
198 {
199  PKEVENT Event;
200 
201  /* Release the lock */
203 
204  /* Loop as long as we keep running out of memory */
205  do
206  {
207  /* Allocate the event */
209  sizeof(KEVENT),
211  if (Event)
212  {
213  /* Initialize it */
215 
216  /* Set it */
217  if (InterlockedCompareExchangePointer((PVOID*)&Resource->ExclusiveWaiters,
218  Event,
219  NULL))
220  {
221  /* Someone already set it, free our event */
222  DPRINT1("WARNING: Handling race condition\n");
224  }
225 
226  break;
227  }
228 
229  /* Wait a bit before trying again */
231  } while (TRUE);
232 
233  /* Re-acquire the lock */
235 }
236 
237 /*++
238  * @name ExpAllocateSharedWaiterSemaphore
239  *
240  * The ExpAllocateSharedWaiterSemaphore routine creates the semaphore that
241  * will be used by shared waiters on the resource.
242  *
243  * @param Resource
244  * Pointer to the resource.
245  *
246  * @param LockHandle
247  * Pointer to in-stack queued spinlock.
248  *
249  * @return None.
250  *
251  * @remarks The pointer to the semaphore must be atomically set.
252  *
253  *--*/
254 VOID
255 NTAPI
258 {
259  PKSEMAPHORE Semaphore;
260 
261  /* Release the lock */
263 
264  /* Loop as long as we keep running out of memory */
265  do
266  {
267  /* Allocate the semaphore */
269  sizeof(KSEMAPHORE),
271  if (Semaphore)
272  {
273  /* Initialize it */
274  KeInitializeSemaphore(Semaphore, 0, MAXLONG);
275 
276  /* Set it */
277  if (InterlockedCompareExchangePointer((PVOID*)&Resource->SharedWaiters,
278  Semaphore,
279  NULL))
280  {
281  /* Someone already set it, free our semaphore */
282  DPRINT1("WARNING: Handling race condition\n");
284  }
285 
286  break;
287  }
288 
289  /* Wait a bit before trying again */
291  } while (TRUE);
292 
293  /* Re-acquire the lock */
295 }
296 
297 /*++
298  * @name ExpExpandResourceOwnerTable
299  *
300  * The ExpExpandResourceOwnerTable routine expands the owner table of the
301  * specified resource.
302  *
303  * @param Resource
304  * Pointer to the resource.
305  *
306  * @param LockHandle
307  * Pointer to in-stack queued spinlock.
308  *
309  * @return None.
310  *
311  * @remarks None.
312  *
313  *--*/
314 VOID
315 NTAPI
318 {
320  KIRQL OldIrql;
321  ULONG NewSize, OldSize;
322 
323  /* Get the owner table */
324  Owner = Resource->OwnerTable;
325  if (!Owner)
326  {
327  /* Start with the default size of 3 */
328  OldSize = 0;
329  NewSize = 3;
330  }
331  else
332  {
333  /* Add 4 more entries */
334  OldSize = Owner->TableSize;
335  NewSize = OldSize + 4;
336  }
337 
338  /* Release the lock */
340 
341  /* Allocate memory for the table */
343  NewSize * sizeof(OWNER_ENTRY),
345 
346  /* Zero the table */
347  RtlZeroMemory(Table + OldSize,
348  (NewSize - OldSize) * sizeof(OWNER_ENTRY));
349 
350  /* Lock the resource */
352 
353  /* Make sure nothing has changed */
354  if ((Owner != Resource->OwnerTable) ||
355  ((Owner) && (OldSize != Owner->TableSize)))
356  {
357  /* Resource changed while we weren't holding the lock; bail out */
360  }
361  else
362  {
363  /* Copy the table */
364  if (Owner) RtlCopyMemory(Table, Owner, OldSize * sizeof(OWNER_ENTRY));
365 
366  /* Acquire dispatcher lock to prevent thread boosting */
368 
369  /* Set the new table data */
370  Table->TableSize = NewSize;
371  Resource->OwnerTable = Table;
372 
373  /* Release dispatcher lock */
375 
376  /* Sanity check */
378 
379  /* Release lock */
381 
382  /* Free the old table */
384 
385  /* Set the resource index */
386  if (!OldSize) OldSize = 1;
387  }
388 
389  /* Set the resource index */
390  KeGetCurrentThread()->ResourceIndex = (UCHAR)OldSize;
391 
392  /* Lock the resource again */
394 }
395 
396 /*++
397  * @name ExpFindFreeEntry
398  *
399  * The ExpFindFreeEntry routine locates an empty owner entry in the
400  * specified resource. If none was found, then the owner table is
401  * expanded.
402  *
403  * @param Resource
404  * Pointer to the resource.
405  *
406  * @param LockHandle
407  * Pointer to in-stack queued spinlock.
408  *
409  * @return Pointer to an empty OWNER_ENTRY structure.
410  *
411  * @remarks None.
412  *
413  *--*/
415 FASTCALL
418 {
420 
421  /* Sanity check */
422  ASSERT(LockHandle != 0);
423  ASSERT(Resource->OwnerEntry.OwnerThread != 0);
424 
425  /* Get the current table pointer */
426  Owner = Resource->OwnerTable;
427  if (Owner)
428  {
429  /* Set the limit, move to the next owner and loop owner entries */
430  Limit = &Owner[Owner->TableSize];
431  Owner++;
432  while (Owner->OwnerThread)
433  {
434  /* Move to the next one */
435  Owner++;
436 
437  /* Check if the entry is free */
438  if (Owner == Limit) goto Expand;
439  }
440 
441  /* Update the resource entry */
442  KeGetCurrentThread()->ResourceIndex = (UCHAR)(Owner - Resource->OwnerTable);
443  }
444  else
445  {
446 Expand:
447  /* No free entry, expand the table */
449  Owner = NULL;
450  }
451 
452  /* Return the entry found */
453  return Owner;
454 }
455 
456 /*++
457  * @name ExpFindEntryForThread
458  *
459  * The ExpFindEntryForThread routine locates the owner entry associated with
460  * the specified thread in the given resource. If none was found, then the
461  * owner table is expanded.
462  *
463  * @param Resource
464  * Pointer to the resource.
465  *
466  * @param Thread
467  * Pointer to the thread to find.
468  *
469  * @param LockHandle
470  * Pointer to in-stack queued spinlock.
471  *
472  * @return Pointer to an empty OWNER_ENTRY structure.
473  *
474  * @remarks None.
475  *
476  *--*/
478 FASTCALL
482  IN BOOLEAN FirstEntryInelligible)
483 {
484  POWNER_ENTRY FreeEntry, Owner, Limit;
485 
486  /* Start by looking in the static array */
487  Owner = &Resource->OwnerEntry;
488  if (Owner->OwnerThread == Thread) return Owner;
489 
490  /* Check if this is a free entry */
491  if ((FirstEntryInelligible) || (Owner->OwnerThread))
492  {
493  /* No free entry */
494  FreeEntry = NULL;
495  }
496  else
497  {
498  /* Use the first entry as our free entry */
499  FreeEntry = Owner;
500  }
501 
502  /* Get the current table pointer */
503  Owner = Resource->OwnerTable;
504  if (Owner)
505  {
506  /* Set the limit, move to the next owner and loop owner entries */
507  Limit = &Owner[Owner->TableSize];
508  Owner++;
509  while (Owner->OwnerThread != Thread)
510  {
511  /* Check if we don't have a free entry */
512  if (!FreeEntry)
513  {
514  /* Check if this entry is free */
515  if (!Owner->OwnerThread)
516  {
517  /* Save it as our free entry */
518  FreeEntry = Owner;
519  }
520  }
521 
522  /* Move to the next one */
523  Owner++;
524 
525  /* Check if the entry is free */
526  if (Owner == Limit) goto Expand;
527  }
528 
529  /* Update the resource entry */
530  KeGetCurrentThread()->ResourceIndex = (UCHAR)(Owner - Resource->OwnerTable);
531  return Owner;
532  }
533  else
534  {
535 Expand:
536  /* Check if it's OK to do an expansion */
537  if (!LockHandle) return NULL;
538 
539  /* If we found a free entry by now, return it */
540  if (FreeEntry)
541  {
542  /* Set the resource index */
543  KeGetCurrentThread()->ResourceIndex = (UCHAR)(FreeEntry - Resource->OwnerTable);
544  return FreeEntry;
545  }
546 
547  /* No free entry, expand the table */
549  return NULL;
550  }
551 }
552 
553 /*++
554  * @name ExpBoostOwnerThread
555  *
556  * The ExpBoostOwnerThread routine increases the priority of a waiting
557  * thread in an attempt to fight a possible deadlock.
558  *
559  * @param Thread
560  * Pointer to the current thread.
561  *
562  * @param OwnerThread
563  * Pointer to thread that owns the resource.
564  *
565  * @return None.
566  *
567  * @remarks None.
568  *
569  *--*/
570 VOID
571 FASTCALL
573  IN PKTHREAD OwnerThread)
574 {
575  /* Make sure the owner thread is a pointer, not an ID */
576  if (!((ULONG_PTR)OwnerThread & 0x3))
577  {
578  /* Check if we can actually boost it */
579  if ((OwnerThread->Priority < Thread->Priority) &&
580  (OwnerThread->Priority < 14))
581  {
582  /* Acquire the thread lock */
584 
585  /* Set the new priority */
586  OwnerThread->PriorityDecrement += 14 - OwnerThread->Priority;
587 
588  /* Update quantum */
589  OwnerThread->Quantum = OwnerThread->QuantumReset;
590 
591  /* Update the kernel state */
592  KiSetPriorityThread(OwnerThread, 14);
593 
594  /* Release the thread lock */
596  }
597  }
598 }
599 
600 /*++
601  * @name ExpWaitForResource
602  *
603  * The ExpWaitForResource routine performs a wait on the specified resource.
604  *
605  * @param Resource
606  * Pointer to the resource to wait on.
607  *
608  * @param OwnerThread
609  * Pointer to object (exclusive event or shared semaphore) to wait on.
610  *
611  * @return None.
612  *
613  * @remarks None.
614  *
615  *--*/
616 VOID
617 FASTCALL
619  IN PVOID Object)
620 {
621  ULONG i;
622  ULONG Size;
624  ULONG WaitCount = 0;
627  PKTHREAD Thread, OwnerThread;
628 #if DBG
630 #endif
631 
632  /* Increase contention count and use a 5 second timeout */
633  Resource->ContentionCount++;
634  Timeout.QuadPart = 500 * -10000;
635  for (;;)
636  {
637  /* Wait for ownership */
639  WrResource,
640  KernelMode,
641  FALSE,
642  &Timeout);
643  if (Status != STATUS_TIMEOUT) break;
644 
645  /* Increase wait count */
646  WaitCount++;
648 
649  /* Check if we've exceeded the limit */
650  if (WaitCount > ExpResourceTimeoutCount)
651  {
652  /* Reset wait count */
653  WaitCount = 0;
654 #if DBG
655  /* Lock the resource */
657 
658  /* Dump debug information */
659  DPRINT1("Resource @ %p\n", Resource);
660  DPRINT1(" ActiveEntries = %04lx Flags = %s%s%s\n",
661  Resource->ActiveEntries,
662  IsOwnedExclusive(Resource) ? "IsOwnedExclusive " : "",
663  IsSharedWaiting(Resource) ? "SharedWaiter " : "",
664  IsExclusiveWaiting(Resource) ? "ExclusiveWaiter " : "");
665  DPRINT1(" NumberOfExclusiveWaiters = %04lx\n",
666  Resource->NumberOfExclusiveWaiters);
667  DPRINT1(" Thread = %08lx, Count = %02x\n",
668  Resource->OwnerEntry.OwnerThread,
669  Resource->OwnerEntry.OwnerCount);
670 
671  /* Dump out the table too */
672  Owner = Resource->OwnerTable;
673  if (Owner)
674  {
675  /* Loop every entry */
676  Size = Owner->TableSize;
677  for (i = 1; i < Size; i++)
678  {
679  /* Print the data */
680  Owner++;
681  DPRINT1(" Thread = %08lx, Count = %02x\n",
682  Owner->OwnerThread,
683  Owner->OwnerCount);
684  }
685  }
686 
687  /* Break */
688  DbgBreakPoint();
689  DPRINT1("EX - Rewaiting\n");
691 #endif
692  }
693 
694  /* Check if we can boost */
696  {
697  /* Get the current kernel thread and lock the dispatcher */
699  Thread->WaitIrql = KiAcquireDispatcherLock();
700  Thread->WaitNext = TRUE;
701 
702  /* Get the owner thread and boost it */
703  OwnerThread = (PKTHREAD)Resource->OwnerEntry.OwnerThread;
704  if (OwnerThread) ExpBoostOwnerThread(Thread, OwnerThread);
705 
706  /* If it's a shared resource */
708  {
709  /* Get the table */
710  Owner = Resource->OwnerTable;
711  if (Owner)
712  {
713  /* Loop every entry */
714  Size = Owner->TableSize;
715  for (i = 1; i < Size; i++)
716  {
717  /* Move to next entry */
718  Owner++;
719 
720  /* Get the thread */
721  OwnerThread = (PKTHREAD)Owner->OwnerThread;
722 
723  /* Boost it */
724  if (OwnerThread) ExpBoostOwnerThread(Thread, OwnerThread);
725  }
726  }
727  }
728  }
729  }
730 }
731 
732 /* FUNCTIONS *****************************************************************/
733 
734 /*++
735  * @name ExAcquireResourceExclusiveLite
736  * @implemented NT4
737  *
738  * The ExAcquireResourceExclusiveLite routine acquires the given resource
739  * for exclusive access by the calling thread.
740  *
741  * @param Resource
742  * Pointer to the resource to acquire.
743  *
744  * @param Wait
745  * Specifies the routine's behavior whenever the resource cannot be
746  * acquired immediately.
747  *
748  * @return TRUE if the resource is acquired. FALSE if the input Wait is FALSE
749  * and exclusive access cannot be granted immediately.
750  *
751  * @remarks The caller can release the resource by calling either
752  * ExReleaseResourceLite or ExReleaseResourceForThreadLite.
753  *
754  * Normal kernel APC delivery must be disabled before calling this
755  * routine. Disable normal kernel APC delivery by calling
756  * KeEnterCriticalRegion. Delivery must remain disabled until the
757  * resource is released, at which point it can be reenabled by calling
758  * KeLeaveCriticalRegion.
759  *
760  * For better performance, call ExTryToAcquireResourceExclusiveLite,
761  * rather than calling ExAcquireResourceExclusiveLite with Wait set
762  * to FALSE.
763  *
764  * Callers of ExAcquireResourceExclusiveLite must be running at IRQL <
765  * DISPATCH_LEVEL.
766  *
767  *--*/
768 BOOLEAN
769 NTAPI
771  IN BOOLEAN Wait)
772 {
776 
777  /* Sanity check */
778  ASSERT((Resource->Flag & ResourceNeverExclusive) == 0);
779 
780  /* Get the thread */
782 
783  /* Sanity check and validation */
786 
787  /* Acquire the lock */
790 
791  /* Check if there is a shared owner or exclusive owner */
792 TryAcquire:
793  if (Resource->ActiveEntries)
794  {
795  /* Check if it's exclusively owned, and we own it */
796  if ((IsOwnedExclusive(Resource)) &&
797  (Resource->OwnerEntry.OwnerThread == Thread))
798  {
799  /* Increase the owning count */
800  Resource->OwnerEntry.OwnerCount++;
801  Success = TRUE;
802  }
803  else
804  {
805  /*
806  * If the caller doesn't want us to wait, we can't acquire the
807  * resource because someone else then us owns it. If we can wait,
808  * then we'll wait.
809  */
810  if (!Wait)
811  {
812  Success = FALSE;
813  }
814  else
815  {
816  /* Check if it has exclusive waiters */
817  if (!Resource->ExclusiveWaiters)
818  {
819  /* It doesn't, allocate the event and try acquiring again */
821  goto TryAcquire;
822  }
823 
824  /* Has exclusive waiters, wait on it */
825  Resource->NumberOfExclusiveWaiters++;
827  ExpWaitForResource(Resource, Resource->ExclusiveWaiters);
828 
829  /* Set owner and return success */
830  Resource->OwnerEntry.OwnerThread = ExGetCurrentResourceThread();
831  return TRUE;
832  }
833  }
834  }
835  else
836  {
837  /* Nobody owns it, so let's! */
838  ASSERT(Resource->ActiveEntries == 0);
839  ASSERT(Resource->ActiveCount == 0);
841  Resource->ActiveEntries = 1;
842  Resource->ActiveCount = 1;
843  Resource->OwnerEntry.OwnerThread = Thread;
844  Resource->OwnerEntry.OwnerCount = 1;
845  Success = TRUE;
846  }
847 
848  /* Release the lock and return */
850  return Success;
851 }
852 
853 /*++
854  * @name ExAcquireResourceSharedLite
855  * @implemented NT4
856  *
857  * The ExAcquireResourceSharedLite routine acquires the given resource
858  * for shared access by the calling thread.
859  *
860  * @param Resource
861  * Pointer to the resource to acquire.
862  *
863  * @param Wait
864  * Specifies the routine's behavior whenever the resource cannot be
865  * acquired immediately.
866  *
867  * @return TRUE if the resource is acquired. FALSE if the input Wait is FALSE
868  * and exclusive access cannot be granted immediately.
869  *
870  * @remarks The caller can release the resource by calling either
871  * ExReleaseResourceLite or ExReleaseResourceForThreadLite.
872  *
873  * Normal kernel APC delivery must be disabled before calling this
874  * routine. Disable normal kernel APC delivery by calling
875  * KeEnterCriticalRegion. Delivery must remain disabled until the
876  * resource is released, at which point it can be reenabled by calling
877  * KeLeaveCriticalRegion.
878  *
879  * Callers of ExAcquireResourceExclusiveLite must be running at IRQL <
880  * DISPATCH_LEVEL.
881  *
882  *--*/
883 BOOLEAN
884 NTAPI
886  IN BOOLEAN Wait)
887 {
891  BOOLEAN FirstEntryBusy;
892 
893  /* Get the thread */
895 
896  /* Sanity check and validation */
899 
900  /* Acquire the lock */
903 
904  /* Check how many active entries we've got */
905  while (Resource->ActiveEntries != 0)
906  {
907  /* Check if it's exclusively owned */
909  {
910  /* Check if we own it */
911  if (Resource->OwnerEntry.OwnerThread == Thread)
912  {
913  /* Increase the owning count */
914  Resource->OwnerEntry.OwnerCount++;
915 
916  /* Release the lock and return */
918  return TRUE;
919  }
920 
921  /* Find a free entry */
923  if (!Owner) continue;
924  }
925  else
926  {
927  /* Resource is shared, find who owns it */
928  FirstEntryBusy = IsExclusiveWaiting(Resource);
930  Thread,
931  &LockHandle,
932  FirstEntryBusy);
933  if (!Owner) continue;
934 
935  /* Is it us? */
936  if (Owner->OwnerThread == Thread)
937  {
938  /* Increase acquire count and return */
939  Owner->OwnerCount++;
940  ASSERT(Owner->OwnerCount != 0);
941 
942  /* Release the lock and return */
944  return TRUE;
945  }
946 
947  /* Try to find if there are exclusive waiters */
948  if (!FirstEntryBusy)
949  {
950  /* There are none, so acquire it */
951  Owner->OwnerThread = Thread;
952  Owner->OwnerCount = 1;
953 
954  /* Check how many active entries we had */
955  if (Resource->ActiveEntries == 0)
956  {
957  /* Set initial counts */
958  ASSERT(Resource->ActiveCount == 0);
959  Resource->ActiveEntries = 1;
960  Resource->ActiveCount = 1;
961  }
962  else
963  {
964  /* Increase active entries */
965  ASSERT(Resource->ActiveCount == 1);
966  Resource->ActiveEntries++;
967  }
968 
969  /* Release the lock and return */
971  return TRUE;
972  }
973  }
974 
975  /* If we got here, then we need to wait. Are we allowed? */
976  if (!Wait)
977  {
978  /* Release the lock and return */
980  return FALSE;
981  }
982 
983  /* Check if we have a shared waiters semaphore */
984  if (!Resource->SharedWaiters)
985  {
986  /* Allocate it and try another acquire */
988  }
989  else
990  {
991  /* We have shared waiters, wait for it */
992  break;
993  }
994  }
995 
996  /* Did we get here because we don't have active entries? */
997  if (Resource->ActiveEntries == 0)
998  {
999  /* Acquire it */
1000  ASSERT(Resource->ActiveEntries == 0);
1001  ASSERT(Resource->ActiveCount == 0);
1002  Resource->ActiveEntries = 1;
1003  Resource->ActiveCount = 1;
1004  Resource->OwnerEntry.OwnerThread = Thread;
1005  Resource->OwnerEntry.OwnerCount = 1;
1006 
1007  /* Release the lock and return */
1009  return TRUE;
1010  }
1011 
1012  /* Now wait for the resource */
1013  Owner->OwnerThread = Thread;
1014  Owner->OwnerCount = 1;
1015  Resource->NumberOfSharedWaiters++;
1016 
1017  /* Release the lock and return */
1019  ExpWaitForResource(Resource, Resource->SharedWaiters);
1020  return TRUE;
1021 }
1022 
1023 /*++
1024  * @name ExAcquireSharedStarveExclusive
1025  * @implemented NT4
1026  *
1027  * The ExAcquireSharedStarveExclusive routine acquires the given resource
1028  * shared access without waiting for any pending attempts to acquire
1029  * exclusive access to the same resource.
1030  *
1031  * @param Resource
1032  * Pointer to the resource to acquire.
1033  *
1034  * @param Wait
1035  * Specifies the routine's behavior whenever the resource cannot be
1036  * acquired immediately.
1037  *
1038  * @return TRUE if the resource is acquired. FALSE if the input Wait is FALSE
1039  * and exclusive access cannot be granted immediately.
1040  *
1041  * @remarks The caller can release the resource by calling either
1042  * ExReleaseResourceLite or ExReleaseResourceForThreadLite.
1043  *
1044  * Normal kernel APC delivery must be disabled before calling this
1045  * routine. Disable normal kernel APC delivery by calling
1046  * KeEnterCriticalRegion. Delivery must remain disabled until the
1047  * resource is released, at which point it can be reenabled by calling
1048  * KeLeaveCriticalRegion.
1049  *
1050  * Callers of ExAcquireSharedStarveExclusive usually need quick access
1051  * to a shared resource in order to save an exclusive accessor from
1052  * doing redundant work. For example, a file system might call this
1053  * routine to modify a cached resource, such as a BCB pinned in the
1054  * cache, before the Cache Manager can acquire exclusive access to the
1055  * resource and write the cache out to disk.
1056  *
1057  * Callers of ExAcquireResourceExclusiveLite must be running at IRQL <
1058  * DISPATCH_LEVEL.
1059  *
1060  *--*/
1061 BOOLEAN
1062 NTAPI
1064  IN BOOLEAN Wait)
1065 {
1069 
1070  /* Get the thread */
1072 
1073  /* Sanity check and validation */
1076 
1077  /* Acquire the lock */
1079 
1080  /* See if anyone owns it */
1081 TryAcquire:
1082  if (Resource->ActiveEntries == 0)
1083  {
1084  /* Nobody owns it, so let's take control */
1085  ASSERT(Resource->ActiveEntries == 0);
1086  ASSERT(Resource->ActiveCount == 0);
1087  Resource->ActiveCount = 1;
1088  Resource->ActiveEntries = 1;
1089  Resource->OwnerEntry.OwnerThread = Thread;
1090  Resource->OwnerEntry.OwnerCount = 1;
1091 
1092  /* Release the lock and return */
1094  return TRUE;
1095  }
1096 
1097  /* Check if it's exclusively owned */
1099  {
1100  /* Check if we own it */
1101  if (Resource->OwnerEntry.OwnerThread == Thread)
1102  {
1103  /* Increase the owning count */
1104  Resource->OwnerEntry.OwnerCount++;
1105 
1106  /* Release the lock and return */
1108  return TRUE;
1109  }
1110 
1111  /* Find a free entry */
1113  if (!Owner) goto TryAcquire;
1114  }
1115  else
1116  {
1117  /* Resource is shared, find who owns it */
1119  if (!Owner) goto TryAcquire;
1120 
1121  /* Is it us? */
1122  if (Owner->OwnerThread == Thread)
1123  {
1124  /* Increase acquire count and return */
1125  Owner->OwnerCount++;
1126  ASSERT(Owner->OwnerCount != 0);
1127 
1128  /* Release the lock and return */
1130  return TRUE;
1131  }
1132 
1133  /* Acquire it */
1134  Owner->OwnerThread = Thread;
1135  Owner->OwnerCount = 1;
1136 
1137  /* Check how many active entries we had */
1138  if (Resource->ActiveEntries == 0)
1139  {
1140  /* Set initial counts */
1141  ASSERT(Resource->ActiveCount == 0);
1142  Resource->ActiveEntries = 1;
1143  Resource->ActiveCount = 1;
1144  }
1145  else
1146  {
1147  /* Increase active entries */
1148  ASSERT(Resource->ActiveCount == 1);
1149  Resource->ActiveEntries++;
1150  }
1151 
1152  /* Release the lock and return */
1154  return TRUE;
1155  }
1156 
1157  /* If we got here, then we need to wait. Are we allowed? */
1158  if (!Wait)
1159  {
1160  /* Release the lock and return */
1162  return FALSE;
1163  }
1164 
1165  /* Check if we have a shared waiters semaphore */
1166  if (!Resource->SharedWaiters)
1167  {
1168  /* Allocate it and try another acquire */
1170  goto TryAcquire;
1171  }
1172 
1173  /* Now wait for the resource */
1174  Owner->OwnerThread = Thread;
1175  Owner->OwnerCount = 1;
1176  Resource->NumberOfSharedWaiters++;
1177 
1178  /* Release the lock and return */
1180  ExpWaitForResource(Resource, Resource->SharedWaiters);
1181  return TRUE;
1182 }
1183 
1184 /*++
1185  * @name ExAcquireSharedWaitForExclusive
1186  * @implemented NT4
1187  *
1188  * The ExAcquireSharedWaitForExclusive routine acquires the given resource
1189  * for shared access if shared access can be granted and there are no
1190  * exclusive waiters.
1191  *
1192  * @param Resource
1193  * Pointer to the resource to acquire.
1194  *
1195  * @param Wait
1196  * Specifies the routine's behavior whenever the resource cannot be
1197  * acquired immediately.
1198  *
1199  * @return TRUE if the resource is acquired. FALSE if the input Wait is FALSE
1200  * and exclusive access cannot be granted immediately.
1201  *
1202  * @remarks The caller can release the resource by calling either
1203  * ExReleaseResourceLite or ExReleaseResourceForThreadLite.
1204  *
1205  * Normal kernel APC delivery must be disabled before calling this
1206  * routine. Disable normal kernel APC delivery by calling
1207  * KeEnterCriticalRegion. Delivery must remain disabled until the
1208  * resource is released, at which point it can be reenabled by calling
1209  * KeLeaveCriticalRegion.
1210  *
1211  * Callers of ExAcquireResourceExclusiveLite must be running at IRQL <
1212  * DISPATCH_LEVEL.
1213  *
1214  *--*/
1215 BOOLEAN
1216 NTAPI
1218  IN BOOLEAN Wait)
1219 {
1223 
1224  /* Get the thread */
1226 
1227  /* Sanity check and validation */
1230 
1231  /* Acquire the lock */
1233 
1234  /* See if nobody owns us */
1235 TryAcquire:
1236  if (!Resource->ActiveEntries)
1237  {
1238  /* Nobody owns it, so let's take control */
1239  ASSERT(Resource->ActiveEntries == 0);
1240  ASSERT(Resource->ActiveCount == 0);
1241  Resource->ActiveCount = 1;
1242  Resource->ActiveEntries = 1;
1243  Resource->OwnerEntry.OwnerThread = Thread;
1244  Resource->OwnerEntry.OwnerCount = 1;
1245 
1246  /* Release the lock and return */
1248  return TRUE;
1249  }
1250 
1251  /* Check if it's exclusively owned */
1253  {
1254  /* Check if we own it */
1255  if (Resource->OwnerEntry.OwnerThread == Thread)
1256  {
1257  /* Increase the owning count */
1258  Resource->OwnerEntry.OwnerCount++;
1259 
1260  /* Release the lock and return */
1262  return TRUE;
1263  }
1264 
1265  /* Find a free entry */
1267  if (!Owner) goto TryAcquire;
1268  }
1269  else
1270  {
1271  /* Try to find if there are exclusive waiters */
1273  {
1274  /* We have to wait for the exclusive waiter to be done */
1275  if (!Wait)
1276  {
1277  /* So bail out if we're not allowed */
1279  return FALSE;
1280  }
1281 
1282  /* Check if we have a shared waiters semaphore */
1283  if (!Resource->SharedWaiters)
1284  {
1285  /* Allocate one and try again */
1287  goto TryAcquire;
1288  }
1289 
1290  /* Now wait for the resource */
1291  Resource->NumberOfSharedWaiters++;
1293  ExpWaitForResource(Resource, Resource->SharedWaiters);
1294 
1295  /* Get the lock back */
1297 
1298  /* Find who owns it now */
1300 
1301  /* Sanity checks */
1303  ASSERT(Resource->ActiveEntries > 0);
1304  ASSERT(Owner->OwnerThread != Thread);
1305 
1306  /* Take control */
1307  Owner->OwnerThread = Thread;
1308  Owner->OwnerCount = 1;
1309 
1310  /* Release the lock and return */
1312  return TRUE;
1313  }
1314  else
1315  {
1316  /* Resource is shared, find who owns it */
1318  if (!Owner) goto TryAcquire;
1319 
1320  /* Is it us? */
1321  if (Owner->OwnerThread == Thread)
1322  {
1323  /* Increase acquire count and return */
1324  Owner->OwnerCount++;
1325  ASSERT(Owner->OwnerCount != 0);
1326 
1327  /* Release the lock and return */
1329  return TRUE;
1330  }
1331 
1332  /* No exclusive waiters, so acquire it */
1333  Owner->OwnerThread = Thread;
1334  Owner->OwnerCount = 1;
1335 
1336  /* Check how many active entries we had */
1337  if (Resource->ActiveEntries == 0)
1338  {
1339  /* Set initial counts */
1340  ASSERT(Resource->ActiveCount == 0);
1341  Resource->ActiveEntries = 1;
1342  Resource->ActiveCount = 1;
1343  }
1344  else
1345  {
1346  /* Increase active entries */
1347  ASSERT(Resource->ActiveCount == 1);
1348  Resource->ActiveEntries++;
1349  }
1350 
1351  /* Release the lock and return */
1353  return TRUE;
1354  }
1355  }
1356 
1357  /* We have to wait for the exclusive waiter to be done */
1358  if (!Wait)
1359  {
1360  /* So bail out if we're not allowed */
1362  return FALSE;
1363  }
1364 
1365  /* Check if we have a shared waiters semaphore */
1366  if (!Resource->SharedWaiters)
1367  {
1368  /* Allocate one and try again */
1370  goto TryAcquire;
1371  }
1372 
1373  /* Take control */
1374  Owner->OwnerThread = Thread;
1375  Owner->OwnerCount = 1;
1376  Resource->NumberOfSharedWaiters++;
1377 
1378  /* Release the lock and return */
1380  ExpWaitForResource(Resource, Resource->SharedWaiters);
1381  return TRUE;
1382 }
1383 
1384 /*++
1385  * @name ExConvertExclusiveToSharedLite
1386  * @implemented NT4
1387  *
1388  * The ExConvertExclusiveToSharedLite routine converts an exclusively
1389  * acquired resource into a resource that can be acquired shared.
1390  *
1391  * @param Resource
1392  * Pointer to the resource to convert.
1393  *
1394  * @return None.
1395  *
1396  * @remarks Callers of ExConvertExclusiveToSharedLite must be running at IRQL <
1397  * DISPATCH_LEVEL.
1398  *
1399  *--*/
1400 VOID
1401 NTAPI
1403 {
1404  ULONG OldWaiters;
1406 
1407  /* Sanity checks */
1411  ASSERT(Resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)PsGetCurrentThread());
1412 
1413  /* Lock the resource */
1415 
1416  /* Erase the exclusive flag */
1417  Resource->Flag &= ~ResourceOwnedExclusive;
1418 
1419  /* Check if we have shared waiters */
1421  {
1422  /* Make the waiters active owners */
1423  OldWaiters = Resource->NumberOfSharedWaiters;
1424  Resource->ActiveEntries += OldWaiters;
1425  Resource->NumberOfSharedWaiters = 0;
1426 
1427  /* Release lock and wake the waiters */
1429  KeReleaseSemaphore(Resource->SharedWaiters, 0, OldWaiters, FALSE);
1430  }
1431  else
1432  {
1433  /* Release lock */
1435  }
1436 }
1437 
1438 /*++
1439  * @name ExDeleteResourceLite
1440  * @implemented NT4
1441  *
1442  * The ExConvertExclusiveToSharedLite routine deletes a given resource
1443  * from the systemís resource list.
1444  *
1445  * @param Resource
1446  * Pointer to the resource to delete.
1447  *
1448  * @return STATUS_SUCCESS if the resource was deleted.
1449  *
1450  * @remarks Callers of ExDeleteResourceLite must be running at IRQL <
1451  * DISPATCH_LEVEL.
1452  *
1453  *--*/
1454 NTSTATUS
1455 NTAPI
1457 {
1459 
1460  /* Sanity checks */
1465 
1466  /* Lock the resource */
1468 
1469  /* Remove the resource */
1470  RemoveEntryList(&Resource->SystemResourcesList);
1471 
1472  /* Release the lock */
1474 
1475  /* Free every structure */
1476  if (Resource->OwnerTable) ExFreePoolWithTag(Resource->OwnerTable, TAG_RESOURCE_TABLE);
1477  if (Resource->SharedWaiters) ExFreePoolWithTag(Resource->SharedWaiters, TAG_RESOURCE_SEMAPHORE);
1478  if (Resource->ExclusiveWaiters) ExFreePoolWithTag(Resource->ExclusiveWaiters, TAG_RESOURCE_EVENT);
1479 
1480  /* Return success */
1481  return STATUS_SUCCESS;
1482 }
1483 
1484 /*++
1485  * @name ExDisableResourceBoostLite
1486  * @implemented NT4
1487  *
1488  * The ExDisableResourceBoostLite routine disables thread boosting for
1489  * the given resource.
1490  *
1491  * @param Resource
1492  * Pointer to the resource whose thread boosting will be disabled.
1493  *
1494  * @return None.
1495  *
1496  * @remarks None.
1497  *
1498  *--*/
1499 VOID
1500 NTAPI
1502 {
1504 
1505  /* Sanity check */
1507 
1508  /* Lock the resource */
1510 
1511  /* Remove the flag */
1513 
1514  /* Release the lock */
1516 }
1517 
1518 /*++
1519  * @name ExGetExclusiveWaiterCount
1520  * @implemented NT4
1521  *
1522  * The ExGetExclusiveWaiterCount routine returns the number of exclusive
1523  * waiters for the given resource.
1524  *
1525  * @param Resource
1526  * Pointer to the resource to check.
1527  *
1528  * @return The number of exclusive waiters.
1529  *
1530  * @remarks None.
1531  *
1532  *--*/
1533 ULONG
1534 NTAPI
1536 {
1537  /* Return the count */
1538  return Resource->NumberOfExclusiveWaiters;
1539 }
1540 
1541 /*++
1542  * @name ExGetSharedWaiterCount
1543  * @implemented NT4
1544  *
1545  * The ExGetSharedWaiterCount routine returns the number of shared
1546  * waiters for the given resource.
1547  *
1548  * @param Resource
1549  * Pointer to the resource to check.
1550  *
1551  * @return The number of shared waiters.
1552  *
1553  * @remarks None.
1554  *
1555  *--*/
1556 ULONG
1557 NTAPI
1559 {
1560  /* Return the count */
1561  return Resource->NumberOfSharedWaiters;
1562 }
1563 
1564 /*++
1565  * @name ExInitializeResourceLite
1566  * @implemented NT4
1567  *
1568  * The ExInitializeResourceLite routine initializes a resource variable.
1569  *
1570  * @param Resource
1571  * Pointer to the resource to check.
1572  *
1573  * @return STATUS_SUCCESS.
1574  *
1575  * @remarks The storage for ERESOURCE must not be allocated from paged pool.
1576  *
1577  * The storage must be 8-byte aligned.
1578  *
1579  *--*/
1580 NTSTATUS
1581 NTAPI
1583 {
1585 
1586  /* Clear the structure */
1587  RtlZeroMemory(Resource, sizeof(ERESOURCE));
1588 
1589  /* Initialize the lock */
1590  KeInitializeSpinLock(&Resource->SpinLock);
1591 
1592  /* Add it into the system list */
1594  InsertTailList(&ExpSystemResourcesList, &Resource->SystemResourcesList);
1596 
1597  /* Return success */
1598  return STATUS_SUCCESS;
1599 }
1600 
1601 /*++
1602  * @name ExIsResourceAcquiredExclusiveLite
1603  * @implemented NT4
1604  *
1605  * The ExIsResourceAcquiredExclusiveLite routine returns whether the
1606  * current thread has exclusive access to a given resource.
1607  *
1608  * @param Resource
1609  * Pointer to the resource to check.
1610  *
1611  * @return TRUE if the caller already has exclusive access to the given resource.
1612  *
1613  * @remarks Callers of ExIsResourceAcquiredExclusiveLite must be running at
1614  * IRQL <= DISPATCH_LEVEL.
1615  *
1616  *--*/
1617 BOOLEAN
1618 NTAPI
1620 {
1621  BOOLEAN IsAcquired = FALSE;
1622 
1623  /* Sanity check */
1625 
1626  /* Check if it's exclusively acquired */
1627  if ((IsOwnedExclusive(Resource)) &&
1628  (Resource->OwnerEntry.OwnerThread == ExGetCurrentResourceThread()))
1629  {
1630  /* It is acquired */
1631  IsAcquired = TRUE;
1632  }
1633 
1634  /* Return if it's acquired */
1635  return IsAcquired;
1636 }
1637 
1638 /*++
1639  * @name ExIsResourceAcquiredSharedLite
1640  * @implemented NT4
1641  *
1642  * The ExIsResourceAcquiredSharedLite routine returns whether the
1643  * current thread has has access (either shared or exclusive) to a
1644  * given resource.
1645  *
1646  * @param Resource
1647  * Pointer to the resource to check.
1648  *
1649  * @return Number of times the caller has acquired the given resource for
1650  * shared or exclusive access.
1651  *
1652  * @remarks Callers of ExIsResourceAcquiredExclusiveLite must be running at
1653  * IRQL <= DISPATCH_LEVEL.
1654  *
1655  *--*/
1656 ULONG
1657 NTAPI
1659 {
1661  ULONG i, Size;
1662  ULONG Count = 0;
1665 
1666  /* Sanity check */
1668 
1669  /* Check if nobody owns us */
1670  if (!Resource->ActiveEntries) return 0;
1671 
1672  /* Get the thread */
1674 
1675  /* Check if we are in the thread list */
1676  if (Resource->OwnerEntry.OwnerThread == Thread)
1677  {
1678  /* Found it, return count */
1679  Count = Resource->OwnerEntry.OwnerCount;
1680  }
1681  else
1682  {
1683  /* We can't own an exclusive resource at this point */
1684  if (IsOwnedExclusive(Resource)) return 0;
1685 
1686  /* Lock the resource */
1688 
1689  /* Not in the list, do a full table look up */
1690  Owner = Resource->OwnerTable;
1691  if (Owner)
1692  {
1693  /* Get the resource index */
1694  i = ((PKTHREAD)Thread)->ResourceIndex;
1695  Size = Owner->TableSize;
1696 
1697  /* Check if the index is valid and check if we don't match */
1698  if ((i >= Size) || (Owner[i].OwnerThread != Thread))
1699  {
1700  /* Sh*t! We need to do a full search */
1701  for (i = 1; i < Size; i++)
1702  {
1703  /* Move to next owner */
1704  Owner++;
1705 
1706  /* Try to find a match */
1707  if (Owner->OwnerThread == Thread)
1708  {
1709  /* Finally! */
1710  Count = Owner->OwnerCount;
1711  break;
1712  }
1713  }
1714  }
1715  else
1716  {
1717  /* We found the match directlry */
1718  Count = Owner[i].OwnerCount;
1719  }
1720  }
1721 
1722  /* Release the lock */
1724  }
1725 
1726  /* Return count */
1727  return Count;
1728 }
1729 
1730 /*++
1731  * @name ExReinitializeResourceLite
1732  * @implemented NT4
1733  *
1734  * The ExReinitializeResourceLite routine routine reinitializes
1735  * an existing resource variable.
1736  *
1737  * @param Resource
1738  * Pointer to the resource to be reinitialized.
1739  *
1740  * @return STATUS_SUCCESS.
1741  *
1742  * @remarks With a single call to ExReinitializeResource, a driver writer can
1743  * replace three calls: one to ExDeleteResourceLite, another to
1744  * ExAllocatePool, and a third to ExInitializeResourceLite. As
1745  * contention for a resource variable increases, memory is dynamically
1746  * allocated and attached to the resource in order to track this
1747  * contention. As an optimization, ExReinitializeResourceLite retains
1748  * and zeroes this previously allocated memory.
1749  *
1750  * Callers of ExReinitializeResourceLite must be running at
1751  * IRQL <= DISPATCH_LEVEL.
1752  *
1753  *--*/
1754 NTSTATUS
1755 NTAPI
1757 {
1758  PKEVENT Event;
1759  PKSEMAPHORE Semaphore;
1760  ULONG i, Size;
1762 
1763  /* Get the owner table */
1764  Owner = Resource->OwnerTable;
1765  if (Owner)
1766  {
1767  /* Get the size and loop it */
1768  Size = Owner->TableSize;
1769  for (i = 0; i < Size; i++)
1770  {
1771  /* Zero the table */
1772  Owner[i].OwnerThread = 0;
1773  Owner[i].OwnerCount = 0;
1774  }
1775  }
1776 
1777  /* Zero the flags and count */
1778  Resource->Flag = 0;
1779  Resource->ActiveCount = 0;
1780  Resource->ActiveEntries = 0;
1781 
1782  /* Reset the semaphore */
1783  Semaphore = Resource->SharedWaiters;
1784  if (Semaphore) KeInitializeSemaphore(Semaphore, 0, MAXLONG);
1785 
1786  /* Reset the event */
1787  Event = Resource->ExclusiveWaiters;
1789 
1790  /* Clear the resource data */
1791  Resource->OwnerEntry.OwnerThread = 0;
1792  Resource->OwnerEntry.OwnerCount = 0;
1793  Resource->ContentionCount = 0;
1794  Resource->NumberOfSharedWaiters = 0;
1795  Resource->NumberOfExclusiveWaiters = 0;
1796  return STATUS_SUCCESS;
1797 }
1798 
1799 /*++
1800  * @name ExReleaseResourceLite
1801  * @implemented NT4
1802  *
1803  * The ExReleaseResourceLite routine routine releases
1804  * a specified executive resource owned by the current thread.
1805  *
1806  * @param Resource
1807  * Pointer to the resource to be released.
1808  *
1809  * @return None.
1810  *
1811  * @remarks Callers of ExReleaseResourceLite must be running at
1812  * IRQL <= DISPATCH_LEVEL.
1813  *
1814  *--*/
1815 VOID
1816 FASTCALL
1818 {
1819  /* Just call the For-Thread function */
1821 }
1822 
1823 /*++
1824  * @name ExReleaseResourceForThreadLite
1825  * @implemented NT4
1826  *
1827  * The ExReleaseResourceForThreadLite routine routine releases
1828  * the input resource of the indicated thread.
1829  *
1830  * @param Resource
1831  * Pointer to the resource to be released.
1832  *
1833  * @param Thread
1834  * Identifies the thread that originally acquired the resource.
1835  *
1836  * @return None.
1837  *
1838  * @remarks Callers of ExReleaseResourceForThreadLite must be running at
1839  * IRQL <= DISPATCH_LEVEL.
1840  *
1841  *--*/
1842 VOID
1843 NTAPI
1846 {
1847  ULONG i;
1848  ULONG Count;
1851  ASSERT(Thread != 0);
1852 
1853  /* Get the thread and lock the resource */
1855 
1856  /* Sanity checks */
1859 
1860  /* Check if it's exclusively owned */
1862  {
1863  /* Decrement owner count and check if we're done */
1864  ASSERT(Resource->OwnerEntry.OwnerThread == Thread);
1865  if (--Resource->OwnerEntry.OwnerCount)
1866  {
1867  /* Done, release lock! */
1869  return;
1870  }
1871 
1872  /* Clear the owner */
1873  Resource->OwnerEntry.OwnerThread = 0;
1874 
1875  /* Decrement the number of active entries */
1876  ASSERT(Resource->ActiveEntries == 1);
1877  Resource->ActiveEntries--;
1878 
1879  /* Check if there are shared waiters */
1881  {
1882  /* Remove the exclusive flag */
1883  Resource->Flag &= ~ResourceOwnedExclusive;
1884 
1885  /* Give ownage to another thread */
1886  Count = Resource->NumberOfSharedWaiters;
1887  Resource->ActiveEntries = Count;
1888  Resource->NumberOfSharedWaiters = 0;
1889 
1890  /* Release lock and let someone else have it */
1891  ASSERT(Resource->ActiveCount == 1);
1893  KeReleaseSemaphore(Resource->SharedWaiters, 0, Count, FALSE);
1894  return;
1895  }
1896  else if (IsExclusiveWaiting(Resource))
1897  {
1898  /* Give exclusive access */
1899  Resource->OwnerEntry.OwnerThread = 1;
1900  Resource->OwnerEntry.OwnerCount = 1;
1901  Resource->ActiveEntries = 1;
1902  Resource->NumberOfExclusiveWaiters--;
1903 
1904  /* Release the lock and give it away */
1905  ASSERT(Resource->ActiveCount == 1);
1907  KeSetEventBoostPriority(Resource->ExclusiveWaiters,
1908  (PKTHREAD*)&Resource->OwnerEntry.OwnerThread);
1909  return;
1910  }
1911 
1912  /* Remove the exclusive flag */
1913  Resource->Flag &= ~ResourceOwnedExclusive;
1914  Resource->ActiveCount = 0;
1915  }
1916  else
1917  {
1918  /* Check if we are in the thread list */
1919  if (Resource->OwnerEntry.OwnerThread == Thread)
1920  {
1921  /* Found it, get owner */
1922  Owner = &Resource->OwnerEntry;
1923  }
1924  else
1925  {
1926  /* Assume no valid index */
1927  i = 1;
1928 
1929  /* If we got a valid pointer, try to get the resource index */
1930  if (!((ULONG)Thread & 3)) i = ((PKTHREAD)Thread)->ResourceIndex;
1931 
1932  /* Do a table lookup */
1933  Owner = Resource->OwnerTable;
1934  ASSERT(Owner != NULL);
1935 
1936  /* Check if we're out of the size and don't match */
1937  if ((i >= Owner->TableSize) || (Owner[i].OwnerThread != Thread))
1938  {
1939  /* Get the last entry */
1940  Limit = &Owner[Owner->TableSize];
1941  for (;;)
1942  {
1943  /* Move to the next entry */
1944  Owner++;
1945 
1946  /* Make sure we're not out of bounds */
1947  if (Owner >= Limit)
1948  {
1949  /* Bugcheck, nobody owns us */
1950  KeBugCheckEx(RESOURCE_NOT_OWNED,
1952  (ULONG_PTR)Thread,
1953  (ULONG_PTR)Resource->OwnerTable,
1954  (ULONG_PTR)3);
1955  }
1956 
1957  /* Check for a match */
1958  if (Owner->OwnerThread == Thread) break;
1959  }
1960  }
1961  else
1962  {
1963  /* Get the entry directly */
1964  Owner = &Owner[i];
1965  }
1966  }
1967 
1968  /* Sanity checks */
1969  ASSERT(Owner->OwnerThread == Thread);
1970  ASSERT(Owner->OwnerCount > 0);
1971 
1972  /* Check if we are the last owner */
1973  if (--Owner->OwnerCount)
1974  {
1975  /* There are other owners, release lock */
1977  return;
1978  }
1979 
1980  /* Clear owner */
1981  Owner->OwnerThread = 0;
1982 
1983  /* See if the resource isn't being owned anymore */
1984  ASSERT(Resource->ActiveEntries > 0);
1985  if (!(--Resource->ActiveEntries))
1986  {
1987  /* Check if there's an exclusive waiter */
1989  {
1990  /* Give exclusive access */
1992  Resource->OwnerEntry.OwnerThread = 1;
1993  Resource->OwnerEntry.OwnerCount = 1;
1994  Resource->ActiveEntries = 1;
1995  Resource->NumberOfExclusiveWaiters--;
1996 
1997  /* Release the lock and give it away */
1998  ASSERT(Resource->ActiveCount == 1);
2000  KeSetEventBoostPriority(Resource->ExclusiveWaiters,
2001  (PKTHREAD*)&Resource->OwnerEntry.OwnerThread);
2002  return;
2003  }
2004 
2005  /* Clear the active count */
2006  Resource->ActiveCount = 0;
2007  }
2008  }
2009 
2010  /* Release lock */
2012 }
2013 
2014 /*++
2015  * @name ExSetResourceOwnerPointer
2016  * @implemented NT4
2017  *
2018  * The ExSetResourceOwnerPointer routine routine sets the owner thread
2019  * thread pointer for an executive resource.
2020  *
2021  * @param Resource
2022  * Pointer to the resource whose owner to change.
2023  *
2024  * @param OwnerPointer
2025  * Pointer to an owner thread pointer of type ERESOURCE_THREAD.
2026  *
2027  * @return None.
2028  *
2029  * @remarks ExSetResourceOwnerPointer, used in conjunction with
2030  * ExReleaseResourceForThreadLite, provides a means for one thread
2031  * (acting as an resource manager thread) to acquire and release
2032  * resources for use by another thread (acting as a resource user
2033  * thread).
2034  *
2035  * After calling ExSetResourceOwnerPointer for a specific resource,
2036  * the only other routine that can be called for that resource is
2037  * ExReleaseResourceForThreadLite.
2038  *
2039  * Callers of ExSetResourceOwnerPointer must be running at
2040  * IRQL <= DISPATCH_LEVEL.
2041  *
2042  *--*/
2043 VOID
2044 NTAPI
2047 {
2050  POWNER_ENTRY Owner, ThisOwner;
2051 
2052  /* Sanity check */
2053  ASSERT((OwnerPointer != 0) && (((ULONG_PTR)OwnerPointer & 3) == 3));
2054 
2055  /* Get the thread */
2057 
2058  /* Sanity check */
2060 
2061  /* Lock the resource */
2063 
2064  /* Check if it's exclusive */
2066  {
2067  /* If it's exclusive, set the first entry no matter what */
2068  ASSERT(Resource->OwnerEntry.OwnerThread == Thread);
2069  ASSERT(Resource->OwnerEntry.OwnerCount > 0);
2070  Resource->OwnerEntry.OwnerThread = (ULONG_PTR)OwnerPointer;
2071  }
2072  else
2073  {
2074  /* Set the thread in both entries */
2075  ThisOwner = ExpFindEntryForThread(Resource,
2077  0,
2078  FALSE);
2080  if (!Owner)
2081  {
2082  /* Nobody owns it, crash */
2083  KeBugCheckEx(RESOURCE_NOT_OWNED,
2085  Thread,
2086  (ULONG_PTR)Resource->OwnerTable,
2087  3);
2088  }
2089 
2090  /* Set if we are the owner */
2091  if (ThisOwner)
2092  {
2093  /* Update data */
2094  ThisOwner->OwnerCount += Owner->OwnerCount;
2095  Owner->OwnerCount = 0;
2096  Owner->OwnerThread = 0;
2097  ASSERT(Resource->ActiveEntries >= 2);
2098  Resource->ActiveEntries--;
2099  }
2100  else
2101  {
2102  /* Update the owner entry instead */
2103  Owner->OwnerThread = (ERESOURCE_THREAD)OwnerPointer;
2104  }
2105  }
2106 
2107  /* Release the resource */
2109 }
2110 
2111 /*++
2112  * @name ExTryToAcquireResourceExclusiveLite
2113  * @implemented NT4
2114  *
2115  * The ExTryToAcquireResourceExclusiveLite routine routine attemps to
2116  * acquire the given resource for exclusive access.
2117  *
2118  * @param Resource
2119  * Pointer to the resource to be acquired.
2120  *
2121  * @return TRUE if the given resource has been acquired for the caller.
2122  *
2123  * @remarks Callers of ExTryToAcquireResourceExclusiveLite must be running at
2124  * IRQL < DISPATCH_LEVEL.
2125  *
2126  *--*/
2127 BOOLEAN
2128 NTAPI
2130 {
2133  BOOLEAN Acquired = FALSE;
2134 
2135  /* Sanity check */
2136  ASSERT((Resource->Flag & ResourceNeverExclusive) == 0);
2137 
2138  /* Get the thread */
2140 
2141  /* Sanity check and validation */
2144 
2145  /* Acquire the lock */
2147 
2148  /* Check if there is an owner */
2149  if (!Resource->ActiveCount)
2150  {
2151  /* No owner, give exclusive access */
2153  Resource->OwnerEntry.OwnerThread = Thread;
2154  Resource->OwnerEntry.OwnerCount = 1;
2155  Resource->ActiveCount = 1;
2156  Resource->ActiveEntries = 1;
2157  Acquired = TRUE;
2158  }
2159  else if ((IsOwnedExclusive(Resource)) &&
2160  (Resource->OwnerEntry.OwnerThread == Thread))
2161  {
2162  /* Do a recursive acquire */
2163  Resource->OwnerEntry.OwnerCount++;
2164  Acquired = TRUE;
2165  }
2166 
2167  /* Release the resource */
2169  return Acquired;
2170 }
2171 
2172 /*++
2173  * @name ExEnterCriticalRegionAndAcquireResourceExclusive
2174  * @implemented NT5.1
2175  *
2176  * The ExEnterCriticalRegionAndAcquireResourceExclusive enters a critical
2177  * region and then exclusively acquires a resource.
2178  *
2179  * @param Resource
2180  * Pointer to the resource to acquire.
2181  *
2182  * @return Pointer to the Win32K thread pointer of the current thread.
2183  *
2184  * @remarks See ExAcquireResourceExclusiveLite.
2185  *
2186  *--*/
2187 PVOID
2188 NTAPI
2190 {
2191  /* Enter critical region */
2193 
2194  /* Acquire the resource */
2196 
2197  /* Return the Win32 Thread */
2198  return KeGetCurrentThread()->Win32Thread;
2199 }
2200 
2201 /*++
2202  * @name ExEnterCriticalRegionAndAcquireResourceShared
2203  * @implemented NT5.2
2204  *
2205  * The ExEnterCriticalRegionAndAcquireResourceShared routine
2206  * enters a critical region and then acquires a resource shared.
2207  *
2208  * @param Resource
2209  * Pointer to the resource to acquire.
2210  *
2211  * @return Pointer to the Win32K thread pointer of the current thread.
2212  *
2213  * @remarks See ExAcquireResourceSharedLite.
2214  *
2215  *--*/
2216 PVOID
2217 NTAPI
2219 {
2220  /* Enter critical region */
2222 
2223  /* Acquire the resource */
2225 
2226  /* Return the Win32 Thread */
2227  return KeGetCurrentThread()->Win32Thread;
2228 }
2229 
2230 /*++
2231  * @name ExEnterCriticalRegionAndAcquireSharedWaitForExclusive
2232  * @implemented NT5.2
2233  *
2234  * The ExEnterCriticalRegionAndAcquireSharedWaitForExclusive routine
2235  * enters a critical region and then acquires a resource shared if
2236  * shared access can be granted and there are no exclusive waiters.
2237  * It then acquires the resource exclusively.
2238  *
2239  * @param Resource
2240  * Pointer to the resource to acquire.
2241  *
2242  * @return Pointer to the Win32K thread pointer of the current thread.
2243  *
2244  * @remarks See ExAcquireSharedWaitForExclusive.
2245  *
2246  *--*/
2247 PVOID
2248 NTAPI
2250 {
2251  /* Enter critical region */
2253 
2254  /* Acquire the resource */
2256 
2257  /* Return the Win32 Thread */
2258  return KeGetCurrentThread()->Win32Thread;
2259 }
2260 
2261 /*++
2262  * @name ExReleaseResourceAndLeaveCriticalRegion
2263  * @implemented NT5.1
2264  *
2265  * The ExReleaseResourceAndLeaveCriticalRegion release a resource and
2266  * then leaves a critical region.
2267  *
2268  * @param Resource
2269  * Pointer to the resource to release.
2270  *
2271  * @return None
2272  *
2273  * @remarks See ExReleaseResourceLite.
2274  *
2275  *--*/
2276 VOID
2277 FASTCALL
2279 {
2280  /* Release the resource */
2282 
2283  /* Leave critical region */
2285 }
BOOLEAN NTAPI ExAcquireSharedWaitForExclusive(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:1217
FORCEINLINE VOID KiReleaseThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:244
ULONG NTAPI ExGetExclusiveWaiterCount(IN PERESOURCE Resource)
Definition: resource.c:1535
#define ExGetCurrentResourceThread()
Definition: env_spec_w32.h:633
#define TAG_RESOURCE_SEMAPHORE
Definition: tag.h:20
Definition: extypes.h:210
ULONG_PTR ERESOURCE_THREAD
Definition: extypes.h:208
LARGE_INTEGER ExShortTime
Definition: resource.c:72
#define IN
Definition: typedefs.h:38
ASMGENDATA Table[]
Definition: genincdata.c:61
#define IsExclusiveWaiting(r)
Definition: resource.c:16
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define ResourceNeverExclusive
Definition: extypes.h:245
NTSTATUS NTAPI ExReinitializeResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1756
POWNER_ENTRY FASTCALL ExpFindFreeEntry(IN PERESOURCE Resource, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: resource.c:416
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define ResourceHasDisabledPriorityBoost
Definition: extypes.h:169
#define MAXLONG
Definition: umtypes.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
_In_ PVOID OwnerPointer
Definition: exfuncs.h:862
VOID NTAPI ExDisableResourceBoostLite(IN PERESOURCE Resource)
Definition: resource.c:1501
VOID NTAPI ExConvertExclusiveToSharedLite(IN PERESOURCE Resource)
Definition: resource.c:1402
void __cdecl _enable(void)
Definition: intrin_arm.h:373
PVOID NTAPI ExEnterCriticalRegionAndAcquireResourceShared(IN PERESOURCE Resource)
Definition: resource.c:2218
LONG NTSTATUS
Definition: precomp.h:26
POWNER_ENTRY FASTCALL ExpFindEntryForThread(IN PERESOURCE Resource, IN ERESOURCE_THREAD Thread, IN PKLOCK_QUEUE_HANDLE LockHandle, IN BOOLEAN FirstEntryInelligible)
Definition: resource.c:479
NTSTATUS NTAPI ExDeleteResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1456
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
#define IsBoostAllowed(r)
Definition: resource.c:19
#define InsertTailList(ListHead, Entry)
VOID FASTCALL KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:130
void DbgBreakPoint()
Definition: mach.c:558
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define FASTCALL
Definition: nt_native.h:50
_Out_ PKIRQL Irql
Definition: csq.h:179
BOOLEAN NTAPI KeIsExecutingDpc(VOID)
Definition: dpc.c:946
uint32_t ULONG_PTR
Definition: typedefs.h:63
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
UCHAR KIRQL
Definition: env_spec_w32.h:591
struct _KTHREAD * PKTHREAD
Definition: nt_native.h:28
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_Acquires_exclusive_lock_ Resource _Acquires_shared_lock_ Resource _Inout_ PERESOURCE Resource
Definition: cdprocs.h:848
#define ExpVerifyResource(r)
Definition: resource.c:150
VOID FASTCALL KiSetPriorityThread(IN PKTHREAD Thread, IN KPRIORITY Priority)
Definition: thrdschd.c:511
static VOID NTAPI SystemThread(_In_ PVOID Context)
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
NTSTATUS NTAPI KeDelayExecutionThread(IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Interval OPTIONAL)
Definition: wait.c:283
KSPIN_LOCK ExpResourceSpinLock
Definition: resource.c:75
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:434
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
BOOLEAN NTAPI ExIsResourceAcquiredExclusiveLite(IN PERESOURCE Resource)
Definition: resource.c:1619
#define FORCEINLINE
Definition: ntbasedef.h:221
FORCEINLINE VOID KiAcquireThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:234
VOID FASTCALL KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:166
ULONG NTAPI ExGetSharedWaiterCount(IN PERESOURCE Resource)
Definition: resource.c:1558
ULONG OwnerCount
Definition: extypes.h:216
BOOLEAN ExResourceStrict
Definition: resource.c:77
VOID NTAPI KeInitializeSemaphore(IN PKSEMAPHORE Semaphore, IN LONG Count, IN LONG Limit)
Definition: semphobj.c:22
LARGE_INTEGER ExpTimeout
Definition: resource.c:73
if(!(yy_init))
Definition: macro.lex.yy.c:714
FORCEINLINE VOID ExReleaseResourceLock(IN PERESOURCE Resource, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: resource.c:37
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
VOID NTAPI ExpAllocateExclusiveWaiterEvent(IN PERESOURCE Resource, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: resource.c:196
#define IsOwnedExclusive(r)
Definition: resource.c:18
static IUnknown Object
Definition: main.c:512
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TAG_RESOURCE_EVENT
Definition: tag.h:19
unsigned char UCHAR
Definition: xmlstorage.h:181
#define ExpCheckForApcsDisabled(b, r, t)
Definition: resource.c:151
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
FORCEINLINE VOID ExAcquireResourceLock(IN PERESOURCE Resource, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: resource.c:25
#define KeEnterCriticalRegion()
Definition: ke_x.h:83
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
Definition: typedefs.h:117
VOID FASTCALL ExReleaseResourceAndLeaveCriticalRegion(IN PERESOURCE Resource)
Definition: resource.c:2278
VOID NTAPI ExSetResourceOwnerPointer(IN PERESOURCE Resource, IN PVOID OwnerPointer)
Definition: resource.c:2045
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
VOID NTAPI ExpAllocateSharedWaiterSemaphore(IN PERESOURCE Resource, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: resource.c:256
Status
Definition: gdiplustypes.h:24
PVOID NTAPI ExEnterCriticalRegionAndAcquireSharedWaitForExclusive(IN PERESOURCE Resource)
Definition: resource.c:2249
BOOLEAN NTAPI ExAcquireSharedStarveExclusive(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:1063
VOID FASTCALL ExpBoostOwnerThread(IN PKTHREAD Thread, IN PKTHREAD OwnerThread)
Definition: resource.c:572
#define KeLeaveCriticalRegion()
Definition: ke_x.h:114
static ULONG Timeout
Definition: ping.c:61
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:152
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
FORCEINLINE KIRQL KiAcquireDispatcherLock(VOID)
Definition: ke_x.h:144
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
BOOLEAN NTAPI ExTryToAcquireResourceExclusiveLite(IN PERESOURCE Resource)
Definition: resource.c:2129
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID Owner
Definition: rtlfuncs.h:1557
INIT_FUNCTION VOID NTAPI ExpResourceInitialization(VOID)
Definition: resource.c:169
LIST_ENTRY ExpSystemResourcesList
Definition: resource.c:76
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
NTSTATUS NTAPI ExInitializeResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1582
#define DPRINT1
Definition: precomp.h:8
VOID NTAPI ExpExpandResourceOwnerTable(IN PERESOURCE Resource, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: resource.c:316
ULONG ExpResourceTimeoutCount
Definition: resource.c:74
void __cdecl _disable(void)
Definition: intrin_arm.h:365
ULONG ERESOURCE
Definition: env_spec_w32.h:594
PVOID NTAPI ExEnterCriticalRegionAndAcquireResourceExclusive(IN PERESOURCE Resource)
Definition: resource.c:2189
unsigned int ULONG
Definition: retypes.h:1
ULONG NTAPI ExIsResourceAcquiredSharedLite(IN PERESOURCE Resource)
Definition: resource.c:1658
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
VOID NTAPI ExReleaseResourceForThreadLite(IN PERESOURCE Resource, IN ERESOURCE_THREAD Thread)
Definition: resource.c:1844
VOID NTAPI KeSetEventBoostPriority(IN PKEVENT Event, IN PKTHREAD *WaitingThread OPTIONAL)
Definition: eventobj.c:229
*LockHandle LockHandle _Out_ PKLOCK_QUEUE_HANDLE LockHandle
Definition: kefuncs.h:742
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define IsSharedWaiting(r)
Definition: resource.c:17
#define KeGetCurrentThread
Definition: hal.h:44
#define TAG_RESOURCE_TABLE
Definition: tag.h:18
return STATUS_SUCCESS
Definition: btrfs.c:2745
VOID FASTCALL ExpWaitForResource(IN PERESOURCE Resource, IN PVOID Object)
Definition: resource.c:618
#define APC_LEVEL
Definition: env_spec_w32.h:695
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:328
#define Int32x32To64(a, b)
#define ResourceOwnedExclusive
Definition: dldetect.h:32
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:107
LONGLONG QuadPart
Definition: typedefs.h:112
IN BOOLEAN Wait
Definition: fatprocs.h:1529