wine  6.0.1
About: Wine is an Open Source implementation of the MS Windows API on top of X, OpenGL, and Unix. Think of Wine as a compatibility layer for running Windows programs.
  Fossies Dox: wine-6.0.1.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

sync.c
Go to the documentation of this file.
1 /*
2  * Kernel synchronization
3  *
4  * Copyright (C) 2018 Zebediah Figura
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <limits.h>
22 #include <stdarg.h>
23 
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winternl.h"
29 #include "ddk/ntddk.h"
30 #include "ddk/wdm.h"
31 #include "ddk/ntifs.h"
32 
33 #include "wine/asm.h"
34 #include "wine/debug.h"
35 #include "wine/heap.h"
36 #include "wine/server.h"
37 
38 #include "ntoskrnl_private.h"
39 
41 
43 {
50 };
51 
53 
54 /***********************************************************************
55  * KeWaitForMultipleObjects (NTOSKRNL.EXE.@)
56  */
59  BOOLEAN alertable, LARGE_INTEGER *timeout, KWAIT_BLOCK *wait_blocks)
60 {
61  DISPATCHER_HEADER **objs = (DISPATCHER_HEADER **)pobjs;
63  NTSTATUS ret;
64  ULONG i;
65 
66  TRACE("count %u, objs %p, wait_type %u, reason %u, mode %d, alertable %u, timeout %p, wait_blocks %p.\n",
67  count, objs, wait_type, reason, mode, alertable, timeout, wait_blocks);
68 
69  /* We co-opt DISPATCHER_HEADER.WaitListHead:
70  * Blink stores a handle to the synchronization object,
71  * Flink stores the number of threads currently waiting on this object. */
72 
74  for (i = 0; i < count; i++)
75  {
76  if (objs[i]->WaitListHead.Blink == INVALID_HANDLE_VALUE)
77  {
79  continue;
80  }
81 
82  ++*((ULONG_PTR *)&objs[i]->WaitListHead.Flink);
83  if (!objs[i]->WaitListHead.Blink)
84  {
85  switch (objs[i]->Type)
86  {
87  case TYPE_MANUAL_TIMER:
88  case TYPE_MANUAL_EVENT:
89  objs[i]->WaitListHead.Blink = CreateEventW( NULL, TRUE, objs[i]->SignalState, NULL );
90  break;
91  case TYPE_AUTO_TIMER:
92  case TYPE_AUTO_EVENT:
93  objs[i]->WaitListHead.Blink = CreateEventW( NULL, FALSE, objs[i]->SignalState, NULL );
94  break;
95  case TYPE_MUTEX:
96  objs[i]->WaitListHead.Blink = CreateMutexW( NULL, FALSE, NULL );
97  break;
98  case TYPE_SEMAPHORE:
99  {
100  KSEMAPHORE *semaphore = CONTAINING_RECORD(objs[i], KSEMAPHORE, Header);
102  semaphore->Header.SignalState, semaphore->Limit, NULL );
103  break;
104  }
105  }
106  }
107 
108  handles[i] = objs[i]->WaitListHead.Blink;
109  }
111 
112  ret = NtWaitForMultipleObjects( count, handles, (wait_type == WaitAny), alertable, timeout );
113 
115  for (i = 0; i < count; i++)
116  {
117  if (ret == i || (!ret && wait_type == WaitAll))
118  {
119  switch (objs[i]->Type)
120  {
121  case TYPE_AUTO_EVENT:
122  case TYPE_AUTO_TIMER:
123  objs[i]->SignalState = FALSE;
124  break;
125  case TYPE_MUTEX:
126  case TYPE_SEMAPHORE:
127  --objs[i]->SignalState;
128  break;
129  }
130  }
131 
132  if (objs[i]->WaitListHead.Blink == INVALID_HANDLE_VALUE)
133  {
134  NtClose( handles[i] );
135  }
136  else if (!--*((ULONG_PTR *)&objs[i]->WaitListHead.Flink))
137  {
138  switch (objs[i]->Type)
139  {
140  case TYPE_AUTO_TIMER:
141  case TYPE_MANUAL_TIMER:
142  case TYPE_MANUAL_EVENT:
143  case TYPE_AUTO_EVENT:
144  case TYPE_SEMAPHORE:
145  CloseHandle(objs[i]->WaitListHead.Blink);
146  objs[i]->WaitListHead.Blink = NULL;
147  break;
148  case TYPE_MUTEX:
149  /* Native will panic if a mutex is destroyed while held, so we
150  * don't have to worry about leaking the handle here. */
151  if (objs[i]->SignalState == 1)
152  {
153  CloseHandle(objs[i]->WaitListHead.Blink);
154  objs[i]->WaitListHead.Blink = NULL;
155  }
156  break;
157  }
158  }
159  }
161 
162  return ret;
163 }
164 
165 /***********************************************************************
166  * KeWaitForSingleObject (NTOSKRNL.EXE.@)
167  */
169  KPROCESSOR_MODE mode, BOOLEAN alertable, LARGE_INTEGER *timeout )
170 {
171  return KeWaitForMultipleObjects( 1, &obj, WaitAny, reason, mode, alertable, timeout, NULL );
172 }
173 
174 /***********************************************************************
175  * KeWaitForMutexObject (NTOSKRNL.EXE.@)
176  */
178  KPROCESSOR_MODE mode, BOOLEAN alertable, LARGE_INTEGER *timeout)
179 {
180  return KeWaitForSingleObject( mutex, reason, mode, alertable, timeout );
181 }
182 
183 
184 /***********************************************************************
185  * KeInitializeEvent (NTOSKRNL.EXE.@)
186  */
188 {
189  TRACE("event %p, type %u, state %u.\n", event, type, state);
190 
191  event->Header.Type = type;
192  event->Header.SignalState = state;
193  event->Header.WaitListHead.Blink = NULL;
194  event->Header.WaitListHead.Flink = NULL;
195 }
196 
197 static void *create_event_object( HANDLE handle )
198 {
200  KEVENT *event;
201 
202  if (!(event = alloc_kernel_object( ExEventObjectType, handle, sizeof(*event), 0 ))) return NULL;
203 
204  if (!NtQueryEvent( handle, EventBasicInformation, &info, sizeof(info), NULL ))
205  KeInitializeEvent( event, info.EventType, info.EventState );
206  event->Header.WaitListHead.Blink = INVALID_HANDLE_VALUE; /* mark as kernel object */
207  return event;
208 }
209 
210 static const WCHAR event_type_name[] = {'E','v','e','n','t',0};
211 
212 static struct _OBJECT_TYPE event_type = {
215 };
216 
218 
219 /***********************************************************************
220  * IoCreateSynchronizationEvent (NTOSKRNL.EXE.@)
221  */
223 {
225  HANDLE handle;
226  KEVENT *event;
227  NTSTATUS ret;
228 
229  TRACE( "(%p %p)\n", name, ret_handle );
230 
233  if (ret) return NULL;
234 
235  if (kernel_object_from_handle( handle, ExEventObjectType, (void**)&event ))
236  {
237  NtClose( handle);
238  return NULL;
239  }
240 
241  *ret_handle = handle;
242  return event;
243 }
244 
245 /***********************************************************************
246  * KeSetEvent (NTOSKRNL.EXE.@)
247  */
249 {
250  HANDLE handle;
251  LONG ret = 0;
252 
253  TRACE("event %p, increment %d, wait %u.\n", event, increment, wait);
254 
255  if (event->Header.WaitListHead.Blink != INVALID_HANDLE_VALUE)
256  {
258  ret = InterlockedExchange( &event->Header.SignalState, TRUE );
259  if ((handle = event->Header.WaitListHead.Blink))
260  SetEvent( handle );
262  }
263  else
264  {
266  {
267  NtSetEvent( handle, &ret );
268  NtClose( handle );
269  }
270  event->Header.SignalState = TRUE;
271  }
272 
273  return ret;
274 }
275 
276 /***********************************************************************
277  * KeResetEvent (NTOSKRNL.EXE.@)
278  */
280 {
281  HANDLE handle;
282  LONG ret = 0;
283 
284  TRACE("event %p.\n", event);
285 
286  if (event->Header.WaitListHead.Blink != INVALID_HANDLE_VALUE)
287  {
289  ret = InterlockedExchange( &event->Header.SignalState, FALSE );
290  if ((handle = event->Header.WaitListHead.Blink))
291  ResetEvent( handle );
293  }
294  else
295  {
297  {
298  NtResetEvent( handle, &ret );
299  NtClose( handle );
300  }
301  event->Header.SignalState = FALSE;
302  }
303 
304  return ret;
305 }
306 
307 /***********************************************************************
308  * KeClearEvent (NTOSKRNL.EXE.@)
309  */
311 {
312  KeResetEvent( event );
313 }
314 
315 /***********************************************************************
316  * KeReadStateEvent (NTOSKRNL.EXE.@)
317  */
319 {
320  HANDLE handle;
321 
322  TRACE("event %p.\n", event);
323 
324  if (event->Header.WaitListHead.Blink == INVALID_HANDLE_VALUE)
325  {
327  {
329  if (!(NtQueryEvent( handle, EventBasicInformation, &event_info, sizeof(event_info), NULL)))
330  event->Header.SignalState = event_info.EventState;
331  NtClose( handle );
332  }
333  }
334  return event->Header.SignalState;
335 }
336 
337 /***********************************************************************
338  * KeInitializeSemaphore (NTOSKRNL.EXE.@)
339  */
341 {
342  TRACE("semaphore %p, count %d, limit %d.\n", semaphore, count, limit);
343 
344  semaphore->Header.Type = TYPE_SEMAPHORE;
345  semaphore->Header.SignalState = count;
346  semaphore->Header.WaitListHead.Blink = NULL;
347  semaphore->Header.WaitListHead.Flink = NULL;
348  semaphore->Limit = limit;
349 }
350 
351 /***********************************************************************
352  * KeReleaseSemaphore (NTOSKRNL.EXE.@)
353  */
355  LONG count, BOOLEAN wait )
356 {
357  HANDLE handle;
358  LONG ret;
359 
360  TRACE("semaphore %p, increment %d, count %d, wait %u.\n",
361  semaphore, increment, count, wait);
362 
364  ret = InterlockedExchangeAdd( &semaphore->Header.SignalState, count );
365  if ((handle = semaphore->Header.WaitListHead.Blink))
366  ReleaseSemaphore( handle, count, NULL );
368 
369  return ret;
370 }
371 
372 static const WCHAR semaphore_type_name[] = {'S','e','m','a','p','h','o','r','e',0};
373 
374 static struct _OBJECT_TYPE semaphore_type =
375 {
377 };
378 
380 
381 /***********************************************************************
382  * KeInitializeMutex (NTOSKRNL.EXE.@)
383  */
385 {
386  TRACE("mutex %p, level %u.\n", mutex, level);
387 
388  mutex->Header.Type = TYPE_MUTEX;
389  mutex->Header.SignalState = 1;
390  mutex->Header.WaitListHead.Blink = NULL;
391  mutex->Header.WaitListHead.Flink = NULL;
392 }
393 
394 /***********************************************************************
395  * KeReleaseMutex (NTOSKRNL.EXE.@)
396  */
398 {
399  LONG ret;
400 
401  TRACE("mutex %p, wait %u.\n", mutex, wait);
402 
404  ret = mutex->Header.SignalState++;
405  if (!ret && !mutex->Header.WaitListHead.Flink)
406  {
407  CloseHandle( mutex->Header.WaitListHead.Blink );
408  mutex->Header.WaitListHead.Blink = NULL;
409  }
411 
412  return ret;
413 }
414 
416 {
417  KTIMER *timer = timer_;
418  KDPC *dpc = timer->Dpc;
419 
420  TRACE("instance %p, timer %p, tp_timer %p.\n", instance, timer, tp_timer);
421 
422  if (dpc && dpc->DeferredRoutine)
423  {
424  TRACE("Calling dpc->DeferredRoutine %p, dpc->DeferredContext %p.\n", dpc->DeferredRoutine, dpc->DeferredContext);
426  }
428  timer->Header.SignalState = TRUE;
429  if (timer->Header.WaitListHead.Blink)
430  SetEvent(timer->Header.WaitListHead.Blink);
432 }
433 
434 /***********************************************************************
435  * KeInitializeTimerEx (NTOSKRNL.EXE.@)
436  */
438 {
439  TRACE("timer %p, type %u.\n", timer, type);
440 
441  RtlZeroMemory(timer, sizeof(KTIMER));
443  timer->Header.SignalState = FALSE;
444  timer->Header.Inserted = FALSE;
445  timer->Header.WaitListHead.Blink = NULL;
446  timer->Header.WaitListHead.Flink = NULL;
447 }
448 
449 /***********************************************************************
450  * KeInitializeTimer (NTOSKRNL.EXE.@)
451  */
453 {
455 }
456 
457 /***********************************************************************
458  * KeSetTimerEx (NTOSKRNL.EXE.@)
459  */
461 {
462  BOOL ret;
463 
464  TRACE("timer %p, duetime %s, period %d, dpc %p.\n",
465  timer, wine_dbgstr_longlong(duetime.QuadPart), period, dpc);
466 
468 
469  if ((ret = timer->Header.Inserted))
471 
472  timer->Header.Inserted = TRUE;
473 
474  if (!timer->TimerListEntry.Blink)
475  timer->TimerListEntry.Blink = (void *)CreateThreadpoolTimer(ke_timer_complete_proc, timer, NULL);
476 
477  if (!timer->TimerListEntry.Blink)
478  ERR("Could not create thread pool timer.\n");
479 
480  timer->DueTime.QuadPart = duetime.QuadPart;
481  timer->Period = period;
482  timer->Dpc = dpc;
483 
484  SetThreadpoolTimer((TP_TIMER *)timer->TimerListEntry.Blink, (FILETIME *)&duetime, period, 0);
486 
487  return ret;
488 }
489 
491 {
492  BOOL ret;
493 
494  TRACE("timer %p.\n", timer);
495 
497  if (timer->TimerListEntry.Blink)
498  {
499  SetThreadpoolTimer((TP_TIMER *)timer->TimerListEntry.Blink, NULL, 0, 0);
500 
502  WaitForThreadpoolTimerCallbacks((TP_TIMER *)timer->TimerListEntry.Blink, TRUE);
504 
505  if (timer->TimerListEntry.Blink)
506  {
507  CloseThreadpoolTimer((TP_TIMER *)timer->TimerListEntry.Blink);
508  timer->TimerListEntry.Blink = NULL;
509  }
510  }
511  timer->Header.SignalState = FALSE;
512  if (timer->Header.WaitListHead.Blink && !*((ULONG_PTR *)&timer->Header.WaitListHead.Flink))
513  {
514  CloseHandle(timer->Header.WaitListHead.Blink);
515  timer->Header.WaitListHead.Blink = NULL;
516  }
517 
518  ret = timer->Header.Inserted;
519  timer->Header.Inserted = FALSE;
521 
522  return ret;
523 }
524 
525 /***********************************************************************
526  * KeDelayExecutionThread (NTOSKRNL.EXE.@)
527  */
529 {
530  TRACE("mode %d, alertable %u, timeout %p.\n", mode, alertable, timeout);
531  return NtDelayExecution( alertable, timeout );
532 }
533 
534 /***********************************************************************
535  * KeInitializeSpinLock (NTOSKRNL.EXE.@)
536  */
538 {
539  TRACE("lock %p.\n", lock);
540  *lock = 0;
541 }
542 
543 static inline void small_pause(void)
544 {
545 #ifdef __x86_64__
546  __asm__ __volatile__( "rep;nop" : : : "memory" );
547 #else
548  __asm__ __volatile__( "" : : : "memory" );
549 #endif
550 }
551 
552 /***********************************************************************
553  * KeAcquireSpinLockAtDpcLevel (NTOSKRNL.EXE.@)
554  */
556 {
557  TRACE("lock %p.\n", lock);
558  while (InterlockedCompareExchangePointer( (void **)lock, (void *)1, (void *)0 ))
559  small_pause();
560 }
561 
562 /***********************************************************************
563  * KeReleaseSpinLockFromDpcLevel (NTOSKRNL.EXE.@)
564  */
566 {
567  TRACE("lock %p.\n", lock);
568  InterlockedExchangePointer( (void **)lock, 0 );
569 }
570 
571 #define QUEUED_SPINLOCK_OWNED 0x2
572 
573 /***********************************************************************
574  * KeAcquireInStackQueuedSpinLockAtDpcLevel (NTOSKRNL.EXE.@)
575  */
578 {
579  KSPIN_LOCK_QUEUE *tail;
580 
581  TRACE("lock %p, queue %p.\n", lock, queue);
582 
583  queue->LockQueue.Next = NULL;
584 
585  if (!(tail = InterlockedExchangePointer( (void **)lock, &queue->LockQueue )))
586  queue->LockQueue.Lock = (KSPIN_LOCK *)((ULONG_PTR)lock | QUEUED_SPINLOCK_OWNED);
587  else
588  {
589  queue->LockQueue.Lock = lock;
590  InterlockedExchangePointer( (void **)&tail->Next, &queue->LockQueue );
591 
592  while (!((ULONG_PTR)InterlockedCompareExchangePointer( (void **)&queue->LockQueue.Lock, 0, 0 )
594  {
595  small_pause();
596  }
597  }
598 }
599 
600 /***********************************************************************
601  * KeReleaseInStackQueuedSpinLockFromDpcLevel (NTOSKRNL.EXE.@)
602  */
605 {
606  KSPIN_LOCK *lock = (KSPIN_LOCK *)((ULONG_PTR)queue->LockQueue.Lock & ~~QUEUED_SPINLOCK_OWNED);
607  KSPIN_LOCK_QUEUE *next;
608 
609  TRACE("lock %p, queue %p.\n", lock, queue);
610 
611  queue->LockQueue.Lock = NULL;
612 
613  if (!(next = queue->LockQueue.Next))
614  {
615  /* If we are truly the last in the queue, the lock will point to us. */
616  if (InterlockedCompareExchangePointer( (void **)lock, NULL, &queue->LockQueue ) == queue)
617  return;
618 
619  /* Otherwise, someone just queued themselves, but hasn't yet set
620  * themselves as successor. Spin waiting for them to do so. */
621  while (!(next = queue->LockQueue.Next))
622  small_pause();
623  }
624 
625  InterlockedExchangePointer( (void **)&next->Lock, (KSPIN_LOCK *)((ULONG_PTR)lock | QUEUED_SPINLOCK_OWNED) );
626 }
627 
628 #ifndef __i386__
629 /***********************************************************************
630  * KeReleaseSpinLock (NTOSKRNL.EXE.@)
631  */
633 {
634  TRACE("lock %p, irql %u.\n", lock, irql);
636 }
637 
638 /***********************************************************************
639  * KeAcquireSpinLockRaiseToDpc (NTOSKRNL.EXE.@)
640  */
642 {
643  TRACE("lock %p.\n", lock);
645  return 0;
646 }
647 
648 /***********************************************************************
649  * KeAcquireInStackQueuedSpinLock (NTOSKRNL.EXE.@)
650  */
652 {
653  TRACE("lock %p, queue %p.\n", lock, queue);
655 }
656 
657 /***********************************************************************
658  * KeReleaseInStackQueuedSpinLock (NTOSKRNL.EXE.@)
659  */
661 {
662  TRACE("queue %p.\n", queue);
664 }
665 #endif
666 
667 /***********************************************************************
668  * KeInitializeApc (NTOSKRNL.EXE.@)
669  */
671  PKRUNDOWN_ROUTINE rundown_routine, PKNORMAL_ROUTINE normal_routine, KPROCESSOR_MODE apc_mode, PVOID ctx)
672 {
673  TRACE("apc %p thread %p env %u krnl_routine %p rundown_routine %p normal_routine %p apc_mode %u ctx %p\n",
674  apc, thread, env, krnl_routine, rundown_routine, normal_routine, apc_mode, ctx);
675 
676  if (env != OriginalApcEnvironment)
677  FIXME("Unhandled APC_ENVIRONMENT\n");
678 
679  apc->Type = 18;
680  apc->Size = sizeof(*apc);
681  apc->Thread = thread;
682  apc->ApcStateIndex = env;
683  apc->KernelRoutine = krnl_routine;
684  apc->RundownRoutine = rundown_routine;
685  apc->NormalRoutine = normal_routine;
686  apc->Inserted = FALSE;
687  if (apc->NormalRoutine)
688  {
689  apc->ApcMode = apc_mode;
690  apc->NormalContext = ctx;
691  }
692  else
693  {
694  apc->ApcMode = KernelMode;
695  apc->NormalContext = NULL;
696  }
697 }
698 
699 /***********************************************************************
700  * KeTestAlertThread (NTOSKRNL.EXE.@)
701  */
703 {
704  FIXME("stub! %u\n", mode);
705  return TRUE;
706 }
707 
708 /***********************************************************************
709  * KeAlertThread (NTOSKRNL.EXE.@)
710  */
712 {
713  FIXME("stub! %p mode %u\n", thread, mode);
714  return TRUE;
715 }
716 
718 
719 /***********************************************************************
720  * IoAcquireCancelSpinLock (NTOSKRNL.EXE.@)
721  */
723 {
724  TRACE("irql %p.\n", irql);
725  KeAcquireSpinLock( &cancel_lock, irql );
726 }
727 
728 /***********************************************************************
729  * IoReleaseCancelSpinLock (NTOSKRNL.EXE.@)
730  */
732 {
733  TRACE("irql %u.\n", irql);
734  KeReleaseSpinLock( &cancel_lock, irql );
735 }
736 
737 /***********************************************************************
738  * ExfInterlockedRemoveHeadList (NTOSKRNL.EXE.@)
739  */
742 {
743  return ExInterlockedRemoveHeadList( list, lock );
744 }
745 
746 /***********************************************************************
747  * ExInterlockedRemoveHeadList (NTOSKRNL.EXE.@)
748  */
750 {
751  LIST_ENTRY *ret;
752  KIRQL irql;
753 
754  TRACE("list %p, lock %p.\n", list, lock);
755 
756  KeAcquireSpinLock( lock, &irql );
757  ret = RemoveHeadList( list );
758  KeReleaseSpinLock( lock, irql );
759 
760  return ret;
761 }
762 
763 
764 /***********************************************************************
765  * InterlockedPopEntrySList (NTOSKRNL.EXE.@)
766  */
769 {
771 }
772 
773 
774 /***********************************************************************
775  * InterlockedPushEntrySList (NTOSKRNL.EXE.@)
776  */
779 {
780  return RtlInterlockedPushEntrySList( list, entry );
781 }
782 
783 
784 /***********************************************************************
785  * ExInterlockedPopEntrySList (NTOSKRNL.EXE.@)
786  */
789 {
791 }
792 
793 
794 /***********************************************************************
795  * ExInterlockedPushEntrySList (NTOSKRNL.EXE.@)
796  */
799 {
800  return RtlInterlockedPushEntrySList( list, entry );
801 }
802 
803 
804 /***********************************************************************
805  * ExInterlockedFlushSList (NTOSKRNL.EXE.@)
806  */
809 {
810  return RtlInterlockedFlushSList( list );
811 }
812 
813 
814 /***********************************************************************
815  * ExAcquireFastMutexUnsafe (NTOSKRNL.EXE.@)
816  */
819 {
820  LONG count;
821 
822  TRACE("mutex %p.\n", mutex);
823 
824  count = InterlockedDecrement( &mutex->Count );
825  if (count < 0)
827 }
828 
829 /***********************************************************************
830  * ExReleaseFastMutexUnsafe (NTOSKRNL.EXE.@)
831  */
834 {
835  LONG count;
836 
837  TRACE("mutex %p.\n", mutex);
838 
839  count = InterlockedIncrement( &mutex->Count );
840  if (count < 1)
841  KeSetEvent( &mutex->Event, IO_NO_INCREMENT, FALSE );
842 }
843 
844 #ifndef __i386__
845 
846 /***********************************************************************
847  * ExAcquireFastMutex (NTOSKRNL.@)
848  */
850 {
851  /* FIXME: lower IRQL */
853 }
854 
855 /***********************************************************************
856  * ExReleaseFastMutex (NTOSKRNL.@)
857  */
859 {
861  /* FIXME: restore IRQL */
862 }
863 
864 #endif /* __i386__ */
865 
866 /* Use of the fields of an ERESOURCE structure seems to vary wildly between
867  * Windows versions. The below implementation uses them as follows:
868  *
869  * OwnerTable - contains a list of shared owners, including threads which do
870  * not currently own the resource
871  * OwnerTable[i].OwnerThread - shared owner TID
872  * OwnerTable[i].OwnerCount - recursion count of this shared owner (may be 0)
873  * OwnerEntry.OwnerThread - the owner TID if exclusively owned
874  * OwnerEntry.TableSize - the number of entries in OwnerTable, including threads
875  * which do not currently own the resource
876  * ActiveEntries - total number of acquisitions (incl. recursive ones)
877  */
878 
879 /***********************************************************************
880  * ExInitializeResourceLite (NTOSKRNL.EXE.@)
881  */
883 {
884  TRACE("resource %p.\n", resource);
885  memset(resource, 0, sizeof(*resource));
886  return STATUS_SUCCESS;
887 }
888 
889 /***********************************************************************
890  * ExDeleteResourceLite (NTOSKRNL.EXE.@)
891  */
893 {
894  TRACE("resource %p.\n", resource);
895  heap_free(resource->OwnerTable);
896  heap_free(resource->ExclusiveWaiters);
897  heap_free(resource->SharedWaiters);
898  return STATUS_SUCCESS;
899 }
900 
901 /* Find an existing entry in the shared owner list, or create a new one. */
903 {
904  ULONG i, count;
905 
906  for (i = 0; i < resource->OwnerEntry.TableSize; ++i)
907  {
908  if (resource->OwnerTable[i].OwnerThread == thread)
909  return &resource->OwnerTable[i];
910  }
911 
912  count = ++resource->OwnerEntry.TableSize;
913  resource->OwnerTable = heap_realloc(resource->OwnerTable, count * sizeof(*resource->OwnerTable));
914  resource->OwnerTable[count - 1].OwnerThread = thread;
915  resource->OwnerTable[count - 1].OwnerCount = 0;
916 
917  return &resource->OwnerTable[count - 1];
918 }
919 
920 /***********************************************************************
921  * ExAcquireResourceExclusiveLite (NTOSKRNL.EXE.@)
922  */
924 {
925  KIRQL irql;
926 
927  TRACE("resource %p, wait %u.\n", resource, wait);
928 
929  KeAcquireSpinLock( &resource->SpinLock, &irql );
930 
931  if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread())
932  {
933  resource->ActiveEntries++;
934  KeReleaseSpinLock( &resource->SpinLock, irql );
935  return TRUE;
936  }
937  /* In order to avoid a race between waiting for the ExclusiveWaiters event
938  * and grabbing the lock, do not grab the resource if it is unclaimed but
939  * has waiters; instead queue ourselves. */
940  else if (!resource->ActiveEntries && !resource->NumberOfExclusiveWaiters && !resource->NumberOfSharedWaiters)
941  {
943  resource->OwnerEntry.OwnerThread = (ERESOURCE_THREAD)KeGetCurrentThread();
944  resource->ActiveEntries++;
945  KeReleaseSpinLock( &resource->SpinLock, irql );
946  return TRUE;
947  }
948  else if (!wait)
949  {
950  KeReleaseSpinLock( &resource->SpinLock, irql );
951  return FALSE;
952  }
953 
954  if (!resource->ExclusiveWaiters)
955  {
956  resource->ExclusiveWaiters = heap_alloc( sizeof(*resource->ExclusiveWaiters) );
957  KeInitializeEvent( resource->ExclusiveWaiters, SynchronizationEvent, FALSE );
958  }
959  resource->NumberOfExclusiveWaiters++;
960 
961  KeReleaseSpinLock( &resource->SpinLock, irql );
962 
963  KeWaitForSingleObject( resource->ExclusiveWaiters, Executive, KernelMode, FALSE, NULL );
964 
965  KeAcquireSpinLock( &resource->SpinLock, &irql );
966 
968  resource->OwnerEntry.OwnerThread = (ERESOURCE_THREAD)KeGetCurrentThread();
969  resource->ActiveEntries++;
970  resource->NumberOfExclusiveWaiters--;
971 
972  KeReleaseSpinLock( &resource->SpinLock, irql );
973 
974  return TRUE;
975 }
976 
977 /***********************************************************************
978  * ExAcquireResourceSharedLite (NTOSKRNL.EXE.@)
979  */
981 {
982  OWNER_ENTRY *entry;
983  KIRQL irql;
984 
985  TRACE("resource %p, wait %u.\n", resource, wait);
986 
987  KeAcquireSpinLock( &resource->SpinLock, &irql );
988 
990 
991  if (resource->Flag & ResourceOwnedExclusive)
992  {
993  if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread())
994  {
995  /* We own the resource exclusively, so increase recursion. */
996  resource->ActiveEntries++;
997  KeReleaseSpinLock( &resource->SpinLock, irql );
998  return TRUE;
999  }
1000  }
1001  else if (entry->OwnerCount || !resource->NumberOfExclusiveWaiters)
1002  {
1003  /* Either we already own the resource shared, or there are no exclusive
1004  * owners or waiters, so we can grab it shared. */
1005  entry->OwnerCount++;
1006  resource->ActiveEntries++;
1007  KeReleaseSpinLock( &resource->SpinLock, irql );
1008  return TRUE;
1009  }
1010 
1011  if (!wait)
1012  {
1013  KeReleaseSpinLock( &resource->SpinLock, irql );
1014  return FALSE;
1015  }
1016 
1017  if (!resource->SharedWaiters)
1018  {
1019  resource->SharedWaiters = heap_alloc( sizeof(*resource->SharedWaiters) );
1020  KeInitializeSemaphore( resource->SharedWaiters, 0, INT_MAX );
1021  }
1022  resource->NumberOfSharedWaiters++;
1023 
1024  KeReleaseSpinLock( &resource->SpinLock, irql );
1025 
1027 
1028  KeAcquireSpinLock( &resource->SpinLock, &irql );
1029 
1030  entry->OwnerCount++;
1031  resource->ActiveEntries++;
1032  resource->NumberOfSharedWaiters--;
1033 
1034  KeReleaseSpinLock( &resource->SpinLock, irql );
1035 
1036  return TRUE;
1037 }
1038 
1039 /***********************************************************************
1040  * ExAcquireSharedStarveExclusive (NTOSKRNL.EXE.@)
1041  */
1043 {
1044  OWNER_ENTRY *entry;
1045  KIRQL irql;
1046 
1047  TRACE("resource %p, wait %u.\n", resource, wait);
1048 
1049  KeAcquireSpinLock( &resource->SpinLock, &irql );
1050 
1052 
1053  if (resource->Flag & ResourceOwnedExclusive)
1054  {
1055  if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread())
1056  {
1057  resource->ActiveEntries++;
1058  KeReleaseSpinLock( &resource->SpinLock, irql );
1059  return TRUE;
1060  }
1061  }
1062  /* We are starving exclusive waiters, but we cannot steal the resource out
1063  * from under an exclusive waiter who is about to acquire it. (Because of
1064  * locking, and because exclusive waiters are always waked first, this is
1065  * guaranteed to be the case if the resource is unowned and there are
1066  * exclusive waiters.) */
1067  else if (!(!resource->ActiveEntries && resource->NumberOfExclusiveWaiters))
1068  {
1069  entry->OwnerCount++;
1070  resource->ActiveEntries++;
1071  KeReleaseSpinLock( &resource->SpinLock, irql );
1072  return TRUE;
1073  }
1074 
1075  if (!wait)
1076  {
1077  KeReleaseSpinLock( &resource->SpinLock, irql );
1078  return FALSE;
1079  }
1080 
1081  if (!resource->SharedWaiters)
1082  {
1083  resource->SharedWaiters = heap_alloc( sizeof(*resource->SharedWaiters) );
1084  KeInitializeSemaphore( resource->SharedWaiters, 0, INT_MAX );
1085  }
1086  resource->NumberOfSharedWaiters++;
1087 
1088  KeReleaseSpinLock( &resource->SpinLock, irql );
1089 
1091 
1092  KeAcquireSpinLock( &resource->SpinLock, &irql );
1093 
1094  entry->OwnerCount++;
1095  resource->ActiveEntries++;
1096  resource->NumberOfSharedWaiters--;
1097 
1098  KeReleaseSpinLock( &resource->SpinLock, irql );
1099 
1100  return TRUE;
1101 }
1102 
1103 /***********************************************************************
1104  * ExAcquireSharedWaitForExclusive (NTOSKRNL.EXE.@)
1105  */
1107 {
1108  OWNER_ENTRY *entry;
1109  KIRQL irql;
1110 
1111  TRACE("resource %p, wait %u.\n", resource, wait);
1112 
1113  KeAcquireSpinLock( &resource->SpinLock, &irql );
1114 
1116 
1117  if (resource->Flag & ResourceOwnedExclusive)
1118  {
1119  if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread())
1120  {
1121  /* We own the resource exclusively, so increase recursion. */
1122  resource->ActiveEntries++;
1123  KeReleaseSpinLock( &resource->SpinLock, irql );
1124  return TRUE;
1125  }
1126  }
1127  /* We may only grab the resource if there are no exclusive waiters, even if
1128  * we already own it shared. */
1129  else if (!resource->NumberOfExclusiveWaiters)
1130  {
1131  entry->OwnerCount++;
1132  resource->ActiveEntries++;
1133  KeReleaseSpinLock( &resource->SpinLock, irql );
1134  return TRUE;
1135  }
1136 
1137  if (!wait)
1138  {
1139  KeReleaseSpinLock( &resource->SpinLock, irql );
1140  return FALSE;
1141  }
1142 
1143  if (!resource->SharedWaiters)
1144  {
1145  resource->SharedWaiters = heap_alloc( sizeof(*resource->SharedWaiters) );
1146  KeInitializeSemaphore( resource->SharedWaiters, 0, INT_MAX );
1147  }
1148  resource->NumberOfSharedWaiters++;
1149 
1150  KeReleaseSpinLock( &resource->SpinLock, irql );
1151 
1153 
1154  KeAcquireSpinLock( &resource->SpinLock, &irql );
1155 
1156  entry->OwnerCount++;
1157  resource->ActiveEntries++;
1158  resource->NumberOfSharedWaiters--;
1159 
1160  KeReleaseSpinLock( &resource->SpinLock, irql );
1161 
1162  return TRUE;
1163 }
1164 
1165 /***********************************************************************
1166  * ExReleaseResourceForThreadLite (NTOSKRNL.EXE.@)
1167  */
1169 {
1170  OWNER_ENTRY *entry;
1171  KIRQL irql;
1172 
1173  TRACE("resource %p, thread %#lx.\n", resource, thread);
1174 
1175  KeAcquireSpinLock( &resource->SpinLock, &irql );
1176 
1177  if (resource->Flag & ResourceOwnedExclusive)
1178  {
1179  if (resource->OwnerEntry.OwnerThread == thread)
1180  {
1181  if (!--resource->ActiveEntries)
1182  {
1183  resource->OwnerEntry.OwnerThread = 0;
1184  resource->Flag &= ~~ResourceOwnedExclusive;
1185  }
1186  }
1187  else
1188  {
1189  ERR("Trying to release %p for thread %#lx, but resource is exclusively owned by %#lx.\n",
1190  resource, thread, resource->OwnerEntry.OwnerThread);
1191  return;
1192  }
1193  }
1194  else
1195  {
1197  if (entry->OwnerCount)
1198  {
1199  entry->OwnerCount--;
1200  resource->ActiveEntries--;
1201  }
1202  else
1203  {
1204  ERR("Trying to release %p for thread %#lx, but resource is not owned by that thread.\n", resource, thread);
1205  return;
1206  }
1207  }
1208 
1209  if (!resource->ActiveEntries)
1210  {
1211  if (resource->NumberOfExclusiveWaiters)
1212  {
1213  KeSetEvent( resource->ExclusiveWaiters, IO_NO_INCREMENT, FALSE );
1214  }
1215  else if (resource->NumberOfSharedWaiters)
1216  {
1217  KeReleaseSemaphore( resource->SharedWaiters, IO_NO_INCREMENT,
1218  resource->NumberOfSharedWaiters, FALSE );
1219  }
1220  }
1221 
1222  KeReleaseSpinLock( &resource->SpinLock, irql );
1223 }
1224 
1225 /***********************************************************************
1226  * ExReleaseResourceLite (NTOSKRNL.EXE.@)
1227  */
1230 {
1232 }
1233 
1234 /***********************************************************************
1235  * ExGetExclusiveWaiterCount (NTOSKRNL.EXE.@)
1236  */
1238 {
1239  ULONG count;
1240  KIRQL irql;
1241 
1242  TRACE("resource %p.\n", resource);
1243 
1244  KeAcquireSpinLock( &resource->SpinLock, &irql );
1245 
1246  count = resource->NumberOfExclusiveWaiters;
1247 
1248  KeReleaseSpinLock( &resource->SpinLock, irql );
1249 
1250  return count;
1251 }
1252 
1253 /***********************************************************************
1254  * ExGetSharedWaiterCount (NTOSKRNL.EXE.@)
1255  */
1257 {
1258  ULONG count;
1259  KIRQL irql;
1260 
1261  TRACE("resource %p.\n", resource);
1262 
1263  KeAcquireSpinLock( &resource->SpinLock, &irql );
1264 
1265  count = resource->NumberOfSharedWaiters;
1266 
1267  KeReleaseSpinLock( &resource->SpinLock, irql );
1268 
1269  return count;
1270 }
1271 
1272 /***********************************************************************
1273  * ExIsResourceAcquiredExclusiveLite (NTOSKRNL.EXE.@)
1274  */
1276 {
1277  BOOLEAN ret;
1278  KIRQL irql;
1279 
1280  TRACE("resource %p.\n", resource);
1281 
1282  KeAcquireSpinLock( &resource->SpinLock, &irql );
1283 
1284  ret = (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread());
1285 
1286  KeReleaseSpinLock( &resource->SpinLock, irql );
1287 
1288  return ret;
1289 }
1290 
1291 /***********************************************************************
1292  * ExIsResourceAcquiredSharedLite (NTOSKRNL.EXE.@)
1293  */
1295 {
1296  ULONG ret;
1297  KIRQL irql;
1298 
1299  TRACE("resource %p.\n", resource);
1300 
1301  KeAcquireSpinLock( &resource->SpinLock, &irql );
1302 
1303  if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread())
1304  ret = resource->ActiveEntries;
1305  else
1306  {
1308  ret = entry->OwnerCount;
1309  }
1310 
1311  KeReleaseSpinLock( &resource->SpinLock, irql );
1312 
1313  return ret;
1314 }
1315 
1316 /***********************************************************************
1317  * IoInitializeRemoveLockEx (NTOSKRNL.EXE.@)
1318  */
1320  ULONG max_minutes, ULONG max_count, ULONG size )
1321 {
1322  TRACE("lock %p, tag %#x, max_minutes %u, max_count %u, size %u.\n",
1323  lock, tag, max_minutes, max_count, size);
1324 
1326  lock->Common.Removed = FALSE;
1327  lock->Common.IoCount = 0;
1328 }
1329 
1330 /***********************************************************************
1331  * IoAcquireRemoveLockEx (NTOSKRNL.EXE.@)
1332  */
1334  const char *file, ULONG line, ULONG size )
1335 {
1336  TRACE("lock %p, tag %p, file %s, line %u, size %u.\n", lock, tag, debugstr_a(file), line, size);
1337 
1338  if (lock->Common.Removed)
1339  return STATUS_DELETE_PENDING;
1340 
1341  InterlockedIncrement( &lock->Common.IoCount );
1342  return STATUS_SUCCESS;
1343 }
1344 
1345 /***********************************************************************
1346  * IoReleaseRemoveLockEx (NTOSKRNL.EXE.@)
1347  */
1349 {
1350  LONG count;
1351 
1352  TRACE("lock %p, tag %p, size %u.\n", lock, tag, size);
1353 
1354  if (!(count = InterlockedDecrement( &lock->Common.IoCount )) && lock->Common.Removed)
1356  else if (count < 0)
1357  ERR("Lock %p is not acquired!\n", lock);
1358 }
1359 
1360 /***********************************************************************
1361  * IoReleaseRemoveLockAndWaitEx (NTOSKRNL.EXE.@)
1362  */
1364 {
1365  LONG count;
1366 
1367  TRACE("lock %p, tag %p, size %u.\n", lock, tag, size);
1368 
1369  lock->Common.Removed = TRUE;
1370 
1371  if (!(count = InterlockedDecrement( &lock->Common.IoCount )))
1373  else if (count < 0)
1374  ERR("Lock %p is not acquired!\n", lock);
1375  else if (count > 0)
1377 }
1378 
1380 {
1381  TRACE("timer %p, duetime %I64x, dpc %p.\n", timer, duetime.QuadPart, dpc);
1382 
1383  return KeSetTimerEx(timer, duetime, 0, dpc);
1384 }
event_type
Definition: android.h:110
#define DEFINE_FASTCALL1_WRAPPER(func)
Definition: asm.h:136
#define DEFINE_FASTCALL_WRAPPER(func, args)
Definition: asm.h:137
unsigned long ULONG_PTR
Definition: basetsd.h:130
LONG NTSTATUS
Definition: bcrypt.h:40
#define WINAPI
Definition: bcrypt.h:23
enum shader_type type
Definition: type.pm:7
#define ERR(...)
Definition: cocoa_app.h:61
static HINSTANCE instance
Definition: main.c:40
static WCHAR reason[128]
Definition: object.c:1941
BOOL CloseHandle(HANDLE handle)
Definition: process.c:390
PTP_TIMER CreateThreadpoolTimer(PTP_TIMER_CALLBACK callback, PVOID userdata, TP_CALLBACK_ENVIRON *environment)
Definition: thread.c:1167
void * memset(void *dst, int c, size_t n)
Definition: string.c:2588
NTSTATUS NtClose(HANDLE handle)
Definition: server.c:1666
static HANDLE thread
Definition: device.c:52
long BOOL
Definition: dxgitype.idl:24
static void heap_free(void *mem)
Definition: heap.h:44
static const event_info_t event_info[]
Definition: htmlevent.c:109
#define DECLARE_CRITICAL_SECTION(cs)
Definition: http.c:36
static const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: debug.h:344
#define WINE_DEFAULT_DEBUG_CHANNEL(ch)
Definition: debug.h:499
static HINF handles[16384]
Definition: infparse.c:48
HANDLE CreateMutexW(SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name)
Definition: sync.c:536
HANDLE CreateEventW(SECURITY_ATTRIBUTES *sa, BOOL manual_reset, BOOL initial_state, LPCWSTR name)
Definition: sync.c:391
BOOL ReleaseSemaphore(HANDLE handle, LONG count, LONG *previous)
Definition: sync.c:671
HANDLE CreateSemaphoreW(SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCWSTR name)
Definition: sync.c:621
BOOL SetEvent(HANDLE handle)
Definition: sync.c:504
BOOL ResetEvent(HANDLE handle)
Definition: sync.c:513
struct version_info info
Definition: version.c:140
#define INT_MAX
Definition: limits.h:26
basic_istream_char obj
Definition: ios.c:13778
enum _TIMER_TYPE TIMER_TYPE
@ NotificationEvent
Definition: ntdef.h:29
@ SynchronizationEvent
Definition: ntdef.h:30
@ WaitAll
Definition: ntdef.h:39
@ WaitAny
Definition: ntdef.h:40
enum _EVENT_TYPE EVENT_TYPE
enum _WAIT_TYPE WAIT_TYPE
@ NotificationTimer
Definition: ntdef.h:34
NTSTATUS NtDelayExecution(BOOLEAN alertable, const LARGE_INTEGER *timeout)
Definition: sync.c:1321
NTSTATUS NtWaitForMultipleObjects(DWORD count, const HANDLE *handles, BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout)
Definition: sync.c:1261
NTSTATUS NtResetEvent(HANDLE handle, LONG *prev_state)
Definition: sync.c:494
NTSTATUS NtCreateEvent(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN state)
Definition: sync.c:423
NTSTATUS NtSetEvent(HANDLE handle, LONG *prev_state)
Definition: sync.c:475
NTSTATUS NtQueryEvent(HANDLE handle, EVENT_INFORMATION_CLASS class, void *info, ULONG len, ULONG *ret_len)
Definition: sync.c:542
void * alloc_kernel_object(POBJECT_TYPE type, HANDLE handle, SIZE_T size, LONG ref)
Definition: ntoskrnl.c:154
PRKTHREAD KeGetCurrentThread(void)
Definition: ntoskrnl.c:2339
NTSTATUS kernel_object_from_handle(HANDLE handle, POBJECT_TYPE type, void **ret)
Definition: ntoskrnl.c:273
NTSTATUS ObOpenObjectByPointer(void *obj, ULONG attr, ACCESS_STATE *access_state, ACCESS_MASK access, POBJECT_TYPE type, KPROCESSOR_MODE mode, HANDLE *handle)
Definition: ntoskrnl.c:372
NTSTATUS ExInitializeResourceLite(ERESOURCE *resource)
Definition: sync.c:882
void ExAcquireFastMutexUnsafe(FAST_MUTEX *mutex)
Definition: sync.c:818
ULONG ExGetExclusiveWaiterCount(ERESOURCE *resource)
Definition: sync.c:1237
static CRITICAL_SECTION sync_cs
Definition: sync.c:52
static KSPIN_LOCK cancel_lock
Definition: sync.c:717
void IoReleaseRemoveLockAndWaitEx(IO_REMOVE_LOCK *lock, void *tag, ULONG size)
Definition: sync.c:1363
void KeInitializeTimerEx(KTIMER *timer, TIMER_TYPE type)
Definition: sync.c:437
void KeReleaseInStackQueuedSpinLockFromDpcLevel(KLOCK_QUEUE_HANDLE *queue)
Definition: sync.c:604
LONG KeReleaseSemaphore(PRKSEMAPHORE semaphore, KPRIORITY increment, LONG count, BOOLEAN wait)
Definition: sync.c:354
PSINGLE_LIST_ENTRY NTOSKRNL_ExInterlockedFlushSList(PSLIST_HEADER list)
Definition: sync.c:808
static void * create_event_object(HANDLE handle)
Definition: sync.c:197
void ExReleaseResourceLite(ERESOURCE *resource)
Definition: sync.c:1229
static OWNER_ENTRY * resource_get_shared_entry(ERESOURCE *resource, ERESOURCE_THREAD thread)
Definition: sync.c:902
void KeAcquireSpinLockAtDpcLevel(KSPIN_LOCK *lock)
Definition: sync.c:555
void ExReleaseFastMutexUnsafe(FAST_MUTEX *mutex)
Definition: sync.c:833
void ExAcquireFastMutex(FAST_MUTEX *mutex)
Definition: sync.c:849
void KeInitializeApc(PRKAPC apc, PRKTHREAD thread, KAPC_ENVIRONMENT env, PKKERNEL_ROUTINE krnl_routine, PKRUNDOWN_ROUTINE rundown_routine, PKNORMAL_ROUTINE normal_routine, KPROCESSOR_MODE apc_mode, PVOID ctx)
Definition: sync.c:670
BOOLEAN ExAcquireSharedWaitForExclusive(ERESOURCE *resource, BOOLEAN wait)
Definition: sync.c:1106
BOOLEAN ExIsResourceAcquiredExclusiveLite(ERESOURCE *resource)
Definition: sync.c:1275
void KeReleaseSpinLockFromDpcLevel(KSPIN_LOCK *lock)
Definition: sync.c:565
NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE mode, BOOLEAN alertable, LARGE_INTEGER *timeout)
Definition: sync.c:528
PSINGLE_LIST_ENTRY NTOSKRNL_InterlockedPopEntrySList(PSLIST_HEADER list)
Definition: sync.c:768
void KeAcquireInStackQueuedSpinLockAtDpcLevel(KSPIN_LOCK *lock, KLOCK_QUEUE_HANDLE *queue)
Definition: sync.c:577
LIST_ENTRY * ExInterlockedRemoveHeadList(LIST_ENTRY *list, KSPIN_LOCK *lock)
Definition: sync.c:749
void ExReleaseFastMutex(FAST_MUTEX *mutex)
Definition: sync.c:858
BOOLEAN KeSetTimerEx(KTIMER *timer, LARGE_INTEGER duetime, LONG period, KDPC *dpc)
Definition: sync.c:460
void IoInitializeRemoveLockEx(IO_REMOVE_LOCK *lock, ULONG tag, ULONG max_minutes, ULONG max_count, ULONG size)
Definition: sync.c:1319
void KeAcquireInStackQueuedSpinLock(KSPIN_LOCK *lock, KLOCK_QUEUE_HANDLE *queue)
Definition: sync.c:651
void KeReleaseInStackQueuedSpinLock(KLOCK_QUEUE_HANDLE *queue)
Definition: sync.c:660
void KeReleaseSpinLock(KSPIN_LOCK *lock, KIRQL irql)
Definition: sync.c:632
void IoReleaseCancelSpinLock(KIRQL irql)
Definition: sync.c:731
void ExReleaseResourceForThreadLite(ERESOURCE *resource, ERESOURCE_THREAD thread)
Definition: sync.c:1168
BOOLEAN KeSetTimer(KTIMER *timer, LARGE_INTEGER duetime, KDPC *dpc)
Definition: sync.c:1379
NTSTATUS IoAcquireRemoveLockEx(IO_REMOVE_LOCK *lock, void *tag, const char *file, ULONG line, ULONG size)
Definition: sync.c:1333
PKEVENT IoCreateSynchronizationEvent(UNICODE_STRING *name, HANDLE *ret_handle)
Definition: sync.c:222
static void ke_timer_complete_proc(PTP_CALLBACK_INSTANCE instance, void *timer_, PTP_TIMER tp_timer)
Definition: sync.c:415
BOOLEAN ExAcquireSharedStarveExclusive(ERESOURCE *resource, BOOLEAN wait)
Definition: sync.c:1042
void IoReleaseRemoveLockEx(IO_REMOVE_LOCK *lock, void *tag, ULONG size)
Definition: sync.c:1348
LONG KeReadStateEvent(PRKEVENT event)
Definition: sync.c:318
ULONG ExGetSharedWaiterCount(ERESOURCE *resource)
Definition: sync.c:1256
NTSTATUS KeWaitForSingleObject(void *obj, KWAIT_REASON reason, KPROCESSOR_MODE mode, BOOLEAN alertable, LARGE_INTEGER *timeout)
Definition: sync.c:168
void KeInitializeMutex(PRKMUTEX mutex, ULONG level)
Definition: sync.c:384
LONG KeResetEvent(PRKEVENT event)
Definition: sync.c:279
void KeClearEvent(PRKEVENT event)
Definition: sync.c:310
ULONG ExIsResourceAcquiredSharedLite(ERESOURCE *resource)
Definition: sync.c:1294
void IoAcquireCancelSpinLock(KIRQL *irql)
Definition: sync.c:722
void KeInitializeEvent(PRKEVENT event, EVENT_TYPE type, BOOLEAN state)
Definition: sync.c:187
PLIST_ENTRY ExfInterlockedRemoveHeadList(LIST_ENTRY *list, KSPIN_LOCK *lock)
Definition: sync.c:741
BOOLEAN KeCancelTimer(KTIMER *timer)
Definition: sync.c:490
PSINGLE_LIST_ENTRY NTOSKRNL_ExInterlockedPushEntrySList(PSLIST_HEADER list, PSINGLE_LIST_ENTRY entry, PKSPIN_LOCK lock)
Definition: sync.c:798
BOOLEAN ExAcquireResourceExclusiveLite(ERESOURCE *resource, BOOLEAN wait)
Definition: sync.c:923
KIRQL KeAcquireSpinLockRaiseToDpc(KSPIN_LOCK *lock)
Definition: sync.c:641
static const WCHAR semaphore_type_name[]
Definition: sync.c:372
void KeInitializeSemaphore(PRKSEMAPHORE semaphore, LONG count, LONG limit)
Definition: sync.c:340
LONG KeReleaseMutex(PRKMUTEX mutex, BOOLEAN wait)
Definition: sync.c:397
NTSTATUS ExDeleteResourceLite(ERESOURCE *resource)
Definition: sync.c:892
POBJECT_TYPE ExEventObjectType
Definition: sync.c:217
static struct _OBJECT_TYPE semaphore_type
Definition: sync.c:374
void KeInitializeSpinLock(KSPIN_LOCK *lock)
Definition: sync.c:537
PSINGLE_LIST_ENTRY NTOSKRNL_InterlockedPushEntrySList(PSLIST_HEADER list, PSINGLE_LIST_ENTRY entry)
Definition: sync.c:778
BOOLEAN KeTestAlertThread(KPROCESSOR_MODE mode)
Definition: sync.c:702
static const WCHAR event_type_name[]
Definition: sync.c:210
BOOLEAN ExAcquireResourceSharedLite(ERESOURCE *resource, BOOLEAN wait)
Definition: sync.c:980
void KeInitializeTimer(KTIMER *timer)
Definition: sync.c:452
LONG KeSetEvent(PRKEVENT event, KPRIORITY increment, BOOLEAN wait)
Definition: sync.c:248
NTSTATUS KeWaitForMutexObject(PRKMUTEX mutex, KWAIT_REASON reason, KPROCESSOR_MODE mode, BOOLEAN alertable, LARGE_INTEGER *timeout)
Definition: sync.c:177
#define QUEUED_SPINLOCK_OWNED
Definition: sync.c:571
static struct _OBJECT_TYPE event_type
Definition: sync.c:212
static void small_pause(void)
Definition: sync.c:543
BOOLEAN KeAlertThread(PKTHREAD thread, KPROCESSOR_MODE mode)
Definition: sync.c:711
NTSTATUS KeWaitForMultipleObjects(ULONG count, void *pobjs[], WAIT_TYPE wait_type, KWAIT_REASON reason, KPROCESSOR_MODE mode, BOOLEAN alertable, LARGE_INTEGER *timeout, KWAIT_BLOCK *wait_blocks)
Definition: sync.c:57
POBJECT_TYPE ExSemaphoreObjectType
Definition: sync.c:379
@ TYPE_MANUAL_EVENT
Definition: sync.c:44
@ TYPE_SEMAPHORE
Definition: sync.c:47
@ TYPE_AUTO_EVENT
Definition: sync.c:45
@ TYPE_MANUAL_TIMER
Definition: sync.c:48
@ TYPE_AUTO_TIMER
Definition: sync.c:49
@ TYPE_MUTEX
Definition: sync.c:46
PSINGLE_LIST_ENTRY NTOSKRNL_ExInterlockedPopEntrySList(PSLIST_HEADER list, PKSPIN_LOCK lock)
Definition: sync.c:788
PSecurityUserData *typedef PSECPKG_EXTENDED_INFORMATION *typedef PVOID
Definition: ntsecpkg.h:378
PSecurityUserData *typedef PSECPKG_EXTENDED_INFORMATION *typedef ULONG
Definition: ntsecpkg.h:377
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:296
#define STATUS_SUCCESS
Definition: ntstatus.h:30
char * tag
Definition: main.c:53
void * heap_realloc(void *op, size_t len)
Definition: util.c:38
void * heap_alloc(size_t len)
Definition: util.c:30
PSINGLE_LIST_ENTRY RtlInterlockedFlushSList(PSLIST_HEADER list)
Definition: rtl.c:1620
PSINGLE_LIST_ENTRY RtlInterlockedPopEntrySList(PSLIST_HEADER list)
Definition: rtl.c:1681
PSINGLE_LIST_ENTRY RtlInterlockedPushEntrySList(PSLIST_HEADER list, PSINGLE_LIST_ENTRY entry)
Definition: rtl.c:1650
void RtlZeroMemory(void *Destination, SIZE_T Length)
Definition: rtl.c:506
WELL_KNOWN_SID_TYPE Type
Definition: security.c:86
LIST_ENTRY WaitListHead
Definition: wdm.h:72
LONG SignalState
Definition: wdm.h:71
IO_REMOVE_LOCK_COMMON_BLOCK Common
Definition: wdm.h:1347
Definition: wdm.h:494
PVOID NormalContext
Definition: wdm.h:503
KPROCESSOR_MODE ApcMode
Definition: wdm.h:507
struct _KTHREAD * Thread
Definition: wdm.h:498
BOOLEAN Inserted
Definition: wdm.h:508
PKNORMAL_ROUTINE NormalRoutine
Definition: wdm.h:502
CCHAR ApcStateIndex
Definition: wdm.h:506
PKKERNEL_ROUTINE KernelRoutine
Definition: wdm.h:500
CSHORT Size
Definition: wdm.h:496
PKRUNDOWN_ROUTINE RundownRoutine
Definition: wdm.h:501
CSHORT Type
Definition: wdm.h:495
Definition: wdm.h:84
PVOID SystemArgument2
Definition: wdm.h:92
PVOID SystemArgument1
Definition: wdm.h:91
PKDEFERRED_ROUTINE DeferredRoutine
Definition: wdm.h:89
PVOID DeferredContext
Definition: wdm.h:90
Definition: wdm.h:75
Definition: wdm.h:118
struct _KSPIN_LOCK_QUEUE *volatile Next
Definition: wdm.h:1367
volatile PKSPIN_LOCK Lock
Definition: wdm.h:1368
Definition: wdm.h:1163
Definition: winnt.h:836
struct _LIST_ENTRY * Blink
Definition: winnt.h:838
Definition: wdm.h:172
ULONG OwnerCount
Definition: wdm.h:181
Definition: cookie.c:202
Definition: filter.c:184
Definition: fci.c:123
Definition: parser.c:56
Definition: list.h:27
Definition: msvcp90.h:319
Definition: name.c:36
Definition: queue.c:172
Definition: ticket.c:41
Definition: thread.h:50
Definition: main.c:768
WINBASEAPI void WINAPI SetThreadpoolTimer(PTP_TIMER, FILETIME *, DWORD, DWORD)
WINBASEAPI void WINAPI CloseThreadpoolTimer(PTP_TIMER)
WINBASEAPI void WINAPI WaitForThreadpoolTimerCallbacks(PTP_TIMER, BOOL)
#define NULL
Definition: ungif.h:66
#define TRUE
Definition: ungif.h:59
#define FALSE
Definition: ungif.h:62
LONGLONG QuadPart
Definition: winnt.h:4948
VOID(WINAPI * PKKERNEL_ROUTINE)(IN struct _KAPC *Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2)
Definition: wdm.h:484
#define KernelMode
Definition: wdm.h:1620
VOID(WINAPI * PKRUNDOWN_ROUTINE)(IN struct _KAPC *Apc)
Definition: wdm.h:491
@ Executive
Definition: wdm.h:134
UCHAR KIRQL
Definition: wdm.h:465
#define IO_NO_INCREMENT
Definition: wdm.h:305
CCHAR KPROCESSOR_MODE
Definition: wdm.h:466
ULONG_PTR KSPIN_LOCK
Definition: wdm.h:44
@ OriginalApcEnvironment
Definition: wdm.h:469
ULONG_PTR * PKSPIN_LOCK
Definition: wdm.h:44
#define KeAcquireSpinLock(lock, irql)
Definition: wdm.h:1719
#define ResourceOwnedExclusive
Definition: wdm.h:189
VOID(WINAPI * PKNORMAL_ROUTINE)(IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: wdm.h:479
enum _KWAIT_REASON KWAIT_REASON
LONG KPRIORITY
Definition: wdm.h:42
ULONG_PTR ERESOURCE_THREAD
Definition: wdm.h:46
enum _KAPC_ENVIRONMENT KAPC_ENVIRONMENT
YY_BUFFER_STATE state
Definition: parser.l:85
DECLSPEC_IMPORT void WINAPI LeaveCriticalSection(CRITICAL_SECTION *lpCrit)
#define INVALID_HANDLE_VALUE
Definition: winbase.h:336
DECLSPEC_IMPORT void WINAPI EnterCriticalSection(CRITICAL_SECTION *lpCrit)
#define CALLBACK
Definition: windef.h:194
GLint mode
Definition: opengl.c:195
#define SYNCHRONIZE
Definition: winnt.h:5379
#define EVENT_QUERY_STATE
Definition: winnt.h:5398
BYTE BOOLEAN
Definition: winnt.h:453
struct _TP_CALLBACK_INSTANCE * PTP_CALLBACK_INSTANCE
Definition: winnt.h:6716
struct _TP_TIMER * PTP_TIMER
Definition: winnt.h:6786
#define PSLIST_ENTRY
Definition: winnt.h:880
unsigned short WCHAR
Definition: winnt.h:468
#define EVENT_MODIFY_STATE
Definition: winnt.h:5399
#define MAXIMUM_WAIT_OBJECTS
Definition: winnt.h:2665
#define EVENT_ALL_ACCESS
Definition: winnt.h:5400
#define FASTCALL
Definition: winnt.h:46
int LONG
Definition: winnt.h:459
struct _TP_TIMER TP_TIMER
Definition: winnt.h:6786
#define CONTAINING_RECORD(address, type, field)
Definition: winnt.h:826
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:2273
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: winternl.h:3772
@ EventBasicInformation
Definition: winternl.h:2411
static PLIST_ENTRY RemoveHeadList(PLIST_ENTRY le)
Definition: winternl.h:3822