mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
- Re-implement KiRequestApcInterrupt in ke_x.h. Make it work by CPU number (as documented) instead of comparing PRCBs.
- Move NtQueueApcThread to ps/state.c since it's a Ps-level function. - Make NtQueueApcThread use POOL_QUOTA_FAIL_INSTEAD_OF_RAISE and add that flag to our DDK. Also fix the check for SystemThread by looking at the flag, not checking if TEB == NULL. Also fix a memory leak and comment header. - Fix comment header in KiInitalizeUserApc. svn path=/trunk/; revision=24051
This commit is contained in:
parent
1462b71058
commit
2fea34f0e1
6 changed files with 153 additions and 144 deletions
|
@ -4108,6 +4108,11 @@ typedef enum _POOL_TYPE {
|
|||
NonPagedPoolCacheAlignedMustSSession
|
||||
} POOL_TYPE;
|
||||
|
||||
#define POOL_COLD_ALLOCATION 256
|
||||
#define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE 8
|
||||
#define POOL_RAISE_IF_ALLOCATION_FAILURE 16
|
||||
|
||||
|
||||
typedef enum _EX_POOL_PRIORITY {
|
||||
LowPoolPriority,
|
||||
LowPoolPrioritySpecialPoolOverrun = 8,
|
||||
|
|
|
@ -428,6 +428,14 @@ KiRundownThread(IN PKTHREAD Thread)
|
|||
}
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiRequestApcInterrupt(IN UCHAR Processor)
|
||||
{
|
||||
/* Request a software interrupt */
|
||||
HalRequestSoftwareInterrupt(APC_LEVEL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
KIRQL
|
||||
|
@ -594,6 +602,22 @@ KiCheckDeferredReadyList(IN PKPRCB Prcb)
|
|||
if (Prcb->DeferredReadyListHead.Next) KiProcessDeferredReadyList(Prcb);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
KiRequestApcInterrupt(IN UCHAR Processor)
|
||||
{
|
||||
/* Check if we're on the same CPU */
|
||||
if (KeGetCurrentPrcb()->Number == Processor)
|
||||
{
|
||||
/* Request a software interrupt */
|
||||
HalRequestSoftwareInterrupt(APC_LEVEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
KiIpiSendRequest(KeGetCurrentPrcb()->SetMember, IPI_APC);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FORCEINLINE
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
|
||||
/* formerly located in ps/notify.c */
|
||||
#define TAG_KAPC TAG('k','p','a','p') /* kpap - kernel ps apc */
|
||||
#define TAG_PS_APC TAG('P', 's', 'a', 'p') /* Psap - Ps APC */
|
||||
|
||||
/* formerly located in rtl/handle.c */
|
||||
#define TAG_HDTB TAG('H', 'D', 'T', 'B')
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
* @name KiCheckForKernelApcDelivery
|
||||
* @implemented NT 5.2
|
||||
*
|
||||
* The KiCheckForKernelApcDelivery routine is called whenever APCs have just
|
||||
* been re-enabled in Kernel Mode, such as after leaving a Critical or
|
||||
* The KiCheckForKernelApcDelivery routine is called whenever APCs have
|
||||
* just been re-enabled in Kernel Mode, such as after leaving a Critical or
|
||||
* Guarded Region. It delivers APCs if the environment is right.
|
||||
*
|
||||
* @param None.
|
||||
|
@ -57,32 +57,6 @@ KiCheckForKernelApcDelivery(VOID)
|
|||
}
|
||||
}
|
||||
|
||||
static
|
||||
__inline
|
||||
VOID
|
||||
KiRequestApcInterrupt(IN PKTHREAD Thread)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
PKPRCB Prcb, CurrentPrcb;
|
||||
LONG i;
|
||||
|
||||
CurrentPrcb = KeGetCurrentPrcb();
|
||||
for (i = 0; i < KeNumberProcessors; i++)
|
||||
{
|
||||
Prcb = ((PKPCR)(KPCR_BASE + i * PAGE_SIZE))->Prcb;
|
||||
if (Prcb->CurrentThread == Thread)
|
||||
{
|
||||
ASSERT (CurrentPrcb != Prcb);
|
||||
KiIpiSendRequest(Prcb->SetMember, IPI_APC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT (i < KeNumberProcessors);
|
||||
#else
|
||||
HalRequestSoftwareInterrupt(APC_LEVEL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*++
|
||||
* KiInsertQueueApc
|
||||
*
|
||||
|
@ -236,7 +210,7 @@ KiInsertQueueApc(PKAPC Apc,
|
|||
if (Thread->State == Running)
|
||||
{
|
||||
/* The thread is running, so send an APC request */
|
||||
KiRequestApcInterrupt(Thread);
|
||||
KiRequestApcInterrupt(Thread->NextProcessor);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -498,18 +472,6 @@ Quickie:
|
|||
return;
|
||||
}
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
KiFreeApcRoutine(PKAPC Apc,
|
||||
PKNORMAL_ROUTINE* NormalRoutine,
|
||||
PVOID* NormalContext,
|
||||
PVOID* SystemArgument1,
|
||||
PVOID* SystemArgument2)
|
||||
{
|
||||
/* Free the APC and do nothing else */
|
||||
ExFreePool(Apc);
|
||||
}
|
||||
|
||||
static __inline
|
||||
VOID RepairList(PLIST_ENTRY Original,
|
||||
PLIST_ENTRY Copy,
|
||||
|
@ -900,94 +862,3 @@ KeAreApcsDisabled(VOID)
|
|||
return KeGetCurrentThread()->CombinedApcDisable ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* NtQueueApcThread
|
||||
* NT4
|
||||
*
|
||||
* This routine is used to queue an APC from user-mode for the specified
|
||||
* thread.
|
||||
*
|
||||
* Params:
|
||||
* Thread Handle - Handle to the Thread. This handle must have THREAD_SET_CONTEXT privileges.
|
||||
*
|
||||
* ApcRoutine - Pointer to the APC Routine to call when the APC executes.
|
||||
*
|
||||
* NormalContext - Pointer to the context to send to the Normal Routine.
|
||||
*
|
||||
* SystemArgument[1-2] - Pointer to a set of two parameters that contain
|
||||
* untyped data.
|
||||
*
|
||||
* Returns:
|
||||
* STATUS_SUCCESS or failure cute from associated calls.
|
||||
*
|
||||
* Remarks:
|
||||
* The thread must enter an alertable wait before the APC will be
|
||||
* delivered.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtQueueApcThread(HANDLE ThreadHandle,
|
||||
PKNORMAL_ROUTINE ApcRoutine,
|
||||
PVOID NormalContext,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2)
|
||||
{
|
||||
PKAPC Apc;
|
||||
PETHREAD Thread;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Get ETHREAD from Handle */
|
||||
Status = ObReferenceObjectByHandle(ThreadHandle,
|
||||
THREAD_SET_CONTEXT,
|
||||
PsThreadType,
|
||||
PreviousMode,
|
||||
(PVOID)&Thread,
|
||||
NULL);
|
||||
|
||||
/* Fail if the Handle is invalid for some reason */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* If this is a Kernel or System Thread, then fail */
|
||||
if (Thread->Tcb.Teb == NULL) {
|
||||
|
||||
ObDereferenceObject(Thread);
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/* Allocate an APC */
|
||||
Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG('P', 's', 'a', 'p'));
|
||||
if (Apc == NULL) {
|
||||
|
||||
ObDereferenceObject(Thread);
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Initialize and Queue a user mode apc (always!) */
|
||||
KeInitializeApc(Apc,
|
||||
&Thread->Tcb,
|
||||
OriginalApcEnvironment,
|
||||
KiFreeApcRoutine,
|
||||
NULL,
|
||||
ApcRoutine,
|
||||
UserMode,
|
||||
NormalContext);
|
||||
|
||||
if (!KeInsertQueueApc(Apc, SystemArgument1, SystemArgument2, IO_NO_INCREMENT)) {
|
||||
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
} else {
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Dereference Thread and Return */
|
||||
ObDereferenceObject(Thread);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,27 +31,28 @@ _SEH_FILTER(KiCopyInformation2)
|
|||
}
|
||||
|
||||
/*++
|
||||
* KiInitializeUserApc
|
||||
* @name KiInitializeUserApc
|
||||
*
|
||||
* Prepares the Context for a User-Mode APC called through NTDLL.DLL
|
||||
*
|
||||
* Params:
|
||||
* Reserved - Pointer to the Exception Frame on non-i386 builds.
|
||||
* @param Reserved
|
||||
* Pointer to the Exception Frame on non-i386 builds.
|
||||
*
|
||||
* TrapFrame - Pointer to the Trap Frame.
|
||||
* @param TrapFrame
|
||||
* Pointer to the Trap Frame.
|
||||
*
|
||||
* NormalRoutine - Pointer to the NormalRoutine to call.
|
||||
* @param NormalRoutine
|
||||
* Pointer to the NormalRoutine to call.
|
||||
*
|
||||
* NormalContext - Pointer to the context to send to the Normal Routine.
|
||||
* @param NormalContext
|
||||
* Pointer to the context to send to the Normal Routine.
|
||||
*
|
||||
* SystemArgument[1-2] - Pointer to a set of two parameters that contain
|
||||
* untyped data.
|
||||
* @param SystemArgument[1-2]
|
||||
* Pointer to a set of two parameters that contain untyped data.
|
||||
*
|
||||
* Returns:
|
||||
* None.
|
||||
* @return None.
|
||||
*
|
||||
* Remarks:
|
||||
* None.
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
|
|
|
@ -15,6 +15,18 @@
|
|||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
PspQueueApcSpecialApc(IN PKAPC Apc,
|
||||
IN OUT PKNORMAL_ROUTINE* NormalRoutine,
|
||||
IN OUT PVOID* NormalContext,
|
||||
IN OUT PVOID* SystemArgument1,
|
||||
IN OUT PVOID* SystemArgument2)
|
||||
{
|
||||
/* Free the APC and do nothing else */
|
||||
ExFreePool(Apc);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PsResumeThread(IN PETHREAD Thread,
|
||||
|
@ -448,4 +460,99 @@ NtTestAlert(VOID)
|
|||
STATUS_ALERTED : STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name NtQueueApcThread
|
||||
* NT4
|
||||
*
|
||||
* This routine is used to queue an APC from user-mode for the specified
|
||||
* thread.
|
||||
*
|
||||
* @param ThreadHandle
|
||||
* Handle to the Thread.
|
||||
* This handle must have THREAD_SET_CONTEXT privileges.
|
||||
*
|
||||
* @param ApcRoutine
|
||||
* Pointer to the APC Routine to call when the APC executes.
|
||||
*
|
||||
* @param NormalContext
|
||||
* Pointer to the context to send to the Normal Routine.
|
||||
*
|
||||
* @param SystemArgument[1-2]
|
||||
* Pointer to a set of two parameters that contain untyped data.
|
||||
*
|
||||
* @return STATUS_SUCCESS or failure cute from associated calls.
|
||||
*
|
||||
* @remarks The thread must enter an alertable wait before the APC will be
|
||||
* delivered.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtQueueApcThread(IN HANDLE ThreadHandle,
|
||||
IN PKNORMAL_ROUTINE ApcRoutine,
|
||||
IN PVOID NormalContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2)
|
||||
{
|
||||
PKAPC Apc;
|
||||
PETHREAD Thread;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Get ETHREAD from Handle */
|
||||
Status = ObReferenceObjectByHandle(ThreadHandle,
|
||||
THREAD_SET_CONTEXT,
|
||||
PsThreadType,
|
||||
ExGetPreviousMode(),
|
||||
(PVOID)&Thread,
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Check if this is a System Thread */
|
||||
if (Thread->SystemThread)
|
||||
{
|
||||
/* Fail */
|
||||
Status = STATUS_INVALID_HANDLE;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* Allocate an APC */
|
||||
Apc = ExAllocatePoolWithTag(NonPagedPool |
|
||||
POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
|
||||
sizeof(KAPC),
|
||||
TAG_PS_APC);
|
||||
if (!Apc)
|
||||
{
|
||||
/* Fail */
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* Initialize the APC */
|
||||
KeInitializeApc(Apc,
|
||||
&Thread->Tcb,
|
||||
OriginalApcEnvironment,
|
||||
PspQueueApcSpecialApc,
|
||||
NULL,
|
||||
ApcRoutine,
|
||||
UserMode,
|
||||
NormalContext);
|
||||
|
||||
/* Queue it */
|
||||
if (!KeInsertQueueApc(Apc,
|
||||
SystemArgument1,
|
||||
SystemArgument2,
|
||||
IO_NO_INCREMENT))
|
||||
{
|
||||
/* We failed, free it */
|
||||
ExFreePool(Apc);
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* Dereference Thread and Return */
|
||||
Quit:
|
||||
ObDereferenceObject(Thread);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue