NOM
makecontext, swapcontext - Manipulation du contexte utilisateur.
SYNOPSIS
#include <ucontext.h>
void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);
int swapcontext(ucontext_t *oucp, ucontext_t *ucp);
Dans un environnement de type System V, on dispose du type ucontext_t
défini dans <ucontext.h> et des quatre fonctions getcontext(2),
setcontext(2), makecontext() et swapcontext() qui permettent, au niveau
utilisateur, des permutations de contextes entre plusieurs threads de
contrôle au sein d’un processus.
Pour le type et les deux premières fonctions, voir getcontext(2).
La fonction makecontext() modifie le contexte pointé par ucp (qui a été
obtenu par un appel à getcontext(2)). Avant d’appeler makecontext(),
l’appelant doit allouer une nouvelle pile pour ce contexte et
l’affecter à ucp->uc_stack et définir un contexte successeur et
l’affecter à ucp->uc_link.
Lorsque ce contexte est activé par la suite (avec setcontext(2) ou
swapcontext()), alors la fonction func() est tout d’abord appelée avec
la série d’arguments de type int spécifiés à la suite de argc ;
l’appelant doit préciser le nombre de ces arguments dans argc. Lorsque
cette fonction s’achève, le contexte successeur est activé. Lorsque le
pointeur sur le contexte successeur vaut NULL, le thread se termine.
La fonction swapcontext() sauvegarde le contexte actuel dans la
structure pointée par oucp et active ensuite le contexte pointé par
ucp.
VALEUR RENVOYÉE
En cas de succès, swapcontext() ne rend pas la main à l’appelant (on
peut toutefois revenir à l’appelant en cas d’activation de oucp ; dans
un tel cas, swapcontext se comporte comme si elle renvoyait 0). En cas
d’erreur, swapcontext() renvoie -1 et positionne errno de façon
appropriée.
ERREURS
ENOMEM Espace de pile disponible insuffisant.
VERSIONS
makecontext() et swapcontext() sont fournies par la glibc depuis la
version 2.1.
CONFORMITÉ
SUSv2, POSIX.1-2001. POSIX.1-2008 supprime les spécifications de
makecontext() et swapcontext() à cause de problèmes de portabilité, et
recommande que les applications soient ré-écrites avec des processus
légers POSIX à la place.
NOTES
L’interprétation de ucp->uc_stack est exactement la même que pour
sigaltstack(2), à savoir, cette structure contient l’adresse de départ
et la longueur d’une zone mémoire destinée à être utilisée comme pile,
et ce, sans considération sur le sens d’expansion de la pile. Il n’est
donc pas nécessaire pour le programme utilisateur de se soucier de ce
sens.
Sur les architectures où le type int et les types « pointeur » sont de
même taille (p. ex., pour x86-32, leur taille est 32 bits), vous
pouvez passer outre en passant des pointeurs comme paramètres à
makecontext() suivi de argc. Cependant, sachez que cela n’est pas
forcément portable, et indéfini selon les standards, et ne fonctionnera
pas sur les architectures où la taille des pointeurs est supérieure à
la taille des entiers int. Néanmoins, avec la version 2.8, la glibc
effectue quelques changements à makecontext(), afin de permettre cela
sur certaines architecture 64 bits (p. ex., x86-64).
EXEMPLE
Le programme d’exemple ci-dessous décrit l’utilisation de
getcontext(2), makecontext() et swapcontext(). Ce programme produit la
sortie suivante :
$ ./a.out
main: swapcontext(&uctx_main, &uctx_func2)
func2: started
func2: swapcontext(&uctx_func2, &uctx_func1)
func1: started
func1: swapcontext(&uctx_func1, &uctx_func2)
func2: returning
func1: returning
main: exiting
Source du programme
#include <ucontext.h>
#include <stdio.h>
#include <stdlib.h>
static ucontext_t uctx_main, uctx_func1, uctx_func2;
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
static void
func1(void)
{
printf("func1: started\n");
printf("func1: swapcontext(&uctx_func1, &uctx_func2)\n");
if (swapcontext(&uctx_func1, &uctx_func2) == -1)
handle_error("swapcontext");
printf("func1: returning\n");
}
static void
func2(void)
{
printf("func2: started\n");
printf("func2: swapcontext(&uctx_func2, &uctx_func1)\n");
if (swapcontext(&uctx_func2, &uctx_func1) == -1)
handle_error("swapcontext");
printf("func2: returning\n");
}
int
main(int argc, char *argv[])
{
char func1_stack[16384];
char func2_stack[16384];
if (getcontext(&uctx_func1) == -1)
handle_error("getcontext");
uctx_func1.uc_stack.ss_sp = func1_stack;
uctx_func1.uc_stack.ss_size = sizeof(func1_stack);
uctx_func1.uc_link = &uctx_main;
makecontext(&uctx_func1, func1, 0);
if (getcontext(&uctx_func2) == -1)
handle_error("getcontext");
uctx_func2.uc_stack.ss_sp = func2_stack;
uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
/* Successor context is f1(), unless argc > 1 */
uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1;
makecontext(&uctx_func2, func2, 0);
printf("main: swapcontext(&uctx_main, &uctx_func2)\n");
if (swapcontext(&uctx_main, &uctx_func2) == -1)
handle_error("swapcontext");
printf("main: exiting\n");
exit(EXIT_SUCCESS);
}
VOIR AUSSI
getcontext(2), sigaction(2), sigaltstack(2), sigprocmask(2),
sigsetjmp(3)
COLOPHON
Cette page fait partie de la publication 3.23 du projet man-pages
Linux. Une description du projet et des instructions pour signaler des
anomalies peuvent être trouvées à l’adresse
http://www.kernel.org/doc/man-pages/.
TRADUCTION
Cette page de manuel a été traduite par Stéphan Rafin <stephan DOT
rafin AT laposte DOT net> en 2002, puis a été mise à jour par Alain
Portal <aportal AT univ-montp2 DOT fr> jusqu’en 2006, et mise à
disposition sur http://manpagesfr.free.fr/.
Les mises à jour et corrections de la version présente dans Debian sont
directement gérées par Florentin Duneau <fduneau@gmail.com> et l’équipe
francophone de traduction de Debian.
Veuillez signaler toute erreur de traduction en écrivant à
<debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
paquet manpages-fr.
Vous pouvez toujours avoir accès à la version anglaise de ce document
en utilisant la commande « man -L C <section> <page_de_man> ».