makecontext(3)

NUME
makecontext, swapcontext - manipulează contextul utilizatorului

BIBLIOTECA
Biblioteca C standard (libc, -lc)

SINOPSIS
#include <ucontext.h>

void makecontext(ucontext_t *ucp, typeof(void (int arg0, ...)) *func,
                 int argc, ...);
int swapcontext(ucontext_t *restrict oucp,
                 const ucontext_t *restrict ucp);

DESCRIERE
Într-un mediu de tip System V, există tipul ucontext_t (definit în <ucontext.h> și descris în getcontext(3)) și cele patru funcții getcontext(3), setcontext(3), makecontext() și swapcontext() care permit comutarea contextului la nivel de utilizator între mai multe fire de control în cadrul unui proces.

Funcția makecontext() modifică contextul indicat de ucp (care a fost obținut în urma unui apel la getcontext(3)). Înainte de a invoca makecontext(), apelantul trebuie să aloce o nouă stivă pentru acest context și să îi atribuie adresa lui ucp->uc_stack, precum și să definească un context succesor și să îi atribuie adresa lui ucp->uc_link.

Atunci când acest context este activat ulterior (utilizând setcontext(3) sau swapcontext()), funcția func este apelată și i se transmite seria de argumente întregi (int) care urmează după argc; apelantul trebuie să specifice numărul acestor argumente în argc. Atunci când această funcție returnează, contextul succesor este activat. Dacă indicatorul contextului succesor este NULL, firul de execuție iese.

Funcția swapcontext() salvează contextul curent în structura indicată de oucp, iar apoi activează contextul indicat de ucp.

VALOAREA RETURNATĂ
Atunci când reușește, swapcontext() nu returnează. (Dar am putea reveni mai târziu, în cazul în care oucp este activat, caz în care se pare că swapcontext() returnează 0.) În caz de eroare, swapcontext() returnează -1 și configurează errno pentru a indica eroarea.

ERORI-IEȘIRE

ENOMEM
    Spațiu rămas în stivă insuficient.

ATRIBUTE
Pentru o explicație a termenilor folosiți în această secțiune, a se vedea attributes(7).
Interfață | Atribut | Valoare
makecontext() | Siguranța firelor | MT-Safe race:ucp
swapcontext() | Siguranța firelor | MT-Safe race:oucp race:ucp

STANDARDE
Niciunul.

ISTORIC
glibc 2.1. SUSv2, POSIX.1-2001. Eliminată în POSIX.1-2008, citând probleme de portabilitate și recomandând ca aplicațiile să fie rescrise pentru a utiliza în schimb fire POSIX.

NOTE
Interpretarea ucp->uc_stack este la fel ca în sigaltstack(2), și anume, această structură conține începutul și lungimea unei zone de memorie care urmează să fie utilizată ca stivă, indiferent de direcția de creștere a stivei. Astfel, nu este necesar ca programul utilizatorului să se preocupe de această direcție.

Pe arhitecturile în care tipurile int și indicatorul sunt de aceeași dimensiune (de exemplu, x86-32, unde ambele tipuri sunt de 32 de biți), este posibil să puteți scăpa pasând indicatorii ca argumente la makecontext() după argc. Cu toate acestea, acest lucru nu este garantat a fi portabil, nu este definit în conformitate cu standardele și nu va funcționa pe arhitecturile în care indicatorii sunt mai mari decât int-urile. Cu toate acestea, începând cu glibc 2.8, glibc face unele modificări la makecontext(), pentru a permite acest lucru pe unele arhitecturi pe 64 de biți (de exemplu, x86-64).

EXEMPLE
Programul de exemplu de mai jos demonstrează utilizarea getcontext(3), makecontext() și swapcontext(). Rularea programului produce următoarea ieșire:

    $ ./a.out
    main: swapcontext(&uctx_main, &uctx_func2)
    func2: inițiată
    func2: swapcontext(&uctx_func2, &uctx_func1)
    func1: inițiată
    func1: swapcontext(&uctx_func1, &uctx_func2)
    func2: returnând
    func1: returnând
    main: se iese

  Sursa programului
    #include <err.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <ucontext.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("%s: inițiată\n", __func__);
        printf("%s: swapcontext(&uctx_func1, &uctx_func2)\n", __func__);
        if (swapcontext(&uctx_func1, &uctx_func2) == -1)
            err(EXIT_FAILURE, "swapcontext");
        printf("%s: returnând\n", __func__);
    }

    static void
    func2(void)
    {
        printf("%s: inițiată\n", __func__);
        printf("%s: swapcontext(&uctx_func2, &uctx_func1)\n", __func__);
        if (swapcontext(&uctx_func2, &uctx_func1) == -1)
            err(EXIT_FAILURE, "swapcontext");
        printf("%s: returnând\n", __func__);
    }

    int
    main(int argc, char *argv[])
    {
        char func1_stack[16384];
        char func2_stack[16384];

        if (getcontext(&uctx_func1) == -1)
            err(EXIT_FAILURE, "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)
            err(EXIT_FAILURE, "getcontext");
        uctx_func2.uc_stack.ss_sp = func2_stack;
        uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
        /* Contextul succesor este f1(), cu excepția cazului în care argc > 1 */
        uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1;
        makecontext(&uctx_func2, func2, 0);

        printf("%s: swapcontext(&uctx_main, &uctx_func2)\n", __func__);
        if (swapcontext(&uctx_main, &uctx_func2) == -1)
            err(EXIT_FAILURE, "swapcontext");

        printf("%s: se iese\n", __func__);
        exit(EXIT_SUCCESS);
    }

CONSULTAȚI ȘI
sigaction(2), sigaltstack(2), sigprocmask(2), getcontext(3), sigsetjmp(3)

TRADUCERE
Traducerea în limba română a acestui manual a fost făcută de Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>

Această traducere este documentație gratuită; citiți Licența publică generală GNU Versiunea 3 (https://www.gnu.org/licenses/gpl-3.0.html) sau o versiune ulterioară cu privire la condiții privind drepturile de autor. NU se asumă NICIO RESPONSABILITATE.

Dacă găsiți erori în traducerea acestui manual, vă rugăm să trimiteți un e-mail la translation-team-ro@lists.sourceforge.net.