"C-coprocessor" ucontext into solution

Source: Internet
Author: User
Tags signal handler

In a System v-like environment, one has the type ucontext_t defined in <ucontext.h> and the four functions Text (2), SetContext (2), Makecontext () and Swapcontext (), allow user-level context switching between multi-ple Control within a process.

In the System V environment, we can switch the user state context in a single process through the Getcontext,setcontext,makecontext,swapcontext function family.


I. Understanding of Ucontext

First of all, we have to understand the structure of the key variables, the structure is as follows, you need to pay attention to the Uc_stack, and Uc_link,uc_stack point to the context switch needs to save the stack space, users need to allocate. Uc_link points to the context in which the context execution function was successfully exited, specifying the activation contexts, and exiting directly if Uc_link is null.

typedef struct UCONTEXT
{
    unsigned long int uc_flags;
    struct Ucontext *uc_link;
    stack_t Uc_stack;
    mcontext_t Uc_mcontext;
    __sigset_t Uc_sigmask;
    struct _fpstate __fpregs_mem;
} ucontext_t;


Second, the cognitive function family

int GetContext (ucontext_t *UCP);
GetContext (2) Gets the current context of the calling process, storing it in the ucontext struct pointed to by UCP.

GetContext to save the current context in UCP


int SetContext (const ucontext_t *UCP);
SetContext (2) Sets the context of the calling process to the "stored in" ucontext struct to by pointed. The struct must either have been created by GetContext (2) or have been passed as the third parameter of the Sigaction (2) Signal handler.

SetContext restores the current process to the context to which the UCP pointer points, UCP must be created by GetContext


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

the  makecontext ()   function  modifies  the  context pointed to by UCP (which is obtained fro M-A call to Getcon-text (2)) .  before invoking Makecontext (), the caller must-a new stack for this allocate Sp and  assign  their address to ucp->uc_stack, and define a successor the context and assign their address to Ucp->u C_link.

when  this  context  is  later  activated (using SetContext (2) or Swapcontext ()) The fun ction Func is called, and passed the series of an integer (int) arguments that follow argc; The caller must specify the number of these  argu-ments in argc.  When this function returns, the successor Cont The ext is activated.  If The successor context pointer is NULL, the thread exits.

Makecontext modifies the context that the UCP pointer points to, the UCP object must be assigned a new stack and assigned to Ucp->uc_stack before the Makecontext is invoked, while defining a restored context after a successful return and assigning the address to the UCP->UC_ Link When UCP is activated (via SetContext or Swapcontext), the Func function is invoked and a system parameter is passed to the Func function. When the Func function returns to the original, Uc_link is activated and the thread exits when Uc_link is null.


int Swapcontext (ucontext_t *oucp, ucontext_t *UCP);
The Swapcontext () function saves the "current" in "structure pointed to by OUCP, and then activates the context pointed to by UCP.

Swapcontext saves the current context in OUCP and activates the UCP.


third, the example

3.1 Man Manual example

#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) {print
    F ("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 (&AMP;UCTX_FUNC2, &uctx_func1) \ n");
    if (Swapcontext (&AMP;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_func2;
    Uctx_func1.uc_link = &uctx_main;

    Makecontext (&uctx_func1, func1, 0);
    if (GetContext (&AMP;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 (&AMP;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); }
Output is as follows :

func2:started
Func2:swapcontext (&UCTX_FUNC2, &uctx_func1)
func1:started
Func1:swapcontext ( &UCTX_FUNC1, &UCTX_FUNC2)
func2:returning
func1:returning
main:exiting


3.2 Producer Consumers

#include <ucontext.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> static
ucontext_t Uc_loop, Uc_main, Uc_consume, uc_produce;

static int ci, pi, loop;
    static void Cb_consume () {printf ("Consume%d\n", CI);
    ci++;
Sleep (1);
    static void Cb_produce () {printf ("Produce%d\n", pi);
pi++;

    int main (void) {char consume_stack[1024], produce_stack[1024];

    GetContext (&uc_loop);
    GetContext (&uc_produce);
    UC_PRODUCE.UC_STACK.SS_SP = Produce_stack;
    uc_produce.uc_stack.ss_size = sizeof (Produce_stack);
    Uc_produce.uc_link = &uc_consume;
    Makecontext (&uc_produce, cb_produce, 0);

    printf ("Finish make produce\n");
    GetContext (&uc_consume);
    UC_CONSUME.UC_STACK.SS_SP = Consume_stack;
    uc_consume.uc_stack.ss_size = sizeof (Consume_stack);
    Uc_consume.uc_link = &uc_main;
    Makecontext (&uc_consume, Cb_consume, 0);

    printf ("Finish make consume\n"); printf ("Swap MaiN to produce\n ");
    Swapcontext (&uc_main, &uc_produce);

    printf ("Swap back to main\n");
    Sleep (1);
    loop++;

    if (Loop < 2) SetContext (&uc_loop);
return 0; }

The output is as follows:

Finish make produce
finish make consume
swap main to produce
produce 0
consume 0
swap back to main
  
   finish make produce
finish make consume
swap main to produce
produce 1
consume 1
swap back to main
  



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.