mirror of
https://github.com/reactos/reactos.git
synced 2025-04-27 00:50:23 +00:00
- Add some definitions to ketypes.h
- Fix multiple bugs in KTHREAD/KPROCESS where signed char values were marked as unsigned (and define SCHAR in ntdef.h) - Change prototype of KiSwapThread for future compatibility. - Fix prototype of KeSetIdealProcessorThread. - Add KiAcquireDispatcherLock, KiReleaseDispatcherLock, KiAcquireDispatcherLockAtDpcLevel, KiReleaseDispatcherLockFromDpcLevel to ke_x.h for future use. - Add KiInsertDeferredReadyList, KiRescheduleThread, KiSetThreadSwapBusy, KiRundownThread, KiCheckDeferredReadyList for future use. - Add KiAcquirePrcbLock, KiReleasePrcbLock, KiAcquireThreadLock, KiReleaseThreadLock for future use. - Add KxQueueReadyThread, KiSelectReadyThread for future use. - Add KiComputeNewPriority for future use. svn path=/trunk/; revision=24022
This commit is contained in:
parent
098292d473
commit
d2cb3868b7
8 changed files with 553 additions and 51 deletions
|
@ -59,6 +59,13 @@ Author:
|
|||
//
|
||||
#define KI_USER_SHARED_DATA_PHYSICAL 0x41000
|
||||
|
||||
//
|
||||
// Quantum values and decrements
|
||||
//
|
||||
#define MAX_QUANTUM 0x7F
|
||||
#define WAIT_QUANTUM_DECREMENT 1
|
||||
#define CLOCK_QUANTUM_DECREMENT 3
|
||||
|
||||
//
|
||||
// Kernel Feature Bits
|
||||
//
|
||||
|
@ -679,13 +686,13 @@ typedef struct _KTHREAD
|
|||
volatile UCHAR NextProcessor;
|
||||
volatile UCHAR DeferredProcessor;
|
||||
UCHAR AdjustReason;
|
||||
UCHAR AdjustIncrement;
|
||||
SCHAR AdjustIncrement;
|
||||
KSPIN_LOCK ApcQueueLock;
|
||||
ULONG ContextSwitches;
|
||||
volatile UCHAR State;
|
||||
UCHAR NpxState;
|
||||
UCHAR WaitIrql;
|
||||
UCHAR WaitMode;
|
||||
SCHAR WaitMode;
|
||||
LONG WaitStatus;
|
||||
union
|
||||
{
|
||||
|
@ -695,7 +702,7 @@ typedef struct _KTHREAD
|
|||
UCHAR Alertable;
|
||||
UCHAR WaitNext;
|
||||
UCHAR WaitReason;
|
||||
UCHAR Priority;
|
||||
SCHAR Priority;
|
||||
UCHAR EnableStackSwap;
|
||||
volatile UCHAR SwapBusy;
|
||||
UCHAR Alerted[2];
|
||||
|
@ -752,7 +759,7 @@ typedef struct _KTHREAD
|
|||
struct
|
||||
{
|
||||
UCHAR WaitBlockFill1[47];
|
||||
UCHAR PreviousMode;
|
||||
SCHAR PreviousMode;
|
||||
};
|
||||
struct
|
||||
{
|
||||
|
@ -810,10 +817,10 @@ typedef struct _KTHREAD
|
|||
union
|
||||
{
|
||||
UCHAR SavedApcStateFill[23];
|
||||
CHAR FreezeCount;
|
||||
SCHAR FreezeCount;
|
||||
};
|
||||
};
|
||||
CHAR SuspendCount;
|
||||
SCHAR SuspendCount;
|
||||
UCHAR UserIdealProcessor;
|
||||
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
|
||||
union
|
||||
|
@ -838,7 +845,7 @@ typedef struct _KTHREAD
|
|||
struct
|
||||
{
|
||||
UCHAR SuspendApcFill0[1];
|
||||
CHAR Quantum;
|
||||
SCHAR Quantum;
|
||||
};
|
||||
struct
|
||||
{
|
||||
|
@ -888,6 +895,9 @@ typedef struct _KTHREAD
|
|||
} KTHREAD;
|
||||
#include <poppack.h>
|
||||
|
||||
#define ASSERT_THREAD(object) \
|
||||
ASSERT((((object)->Header.Type & KOBJECT_TYPE_MASK) == ThreadObject))
|
||||
|
||||
//
|
||||
// Kernel Process (KPROCESS)
|
||||
//
|
||||
|
@ -923,8 +933,8 @@ typedef struct _KPROCESS
|
|||
};
|
||||
ULONG ProcessFlags;
|
||||
};
|
||||
CHAR BasePriority;
|
||||
CHAR QuantumReset;
|
||||
SCHAR BasePriority;
|
||||
SCHAR QuantumReset;
|
||||
UCHAR State;
|
||||
UCHAR ThreadSeed;
|
||||
UCHAR PowerState;
|
||||
|
|
|
@ -64,6 +64,8 @@ typedef STRING CANSI_STRING;
|
|||
typedef PSTRING PCANSI_STRING;
|
||||
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
|
||||
typedef CONST CHAR *LPCCH, *PCCH;
|
||||
typedef signed char SCHAR;
|
||||
typedef SCHAR *PSCHAR;
|
||||
typedef enum _SECTION_INHERIT {
|
||||
ViewShare = 1,
|
||||
ViewUnmap = 2
|
||||
|
|
|
@ -132,28 +132,8 @@ extern VOID KiTrap2(VOID);
|
|||
|
||||
/* MACROS *************************************************************************/
|
||||
|
||||
/*
|
||||
* 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) \
|
||||
KiExitDispatcher(OldIrql);
|
||||
#else
|
||||
#define KeInitializeDispatcher()
|
||||
#define KeAcquireDispatcherDatabaseLock() KeRaiseIrqlToDpcLevel();
|
||||
#define KeReleaseDispatcherDatabaseLock(OldIrql) KiExitDispatcher(OldIrql);
|
||||
#define KeAcquireDispatcherDatabaseLockAtDpcLevel()
|
||||
#define KeReleaseDispatcherDatabaseLockFromDpcLevel()
|
||||
#endif
|
||||
|
||||
#define AFFINITY_MASK(Id) KiMask32Array[Id]
|
||||
#define PRIORITY_MASK(Id) KiMask32Array[Id]
|
||||
|
||||
/* The following macro initializes a dispatcher object's header */
|
||||
#define KeInitializeDispatcherHeader(Header, t, s, State) \
|
||||
|
@ -166,8 +146,6 @@ extern VOID KiTrap2(VOID);
|
|||
InitializeListHead(&((Header)->WaitListHead)); \
|
||||
}
|
||||
|
||||
extern KSPIN_LOCK DispatcherDatabaseLock;
|
||||
|
||||
#define KeEnterCriticalRegion() \
|
||||
{ \
|
||||
PKTHREAD _Thread = KeGetCurrentThread(); \
|
||||
|
@ -209,9 +187,11 @@ extern KSPIN_LOCK DispatcherDatabaseLock;
|
|||
|
||||
/* INTERNAL KERNEL FUNCTIONS ************************************************/
|
||||
|
||||
/* threadsch.c ********************************************************************/
|
||||
|
||||
/* Thread Scheduler Functions */
|
||||
#define KeInitializeDispatcher()
|
||||
#define KeAcquireDispatcherDatabaseLock() KeRaiseIrqlToDpcLevel();
|
||||
#define KeReleaseDispatcherDatabaseLock(OldIrql) KiExitDispatcher(OldIrql);
|
||||
#define KeAcquireDispatcherDatabaseLockAtDpcLevel()
|
||||
#define KeReleaseDispatcherDatabaseLockFromDpcLevel()
|
||||
|
||||
/* Readies a Thread for Execution. */
|
||||
BOOLEAN
|
||||
|
@ -225,9 +205,10 @@ KiDispatchThread(ULONG NewThreadStatus);
|
|||
|
||||
/* Finds a new thread to run */
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FASTCALL
|
||||
KiSwapThread(
|
||||
VOID
|
||||
IN PKTHREAD Thread,
|
||||
IN PKPRCB Prcb
|
||||
);
|
||||
|
||||
VOID
|
||||
|
@ -238,7 +219,7 @@ NTSTATUS
|
|||
NTAPI
|
||||
KeSuspendThread(PKTHREAD Thread);
|
||||
|
||||
NTSTATUS
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
KiSwapContext(
|
||||
IN PKTHREAD CurrentThread,
|
||||
|
@ -253,6 +234,23 @@ VOID
|
|||
FASTCALL
|
||||
KiExitDispatcher(KIRQL OldIrql);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiDeferredReadyThread(IN PKTHREAD Thread);
|
||||
|
||||
KAFFINITY
|
||||
NTAPI
|
||||
KiSetAffinityThread(
|
||||
IN PKTHREAD Thread,
|
||||
IN KAFFINITY Affinity
|
||||
);
|
||||
|
||||
PKTHREAD
|
||||
NTAPI
|
||||
KiSelectNextThread(
|
||||
IN PKPRCB Prcb
|
||||
);
|
||||
|
||||
/* gmutex.c ********************************************************************/
|
||||
|
||||
VOID
|
||||
|
@ -438,6 +436,30 @@ NTSTATUS
|
|||
NTAPI
|
||||
KeReleaseThread(PKTHREAD Thread);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiSuspendRundown(
|
||||
IN PKAPC Apc
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiSuspendNop(
|
||||
IN PKAPC Apc,
|
||||
IN PKNORMAL_ROUTINE *NormalRoutine,
|
||||
IN PVOID *NormalContext,
|
||||
IN PVOID *SystemArgument1,
|
||||
IN PVOID *SystemArgument2
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiSuspendThread(
|
||||
IN PVOID NormalContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2
|
||||
);
|
||||
|
||||
LONG
|
||||
NTAPI
|
||||
KeQueryBasePriorityThread(IN PKTHREAD Thread);
|
||||
|
@ -445,9 +467,9 @@ KeQueryBasePriorityThread(IN PKTHREAD Thread);
|
|||
VOID
|
||||
NTAPI
|
||||
KiSetPriorityThread(
|
||||
PKTHREAD Thread,
|
||||
KPRIORITY Priority,
|
||||
PBOOLEAN Released
|
||||
IN PKTHREAD Thread,
|
||||
IN KPRIORITY Priority,
|
||||
IN PBOOLEAN Released // hack
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
|
@ -825,6 +847,13 @@ KiInitSystem(
|
|||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
KiInsertQueueApc(
|
||||
IN PKAPC Apc,
|
||||
IN KPRIORITY PriorityBoost
|
||||
);
|
||||
|
||||
#include "ke_x.h"
|
||||
|
||||
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_KE_H */
|
||||
|
|
|
@ -248,3 +248,464 @@ KiRecalculateDueTime(IN PLARGE_INTEGER OriginalDueTime,
|
|||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
//
|
||||
// Thread Scheduling Routines
|
||||
//
|
||||
#ifndef _CONFIG_SMP
|
||||
KIRQL
|
||||
FORCEINLINE
|
||||
KiAcquireDispatcherLock(VOID)
|
||||
{
|
||||
/* Raise to DPC level */
|
||||
return KeRaiseIrqlToDpcLevel();
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
KiReleaseDispatcherLock(IN KIRQL OldIrql)
|
||||
{
|
||||
/* Just exit the dispatcher */
|
||||
KiExitDispatcher(OldIrql);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
KiAcquireDispatcherLockAtDpcLevel(VOID)
|
||||
{
|
||||
/* This is a no-op at DPC Level for UP systems */
|
||||
return;
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
KiReleaseDispatcherLockFromDpcLevel(VOID)
|
||||
{
|
||||
/* This is a no-op at DPC Level for UP systems */
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// This routine makes the thread deferred ready on the boot CPU.
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiInsertDeferredReadyList(IN PKTHREAD Thread)
|
||||
{
|
||||
/* Set the thread to deferred state and boot CPU */
|
||||
Thread->State = DeferredReady;
|
||||
Thread->DeferredProcessor = 0;
|
||||
|
||||
/* Make the thread ready immediately */
|
||||
KiDeferredReadyThread(Thread);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiRescheduleThread(IN BOOLEAN NewThread,
|
||||
IN ULONG Cpu)
|
||||
{
|
||||
/* This is meaningless on UP systems */
|
||||
UNREFERENCED_PARAMETER(NewThread);
|
||||
UNREFERENCED_PARAMETER(Cpu);
|
||||
}
|
||||
|
||||
//
|
||||
// This routine protects against multiple CPU acquires, it's meaningless on UP.
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiSetThreadSwapBusy(IN PKTHREAD Thread)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Thread);
|
||||
}
|
||||
|
||||
//
|
||||
// This routine protects against multiple CPU acquires, it's meaningless on UP.
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiAcquirePrcbLock(IN PKPRCB Prcb)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Prcb);
|
||||
}
|
||||
|
||||
//
|
||||
// This routine protects against multiple CPU acquires, it's meaningless on UP.
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiReleasePrcbLock(IN PKPRCB Prcb)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Prcb);
|
||||
}
|
||||
|
||||
//
|
||||
// This routine protects against multiple CPU acquires, it's meaningless on UP.
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiAcquireThreadLock(IN PKTHREAD Thread)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Thread);
|
||||
}
|
||||
|
||||
//
|
||||
// This routine protects against multiple CPU acquires, it's meaningless on UP.
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiReleaseThreadLock(IN PKTHREAD Thread)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Thread);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiCheckDeferredReadyList(IN PKPRCB Prcb)
|
||||
{
|
||||
/* There are no deferred ready lists on UP systems */
|
||||
UNREFERENCED_PARAMETER(Prcb);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiRundownThread(IN PKTHREAD Thread)
|
||||
{
|
||||
/* Check if this is the NPX Thread */
|
||||
if (KeGetCurrentPrcb()->NpxThread == Thread)
|
||||
{
|
||||
/* Clear it */
|
||||
KeGetCurrentPrcb()->NpxThread = NULL;
|
||||
#ifdef __GNUC__
|
||||
__asm__("fninit\n\t");
|
||||
#else
|
||||
__asm fninit;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
KIRQL
|
||||
FORCEINLINE
|
||||
KiAcquireDispatcherLock(VOID)
|
||||
{
|
||||
/* Raise to synchronization level and acquire the dispatcher lock */
|
||||
return KeAcquireQueuedSpinLockRaiseToSynch(LockQueueDispatcherLock);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
KiReleaseDispatcherLock(IN KIRQL OldIrql)
|
||||
{
|
||||
/* First release the lock */
|
||||
KeReleaseQueuedSpinLockFromDpcLevel(&KeGetCurrentPrcb()->
|
||||
LockQueue[LockQueueDispatcherLock]);
|
||||
|
||||
/* Then exit the dispatcher */
|
||||
KiExitDispatcher(OldIrql);
|
||||
}
|
||||
|
||||
//
|
||||
// This routine inserts a thread into the deferred ready list of the given CPU
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiInsertDeferredReadyList(IN PKTHREAD Thread)
|
||||
{
|
||||
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||
|
||||
/* Set the thread to deferred state and CPU */
|
||||
Thread->State = DeferredReady;
|
||||
Thread->DeferredProcessor = Prcb->Number;
|
||||
|
||||
/* Add it on the list */
|
||||
PushEntryList(&Prcb->DeferredReadyListHead, &Thread->SwapListEntry);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiRescheduleThread(IN BOOLEAN NewThread,
|
||||
IN ULONG Cpu)
|
||||
{
|
||||
/* Check if a new thread needs to be scheduled on a different CPU */
|
||||
if ((NewThread) && !(KeGetPcr()->Number == Cpu))
|
||||
{
|
||||
/* Send an IPI to request delivery */
|
||||
KiIpiSendRequest(AFFINITY_MASK(Cpu), IPI_DPC);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// This routine sets the current thread in a swap busy state, which ensure that
|
||||
// nobody else tries to swap it concurrently.
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiSetThreadSwapBusy(IN PKTHREAD Thread)
|
||||
{
|
||||
/* Make sure nobody already set it */
|
||||
ASSERT(Thread->SwapBusy == FALSE);
|
||||
|
||||
/* Set it ourselves */
|
||||
Thread->SwapBusy = TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// This routine acquires the PRCB lock so that only one caller can touch
|
||||
// volatile PRCB data.
|
||||
//
|
||||
// Since this is a simple optimized spin-lock, it must be be only acquired
|
||||
// at dispatcher level or higher!
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiAcquirePrcbLock(IN PKPRCB Prcb)
|
||||
{
|
||||
/* Make sure we're at a safe level to touch the PRCB lock */
|
||||
ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
|
||||
|
||||
/* Start acquire loop */
|
||||
for (;;)
|
||||
{
|
||||
/* Acquire the lock and break out if we acquired it first */
|
||||
if (!InterlockedExchange(&Prcb->PrcbLock, 1)) break;
|
||||
|
||||
/* Loop until the other CPU releases it */
|
||||
do
|
||||
{
|
||||
/* Let the CPU know that this is a loop */
|
||||
YieldProcessor();
|
||||
} while (Prcb->PrcbLock);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// This routine releases the PRCB lock so that other callers can touch
|
||||
// volatile PRCB data.
|
||||
//
|
||||
// Since this is a simple optimized spin-lock, it must be be only acquired
|
||||
// at dispatcher level or higher!
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiReleasePrcbLock(IN PKPRCB Prcb)
|
||||
{
|
||||
/* Make sure it's acquired! */
|
||||
ASSERT(Prcb->PrcbLock != 0);
|
||||
|
||||
/* Release it */
|
||||
InterlockedAnd(&Prcb->PrcbLock, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// This routine acquires the thread lock so that only one caller can touch
|
||||
// volatile thread data.
|
||||
//
|
||||
// Since this is a simple optimized spin-lock, it must be be only acquired
|
||||
// at dispatcher level or higher!
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiAcquireThreadLock(IN PKTHREAD Thread)
|
||||
{
|
||||
/* Make sure we're at a safe level to touch the thread lock */
|
||||
ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
|
||||
|
||||
/* Start acquire loop */
|
||||
for (;;)
|
||||
{
|
||||
/* Acquire the lock and break out if we acquired it first */
|
||||
if (!InterlockedExchange(&Thread->ThreadLock, 1)) break;
|
||||
|
||||
/* Loop until the other CPU releases it */
|
||||
do
|
||||
{
|
||||
/* Let the CPU know that this is a loop */
|
||||
YieldProcessor();
|
||||
} while (Thread->ThreadLock);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// This routine releases the thread lock so that other callers can touch
|
||||
// volatile thread data.
|
||||
//
|
||||
// Since this is a simple optimized spin-lock, it must be be only acquired
|
||||
// at dispatcher level or higher!
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiReleaseThreadLock(IN PKTHREAD Thread)
|
||||
{
|
||||
/* Release it */
|
||||
InterlockedAnd(&Thread->ThreadLock, 0);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiCheckDeferredReadyList(IN PKPRCB Prcb)
|
||||
{
|
||||
/* Scan the deferred ready lists if required */
|
||||
if (Prcb->DeferredReadyListHead.Next) KiProcessDeferredReadyList(Prcb);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// This routine queues a thread that is ready on the PRCB's ready lists.
|
||||
// If this thread cannot currently run on this CPU, then the thread is
|
||||
// added to the deferred ready list instead.
|
||||
//
|
||||
// This routine must be entered with the PRCB lock held and it will exit
|
||||
// with the PRCB lock released!
|
||||
//
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KxQueueReadyThread(IN PKTHREAD Thread,
|
||||
IN PKPRCB Prcb)
|
||||
{
|
||||
BOOLEAN Preempted;
|
||||
KPRIORITY Priority;
|
||||
|
||||
/* Sanity checks */
|
||||
ASSERT(Prcb == KeGetCurrentPrcb());
|
||||
ASSERT(Thread->State == Running);
|
||||
ASSERT(Thread->NextProcessor == Prcb->Number);
|
||||
|
||||
/* Check if this thread is allowed to run in this CPU */
|
||||
#ifdef _CONFIG_SMP
|
||||
if ((Thread->Affinity) & (Prcb->SetMember))
|
||||
#else
|
||||
if (TRUE)
|
||||
#endif
|
||||
{
|
||||
/* Set thread ready for execution */
|
||||
Thread->State = Ready;
|
||||
|
||||
/* Save current priority and if someone had pre-empted it */
|
||||
Priority = Thread->Priority;
|
||||
Preempted = Thread->Preempted;
|
||||
|
||||
/* We're not pre-empting now, and set the wait time */
|
||||
Thread->Preempted = FALSE;
|
||||
Thread->WaitTime = KeTickCount.LowPart;
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT((Priority >= 0) && (Priority <= HIGH_PRIORITY));
|
||||
|
||||
/* Insert this thread in the appropriate order */
|
||||
Preempted ? InsertHeadList(&Prcb->DispatcherReadyListHead[Priority],
|
||||
&Thread->WaitListEntry) :
|
||||
InsertTailList(&Prcb->DispatcherReadyListHead[Priority],
|
||||
&Thread->WaitListEntry);
|
||||
|
||||
/* Update the ready summary */
|
||||
Prcb->ReadySummary |= PRIORITY_MASK(Priority);
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT(Priority == Thread->Priority);
|
||||
|
||||
/* Release the PRCB lock */
|
||||
KiReleasePrcbLock(Prcb);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, prepare this thread to be deferred */
|
||||
Thread->State = DeferredReady;
|
||||
Thread->DeferredProcessor = Prcb->Number;
|
||||
|
||||
/* Release the lock and defer scheduling */
|
||||
KiReleasePrcbLock(Prcb);
|
||||
KiDeferredReadyThread(Thread);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// This routine scans for an appropriate ready thread to select at the
|
||||
// given priority and for the given CPU.
|
||||
//
|
||||
FORCEINLINE
|
||||
PKTHREAD
|
||||
KiSelectReadyThread(IN KPRIORITY Priority,
|
||||
IN PKPRCB Prcb)
|
||||
{
|
||||
LONG PriorityMask, PrioritySet, HighPriority;
|
||||
PLIST_ENTRY ListEntry;
|
||||
PKTHREAD Thread;
|
||||
|
||||
/* Save the current mask and get the priority set for the CPU */
|
||||
PriorityMask = Priority;
|
||||
PrioritySet = Prcb->ReadySummary >> (UCHAR)Priority;
|
||||
if (!PrioritySet) return NULL;
|
||||
|
||||
/* Get the highest priority possible */
|
||||
BitScanReverse(&HighPriority, PrioritySet);
|
||||
ASSERT((PrioritySet & PRIORITY_MASK(HighPriority)) != 0);
|
||||
HighPriority += PriorityMask;
|
||||
|
||||
/* Make sure the list isn't at highest priority */
|
||||
ASSERT(IsListEmpty(&Prcb->DispatcherReadyListHead[HighPriority]) == FALSE);
|
||||
|
||||
/* Get the first thread on the list */
|
||||
ListEntry = &Prcb->DispatcherReadyListHead[HighPriority];
|
||||
Thread = CONTAINING_RECORD(ListEntry, KTHREAD, WaitListEntry);
|
||||
|
||||
/* Make sure this thread is here for a reason */
|
||||
ASSERT(HighPriority == Thread->Priority);
|
||||
ASSERT(Thread->Affinity & AFFINITY_MASK(Prcb->Number));
|
||||
ASSERT(Thread->NextProcessor == Prcb->Number);
|
||||
|
||||
/* Remove it from the list */
|
||||
RemoveEntryList(&Thread->WaitListEntry);
|
||||
if (IsListEmpty(&Thread->WaitListEntry))
|
||||
{
|
||||
/* The list is empty now, reset the ready summary */
|
||||
Prcb->ReadySummary ^= PRIORITY_MASK(HighPriority);
|
||||
}
|
||||
|
||||
/* Sanity check and return the thread */
|
||||
ASSERT((Thread == NULL) ||
|
||||
(Thread->BasePriority == 0) ||
|
||||
(Thread->Priority != 0));
|
||||
return Thread;
|
||||
}
|
||||
|
||||
//
|
||||
// This routine computes the new priority for a thread. It is only valid for
|
||||
// threads with priorities in the dynamic priority range.
|
||||
//
|
||||
SCHAR
|
||||
FORCEINLINE
|
||||
KiComputeNewPriority(IN PKTHREAD Thread)
|
||||
{
|
||||
SCHAR Priority;
|
||||
|
||||
/* Priority sanity checks */
|
||||
ASSERT((Thread->PriorityDecrement >= 0) &&
|
||||
(Thread->PriorityDecrement <= Thread->Priority));
|
||||
ASSERT((Thread->Priority < LOW_REALTIME_PRIORITY) ?
|
||||
TRUE : (Thread->PriorityDecrement == 0));
|
||||
|
||||
/* Get the current priority */
|
||||
Priority = Thread->Priority;
|
||||
if (Priority < LOW_REALTIME_PRIORITY)
|
||||
{
|
||||
/* Set the New Priority and add the Priority Decrement */
|
||||
Priority += (Priority - Thread->PriorityDecrement - 1);
|
||||
|
||||
/* Don't go out of bounds */
|
||||
if (Priority < Thread->BasePriority) Priority = Thread->BasePriority;
|
||||
|
||||
/* Reset the priority decrement */
|
||||
Thread->PriorityDecrement = 0;
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT((Thread->BasePriority == 0) || (Priority != 0));
|
||||
|
||||
/* Return the new priority */
|
||||
return Priority;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ KeWaitForGate(IN PKGATE Gate,
|
|||
if (CurrentThread->Queue) KiWakeQueue(CurrentThread->Queue);
|
||||
|
||||
/* Find a new thread to run */
|
||||
Status = KiSwapThread();
|
||||
Status = KiSwapThread(CurrentThread, KeGetCurrentPrcb());
|
||||
|
||||
/* Check if we were executing an APC */
|
||||
if (Status != STATUS_KERNEL_APC) return;
|
||||
|
|
|
@ -200,10 +200,10 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus)
|
|||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KiSwapThread(VOID)
|
||||
FASTCALL
|
||||
KiSwapThread(IN PKTHREAD CurrentThread,
|
||||
IN PKPRCB Prcb)
|
||||
{
|
||||
PKTHREAD CurrentThread = KeGetCurrentThread();
|
||||
BOOLEAN ApcState;
|
||||
|
||||
/* Find a new thread to run */
|
||||
|
@ -1068,10 +1068,10 @@ KeRevertToUserAffinityThread(VOID)
|
|||
/*
|
||||
* @implemented
|
||||
*/
|
||||
CCHAR
|
||||
UCHAR
|
||||
STDCALL
|
||||
KeSetIdealProcessorThread(IN PKTHREAD Thread,
|
||||
IN CCHAR Processor)
|
||||
IN UCHAR Processor)
|
||||
{
|
||||
CCHAR PreviousIdealProcessor;
|
||||
KIRQL OldIrql;
|
||||
|
|
|
@ -426,7 +426,7 @@ KeRemoveQueue(IN PKQUEUE Queue,
|
|||
|
||||
/* Find a new thread to run */
|
||||
KiAddThreadToWaitList(Thread, Swappable);
|
||||
Status = KiSwapThread();
|
||||
Status = KiSwapThread(Thread, KeGetCurrentPrcb());
|
||||
|
||||
/* Reset the wait reason */
|
||||
Thread->WaitReason = 0;
|
||||
|
|
|
@ -352,7 +352,7 @@ KeDelayExecutionThread(IN KPROCESSOR_MODE WaitMode,
|
|||
|
||||
/* Find a new thread to run */
|
||||
KiAddThreadToWaitList(CurrentThread, Swappable);
|
||||
WaitStatus = KiSwapThread();
|
||||
WaitStatus = KiSwapThread(CurrentThread, KeGetCurrentPrcb());
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
|
||||
/* Check if we were executing an APC or if we timed out */
|
||||
|
@ -540,7 +540,7 @@ KeWaitForSingleObject(IN PVOID Object,
|
|||
|
||||
/* Find a new thread to run */
|
||||
KiAddThreadToWaitList(CurrentThread, Swappable);
|
||||
WaitStatus = KiSwapThread();
|
||||
WaitStatus = KiSwapThread(CurrentThread, KeGetCurrentPrcb());
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
|
||||
/* Check if we were executing an APC */
|
||||
|
@ -828,7 +828,7 @@ KeWaitForMultipleObjects(IN ULONG Count,
|
|||
|
||||
/* Find a new thread to run */
|
||||
KiAddThreadToWaitList(CurrentThread, Swappable);
|
||||
WaitStatus = KiSwapThread();
|
||||
WaitStatus = KiSwapThread(CurrentThread, KeGetCurrentPrcb());
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
|
||||
/* Check if we were executing an APC */
|
||||
|
|
Loading…
Reference in a new issue