*/
LIST_ENTRY PiThreadListHead;
static LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY];
+static ULONG PriorityListMask = 0;
static BOOLEAN DoneInitYet = FALSE;
static PETHREAD IdleThreads[MAXIMUM_PROCESSORS];
ULONG PiNrThreads = 0;
/* FUNCTIONS ***************************************************************/
+/*
+ * @implemented
+ */
PKTHREAD STDCALL KeGetCurrentThread(VOID)
{
- return(KeGetCurrentKPCR()->CurrentThread);
+ return(((PIKPCR) KeGetCurrentKPCR())->CurrentThread);
}
+/*
+ * @implemented
+ */
HANDLE STDCALL PsGetCurrentThreadId(VOID)
{
return(PsGetCurrentThread()->Cid.UniqueThread);
}
-VOID
+static VOID
PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread)
{
- if (Priority >= MAXIMUM_PRIORITY || Priority < 0)
+ assert(THREAD_STATE_READY == Thread->Tcb.State);
+ if (Priority >= MAXIMUM_PRIORITY || Priority < LOW_PRIORITY)
{
- DPRINT1("Invalid thread priority\n");
- KeBugCheck(0);
+ DPRINT1("Invalid thread priority (%d)\n", Priority);
+ KEBUGCHECK(0);
}
InsertTailList(&PriorityListHead[Priority], &Thread->Tcb.QueueListEntry);
+ PriorityListMask |= (1 << Priority);
PiNrReadyThreads++;
}
+static VOID PsRemoveFromThreadList(PETHREAD Thread)
+{
+ assert(THREAD_STATE_READY == Thread->Tcb.State);
+ RemoveEntryList(&Thread->Tcb.QueueListEntry);
+ if (IsListEmpty(&PriorityListHead[(ULONG)Thread->Tcb.Priority]))
+ {
+ PriorityListMask &= ~(1 << Thread->Tcb.Priority);
+ }
+ PiNrReadyThreads--;
+}
+
+
VOID PsDumpThreads(BOOLEAN IncludeSystem)
{
PLIST_ENTRY current_entry;
{
PLIST_ENTRY current_entry;
PETHREAD current;
+ ULONG Mask;
- current_entry = PriorityListHead[Priority].Flink;
- while (current_entry != &PriorityListHead[Priority])
+ Mask = (1 << Priority);
+ if (PriorityListMask & Mask)
{
- current = CONTAINING_RECORD(current_entry, ETHREAD,
- Tcb.QueueListEntry);
- assert(current->Tcb.State == THREAD_STATE_READY);
- DPRINT("current->Tcb.UserAffinity %x Affinity %x PID %d %d\n",
- current->Tcb.UserAffinity, Affinity, current->Cid.UniqueThread,
- Priority);
- if (current->Tcb.UserAffinity & Affinity)
- {
- RemoveEntryList(¤t->Tcb.QueueListEntry);
- return(current);
+ current_entry = PriorityListHead[Priority].Flink;
+ while (current_entry != &PriorityListHead[Priority])
+ {
+ current = CONTAINING_RECORD(current_entry, ETHREAD,
+ Tcb.QueueListEntry);
+ if (current->Tcb.State != THREAD_STATE_READY)
+ {
+ DPRINT1("%d/%d\n", current->Cid.UniqueThread, current->Tcb.State);
+ }
+ assert(current->Tcb.State == THREAD_STATE_READY);
+ DPRINT("current->Tcb.UserAffinity %x Affinity %x PID %d %d\n",
+ current->Tcb.UserAffinity, Affinity, current->Cid.UniqueThread,
+ Priority);
+ if (current->Tcb.UserAffinity & Affinity)
+ {
+ PsRemoveFromThreadList(current);
+ return(current);
+ }
+ current_entry = current_entry->Flink;
}
- current_entry = current_entry->Flink;
}
return(NULL);
}
KPRIORITY CurrentPriority;
PETHREAD Candidate;
ULONG Affinity;
- PKTHREAD KCurrentThread = KeGetCurrentKPCR()->CurrentThread;
+ PKTHREAD KCurrentThread = ((PIKPCR) KeGetCurrentKPCR())->CurrentThread;
PETHREAD CurrentThread = CONTAINING_RECORD(KCurrentThread, ETHREAD, Tcb);
- DPRINT("PsDispatchThread() %d/%d\n", KeGetCurrentProcessorNumber(),
- CurrentThread->Cid.UniqueThread);
+ DPRINT("PsDispatchThread() %d/%d/%d/%d\n", KeGetCurrentProcessorNumber(),
+ CurrentThread->Cid.UniqueThread, NewThreadStatus, CurrentThread->Tcb.State);
CurrentThread->Tcb.State = NewThreadStatus;
if (CurrentThread->Tcb.State == THREAD_STATE_READY)
{
- PiNrReadyThreads++;
PsInsertIntoThreadList(CurrentThread->Tcb.Priority,
CurrentThread);
}
Candidate = PsScanThreadList(CurrentPriority, Affinity);
if (Candidate == CurrentThread)
{
+ Candidate->Tcb.State = THREAD_STATE_RUNNING;
KeReleaseSpinLockFromDpcLevel(&PiThreadListLock);
return;
}
OldThread = CurrentThread;
CurrentThread = Candidate;
-
+#if 0
+ /*
+ * This code is moved to the end of KiArchContextSwitch.
+ * It should be execute after the context switch.
+ */
KeReleaseSpinLockFromDpcLevel(&PiThreadListLock);
if (PiNrThreadsAwaitingReaping > 0)
{
PiWakeupReaperThread();
}
+#endif
KiArchContextSwitch(&CurrentThread->Tcb, &OldThread->Tcb);
return;
}
}
CPRINT("CRITICAL: No threads are ready\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
VOID STDCALL
/*
* Save wait IRQL
*/
- KeGetCurrentKPCR()->CurrentThread->WaitIrql = oldIrql;
+ ((PIKPCR) KeGetCurrentKPCR())->CurrentThread->WaitIrql = oldIrql;
PsDispatchThreadNoLock(NewThreadStatus);
KeLowerIrql(oldIrql);
}
KIRQL oldIrql;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
- if (WaitStatus != NULL)
+ if (THREAD_STATE_TERMINATED_1 == Thread->Tcb.State ||
+ THREAD_STATE_TERMINATED_2 == Thread->Tcb.State)
{
- Thread->Tcb.WaitStatus = *WaitStatus;
+ DPRINT("Can't unblock thread %d because it's terminating\n",
+ Thread->Cid.UniqueThread);
+ }
+ else if (THREAD_STATE_READY == Thread->Tcb.State ||
+ THREAD_STATE_RUNNING == Thread->Tcb.State)
+ {
+ DPRINT("Can't unblock thread %d because it's ready or running\n",
+ Thread->Cid.UniqueThread);
+ }
+ else
+ {
+ if (WaitStatus != NULL)
+ {
+ Thread->Tcb.WaitStatus = *WaitStatus;
+ }
+ Thread->Tcb.State = THREAD_STATE_READY;
+ PsInsertIntoThreadList(Thread->Tcb.Priority, Thread);
}
- Thread->Tcb.State = THREAD_STATE_READY;
- PsInsertIntoThreadList(Thread->Tcb.Priority, Thread);
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
}
BOOLEAN DispatcherLock, KIRQL WaitIrql, UCHAR WaitReason)
{
KIRQL oldIrql;
- PKTHREAD KThread = KeGetCurrentKPCR()->CurrentThread;
- PETHREAD Thread = CONTAINING_RECORD (KThread, ETHREAD, Tcb);
+ PKTHREAD KThread;
+ PETHREAD Thread;
PKWAIT_BLOCK WaitBlock;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
+ KThread = ((PIKPCR) KeGetCurrentKPCR())->CurrentThread;
+ Thread = CONTAINING_RECORD (KThread, ETHREAD, Tcb);
if (KThread->ApcState.KernelApcPending)
{
if (!DispatcherLock)
VOID
PsApplicationProcessorInit(VOID)
{
- KeGetCurrentKPCR()->CurrentThread =
+ ((PIKPCR) KeGetCurrentKPCR())->CurrentThread =
(PVOID)IdleThreads[KeGetCurrentProcessorNumber()];
}
THREAD_ALL_ACCESS,NULL, TRUE);
FirstThread->Tcb.State = THREAD_STATE_RUNNING;
FirstThread->Tcb.FreezeCount = 0;
- KeGetCurrentKPCR()->CurrentThread = (PVOID)FirstThread;
+ ((PIKPCR) KeGetCurrentKPCR())->CurrentThread = (PVOID)FirstThread;
NtClose(FirstThreadHandle);
DPRINT("FirstThread %x\n",FirstThread);
NULL,
NULL,
NULL,
- PiReaperThreadMain,
+ (PKSTART_ROUTINE) PiReaperThreadMain,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("PS: Failed to create reaper thread.\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
}
+/*
+ * @implemented
+ */
LONG STDCALL
KeSetBasePriorityThread (PKTHREAD Thread,
LONG Increment)
* Should only be passed in THREAD_PRIORITY_ constants in pstypes.h
*/
{
- Thread->BasePriority =
- ((PETHREAD)Thread)->ThreadsProcess->Pcb.BasePriority + Increment;
- if (Thread->BasePriority < LOW_PRIORITY)
- Thread->BasePriority = LOW_PRIORITY;
- else if (Thread->BasePriority >= MAXIMUM_PRIORITY)
- Thread->BasePriority = HIGH_PRIORITY;
- Thread->Priority = Thread->BasePriority;
+ KPRIORITY Priority;
+ if (Increment < -2)
+ {
+ Increment = -2;
+ }
+ else if (Increment > 2)
+ {
+ Increment = 2;
+ }
+ Priority = ((PETHREAD)Thread)->ThreadsProcess->Pcb.BasePriority + Increment;
+ if (Priority < LOW_PRIORITY)
+ {
+ Priority = LOW_PRIORITY;
+ }
+ else if (Priority >= MAXIMUM_PRIORITY)
+ {
+ Thread->BasePriority = HIGH_PRIORITY;
+ }
+ KeSetPriorityThread(Thread, Priority);
return 1;
}
+/*
+ * @implemented
+ */
KPRIORITY STDCALL
KeSetPriorityThread (PKTHREAD Thread, KPRIORITY Priority)
{
KPRIORITY OldPriority;
KIRQL oldIrql;
+ PKTHREAD CurrentThread;
+ ULONG Mask;
- if (Priority < 0 || Priority >= MAXIMUM_PRIORITY)
+ if (Priority < LOW_PRIORITY || Priority >= MAXIMUM_PRIORITY)
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
+ KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
+
OldPriority = Thread->Priority;
- Thread->Priority = (CHAR)Priority;
+ Thread->BasePriority = Thread->Priority = (CHAR)Priority;
- KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
- if (Thread->State == THREAD_STATE_READY)
- {
- RemoveEntryList(&Thread->QueueListEntry);
- PsInsertIntoThreadList(Thread->BasePriority,
- CONTAINING_RECORD(Thread,ETHREAD,Tcb));
+ if (OldPriority != Priority)
+ {
+ if (Thread->State == THREAD_STATE_READY)
+ {
+ PsRemoveFromThreadList((PETHREAD)Thread);
+ PsInsertIntoThreadList(Priority, (PETHREAD)Thread);
+ CurrentThread = ((PIKPCR) KeGetCurrentKPCR())->CurrentThread;
+ if (CurrentThread->Priority < Priority)
+ {
+ PsDispatchThreadNoLock(THREAD_STATE_READY);
+ KeLowerIrql(oldIrql);
+ return (OldPriority);
+ }
+ }
+ else if (Thread->State == THREAD_STATE_RUNNING)
+ {
+ if (Priority < OldPriority)
+ {
+ /* Check for threads with a higher priority */
+ Mask = ~((1 << (Priority + 1)) - 1);
+ if (PriorityListMask & Mask)
+ {
+ PsDispatchThreadNoLock(THREAD_STATE_READY);
+ KeLowerIrql(oldIrql);
+ return (OldPriority);
+ }
+ }
+ }
}
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
return(OldPriority);
}
+/*
+ * @unimplemented
+ */
NTSTATUS STDCALL
KeSetAffinityThread(PKTHREAD Thread,
- PVOID AfMask)
+ PVOID AfMask)
/*
* Sets thread's affinity
*/
return(STATUS_SUCCESS);
}
+/**********************************************************************
+ * NtOpenThread/4
+ *
+ * @implemented
+ */
NTSTATUS STDCALL
NtOpenThread(OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId)
{
- UNIMPLEMENTED;
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ if((NULL != ThreadHandle)&&(NULL != ObjectAttributes))
+ {
+ PETHREAD EThread = NULL;
+
+ if((ClientId)
+ && (ClientId->UniqueProcess)
+ && (ClientId->UniqueThread))
+ {
+ // It is an error to specify both
+ // ObjectAttributes.ObjectName
+ // and ClientId.
+ if((ObjectAttributes)
+ && (ObjectAttributes->ObjectName)
+ && (0 < ObjectAttributes->ObjectName->Length))
+ {
+ return(STATUS_INVALID_PARAMETER_MIX);
+ }
+ // Parameters mix OK
+ Status = PsLookupProcessThreadByCid(ClientId,
+ NULL,
+ & EThread);
+ }
+ else if((ObjectAttributes)
+ && (ObjectAttributes->ObjectName)
+ && (0 < ObjectAttributes->ObjectName->Length))
+ {
+ // Three Ob attributes are forbidden
+ if(!(ObjectAttributes->Attributes &
+ (OBJ_PERMANENT | OBJ_EXCLUSIVE | OBJ_OPENIF)))
+ {
+ Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
+ ObjectAttributes->Attributes,
+ NULL,
+ DesiredAccess,
+ PsThreadType,
+ UserMode,
+ NULL,
+ (PVOID*) & EThread);
+ }
+ }
+ // EThread may be OK...
+ if(STATUS_SUCCESS == Status)
+ {
+ Status = ObCreateHandle(PsGetCurrentProcess(),
+ EThread,
+ DesiredAccess,
+ FALSE,
+ ThreadHandle);
+ ObDereferenceObject(EThread);
+ }
+ }
+ return(Status);
}
NTSTATUS STDCALL
if (TrapFrame == NULL)
{
CPRINT("NtContinue called but TrapFrame was NULL\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
KeContextToTrapFrame(Context, TrapFrame);
return(STATUS_SUCCESS);
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
OUT PEPROCESS *Process OPTIONAL,
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
PsLookupThreadByThreadId(IN PVOID ThreadId,
OUT PETHREAD *Thread)