- Invert CONFIG_SMP defines as requested by Hartmut
[reactos.git] / reactos / ntoskrnl / include / internal / ke.h
index d47d299..1b8e32a 100644 (file)
@@ -44,29 +44,177 @@ extern ULONG_PTR KERNEL_BASE;
 
 /* MACROS *************************************************************************/
 
-#define KeEnterCriticalRegion() \
-{ \
-    PKTHREAD _Thread = KeGetCurrentThread(); \
-    if (_Thread) _Thread->KernelApcDisable--; \
+/*
+ * On UP machines, we don't actually have a spinlock, we merely raise
+ * IRQL to DPC level.
+ */
+#ifdef CONFIG_SMP
+#define KeInitializeDispatcher() KeInitializeSpinLock(&DispatcherDatabaseLock);
+#define KeAcquireDispatcherDatabaseLock() KfAcquireSpinLock(&DispatcherDatabaseLock);
+#define KeAcquireDispatcherDatabaseLockAtDpcLevel() \
+    KeAcquireSpinLockAtDpcLevel (&DispatcherDatabaseLock);
+#define KeReleaseDispatcherDatabaseLockFromDpcLevel() \
+    KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock);
+#define KeReleaseDispatcherDatabaseLock(OldIrql) \
+    KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock); \
+    KiExitDispatcher(OldIrql);
+#else
+#define KeInitializeDispatcher()
+#define KeAcquireDispatcherDatabaseLock() KeRaiseIrqlToDpcLevel();
+#define KeReleaseDispatcherDatabaseLock(OldIrql) KiExitDispatcher(OldIrql);
+#define KeAcquireDispatcherDatabaseLockAtDpcLevel()
+#define KeReleaseDispatcherDatabaseLockFromDpcLevel()
+#endif
+
+/* The following macro initializes a dispatcher object's header */
+#define KeInitializeDispatcherHeader(Header, t, s, State)                   \
+{                                                                           \
+    (Header)->Type = t;                                                     \
+    (Header)->Absolute = 0;                                                 \
+    (Header)->Inserted = 0;                                                 \
+    (Header)->Size = s;                                                     \
+    (Header)->SignalState = State;                                          \
+    InitializeListHead(&((Header)->WaitListHead));                          \
 }
 
-#define KeLeaveCriticalRegion() \
-{ \
-    PKTHREAD _Thread = KeGetCurrentThread(); \
-    if((_Thread) && (++_Thread->KernelApcDisable == 0)) \
-    { \
-        if (!IsListEmpty(&_Thread->ApcState.ApcListHead[KernelMode])) \
-        { \
-            KiKernelApcDeliveryCheck(); \
-        } \
-    } \
+/* The following macro satisfies the wait of any dispatcher object */
+#define KiSatisfyObjectWait(Object, Thread)                                 \
+{                                                                           \
+    /* Special case for Mutants */                                          \
+    if ((Object)->Header.Type == MutantObject)                              \
+    {                                                                       \
+        /* Decrease the Signal State */                                     \
+        (Object)->Header.SignalState--;                                     \
+                                                                            \
+        /* Check if it's now non-signaled */                                \
+        if (!(Object)->Header.SignalState)                                  \
+        {                                                                   \
+            /* Set the Owner Thread */                                      \
+            (Object)->OwnerThread = Thread;                                 \
+                                                                            \
+            /* Disable APCs if needed */                                    \
+            Thread->KernelApcDisable -= (Object)->ApcDisable;               \
+                                                                            \
+            /* Check if it's abandoned */                                   \
+            if ((Object)->Abandoned)                                        \
+            {                                                               \
+                /* Unabandon it */                                          \
+                (Object)->Abandoned = FALSE;                                \
+                                                                            \
+                /* Return Status */                                         \
+                Thread->WaitStatus = STATUS_ABANDONED;                      \
+            }                                                               \
+                                                                            \
+            /* Insert it into the Mutant List */                            \
+            InsertHeadList(&Thread->MutantListHead,                         \
+                           &(Object)->MutantListEntry);                     \
+        }                                                                   \
+    }                                                                       \
+    else if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) ==               \
+             EventSynchronizationObject)                                    \
+    {                                                                       \
+        /* Synchronization Timers and Events just get un-signaled */        \
+        (Object)->Header.SignalState = 0;                                   \
+    }                                                                       \
+    else if ((Object)->Header.Type == SemaphoreObject)                      \
+    {                                                                       \
+        /* These ones can have multiple states, so we only decrease it */   \
+        (Object)->Header.SignalState--;                                     \
+    }                                                                       \
 }
 
-#define KEBUGCHECKWITHTF(a,b,c,d,e,f) \
-    DbgPrint("KeBugCheckWithTf at %s:%i\n",__FILE__,__LINE__), KeBugCheckWithTf(a,b,c,d,e,f)
+/* The following macro satisfies the wait of a mutant dispatcher object */
+#define KiSatisfyMutantWait(Object, Thread)                                 \
+{                                                                           \
+    /* Decrease the Signal State */                                         \
+    (Object)->Header.SignalState--;                                         \
+                                                                            \
+    /* Check if it's now non-signaled */                                    \
+    if (!(Object)->Header.SignalState)                                      \
+    {                                                                       \
+        /* Set the Owner Thread */                                          \
+        (Object)->OwnerThread = Thread;                                     \
+                                                                            \
+        /* Disable APCs if needed */                                        \
+        Thread->KernelApcDisable -= (Object)->ApcDisable;                   \
+                                                                            \
+        /* Check if it's abandoned */                                       \
+        if ((Object)->Abandoned)                                            \
+        {                                                                   \
+            /* Unabandon it */                                              \
+            (Object)->Abandoned = FALSE;                                    \
+                                                                            \
+            /* Return Status */                                             \
+            Thread->WaitStatus = STATUS_ABANDONED;                          \
+        }                                                                   \
+                                                                            \
+        /* Insert it into the Mutant List */                                \
+        InsertHeadList(&Thread->MutantListHead,                             \
+                       &(Object)->MutantListEntry);                         \
+    }                                                                       \
+}
+
+/* The following macro satisfies the wait of any nonmutant dispatcher object */
+#define KiSatisfyNonMutantWait(Object, Thread)                              \
+{                                                                           \
+    if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) ==                    \
+             EventSynchronizationObject)                                    \
+    {                                                                       \
+        /* Synchronization Timers and Events just get un-signaled */        \
+        (Object)->Header.SignalState = 0;                                   \
+    }                                                                       \
+    else if ((Object)->Header.Type == SemaphoreObject)                      \
+    {                                                                       \
+        /* These ones can have multiple states, so we only decrease it */   \
+        (Object)->Header.SignalState--;                                     \
+    }                                                                       \
+}
+
+/* The following macro satisfies multiple objects in a wait state */
+#define KiSatisifyMultipleObjectWaits(FirstBlock)                           \
+{                                                                           \
+    PKWAIT_BLOCK WaitBlock = FirstBlock;                                    \
+    PKTHREAD WaitThread = WaitBlock->Thread;                                \
+                                                                            \
+    /* Loop through all the Wait Blocks, and wake each Object */            \
+    do                                                                      \
+    {                                                                       \
+        /* Make sure it hasn't timed out */                                 \
+        if (WaitBlock->WaitKey != STATUS_TIMEOUT)                           \
+        {                                                                   \
+            /* Wake the Object */                                           \
+            KiSatisfyObjectWait((PKMUTANT)WaitBlock->Object, WaitThread);   \
+        }                                                                   \
+                                                                            \
+        /* Move to the next block */                                        \
+        WaitBlock = WaitBlock->NextWaitBlock;                               \
+    } while (WaitBlock != FirstBlock);                                      \
+}
+
+extern KSPIN_LOCK DispatcherDatabaseLock;
 
-#define MAXIMUM_PROCESSORS      32
+#define KeEnterCriticalRegion()                                             \
+{                                                                           \
+    PKTHREAD _Thread = KeGetCurrentThread();                                \
+    if (_Thread) _Thread->KernelApcDisable--;                               \
+}
+
+#define KeLeaveCriticalRegion()                                             \
+{                                                                           \
+    PKTHREAD _Thread = KeGetCurrentThread();                                \
+    if((_Thread) && (++_Thread->KernelApcDisable == 0))                     \
+    {                                                                       \
+        if (!IsListEmpty(&_Thread->ApcState.ApcListHead[KernelMode]) &&     \
+            (_Thread->SpecialApcDisable == 0))                              \
+        {                                                                   \
+            KiCheckForKernelApcDelivery();                                  \
+        }                                                                   \
+    }                                                                       \
+}
 
+#define KEBUGCHECKWITHTF(a,b,c,d,e,f) \
+    DbgPrint("KeBugCheckWithTf at %s:%i\n",__FILE__,__LINE__), \
+             KeBugCheckWithTf(a,b,c,d,e,f)
 
 /* INTERNAL KERNEL FUNCTIONS ************************************************/
 
@@ -84,14 +232,11 @@ VOID
 STDCALL
 KiDispatchThread(ULONG NewThreadStatus);
 
-/* Puts a Thread into a block state. */
-VOID
-STDCALL
-KiBlockThread(
-    PNTSTATUS Status,
-    UCHAR Alertable,
-    ULONG WaitMode,
-    UCHAR WaitReason
+/* Finds a new thread to run */
+NTSTATUS
+NTAPI
+KiSwapThread(
+    VOID
 );
 
 /* Removes a thread out of a block state. */
@@ -115,6 +260,10 @@ VOID
 STDCALL
 KiAdjustQuantumThread(IN PKTHREAD Thread);
 
+VOID
+FASTCALL
+KiExitDispatcher(KIRQL OldIrql);
+
 /* gmutex.c ********************************************************************/
 
 VOID
@@ -187,7 +336,7 @@ KeStartProfile(
     PVOID Buffer
 );
 
-VOID
+BOOLEAN
 STDCALL
 KeStopProfile(struct _KPROFILE* Profile);
 
@@ -242,26 +391,6 @@ KiExpireTimers(
     PVOID SystemArgument2
 );
 
-KIRQL
-inline
-FASTCALL
-KeAcquireDispatcherDatabaseLock(VOID);
-
-VOID
-__inline
-FASTCALL
-KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID);
-
-VOID
-__inline
-FASTCALL
-KeReleaseDispatcherDatabaseLock(KIRQL Irql);
-
-VOID
-__inline
-FASTCALL
-KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
-
 VOID
 STDCALL
 KeInitializeThread(
@@ -311,16 +440,6 @@ KeExpireTimers(
     PVOID Arg3
 );
 
-VOID
-__inline
-FASTCALL
-KeInitializeDispatcherHeader(
-    DISPATCHER_HEADER* Header,
-    ULONG Type,
-    ULONG Size,
-    ULONG SignalState
-);
-
 VOID
 NTAPI
 KeDumpStackFrames(PULONG Frame);
@@ -361,31 +480,18 @@ KiInsertTimer(
     LARGE_INTEGER DueTime
 );
 
-VOID
-inline
-FASTCALL
-KiSatisfyObjectWait(
-    PDISPATCHER_HEADER Object,
-    PKTHREAD Thread
-);
-
 BOOLEAN
-inline
+__inline
 FASTCALL
 KiIsObjectSignaled(
     PDISPATCHER_HEADER Object,
     PKTHREAD Thread
 );
 
-VOID
-inline
-FASTCALL
-KiSatisifyMultipleObjectWaits(PKWAIT_BLOCK WaitBlock);
-
 VOID
 FASTCALL
 KiWaitTest(
-    PDISPATCHER_HEADER Object,
+    PVOID Object,
     KPRIORITY Increment
 );
 
@@ -412,7 +518,7 @@ KiDeliverApc(
 
 VOID
 STDCALL
-KiKernelApcDeliveryCheck(VOID);
+KiCheckForKernelApcDelivery(VOID);
 
 LONG
 STDCALL
@@ -505,11 +611,6 @@ VOID
 NTAPI
 KeInitDispatcher(VOID);
 
-VOID
-__inline
-FASTCALL
-KeInitializeDispatcher(VOID);
-
 VOID
 NTAPI
 KiInitializeSystemClock(VOID);