1. NOM

makecontext, swapcontext - Manipulation du contexte utilisateur

2. SYNOPSIS

#include <ucontext.h>

void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);

int swapcontext(ucontext_t *oucp, ucontext_t *ucp);

3. DESCRIPTION

Dans un environnement de type System V, on dispose du type ucontext_t défini dans <ucontext.h> et des quatre fonctions getcontext(3), 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(3).

La fonction makecontext() modifie le contexte pointé par ucp (qui a été obtenu par un appel à getcontext(3)). 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(3) 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.

4. 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.

5. ERREURS

  • ENOMEM
        Espace de pile disponible insuffisant.

6. VERSIONS

makecontext() et swapcontext() sont fournies par la glibc depuis la version 2.1.

7. 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.

8. 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).

9. EXEMPLE

Le programme d'exemple ci-dessous décrit l'utilisation de getcontext(3), makecontext() et swapcontext(). Ce programme produit la sortie suivante :

 
Sélectionnez
$ ./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

9.1. Source du programme

 
Sélectionnez
#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);
}

10. VOIR AUSSI

11. COLOPHON

Cette page fait partie de la publication 3.52 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/.

12. 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 à <>.

Vous pouvez toujours avoir accès à la version anglaise de ce document en utilisant la commande « LC_ALL=C man <section> <page_de_man> ».