uc_linkpointe vers le contexte qui sera repris lorsque le contexte actuel se termine, si ce dernier a été créé avec makecontext(un contexte secondaire). uc_sigmasksert à stocker l'ensemble des signaux bloqués dans le contexte, et uc_stackreprésente la pile utilisée par ce contexte. uc_mcontextstocke l'état d'exécution , y compris tous les registres et indicateurs du processeur , le pointeur d'instruction et le pointeur de pile ; est un type opaque .mcontext_t
Les fonctions sont :
intsetcontext(constucontext_t*ucp)- Cette fonction transfère le contrôle au contexte dans
ucp. L'exécution reprend à partir du point où le contexte a été stocké dansucp.setcontextne retourne pas.
- Cette fonction transfère le contrôle au contexte dans
intgetcontext(ucontext_t*ucp)- Enregistre le contexte actuel
ucp. Cette fonction renvoie `true` dans deux cas : après l’appel initial, ou lorsqu’un thread bascule vers le contexte via `get`ucpousetcontext`return`swapcontext. Lagetcontextfonction ne fournit pas de valeur de retour permettant de distinguer les cas (sa valeur de retour sert uniquement à signaler une erreur), le programmeur doit donc utiliser une variable d’indicateur explicite, qui ne doit pas être un registre et doit être déclarée `volatile` pour éviter la propagation de constantes ou d’autres optimisations du compilateur .
- Enregistre le contexte actuel
voidmakecontext(ucontext_t*ucp,void(*func)(),intargc,...)- Cette
makecontextfonction établit un thread d'exécution alternatif dansucp, préalablement initialisé à l'aide degetcontext. Leucp.uc_stackmembre doit pointer vers une pile de taille appropriée ; la constanteSIGSTKSZest couramment utilisée. Lorsqueucpest sauté à l'aide desetcontextouswapcontext, l'exécution commencera au point d'entrée de la fonction pointée parfunc, avecargcles arguments spécifiés. Lorsquefuncse termine, le contrôle est rendu àucp.uc_link.
- Cette
intswapcontext(ucontext_t*oucp,ucontext_t*ucp)- Transfère le contrôle
ucpet enregistre l'état d'exécution actuel dansoucp.
- Transfère le contrôle
Exemple
L'exemple ci-dessous illustre un itérateur utilisant setcontext.
REMARQUE : cet exemple est incorrect , mais peut fonctionner comme prévu dans certains cas. La fonction makecontextexige que les paramètres supplémentaires soient de type `int` int, or l’exemple utilise des pointeurs. Par conséquent, l’exemple peut échouer sur les machines 64 bits (en particulier les architectures LP64 ). Ce problème peut être contourné en décomposant puis en reconstruisant les valeurs 64 bits, mais cela entraîne une perte de performance.sizeof(void*)>sizeof(int)
Sur les architectures où les types `int` et `pointer` ont la même taille (par exemple, x86-32, où les deux types sont codés sur 32 bits), il est possible de passer des pointeurs comme arguments à `makecontext()` après `argc`. Cependant, cette méthode n'est pas portable, n'est pas conforme aux normes et ne fonctionne pas sur les architectures où les pointeurs sont plus grands que les entiers. Néanmoins, à partir de la version 2.8, glibc apporte des modifications pour
makecontext(3)autoriser cette pratique sur certaines architectures 64 bits (par exemple, x86-64).
Pour obtenir et définir un contexte, un contexte plus petit peut s'avérer utile :
Cela crée une boucle infinie car le contexte contient le compteur de programme.