mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
new APC code ready for prime time
svn path=/trunk/; revision=865
This commit is contained in:
parent
53b1677997
commit
9a22766e36
4 changed files with 99 additions and 126 deletions
|
@ -6,6 +6,7 @@
|
|||
* PROGRAMMER: David Welch (welch@cwcom.net)
|
||||
* UPDATE HISTORY:
|
||||
* Created 22/05/98
|
||||
* 12/11/99: Phillip Susi: Reworked the APC code
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
@ -20,7 +21,7 @@
|
|||
#include <internal/debug.h>
|
||||
|
||||
extern VOID KeApcProlog(VOID);
|
||||
extern KSPIN_LOCK PiThreadListLock;
|
||||
static KSPIN_LOCK PiApcLock;
|
||||
|
||||
/* PROTOTYPES ****************************************************************/
|
||||
|
||||
|
@ -41,13 +42,15 @@ BOOLEAN KiTestAlert(PKTHREAD Thread,
|
|||
PLIST_ENTRY current_entry;
|
||||
PKAPC Apc;
|
||||
PULONG Esp = (PULONG)UserContext->Esp;
|
||||
KIRQL oldlvl;
|
||||
|
||||
DPRINT("KiTestAlert(Thread %x, UserContext %x)\n");
|
||||
|
||||
KeAcquireSpinLock( &PiApcLock, &oldlvl );
|
||||
current_entry = Thread->ApcState.ApcListHead[1].Flink;
|
||||
|
||||
if (current_entry == &Thread->ApcState.ApcListHead[1])
|
||||
{
|
||||
KeReleaseSpinLock( &PiApcLock, oldlvl );
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
@ -81,19 +84,28 @@ BOOLEAN KiTestAlert(PKTHREAD Thread,
|
|||
return(TRUE);
|
||||
}
|
||||
|
||||
VOID KeApcProlog2(PKAPC Apc)
|
||||
VOID KeApcProlog2()
|
||||
{
|
||||
PKTHREAD Thread;
|
||||
PETHREAD Thread = PsGetCurrentThread();
|
||||
PLIST_ENTRY current;
|
||||
PKAPC Apc;
|
||||
KIRQL oldlvl;
|
||||
|
||||
DPRINT("KeApcProlog2(Apc %x)\n", Apc);
|
||||
|
||||
Thread = Apc->Thread;
|
||||
KeLowerIrql(PASSIVE_LEVEL);
|
||||
DPRINT( "KeApcProlog2()\n" );
|
||||
KeLowerIrql( APC_LEVEL );
|
||||
KeAcquireSpinLock( &PiApcLock, &oldlvl );
|
||||
while( !IsListEmpty( &(Thread->Tcb.ApcState.ApcListHead[0]) ) )
|
||||
{
|
||||
DPRINT( "Delivering APC\n" );
|
||||
current = RemoveTailList( &(Thread->Tcb.ApcState.ApcListHead[0]) );
|
||||
KeReleaseSpinLock( &PiApcLock, oldlvl );
|
||||
Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry);
|
||||
KeApcProlog3(Apc);
|
||||
PsSuspendThread(CONTAINING_RECORD(Thread,ETHREAD,Tcb),
|
||||
NULL,
|
||||
Thread->Alertable,
|
||||
Thread->WaitMode);
|
||||
KeAcquireSpinLock( &PiApcLock, &oldlvl );
|
||||
}
|
||||
KeReleaseSpinLock( &PiApcLock, oldlvl );
|
||||
Thread->Tcb.WaitStatus = STATUS_ALERTED;
|
||||
KeLowerIrql( PASSIVE_LEVEL );
|
||||
}
|
||||
|
||||
VOID KeApcProlog3(PKAPC Apc)
|
||||
|
@ -102,70 +114,41 @@ VOID KeApcProlog3(PKAPC Apc)
|
|||
* a kernel APC
|
||||
*/
|
||||
{
|
||||
PKTHREAD Thread;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
DPRINT("KeApcProlog3(Apc %x)\n",Apc);
|
||||
InterlockedIncrement( &(Thread->ApcState.KernelApcInProgress) );
|
||||
InterlockedDecrement( &(Thread->ApcState.KernelApcPending) );
|
||||
|
||||
DPRINT("KeApcProlog2(Apc %x)\n",Apc);
|
||||
KeEnterCriticalRegion();
|
||||
Apc->Thread->ApcState.KernelApcInProgress++;
|
||||
Apc->Thread->ApcState.KernelApcPending--;
|
||||
RemoveEntryList(&Apc->ApcListEntry);
|
||||
Thread = Apc->Thread;
|
||||
Apc->KernelRoutine(Apc,
|
||||
&Apc->NormalRoutine,
|
||||
&Apc->NormalContext,
|
||||
&Apc->SystemArgument1,
|
||||
&Apc->SystemArgument2);
|
||||
Thread->ApcState.KernelApcInProgress--;
|
||||
KeLeaveCriticalRegion();
|
||||
InterlockedDecrement( &(Thread->ApcState.KernelApcInProgress) );
|
||||
}
|
||||
|
||||
VOID KeDeliverKernelApc(PKAPC Apc)
|
||||
VOID KeDeliverKernelApc( PKTHREAD TargetThread )
|
||||
/*
|
||||
* FUNCTION: Simulates an interrupt on the target thread which will transfer
|
||||
* control to a kernel mode routine
|
||||
* Must be called while holding the PiApcLock
|
||||
*/
|
||||
{
|
||||
PKTHREAD TargetThread;
|
||||
PULONG Stack;
|
||||
|
||||
DPRINT("KeDeliverKernelApc(Apc %x)\n", Apc);
|
||||
|
||||
TargetThread = Apc->Thread;
|
||||
|
||||
DPRINT( "KeDeliverKernelApc( TargetThread %x)\n", TargetThread );
|
||||
if (TargetThread == KeGetCurrentThread())
|
||||
{
|
||||
KeApcProlog3(Apc);
|
||||
KeApcProlog2();
|
||||
return;
|
||||
}
|
||||
|
||||
if (TargetThread->Context.cs == KERNEL_CS)
|
||||
{
|
||||
TargetThread->Context.esp = TargetThread->Context.esp - 16;
|
||||
TargetThread->Context.esp = TargetThread->Context.esp - 12;
|
||||
Stack = (PULONG)TargetThread->Context.esp;
|
||||
Stack[0] = TargetThread->Context.eax;
|
||||
Stack[1] = TargetThread->Context.eip;
|
||||
Stack[2] = TargetThread->Context.cs;
|
||||
Stack[3] = TargetThread->Context.eflags;
|
||||
Stack[0] = TargetThread->Context.eip;
|
||||
Stack[1] = TargetThread->Context.cs;
|
||||
Stack[2] = TargetThread->Context.eflags;
|
||||
TargetThread->Context.eip = (ULONG)KeApcProlog;
|
||||
TargetThread->Context.eax = (ULONG)Apc;
|
||||
}
|
||||
else
|
||||
{
|
||||
TargetThread->Context.esp = TargetThread->Context.esp - 40;
|
||||
Stack = (PULONG)TargetThread->Context.esp;
|
||||
Stack[9] = TargetThread->Context.gs;
|
||||
Stack[8] = TargetThread->Context.fs;
|
||||
Stack[7] = TargetThread->Context.ds;
|
||||
Stack[6] = TargetThread->Context.es;
|
||||
Stack[5] = TargetThread->Context.ss;
|
||||
Stack[4] = TargetThread->Context.esp;
|
||||
Stack[3] = TargetThread->Context.eflags;
|
||||
Stack[2] = TargetThread->Context.cs;
|
||||
Stack[1] = TargetThread->Context.eip;
|
||||
Stack[0] = TargetThread->Context.eax;
|
||||
TargetThread->Context.eip = (ULONG)KeApcProlog;
|
||||
TargetThread->Context.eax = (ULONG)Apc;
|
||||
}
|
||||
|
||||
PsResumeThread(CONTAINING_RECORD(TargetThread,ETHREAD,Tcb),
|
||||
NULL);
|
||||
|
@ -190,7 +173,7 @@ VOID KeInsertQueueApc(PKAPC Apc,
|
|||
"SystemArgument2 %x, Mode %d)\n",Apc,SystemArgument1,
|
||||
SystemArgument2,Mode);
|
||||
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
|
||||
KeAcquireSpinLock( &PiApcLock, &oldlvl );
|
||||
|
||||
Apc->SystemArgument1 = SystemArgument1;
|
||||
Apc->SystemArgument2 = SystemArgument2;
|
||||
|
@ -220,9 +203,18 @@ VOID KeInsertQueueApc(PKAPC Apc,
|
|||
DPRINT("TargetThread->KernelApcDisable %d\n",
|
||||
TargetThread->KernelApcDisable);
|
||||
DPRINT("Apc->KernelRoutine %x\n", Apc->KernelRoutine);
|
||||
if (Apc->ApcMode == KernelMode && TargetThread->KernelApcDisable >= 1)
|
||||
DPRINT( "TargetThread->Altertable = %x, TargetThread->WaitIrql = %d\n", TargetThread->Alertable, TargetThread->WaitIrql );
|
||||
if (Apc->ApcMode == KernelMode && TargetThread->KernelApcDisable >= 1 )
|
||||
if( TargetThread != PsGetCurrentThread() )
|
||||
{
|
||||
KeDeliverKernelApc(Apc);
|
||||
PsSuspendThread( CONTAINING_RECORD( TargetThread, ETHREAD, Tcb ), NULL, TRUE, KernelMode );
|
||||
KeReleaseSpinLock( &PiApcLock, oldlvl );
|
||||
if( TargetThread->WaitIrql < APC_LEVEL )
|
||||
KeDeliverKernelApc( TargetThread );
|
||||
}
|
||||
else {
|
||||
if( TargetThread->WaitIrql < APC_LEVEL )
|
||||
KeDeliverKernelApc( TargetThread );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -239,7 +231,6 @@ VOID KeInsertQueueApc(PKAPC Apc,
|
|||
PsResumeThread((PETHREAD)TargetThread,
|
||||
&Status);
|
||||
}
|
||||
KeLowerIrql(oldlvl);
|
||||
}
|
||||
|
||||
VOID KeInitializeApc(PKAPC Apc,
|
||||
|
@ -340,3 +331,9 @@ NTSTATUS STDCALL NtTestAlert(VOID)
|
|||
KiTestAlert(KeGetCurrentThread(),NULL);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
VOID PiInitApcManagement()
|
||||
{
|
||||
KeInitializeSpinLock( &PiApcLock );
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,7 @@ void KeApcProlog(void);
|
|||
__asm__("\n\t.global _KeApcProlog\n\t"
|
||||
"_KeApcProlog:\n\t"
|
||||
"pusha\n\t"
|
||||
"pushl %eax\n\t"
|
||||
"call _KeApcProlog2\n\t"
|
||||
"popl %eax\n\t"
|
||||
"popa\n\t"
|
||||
"popl %eax\n\t"
|
||||
"iret\n\t");
|
||||
|
||||
|
|
|
@ -27,5 +27,5 @@ VOID PiInitProcessManager(VOID)
|
|||
PsInitProcessManagment();
|
||||
PsInitThreadManagment();
|
||||
PsInitIdleThread();
|
||||
// PiInitApcManagement();
|
||||
PiInitApcManagement();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: thread.c,v 1.38 1999/12/12 00:59:39 dwelch Exp $
|
||||
/* $Id: thread.c,v 1.39 1999/12/12 03:56:53 phreak Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -46,7 +46,7 @@ KSPIN_LOCK PiThreadListLock;
|
|||
/*
|
||||
* PURPOSE: List of threads associated with each priority level
|
||||
*/
|
||||
static LIST_ENTRY PiThreadListHead;
|
||||
static LIST_ENTRY PiThreadListHead = { &PiThreadListHead, &PiThreadListHead };
|
||||
static LIST_ENTRY PriorityListHead[NR_THREAD_PRIORITY_LEVELS];
|
||||
static BOOLEAN DoneInitYet = FALSE;
|
||||
ULONG PiNrThreads = 0;
|
||||
|
@ -122,11 +122,6 @@ VOID PsDumpThreads(VOID)
|
|||
PLIST_ENTRY current_entry;
|
||||
PETHREAD current;
|
||||
|
||||
if (!DoneInitYet)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
current_entry = PiThreadListHead.Flink;
|
||||
|
||||
while (current_entry != &PiThreadListHead)
|
||||
|
@ -153,8 +148,6 @@ VOID PsReapThreads(VOID)
|
|||
|
||||
// DPRINT1("PsReapThreads()\n");
|
||||
|
||||
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
|
||||
|
||||
current_entry = PiThreadListHead.Flink;
|
||||
|
||||
while (current_entry != &PiThreadListHead)
|
||||
|
@ -171,8 +164,6 @@ VOID PsReapThreads(VOID)
|
|||
ObDereferenceObject(current);
|
||||
}
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
|
||||
}
|
||||
|
||||
static PETHREAD PsScanThreadList (KPRIORITY Priority)
|
||||
|
@ -222,7 +213,6 @@ static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
|
|||
Candidate = PsScanThreadList(CurrentPriority);
|
||||
if (Candidate == CurrentThread)
|
||||
{
|
||||
KeReleaseSpinLockFromDpcLevel(&PiThreadListLock);
|
||||
return;
|
||||
}
|
||||
if (Candidate != NULL)
|
||||
|
@ -233,9 +223,12 @@ static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
|
|||
|
||||
CurrentThread = Candidate;
|
||||
|
||||
KeReleaseSpinLockFromDpcLevel(&PiThreadListLock);
|
||||
KeReleaseSpinLockFromDpcLevel( &PiThreadListLock );
|
||||
HalTaskSwitch(&CurrentThread->Tcb);
|
||||
KeAcquireSpinLockAtDpcLevel( &PiThreadListLock );
|
||||
DPRINT( "Woken up, grabbed lock\n" );
|
||||
PsReapThreads();
|
||||
DPRINT( "Reaped\n" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -258,23 +251,16 @@ VOID PsDispatchThread(ULONG NewThreadStatus)
|
|||
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
|
||||
CurrentThread->Tcb.WaitIrql = oldIrql; // save wait Irql
|
||||
PsDispatchThreadNoLock(NewThreadStatus);
|
||||
// KeReleaseSpinLock(&PiThreadListLock, oldIrql);
|
||||
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
|
||||
KeLowerIrql(oldIrql);
|
||||
// DPRINT("oldIrql %d\n",oldIrql);
|
||||
}
|
||||
|
||||
static VOID PiTimeoutThread(struct _KDPC *dpc,
|
||||
PVOID Context,
|
||||
PVOID arg1,
|
||||
PVOID arg2 )
|
||||
static VOID PiTimeoutThread( struct _KDPC *dpc, PVOID Context, PVOID arg1, PVOID arg2 )
|
||||
{
|
||||
/*
|
||||
* wake up the thread, and tell it it timed out
|
||||
*/
|
||||
// wake up the thread, and tell it it timed out
|
||||
NTSTATUS Status = STATUS_TIMEOUT;
|
||||
|
||||
DPRINT("PiTimeoutThread()\n");
|
||||
PsResumeThread((ETHREAD *)Context, &Status);
|
||||
PsResumeThread( (ETHREAD *)Context, &Status );
|
||||
}
|
||||
|
||||
NTSTATUS PsInitializeThread(HANDLE ProcessHandle,
|
||||
|
@ -347,21 +333,24 @@ NTSTATUS PsInitializeThread(HANDLE ProcessHandle,
|
|||
}
|
||||
|
||||
|
||||
// Suspend and resume may only be called to suspend the current thread, except by apc.c
|
||||
|
||||
ULONG PsResumeThread(PETHREAD Thread,
|
||||
PNTSTATUS WaitStatus)
|
||||
{
|
||||
ULONG r;
|
||||
KIRQL oldIrql;
|
||||
ULONG r;
|
||||
|
||||
DPRINT("PsResumeThread(Thread %x) CurrentThread %x \n",Thread,
|
||||
PsGetCurrentThread());
|
||||
DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount);
|
||||
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
|
||||
r = InterlockedDecrement(&Thread->Tcb.SuspendCount);
|
||||
DPRINT("r %d Thread->Tcb.SuspendCount %d\n",r,Thread->Tcb.SuspendCount);
|
||||
if (r <= 0)
|
||||
DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount);
|
||||
r = Thread->Tcb.SuspendCount;
|
||||
if ( Thread->Tcb.SuspendCount == TRUE )
|
||||
{
|
||||
// DPRINT("Marking thread %x as runnable\n",Thread);
|
||||
Thread->Tcb.SuspendCount = FALSE;
|
||||
Thread->Tcb.State = THREAD_STATE_RUNNABLE;
|
||||
if (WaitStatus != NULL)
|
||||
{
|
||||
|
@ -373,7 +362,7 @@ ULONG PsResumeThread(PETHREAD Thread,
|
|||
DPRINT("About release ThreadListLock = %x\n", &PiThreadListLock);
|
||||
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
|
||||
DPRINT("Finished PsResumeThread()\n");
|
||||
return(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
@ -382,31 +371,25 @@ ULONG PsSuspendThread(PETHREAD Thread,
|
|||
UCHAR Alertable,
|
||||
ULONG WaitMode)
|
||||
{
|
||||
ULONG r;
|
||||
KIRQL oldIrql;
|
||||
|
||||
assert_irql(PASSIVE_LEVEL);
|
||||
ULONG r;
|
||||
|
||||
DPRINT("PsSuspendThread(Thread %x)\n",Thread);
|
||||
DPRINT("Thread->Tcb.BasePriority %d\n", Thread->Tcb.BasePriority);
|
||||
DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount);
|
||||
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
|
||||
r = InterlockedIncrement(&Thread->Tcb.SuspendCount);
|
||||
DPRINT("r %d Thread->Tcb.SuspendCount %d\n",r,Thread->Tcb.SuspendCount);
|
||||
|
||||
if (r > 0)
|
||||
r = Thread->Tcb.SuspendCount;
|
||||
if ( Thread->Tcb.SuspendCount == FALSE )
|
||||
{
|
||||
Thread->Tcb.SuspendCount = TRUE;
|
||||
if (Thread != PsGetCurrentThread())
|
||||
{
|
||||
if (Thread->Tcb.State == THREAD_STATE_RUNNABLE)
|
||||
{
|
||||
RemoveEntryList(&Thread->Tcb.QueueListEntry);
|
||||
}
|
||||
Thread->Tcb.State = THREAD_STATE_SUSPENDED;
|
||||
Thread->Tcb.Alertable = Alertable;
|
||||
Thread->Tcb.WaitMode = WaitMode;
|
||||
PiNrRunnableThreads--;
|
||||
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -416,20 +399,16 @@ ULONG PsSuspendThread(PETHREAD Thread,
|
|||
PiNrRunnableThreads--;
|
||||
Thread->Tcb.WaitIrql = oldIrql; // save wait IRQL
|
||||
PsDispatchThreadNoLock(THREAD_STATE_SUSPENDED);
|
||||
KeLowerIrql(oldIrql);
|
||||
if (WaitStatus != NULL)
|
||||
{
|
||||
*WaitStatus = PsGetCurrentThread()->Tcb.WaitStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("About to release ThreadListLock = %x\n", &PiThreadListLock);
|
||||
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
|
||||
}
|
||||
DPRINT("PsSuspendThread() finished\n");
|
||||
return(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue