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);
DESCRIPTION¶
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, consultez
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.
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 (par exemple, pour
x86-32, leur taille est de 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 a
effectué quelques changements à
makecontext(), afin de
permettre cela sur certaines architecture 64 bits (par exemple, 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.44 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¶
Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a
<
http://po4a.alioth.debian.org/> par l'équipe de traduction
francophone au sein du projet perkamon
<
http://perkamon.alioth.debian.org/>.
Stéphan Rafin (2002), Alain Portal
<
http://manpagesfr.free.fr/> (2006). Florentin Duneau et
l'équipe francophone de traduction de Debian (2006-2009).
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> ».