2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/process.c
5 * PURPOSE: Kernel Process Management and System Call Tables
6 * PROGRAMMERS: Alex Ionescu
10 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 LIST_ENTRY KiProcessListHead
;
19 LIST_ENTRY KiProcessInSwapListHead
, KiProcessOutSwapListHead
;
20 LIST_ENTRY KiStackInSwapListHead
;
23 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable
[SSDT_MAX_ENTRIES
];
24 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow
[SSDT_MAX_ENTRIES
];
26 PVOID KeUserApcDispatcher
;
27 PVOID KeUserCallbackDispatcher
;
28 PVOID KeUserExceptionDispatcher
;
29 PVOID KeRaiseUserExceptionDispatcher
;
31 /* PRIVATE FUNCTIONS *********************************************************/
35 KiAttachProcess(IN PKTHREAD Thread
,
37 IN PKLOCK_QUEUE_HANDLE ApcLock
,
38 IN PRKAPC_STATE SavedApcState
)
41 PLIST_ENTRY ListHead
, NextEntry
;
42 PKTHREAD CurrentThread
;
44 ASSERT(Process
!= Thread
->ApcState
.Process
);
46 /* Increase Stack Count */
47 ASSERT(Process
->StackCount
!= MAXULONG_PTR
);
48 Process
->StackCount
++;
50 /* Swap the APC Environment */
51 KiMoveApcState(&Thread
->ApcState
, SavedApcState
);
53 /* Reinitialize Apc State */
54 InitializeListHead(&Thread
->ApcState
.ApcListHead
[KernelMode
]);
55 InitializeListHead(&Thread
->ApcState
.ApcListHead
[UserMode
]);
56 Thread
->ApcState
.Process
= Process
;
57 Thread
->ApcState
.KernelApcInProgress
= FALSE
;
58 Thread
->ApcState
.KernelApcPending
= FALSE
;
59 Thread
->ApcState
.UserApcPending
= FALSE
;
61 /* Update Environment Pointers if needed*/
62 if (SavedApcState
== &Thread
->SavedApcState
)
64 Thread
->ApcStatePointer
[OriginalApcEnvironment
] = &Thread
->
66 Thread
->ApcStatePointer
[AttachedApcEnvironment
] = &Thread
->ApcState
;
67 Thread
->ApcStateIndex
= AttachedApcEnvironment
;
70 /* Check if the process is paged in */
71 if (Process
->State
== ProcessInMemory
)
73 /* Scan the ready list */
75 ListHead
= &Process
->ReadyListHead
;
76 NextEntry
= ListHead
->Flink
;
77 while (NextEntry
!= ListHead
)
80 CurrentThread
= CONTAINING_RECORD(NextEntry
, KTHREAD
, WaitListEntry
);
83 RemoveEntryList(NextEntry
);
84 CurrentThread
->ProcessReadyQueue
= FALSE
;
87 KiReadyThread(CurrentThread
);
89 /* Go to the next one */
90 NextEntry
= ListHead
->Flink
;
94 /* Release dispatcher lock */
95 KiReleaseDispatcherLockFromDpcLevel();
98 KiReleaseApcLockFromDpcLevel(ApcLock
);
101 KiSwapProcess(Process
, SavedApcState
->Process
);
103 /* Exit the dispatcher */
104 KiExitDispatcher(ApcLock
->OldIrql
);
108 DPRINT1("Errr. ReactOS doesn't support paging out processes yet...\n");
115 KeInitializeProcess(IN OUT PKPROCESS Process
,
116 IN KPRIORITY Priority
,
117 IN KAFFINITY Affinity
,
118 IN PULONG_PTR DirectoryTableBase
,
127 /* Initialize the Dispatcher Header */
128 Process
->Header
.Type
= ProcessObject
;
129 Process
->Header
.Size
= sizeof(KPROCESS
) / sizeof(ULONG
);
130 Process
->Header
.SignalState
= 0;
131 InitializeListHead(&(Process
->Header
.WaitListHead
));
133 /* Initialize Scheduler Data, Alignment Faults and Set the PDE */
134 Process
->Affinity
= Affinity
;
135 Process
->BasePriority
= (CHAR
)Priority
;
136 Process
->QuantumReset
= 6;
137 Process
->DirectoryTableBase
[0] = DirectoryTableBase
[0];
138 Process
->DirectoryTableBase
[1] = DirectoryTableBase
[1];
139 Process
->AutoAlignment
= Enable
;
141 Process
->IopmOffset
= KiComputeIopmOffset(IO_ACCESS_MAP_NONE
);
144 /* Initialize the lists */
145 InitializeListHead(&Process
->ThreadListHead
);
146 InitializeListHead(&Process
->ProfileListHead
);
147 InitializeListHead(&Process
->ReadyListHead
);
149 /* Initialize the current State */
150 Process
->State
= ProcessInMemory
;
152 /* Check how many Nodes there are on the system */
154 if (KeNumberNodes
> 1)
156 /* Set the new seed */
157 KeProcessNodeSeed
= (KeProcessNodeSeed
+ 1) / KeNumberNodes
;
158 IdealNode
= KeProcessNodeSeed
;
160 /* Loop every node */
163 /* Check if the affinity matches */
164 if (KeNodeBlock
[IdealNode
]->ProcessorMask
!= Affinity
) break;
166 /* No match, try next Ideal Node and increase node loop index */
170 /* Check if the Ideal Node is beyond the total number of nodes */
171 if (IdealNode
>= KeNumberNodes
)
173 /* Normalize the Ideal Node */
174 IdealNode
-= KeNumberNodes
;
176 } while (i
< KeNumberNodes
);
179 /* Set the ideal node and get the ideal node block */
180 Process
->IdealNode
= IdealNode
;
181 Node
= KeNodeBlock
[IdealNode
];
182 ASSERT(Node
->ProcessorMask
& Affinity
);
184 /* Find the matching affinity set to calculate the thread seed */
185 Affinity
&= Node
->ProcessorMask
;
186 Process
->ThreadSeed
= KeFindNextRightSetAffinity(Node
->Seed
,
188 Node
->Seed
= Process
->ThreadSeed
;
194 KeSetProcess(IN PKPROCESS Process
,
195 IN KPRIORITY Increment
,
200 ASSERT_PROCESS(Process
);
201 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
203 /* Lock Dispatcher */
204 OldIrql
= KiAcquireDispatcherLock();
207 OldState
= Process
->Header
.SignalState
;
209 /* Signal the Process */
210 Process
->Header
.SignalState
= TRUE
;
212 /* Check if was unsignaled and has waiters */
214 !(IsListEmpty(&Process
->Header
.WaitListHead
)))
216 /* Unwait the threads */
217 KxUnwaitThread(&Process
->Header
, Increment
);
220 /* Release Dispatcher Database */
221 KiReleaseDispatcherLock(OldIrql
);
223 /* Return the previous State */
229 KeSetQuantumProcess(IN PKPROCESS Process
,
232 KLOCK_QUEUE_HANDLE ProcessLock
;
233 PLIST_ENTRY NextEntry
, ListHead
;
235 ASSERT_PROCESS(Process
);
236 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
238 /* Lock the process */
239 KiAcquireProcessLock(Process
, &ProcessLock
);
241 /* Set new quantum */
242 Process
->QuantumReset
= Quantum
;
244 /* Loop all child threads */
245 ListHead
= &Process
->ThreadListHead
;
246 NextEntry
= ListHead
->Flink
;
247 while (ListHead
!= NextEntry
)
250 Thread
= CONTAINING_RECORD(NextEntry
, KTHREAD
, ThreadListEntry
);
253 Thread
->QuantumReset
= Quantum
;
255 /* Go to the next one */
256 NextEntry
= NextEntry
->Flink
;
260 KiReleaseProcessLock(&ProcessLock
);
265 KeSetAffinityProcess(IN PKPROCESS Process
,
266 IN KAFFINITY Affinity
)
269 KLOCK_QUEUE_HANDLE ProcessLock
;
270 PLIST_ENTRY NextEntry
, ListHead
;
271 KAFFINITY OldAffinity
;
273 ASSERT_PROCESS(Process
);
274 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
275 ASSERT((Affinity
& KeActiveProcessors
) != 0);
277 /* Lock the process */
278 KiAcquireProcessLock(Process
, &ProcessLock
);
280 /* Acquire the dispatcher lock */
281 KiAcquireDispatcherLockAtDpcLevel();
283 /* Capture old affinity and update it */
284 OldAffinity
= Process
->Affinity
;
285 Process
->Affinity
= Affinity
;
287 /* Loop all child threads */
288 ListHead
= &Process
->ThreadListHead
;
289 NextEntry
= ListHead
->Flink
;
290 while (ListHead
!= NextEntry
)
293 Thread
= CONTAINING_RECORD(NextEntry
, KTHREAD
, ThreadListEntry
);
295 /* Set affinity on it */
296 KiSetAffinityThread(Thread
, Affinity
);
297 NextEntry
= NextEntry
->Flink
;
300 /* Release Dispatcher Database */
301 KiReleaseDispatcherLockFromDpcLevel();
303 /* Release the process lock */
304 KiReleaseProcessLockFromDpcLevel(&ProcessLock
);
305 KiExitDispatcher(ProcessLock
.OldIrql
);
307 /* Return previous affinity */
313 KeSetAutoAlignmentProcess(IN PKPROCESS Process
,
316 /* Set or reset the bit depending on what the enable flag says */
319 return InterlockedBitTestAndSet(&Process
->ProcessFlags
,
320 KPSF_AUTO_ALIGNMENT_BIT
);
324 return InterlockedBitTestAndReset(&Process
->ProcessFlags
,
325 KPSF_AUTO_ALIGNMENT_BIT
);
331 KeSetDisableBoostProcess(IN PKPROCESS Process
,
334 /* Set or reset the bit depending on what the disable flag says */
337 return InterlockedBitTestAndSet(&Process
->ProcessFlags
,
338 KPSF_DISABLE_BOOST_BIT
);
342 return InterlockedBitTestAndReset(&Process
->ProcessFlags
,
343 KPSF_DISABLE_BOOST_BIT
);
349 KeSetPriorityAndQuantumProcess(IN PKPROCESS Process
,
350 IN KPRIORITY Priority
,
351 IN UCHAR Quantum OPTIONAL
)
353 KLOCK_QUEUE_HANDLE ProcessLock
;
355 PLIST_ENTRY NextEntry
, ListHead
;
356 KPRIORITY NewPriority
, OldPriority
;
358 ASSERT_PROCESS(Process
);
359 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
361 /* Check if the process already has this priority */
362 if (Process
->BasePriority
== Priority
) return Process
->BasePriority
;
364 /* If the caller gave priority 0, normalize to 1 */
365 if (!Priority
) Priority
= LOW_PRIORITY
+ 1;
367 /* Lock the process */
368 KiAcquireProcessLock(Process
, &ProcessLock
);
370 /* Check if we are modifying the quantum too */
371 if (Quantum
) Process
->QuantumReset
= Quantum
;
373 /* Save the current base priority and update it */
374 OldPriority
= Process
->BasePriority
;
375 Process
->BasePriority
= (SCHAR
)Priority
;
377 /* Calculate the priority delta */
378 Delta
= Priority
- OldPriority
;
380 /* Set the list head and list entry */
381 ListHead
= &Process
->ThreadListHead
;
382 NextEntry
= ListHead
->Flink
;
384 /* Check if this is a real-time priority */
385 if (Priority
>= LOW_REALTIME_PRIORITY
)
387 /* Loop the thread list */
388 while (NextEntry
!= ListHead
)
391 Thread
= CONTAINING_RECORD(NextEntry
, KTHREAD
, ThreadListEntry
);
393 /* Update the quantum if we had one */
394 if (Quantum
) Thread
->QuantumReset
= Quantum
;
396 /* Acquire the thread lock */
397 KiAcquireThreadLock(Thread
);
399 /* Calculate the new priority */
400 NewPriority
= Thread
->BasePriority
+ Delta
;
401 if (NewPriority
< LOW_REALTIME_PRIORITY
)
403 /* We're in real-time range, don't let it go below */
404 NewPriority
= LOW_REALTIME_PRIORITY
;
406 else if (NewPriority
> HIGH_PRIORITY
)
408 /* We're going beyond the maximum priority, normalize */
409 NewPriority
= HIGH_PRIORITY
;
413 * If priority saturation occured or the old priority was still in
414 * the real-time range, don't do anything.
416 if (!(Thread
->Saturation
) || (OldPriority
< LOW_REALTIME_PRIORITY
))
418 /* Check if we had priority saturation */
419 if (Thread
->Saturation
> 0)
421 /* Boost priority to maximum */
422 NewPriority
= HIGH_PRIORITY
;
424 else if (Thread
->Saturation
< 0)
426 /* If we had negative saturation, set minimum priority */
427 NewPriority
= LOW_REALTIME_PRIORITY
;
430 /* Update priority and quantum */
431 Thread
->BasePriority
= (SCHAR
)NewPriority
;
432 Thread
->Quantum
= Thread
->QuantumReset
;
434 /* Disable decrements and update priority */
435 Thread
->PriorityDecrement
= 0;
436 KiSetPriorityThread(Thread
, NewPriority
);
439 /* Release the thread lock */
440 KiReleaseThreadLock(Thread
);
442 /* Go to the next thread */
443 NextEntry
= NextEntry
->Flink
;
448 /* Loop the thread list */
449 while (NextEntry
!= ListHead
)
452 Thread
= CONTAINING_RECORD(NextEntry
, KTHREAD
, ThreadListEntry
);
454 /* Update the quantum if we had one */
455 if (Quantum
) Thread
->QuantumReset
= Quantum
;
457 /* Lock the thread */
458 KiAcquireThreadLock(Thread
);
460 /* Calculate the new priority */
461 NewPriority
= Thread
->BasePriority
+ Delta
;
462 if (NewPriority
>= LOW_REALTIME_PRIORITY
)
464 /* We're not real-time range, don't let it enter RT range */
465 NewPriority
= LOW_REALTIME_PRIORITY
- 1;
467 else if (NewPriority
<= LOW_PRIORITY
)
469 /* We're going below the minimum priority, normalize */
474 * If priority saturation occured or the old priority was still in
475 * the real-time range, don't do anything.
477 if (!(Thread
->Saturation
) ||
478 (OldPriority
>= LOW_REALTIME_PRIORITY
))
480 /* Check if we had priority saturation */
481 if (Thread
->Saturation
> 0)
483 /* Boost priority to maximum */
484 NewPriority
= LOW_REALTIME_PRIORITY
- 1;
486 else if (Thread
->Saturation
< 0)
488 /* If we had negative saturation, set minimum priority */
492 /* Update priority and quantum */
493 Thread
->BasePriority
= (SCHAR
)NewPriority
;
494 Thread
->Quantum
= Thread
->QuantumReset
;
496 /* Disable decrements and update priority */
497 Thread
->PriorityDecrement
= 0;
498 KiSetPriorityThread(Thread
, NewPriority
);
501 /* Release the thread lock */
502 KiReleaseThreadLock(Thread
);
504 /* Go to the next thread */
505 NextEntry
= NextEntry
->Flink
;
509 /* Release Dispatcher Database */
510 KiReleaseDispatcherLockFromDpcLevel();
512 /* Release the process lock */
513 KiReleaseProcessLockFromDpcLevel(&ProcessLock
);
514 KiExitDispatcher(ProcessLock
.OldIrql
);
516 /* Return previous priority */
520 /* PUBLIC FUNCTIONS **********************************************************/
527 KeAttachProcess(IN PKPROCESS Process
)
529 KLOCK_QUEUE_HANDLE ApcLock
;
530 PKTHREAD Thread
= KeGetCurrentThread();
531 ASSERT_PROCESS(Process
);
532 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
534 /* Check if we're already in that process */
535 if (Thread
->ApcState
.Process
== Process
) return;
537 /* Check if a DPC is executing or if we're already attached */
538 if ((Thread
->ApcStateIndex
!= OriginalApcEnvironment
) ||
539 (KeIsExecutingDpc()))
541 /* Invalid attempt */
542 KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT
,
544 (ULONG_PTR
)Thread
->ApcState
.Process
,
545 Thread
->ApcStateIndex
,
550 /* Acquire APC Lock */
551 KiAcquireApcLock(Thread
, &ApcLock
);
553 /* Acquire the dispatcher lock */
554 KiAcquireDispatcherLockAtDpcLevel();
556 /* Legit attach attempt: do it! */
557 KiAttachProcess(Thread
, Process
, &ApcLock
, &Thread
->SavedApcState
);
566 KeDetachProcess(VOID
)
568 PKTHREAD Thread
= KeGetCurrentThread();
569 KLOCK_QUEUE_HANDLE ApcLock
;
571 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
573 /* Check if it's attached */
574 if (Thread
->ApcStateIndex
== OriginalApcEnvironment
) return;
576 /* Acquire APC Lock */
577 KiAcquireApcLock(Thread
, &ApcLock
);
579 /* Check for invalid attach attempts */
580 if ((Thread
->ApcState
.KernelApcInProgress
) ||
581 !(IsListEmpty(&Thread
->ApcState
.ApcListHead
[KernelMode
])) ||
582 !(IsListEmpty(&Thread
->ApcState
.ApcListHead
[UserMode
])))
584 /* Crash the system */
585 KeBugCheck(INVALID_PROCESS_DETACH_ATTEMPT
);
588 /* Get the process */
589 Process
= Thread
->ApcState
.Process
;
591 /* Acquire dispatcher lock */
592 KiAcquireDispatcherLockAtDpcLevel();
594 /* Decrease the stack count */
595 ASSERT(Process
->StackCount
!= 0);
596 ASSERT(Process
->State
== ProcessInMemory
);
597 Process
->StackCount
--;
599 /* Check if we can swap the process out */
600 if (!Process
->StackCount
)
602 /* FIXME: Swap the process out */
605 /* Release dispatcher lock */
606 KiReleaseDispatcherLockFromDpcLevel();
608 /* Restore the APC State */
609 KiMoveApcState(&Thread
->SavedApcState
, &Thread
->ApcState
);
610 Thread
->SavedApcState
.Process
= NULL
;
611 Thread
->ApcStatePointer
[OriginalApcEnvironment
] = &Thread
->ApcState
;
612 Thread
->ApcStatePointer
[AttachedApcEnvironment
] = &Thread
->SavedApcState
;
613 Thread
->ApcStateIndex
= OriginalApcEnvironment
;
616 KiReleaseApcLockFromDpcLevel(&ApcLock
);
619 KiSwapProcess(Thread
->ApcState
.Process
, Process
);
621 /* Exit the dispatcher */
622 KiExitDispatcher(ApcLock
.OldIrql
);
624 /* Check if we have pending APCs */
625 if (!(IsListEmpty(&Thread
->ApcState
.ApcListHead
[KernelMode
])))
627 /* What do you know, we do! Request them to be delivered */
628 Thread
->ApcState
.KernelApcPending
= TRUE
;
629 HalRequestSoftwareInterrupt(APC_LEVEL
);
638 KeIsAttachedProcess(VOID
)
640 /* Return the APC State */
641 return KeGetCurrentThread()->ApcStateIndex
;
649 KeStackAttachProcess(IN PKPROCESS Process
,
650 OUT PRKAPC_STATE ApcState
)
652 KLOCK_QUEUE_HANDLE ApcLock
;
653 PKTHREAD Thread
= KeGetCurrentThread();
654 ASSERT_PROCESS(Process
);
655 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
657 /* Crash system if DPC is being executed! */
658 if (KeIsExecutingDpc())
660 /* Executing a DPC, crash! */
661 KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT
,
663 (ULONG_PTR
)Thread
->ApcState
.Process
,
664 Thread
->ApcStateIndex
,
668 /* Check if we are already in the target process */
669 if (Thread
->ApcState
.Process
== Process
)
671 /* Set magic value so we don't crash later when detaching */
672 ApcState
->Process
= (PKPROCESS
)1;
676 /* Acquire APC Lock */
677 KiAcquireApcLock(Thread
, &ApcLock
);
679 /* Acquire dispatcher lock */
680 KiAcquireDispatcherLockAtDpcLevel();
682 /* Check if the Current Thread is already attached */
683 if (Thread
->ApcStateIndex
!= OriginalApcEnvironment
)
685 /* We're already attached, so save the APC State into what we got */
686 KiAttachProcess(Thread
, Process
, &ApcLock
, ApcState
);
690 /* We're not attached, so save the APC State into SavedApcState */
691 KiAttachProcess(Thread
, Process
, &ApcLock
, &Thread
->SavedApcState
);
692 ApcState
->Process
= NULL
;
701 KeUnstackDetachProcess(IN PRKAPC_STATE ApcState
)
703 KLOCK_QUEUE_HANDLE ApcLock
;
704 PKTHREAD Thread
= KeGetCurrentThread();
706 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
708 /* Check for magic value meaning we were already in the same process */
709 if (ApcState
->Process
== (PKPROCESS
)1) return;
711 /* Loop to make sure no APCs are pending */
714 /* Acquire APC Lock */
715 KiAcquireApcLock(Thread
, &ApcLock
);
717 /* Check if a kernel APC is pending */
718 if (Thread
->ApcState
.KernelApcPending
)
720 /* Check if kernel APC should be delivered */
721 if (!(Thread
->KernelApcDisable
) && (ApcLock
.OldIrql
<= APC_LEVEL
))
723 /* Release the APC lock so that the APC can be delivered */
724 KiReleaseApcLock(&ApcLock
);
729 /* Otherwise, break out */
734 * Check if the process isn't attacked, or has a Kernel APC in progress
735 * or has pending APC of any kind.
737 if ((Thread
->ApcStateIndex
== OriginalApcEnvironment
) ||
738 (Thread
->ApcState
.KernelApcInProgress
) ||
739 (!IsListEmpty(&Thread
->ApcState
.ApcListHead
[KernelMode
])) ||
740 (!IsListEmpty(&Thread
->ApcState
.ApcListHead
[UserMode
])))
742 /* Bugcheck the system */
743 KeBugCheck(INVALID_PROCESS_DETACH_ATTEMPT
);
746 /* Get the process */
747 Process
= Thread
->ApcState
.Process
;
749 /* Acquire dispatcher lock */
750 KiAcquireDispatcherLockAtDpcLevel();
752 /* Decrease the stack count */
753 ASSERT(Process
->StackCount
!= 0);
754 ASSERT(Process
->State
== ProcessInMemory
);
755 Process
->StackCount
--;
757 /* Check if we can swap the process out */
758 if (!Process
->StackCount
)
760 /* FIXME: Swap the process out */
763 /* Release dispatcher lock */
764 KiReleaseDispatcherLockFromDpcLevel();
766 /* Check if there's an APC state to restore */
767 if (ApcState
->Process
)
769 /* Restore the APC State */
770 KiMoveApcState(ApcState
, &Thread
->ApcState
);
774 /* The ApcState parameter is useless, so use the saved data and reset it */
775 KiMoveApcState(&Thread
->SavedApcState
, &Thread
->ApcState
);
776 Thread
->SavedApcState
.Process
= NULL
;
777 Thread
->ApcStateIndex
= OriginalApcEnvironment
;
778 Thread
->ApcStatePointer
[OriginalApcEnvironment
] = &Thread
->ApcState
;
779 Thread
->ApcStatePointer
[AttachedApcEnvironment
] = &Thread
->SavedApcState
;
783 KiReleaseApcLockFromDpcLevel(&ApcLock
);
786 KiSwapProcess(Thread
->ApcState
.Process
, Process
);
788 /* Exit the dispatcher */
789 KiExitDispatcher(ApcLock
.OldIrql
);
791 /* Check if we have pending APCs */
792 if (!(IsListEmpty(&Thread
->ApcState
.ApcListHead
[KernelMode
])))
794 /* What do you know, we do! Request them to be delivered */
795 Thread
->ApcState
.KernelApcPending
= TRUE
;
796 HalRequestSoftwareInterrupt(APC_LEVEL
);
805 KeQueryRuntimeProcess(IN PKPROCESS Process
,
808 ULONG TotalUser
, TotalKernel
;
809 KLOCK_QUEUE_HANDLE ProcessLock
;
810 PLIST_ENTRY NextEntry
, ListHead
;
813 ASSERT_PROCESS(Process
);
815 /* Initialize user and kernel times */
816 TotalUser
= Process
->UserTime
;
817 TotalKernel
= Process
->KernelTime
;
819 /* Lock the process */
820 KiAcquireProcessLock(Process
, &ProcessLock
);
822 /* Loop all child threads and sum up their times */
823 ListHead
= &Process
->ThreadListHead
;
824 NextEntry
= ListHead
->Flink
;
825 while (ListHead
!= NextEntry
)
828 Thread
= CONTAINING_RECORD(NextEntry
, KTHREAD
, ThreadListEntry
);
831 TotalKernel
+= Thread
->KernelTime
;
832 TotalUser
+= Thread
->UserTime
;
834 /* Go to the next one */
835 NextEntry
= NextEntry
->Flink
;
839 KiReleaseProcessLock(&ProcessLock
);
841 /* Return the user time */
842 *UserTime
= TotalUser
;
844 /* Return the kernel time */
853 KeAddSystemServiceTable(IN PULONG_PTR Base
,
854 IN PULONG Count OPTIONAL
,
861 /* Check if descriptor table entry is free */
862 if ((Index
> SSDT_MAX_ENTRIES
- 1) ||
863 (KeServiceDescriptorTable
[Index
].Base
) ||
864 (KeServiceDescriptorTableShadow
[Index
].Base
))
870 /* Initialize the shadow service descriptor table */
871 KeServiceDescriptorTableShadow
[Index
].Base
= Base
;
872 KeServiceDescriptorTableShadow
[Index
].Limit
= Limit
;
873 KeServiceDescriptorTableShadow
[Index
].Number
= Number
;
874 KeServiceDescriptorTableShadow
[Index
].Count
= Count
;
883 KeRemoveSystemServiceTable(IN ULONG Index
)
887 /* Make sure the Index is valid */
888 if (Index
> (SSDT_MAX_ENTRIES
- 1)) return FALSE
;
890 /* Is there a Normal Descriptor Table? */
891 if (!KeServiceDescriptorTable
[Index
].Base
)
893 /* Not with the index, is there a shadow at least? */
894 if (!KeServiceDescriptorTableShadow
[Index
].Base
) return FALSE
;
897 /* Now clear from the Shadow Table. */
898 KeServiceDescriptorTableShadow
[Index
].Base
= NULL
;
899 KeServiceDescriptorTableShadow
[Index
].Number
= NULL
;
900 KeServiceDescriptorTableShadow
[Index
].Limit
= 0;
901 KeServiceDescriptorTableShadow
[Index
].Count
= NULL
;
903 /* Check if we should clean from the Master one too */
906 KeServiceDescriptorTable
[Index
].Base
= NULL
;
907 KeServiceDescriptorTable
[Index
].Number
= NULL
;
908 KeServiceDescriptorTable
[Index
].Limit
= 0;
909 KeServiceDescriptorTable
[Index
].Count
= NULL
;