2017-09-14 3 views
-1

Ceci est en quelque sorte lié à un former question sur le fonctionnement de SleepEx. The docs indique que le thread exécutant SleepEx est repris à chaque fois qu'APC est mis en file d'attente et APC peut continuer à être mis en file d'attente alors que le thread exécute déjà APC.Combien d'APC sont traités pendant SleepEx?

Combien de temps le thread continue-t-il d'exécuter les APC? Est-ce que jusqu'à ce que la file d'attente soit vide à chaque fois qu'elle est vérifiée et à ce moment SleepEx renvoie le contrôle à l'appelant? Ou est seulement exactement un APC exécuté par ce thread, alors SleepEx retourne et une autre exécution de APC aurait besoin de SleepEx pour être appelé une fois de plus? J'ai l'impression que les APC sont exécutées jusqu'à ce que la file d'attente soit vide pour la première fois. Merci!

+1

Il est inconnaissable. Le thread qui appelle QueueUserApc() n'a aucune idée si le thread alertable a repris. Que le fil d'alerte fonctionne ou non dans la file d'attente avant de reprendre n'a plus d'importance. –

+0

@HansPassant Ma question n'est pas du point de vue de QueueUserApc, mais comment fonctionne SleepEx. –

+0

@HansPassant - vous vous trompez. ceci est probablement non documenté, mais on sait exactement - quand le retour de thread de * APC * - vérification du système est APC supplémentaire inséré dans le fil. et si oui, exécutez-le. donc ce sera en boucle, jusqu'à ce que plus aucun APC dans le fil – RbMm

Répondre

2

Les APC sont exécutées jusqu'à ce que la file d'attente soit vide. lorsque votre code renvoyé par APC - vérification du système sont un autre APC inséré - si oui - suivant APC est exécuté, jusqu'à ce que plus aucun APC inséré dans le fil. après cette SleepEx (ou tout autre api alertable d'attente) commande de retour pour vous


l'APC exécuté de manière suivante - lorsque vous appelez certains api (SleepEx, MsgWaitForMultipleObjectsEx, WaitForSingleObjectEx, WaitForMultipleObjectsEx .. avec jeu de paramètres bAlertable de la fonction TRUE) vérification du noyau sont APC inséré dans l'objet thread. si oui - le noyau copie le contexte du thread en mode utilisateur dans la pile, remplace le contexte du thread (l'adresse de retour du mode utilisateur est définie sur ntdll.KiUserApcDispatcher) et renvoie. comme le code de retour ne retourne pas d'où il est entré au noyau (dans le cas SleepEx c'est ZwDelayExecution qui appelle en interne) mais au KiUserApcDispatcher. cette API exécute APC puis appelle le ZwContinue. ce api déclaré:

NTSYSAPI NTSTATUS NTAPI ZwContinue(PCONTEXT Context, BOOLEAN TestAlert); 

en place Contexte utilisé enregistré dans la pile contexte de fil, pour le retour au point, à partir de laquelle api alertable a été appelé, et TestAlert indique si doit vérifier apc supplémentaire inséré. si appeler ZwContinue avec TestAlert == FALSE système ne sera plus vérifier pour APC dans la file d'attente de threads jusqu'à ce que vous n'appelez pas vous-même SleepEx ou autre api - sera exactement 1 APC exécuté. mais dans KiUserApcDispatcherTestAlert à hardcoded TRUE - vous pouvez facilement regarder vous-même, si comprendre le code de montage (le KiUserApcDispatcher est minuscule)

+0

Ceci est tout à fait correct, mais je pense que Hans a raison aussi: si votre code * dépend * de ce comportement, vous faites très probablement quelque chose de mal. (Il peut y avoir des cas marginaux.) –

+0

@HarryJohnston - oui, d'accord. mais je réponds simplement à la question telle quelle. expliquer comment fonctionne apc – RbMm