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:
David Welch 2001-04-17 23:39:26 +00:00
parent f29036d97b
commit d41145488c
11 changed files with 164 additions and 143 deletions

View file

@ -7,3 +7,4 @@ depends
depends.exe
mkconfig
mkconfig.exe
ntoskrnl.dbg

View file

@ -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");
}

View file

@ -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);
}
}
}
}
}

View file

@ -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

View file

@ -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)

View file

@ -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
*/

View file

@ -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);
}

View file

@ -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
*/

View file

@ -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));
}

View file

@ -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(&current->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);

View file

@ -74,7 +74,7 @@ NtSetInformationThread(HANDLE ThreadHandle,
break;
case ThreadAffinityMask:
Status = STATUS_NOT_IMPLEMENTED;
Thread->Tcb.UserAffinity = *((PULONG)ThreadInformation);
break;
case ThreadImpersonationToken: