X-Git-Url: http://git.jankratochvil.net/?p=reactos.git;a=blobdiff_plain;f=ntoskrnl%2Fps%2Fthread.c;h=b99447b8db03371258e862d8ccc10a784cb6a4c0;hp=35d772e070f293a87840bf17a26f15ebe886d366;hb=HEAD;hpb=7c0db166f81fbe8c8b913d7f26048e337d383605 diff --git a/ntoskrnl/ps/thread.c b/ntoskrnl/ps/thread.c index 35d772e..b99447b 100644 --- a/ntoskrnl/ps/thread.c +++ b/ntoskrnl/ps/thread.c @@ -45,6 +45,7 @@ KSPIN_LOCK PiThreadListLock; */ 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; @@ -61,28 +62,48 @@ static GENERIC_MAPPING PiThreadMapping = {THREAD_READ, /* 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; @@ -142,22 +163,31 @@ static PETHREAD PsScanThreadList (KPRIORITY Priority, ULONG Affinity) { 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); } @@ -191,16 +221,15 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus) 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); } @@ -217,6 +246,7 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus) Candidate = PsScanThreadList(CurrentPriority, Affinity); if (Candidate == CurrentThread) { + Candidate->Tcb.State = THREAD_STATE_RUNNING; KeReleaseSpinLockFromDpcLevel(&PiThreadListLock); return; } @@ -230,18 +260,23 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus) 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 @@ -258,7 +293,7 @@ PsDispatchThread(ULONG NewThreadStatus) /* * Save wait IRQL */ - KeGetCurrentKPCR()->CurrentThread->WaitIrql = oldIrql; + ((PIKPCR) KeGetCurrentKPCR())->CurrentThread->WaitIrql = oldIrql; PsDispatchThreadNoLock(NewThreadStatus); KeLowerIrql(oldIrql); } @@ -269,12 +304,27 @@ PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus) 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); } @@ -283,12 +333,14 @@ PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode, 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) @@ -362,7 +414,7 @@ PsFreezeAllThreads(PEPROCESS Process) VOID PsApplicationProcessorInit(VOID) { - KeGetCurrentKPCR()->CurrentThread = + ((PIKPCR) KeGetCurrentKPCR())->CurrentThread = (PVOID)IdleThreads[KeGetCurrentProcessorNumber()]; } @@ -435,7 +487,7 @@ PsInitThreadManagment(VOID) 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); @@ -451,15 +503,18 @@ PsInitThreadManagment(VOID) 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) @@ -468,45 +523,89 @@ KeSetBasePriorityThread (PKTHREAD Thread, * 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 */ @@ -549,13 +648,71 @@ NTSTATUS STDCALL NtAlertThread (IN HANDLE ThreadHandle) 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 @@ -573,7 +730,7 @@ NtContinue(IN PCONTEXT Context, if (TrapFrame == NULL) { CPRINT("NtContinue called but TrapFrame was NULL\n"); - KeBugCheck(0); + KEBUGCHECK(0); } KeContextToTrapFrame(Context, TrapFrame); return(STATUS_SUCCESS); @@ -588,6 +745,9 @@ NtYieldExecution(VOID) } +/* + * @implemented + */ NTSTATUS STDCALL PsLookupProcessThreadByCid(IN PCLIENT_ID Cid, OUT PEPROCESS *Process OPTIONAL, @@ -630,6 +790,9 @@ PsLookupProcessThreadByCid(IN PCLIENT_ID Cid, } +/* + * @implemented + */ NTSTATUS STDCALL PsLookupThreadByThreadId(IN PVOID ThreadId, OUT PETHREAD *Thread)