mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
SMP scheduling fixes
Obey thread affinity Fix bogus invariant in KeAcquireSpinLockAtDpcLevel Protect display with spinlock svn path=/trunk/; revision=1809
This commit is contained in:
parent
f29036d97b
commit
d41145488c
11 changed files with 164 additions and 143 deletions
|
@ -7,3 +7,4 @@ depends
|
|||
depends.exe
|
||||
mkconfig
|
||||
mkconfig.exe
|
||||
ntoskrnl.dbg
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: display.c,v 1.12 2001/03/16 18:11:21 dwelch Exp $
|
||||
/* $Id: display.c,v 1.13 2001/04/17 23:39:25 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -179,11 +179,8 @@ HalAcquireDisplayOwnership (
|
|||
}
|
||||
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
HalDisplayString (
|
||||
IN PCH String
|
||||
)
|
||||
VOID STDCALL
|
||||
HalDisplayString (IN PCH String)
|
||||
/*
|
||||
* FUNCTION: Switches the screen to HAL console mode (BSOD) if not there
|
||||
* already and displays a string
|
||||
|
@ -193,64 +190,70 @@ HalDisplayString (
|
|||
* mode
|
||||
*/
|
||||
{
|
||||
PCH pch;
|
||||
PCH pch;
|
||||
#ifdef SCREEN_SYNCHRONIZATION
|
||||
int offset;
|
||||
int offset;
|
||||
#endif
|
||||
static KSPIN_LOCK Lock;
|
||||
|
||||
pch = String;
|
||||
pch = String;
|
||||
|
||||
if (HalOwnsDisplay == FALSE)
|
||||
__asm__ ("cli\n\t");
|
||||
KeAcquireSpinLockAtDpcLevel(&Lock);
|
||||
|
||||
if (HalOwnsDisplay == FALSE)
|
||||
{
|
||||
HalResetDisplay ();
|
||||
HalResetDisplay ();
|
||||
}
|
||||
|
||||
|
||||
#ifdef SCREEN_SYNCHRONIZATION
|
||||
WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURHI);
|
||||
offset = READ_PORT_UCHAR((PUCHAR)CRTC_DATA)<<8;
|
||||
WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURLO);
|
||||
offset += READ_PORT_UCHAR((PUCHAR)CRTC_DATA);
|
||||
|
||||
CursorY = offset / SizeX;
|
||||
CursorX = offset % SizeX;
|
||||
WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURHI);
|
||||
offset = READ_PORT_UCHAR((PUCHAR)CRTC_DATA)<<8;
|
||||
WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURLO);
|
||||
offset += READ_PORT_UCHAR((PUCHAR)CRTC_DATA);
|
||||
|
||||
CursorY = offset / SizeX;
|
||||
CursorX = offset % SizeX;
|
||||
#endif
|
||||
|
||||
while (*pch != 0)
|
||||
|
||||
while (*pch != 0)
|
||||
{
|
||||
if (*pch == '\n')
|
||||
if (*pch == '\n')
|
||||
{
|
||||
CursorY++;
|
||||
CursorX = 0;
|
||||
CursorY++;
|
||||
CursorX = 0;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
HalPutCharacter (*pch);
|
||||
CursorX++;
|
||||
|
||||
if (CursorX >= SizeX)
|
||||
HalPutCharacter (*pch);
|
||||
CursorX++;
|
||||
|
||||
if (CursorX >= SizeX)
|
||||
{
|
||||
CursorY++;
|
||||
CursorX = 0;
|
||||
CursorY++;
|
||||
CursorX = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (CursorY >= SizeY)
|
||||
|
||||
if (CursorY >= SizeY)
|
||||
{
|
||||
HalScrollDisplay ();
|
||||
CursorY = SizeY - 1;
|
||||
HalScrollDisplay ();
|
||||
CursorY = SizeY - 1;
|
||||
}
|
||||
|
||||
pch++;
|
||||
|
||||
pch++;
|
||||
}
|
||||
|
||||
|
||||
#ifdef SCREEN_SYNCHRONIZATION
|
||||
offset = (CursorY * SizeX) + CursorX;
|
||||
|
||||
WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURLO);
|
||||
WRITE_PORT_UCHAR((PUCHAR)CRTC_DATA, offset & 0xff);
|
||||
WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURHI);
|
||||
WRITE_PORT_UCHAR((PUCHAR)CRTC_DATA, (offset >> 8) & 0xff);
|
||||
offset = (CursorY * SizeX) + CursorX;
|
||||
|
||||
WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURLO);
|
||||
WRITE_PORT_UCHAR((PUCHAR)CRTC_DATA, offset & 0xff);
|
||||
WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURHI);
|
||||
WRITE_PORT_UCHAR((PUCHAR)CRTC_DATA, (offset >> 8) & 0xff);
|
||||
#endif
|
||||
KeReleaseSpinLockFromDpcLevel(&Lock);
|
||||
__asm__ ("sti\n\t");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: mp.c,v 1.10 2001/04/16 23:29:54 dwelch Exp $
|
||||
/* $Id: mp.c,v 1.11 2001/04/17 23:39:25 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -227,59 +227,60 @@ VOID IOAPICUnmaskIrq(
|
|||
IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq, *((PULONG)&Entry));
|
||||
}
|
||||
|
||||
static VOID IOAPICSetupIds(
|
||||
VOID)
|
||||
static VOID
|
||||
IOAPICSetupIds(VOID)
|
||||
{
|
||||
ULONG tmp, apic, i;
|
||||
UCHAR old_id;
|
||||
|
||||
/*
|
||||
* Set the IOAPIC ID to the value stored in the MPC table.
|
||||
*/
|
||||
for (apic = 0; apic < IOAPICCount; apic++) {
|
||||
|
||||
/* Read the register 0 value */
|
||||
ULONG tmp, apic, i;
|
||||
UCHAR old_id;
|
||||
|
||||
/*
|
||||
* Set the IOAPIC ID to the value stored in the MPC table.
|
||||
*/
|
||||
for (apic = 0; apic < IOAPICCount; apic++) {
|
||||
|
||||
/* Read the register 0 value */
|
||||
tmp = IOAPICRead(apic, IOAPIC_ID);
|
||||
|
||||
old_id = IOAPICMap[apic].ApicId;
|
||||
|
||||
if (IOAPICMap[apic].ApicId >= 0xf) {
|
||||
DPRINT1("BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
|
||||
apic, IOAPICMap[apic].ApicId);
|
||||
DPRINT1("... fixing up to %d. (tell your hw vendor)\n", GET_IOAPIC_ID(tmp));
|
||||
|
||||
old_id = IOAPICMap[apic].ApicId;
|
||||
|
||||
if (IOAPICMap[apic].ApicId >= 0xf) {
|
||||
DPRINT1("BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
|
||||
apic, IOAPICMap[apic].ApicId);
|
||||
DPRINT1("... fixing up to %d. (tell your hw vendor)\n",
|
||||
GET_IOAPIC_ID(tmp));
|
||||
IOAPICMap[apic].ApicId = GET_IOAPIC_ID(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to adjust the IRQ routing table
|
||||
* if the ID changed.
|
||||
*/
|
||||
if (old_id != IOAPICMap[apic].ApicId)
|
||||
for (i = 0; i < IRQCount; i++)
|
||||
if (IRQMap[i].DstApicId == old_id)
|
||||
IRQMap[i].DstApicId = IOAPICMap[apic].ApicId;
|
||||
|
||||
/*
|
||||
* Read the right value from the MPC table and
|
||||
* write it into the ID register.
|
||||
*/
|
||||
DPRINT("Changing IO-APIC physical APIC ID to %d\n",
|
||||
IOAPICMap[apic].ApicId);
|
||||
|
||||
tmp &= ~IOAPIC_ID_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to adjust the IRQ routing table
|
||||
* if the ID changed.
|
||||
*/
|
||||
if (old_id != IOAPICMap[apic].ApicId)
|
||||
for (i = 0; i < IRQCount; i++)
|
||||
if (IRQMap[i].DstApicId == old_id)
|
||||
IRQMap[i].DstApicId = IOAPICMap[apic].ApicId;
|
||||
|
||||
/*
|
||||
* Read the right value from the MPC table and
|
||||
* write it into the ID register.
|
||||
*/
|
||||
DPRINT("Changing IO-APIC physical APIC ID to %d\n",
|
||||
IOAPICMap[apic].ApicId);
|
||||
|
||||
tmp &= ~IOAPIC_ID_MASK;
|
||||
tmp |= SET_IOAPIC_ID(IOAPICMap[apic].ApicId);
|
||||
|
||||
IOAPICWrite(apic, IOAPIC_ID, tmp);
|
||||
|
||||
/*
|
||||
* Sanity check
|
||||
*/
|
||||
tmp = IOAPICRead(apic, 0);
|
||||
if (GET_IOAPIC_ID(tmp) != IOAPICMap[apic].ApicId) {
|
||||
DPRINT1("Could not set I/O APIC ID!\n");
|
||||
|
||||
IOAPICWrite(apic, IOAPIC_ID, tmp);
|
||||
|
||||
/*
|
||||
* Sanity check
|
||||
*/
|
||||
tmp = IOAPICRead(apic, 0);
|
||||
if (GET_IOAPIC_ID(tmp) != IOAPICMap[apic].ApicId) {
|
||||
DPRINT1("Could not set I/O APIC ID!\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -89,6 +89,8 @@ KeApplicationProcessorInit(VOID)
|
|||
* Initialize a default LDT
|
||||
*/
|
||||
Ki386InitializeLdt();
|
||||
|
||||
__asm__ __volatile__ ("sti\n\t");
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -122,6 +124,8 @@ KeInit1(VOID)
|
|||
PcrsAllocated++;
|
||||
|
||||
Ki386InitializeLdt();
|
||||
|
||||
__asm__ __volatile__ ("sti\n\t");
|
||||
}
|
||||
|
||||
VOID
|
||||
|
|
|
@ -75,7 +75,7 @@ _Ki386RetToV86Mode:
|
|||
/*
|
||||
* Save the old initial stack
|
||||
*/
|
||||
movl _CurrentThread, %esi
|
||||
movl %fs:KPCR_CURRENT_THREAD, %esi
|
||||
movl KTHREAD_INITIAL_STACK(%esi), %edi
|
||||
pushl %edi
|
||||
|
||||
|
@ -187,7 +187,7 @@ _KiV86Complete:
|
|||
/*
|
||||
* We also need to set the stack in the kthread structure
|
||||
*/
|
||||
movl $_CurrentThread, %esi
|
||||
movl %fs:KPCR_CURRENT_THREAD, %esi
|
||||
movl KTHREAD_INITIAL_STACK(%esi), %edi
|
||||
movl %eax, KTHREAD_INITIAL_STACK(%esi)
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: main.c,v 1.92 2001/04/17 04:11:00 dwelch Exp $
|
||||
/* $Id: main.c,v 1.93 2001/04/17 23:39:25 dwelch Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ke/main.c
|
||||
|
@ -455,8 +455,11 @@ ExpInitializeExecutive(VOID)
|
|||
|
||||
while (!HalAllProcessorsStarted())
|
||||
{
|
||||
KePrepareForApplicationProcessorInit(KeNumberProcessors);
|
||||
PsPrepareForApplicationProcessorInit(KeNumberProcessors);
|
||||
if (KeNumberProcessors != 0)
|
||||
{
|
||||
KePrepareForApplicationProcessorInit(KeNumberProcessors);
|
||||
PsPrepareForApplicationProcessorInit(KeNumberProcessors);
|
||||
}
|
||||
HalInitializeProcessor(KeNumberProcessors);
|
||||
KeNumberProcessors++;
|
||||
}
|
||||
|
@ -493,7 +496,7 @@ ExpInitializeExecutive(VOID)
|
|||
#ifdef KDBG
|
||||
KdbEnter();
|
||||
#endif /* KDBG */
|
||||
|
||||
|
||||
/*
|
||||
* Initalize services loaded at boot time
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: spinlock.c,v 1.7 2001/04/17 04:11:01 dwelch Exp $
|
||||
/* $Id: spinlock.c,v 1.8 2001/04/17 23:39:25 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -73,10 +73,14 @@ KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK SpinLock)
|
|||
*/
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
if (!(SpinLock->Lock == 0 || SpinLock->Lock == 1))
|
||||
|
||||
/*
|
||||
* FIXME: This depends on gcc assembling this test to a single load from
|
||||
* the spinlock's value.
|
||||
*/
|
||||
if ((ULONG)SpinLock->Lock >= 2)
|
||||
{
|
||||
DbgPrint("Lock %x has bad value %x\n", SpinLock, i);
|
||||
DbgPrint("Lock %x has bad value %x\n", SpinLock, SpinLock->Lock);
|
||||
KeBugCheck(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: timer.c,v 1.44 2001/04/13 16:12:25 chorns Exp $
|
||||
/* $Id: timer.c,v 1.45 2001/04/17 23:39:25 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -422,8 +422,6 @@ KiUpdateSystemTime (KIRQL oldIrql, ULONG Eip)
|
|||
* FUNCTION: Handles a timer interrupt
|
||||
*/
|
||||
{
|
||||
char* vidmem=(char *)physical_to_linear(0xb8000 + 160 - 2);
|
||||
|
||||
KiRawTicks++;
|
||||
|
||||
if (TimerInitDone == FALSE)
|
||||
|
@ -436,16 +434,6 @@ KiUpdateSystemTime (KIRQL oldIrql, ULONG Eip)
|
|||
KiTimerTicks++;
|
||||
system_time = system_time + CLOCK_INCREMENT;
|
||||
|
||||
vidmem[0] = ' ';
|
||||
if (oldIrql < DISPATCH_LEVEL)
|
||||
{
|
||||
vidmem[1] = 0x17;
|
||||
}
|
||||
else
|
||||
{
|
||||
vidmem[1] = 0x27;
|
||||
}
|
||||
|
||||
/*
|
||||
* Queue a DPC that will expire timers
|
||||
*/
|
||||
|
|
|
@ -32,20 +32,21 @@ PsIdleThreadMain(PVOID Context)
|
|||
|
||||
for(;;)
|
||||
{
|
||||
if (DpcQueueSize > 0)
|
||||
{
|
||||
KeRaiseIrql(DISPATCH_LEVEL,&oldlvl);
|
||||
KiDispatchInterrupt();
|
||||
KeLowerIrql(oldlvl);
|
||||
}
|
||||
NtYieldExecution();
|
||||
if (DpcQueueSize > 0)
|
||||
{
|
||||
KeRaiseIrql(DISPATCH_LEVEL,&oldlvl);
|
||||
KiDispatchInterrupt();
|
||||
KeLowerIrql(oldlvl);
|
||||
}
|
||||
NtYieldExecution();
|
||||
}
|
||||
}
|
||||
|
||||
VOID PsInitIdleThread(VOID)
|
||||
{
|
||||
KPRIORITY Priority;
|
||||
|
||||
ULONG Affinity;
|
||||
|
||||
PsCreateSystemThread(&PsIdleThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
|
@ -59,4 +60,9 @@ VOID PsInitIdleThread(VOID)
|
|||
ThreadPriority,
|
||||
&Priority,
|
||||
sizeof(Priority));
|
||||
Affinity = 1 << 0;
|
||||
NtSetInformationThread(PsIdleThreadHandle,
|
||||
ThreadAffinityMask,
|
||||
&Affinity,
|
||||
sizeof(Affinity));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: thread.c,v 1.76 2001/04/17 04:11:01 dwelch Exp $
|
||||
/* $Id: thread.c,v 1.77 2001/04/17 23:39:26 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -48,8 +48,6 @@ static PETHREAD IdleThreads[MAXIMUM_PROCESSORS];
|
|||
ULONG PiNrThreads = 0;
|
||||
ULONG PiNrRunnableThreads = 0;
|
||||
|
||||
PETHREAD CurrentThread = NULL;
|
||||
|
||||
static GENERIC_MAPPING PiThreadMapping = {THREAD_READ,
|
||||
THREAD_WRITE,
|
||||
THREAD_EXECUTE,
|
||||
|
@ -59,12 +57,13 @@ static GENERIC_MAPPING PiThreadMapping = {THREAD_READ,
|
|||
|
||||
PKTHREAD STDCALL KeGetCurrentThread(VOID)
|
||||
{
|
||||
return(&(CurrentThread->Tcb));
|
||||
return(KeGetCurrentKPCR()->CurrentThread);
|
||||
}
|
||||
|
||||
PETHREAD STDCALL PsGetCurrentThread(VOID)
|
||||
{
|
||||
return(CurrentThread);
|
||||
PKTHREAD CurrentThread = KeGetCurrentKPCR()->CurrentThread;
|
||||
return(CONTAINING_RECORD(CurrentThread, ETHREAD, Tcb));
|
||||
}
|
||||
|
||||
HANDLE STDCALL PsGetCurrentThreadId(VOID)
|
||||
|
@ -144,8 +143,13 @@ static PETHREAD PsScanThreadList (KPRIORITY Priority, ULONG Affinity)
|
|||
{
|
||||
current = CONTAINING_RECORD(current_entry, ETHREAD,
|
||||
Tcb.QueueListEntry);
|
||||
assert(current->Tcb.State == THREAD_STATE_RUNNABLE);
|
||||
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 = current_entry->Flink;
|
||||
|
@ -160,6 +164,11 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
|
|||
KPRIORITY CurrentPriority;
|
||||
PETHREAD Candidate;
|
||||
ULONG Affinity;
|
||||
PKTHREAD KCurrentThread = KeGetCurrentKPCR()->CurrentThread;
|
||||
PETHREAD CurrentThread = CONTAINING_RECORD(KCurrentThread, ETHREAD, Tcb);
|
||||
|
||||
DPRINT("PsDispatchThread() %d/%d\n", KeGetCurrentProcessorNumber(),
|
||||
CurrentThread->Cid.UniqueThread);
|
||||
|
||||
CurrentThread->Tcb.State = NewThreadStatus;
|
||||
if (CurrentThread->Tcb.State == THREAD_STATE_RUNNABLE)
|
||||
|
@ -184,24 +193,25 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
|
|||
{
|
||||
PETHREAD OldThread;
|
||||
|
||||
DPRINT("Scheduling %x(%d)\n",Candidate, CurrentPriority);
|
||||
DPRINT("Scheduling %x(%d)\n",Candidate, CurrentPriority);
|
||||
|
||||
Candidate->Tcb.State = THREAD_STATE_RUNNING;
|
||||
|
||||
OldThread = CurrentThread;
|
||||
CurrentThread = Candidate;
|
||||
|
||||
Candidate->Tcb.State = THREAD_STATE_RUNNING;
|
||||
|
||||
OldThread = CurrentThread;
|
||||
CurrentThread = Candidate;
|
||||
|
||||
KeReleaseSpinLockFromDpcLevel(&PiThreadListLock);
|
||||
Ki386ContextSwitch(&CurrentThread->Tcb, &OldThread->Tcb);
|
||||
PsReapThreads();
|
||||
return;
|
||||
KeReleaseSpinLockFromDpcLevel(&PiThreadListLock);
|
||||
Ki386ContextSwitch(&CurrentThread->Tcb, &OldThread->Tcb);
|
||||
PsReapThreads();
|
||||
return;
|
||||
}
|
||||
}
|
||||
DbgPrint("CRITICAL: No threads are runnable\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
|
||||
VOID PsDispatchThread(ULONG NewThreadStatus)
|
||||
VOID
|
||||
PsDispatchThread(ULONG NewThreadStatus)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
|
||||
|
@ -214,7 +224,7 @@ VOID PsDispatchThread(ULONG NewThreadStatus)
|
|||
/*
|
||||
* Save wait IRQL
|
||||
*/
|
||||
CurrentThread->Tcb.WaitIrql = oldIrql;
|
||||
KeGetCurrentKPCR()->CurrentThread->WaitIrql = oldIrql;
|
||||
PsDispatchThreadNoLock(NewThreadStatus);
|
||||
KeLowerIrql(oldIrql);
|
||||
}
|
||||
|
@ -316,6 +326,8 @@ PsPrepareForApplicationProcessorInit(ULONG Id)
|
|||
IdleThreads[Id] = IdleThread;
|
||||
|
||||
NtClose(IdleThreadHandle);
|
||||
DbgPrint("IdleThread for Processor %d has PID %d\n",
|
||||
Id, IdleThread->Cid.UniqueThread);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -363,7 +375,6 @@ PsInitThreadManagment(VOID)
|
|||
HalInitFirstTask(FirstThread);
|
||||
FirstThread->Tcb.State = THREAD_STATE_RUNNING;
|
||||
FirstThread->Tcb.FreezeCount = 0;
|
||||
CurrentThread = FirstThread;
|
||||
KeGetCurrentKPCR()->CurrentThread = (PVOID)FirstThread;
|
||||
NtClose(FirstThreadHandle);
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ NtSetInformationThread(HANDLE ThreadHandle,
|
|||
break;
|
||||
|
||||
case ThreadAffinityMask:
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
Thread->Tcb.UserAffinity = *((PULONG)ThreadInformation);
|
||||
break;
|
||||
|
||||
case ThreadImpersonationToken:
|
||||
|
|
Loading…
Reference in a new issue