-2

There are 2 questions. 1. Can I find out which context is currently active ?
2. Can I pass in somehow a ucontext, from one function to another as an argument . I want to do something like this.:

    //Instead of this


      #include <pthread.h>
    #include <iostream>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <ucontext.h>
    #include <queue>

    #define MEM 64000
    #define MEMS 16000
    #define MEL 32000
    using namespace std;
    ucontext_t N1,N2, Main;

    void fn1()
    {
    for(int i=0;i<=3;i++){
    cout<<i<<ndl;
    swapcontext(&N1,&N2);
    }
    }

    void fn2()
    { 
    for(int i=4;i<=7;i++){
    cout<<i<<endl;
    if(i==7)
    swapcontext(&N2,&Main);
    else
    swapcontext(&N2,&N1);
    }
    }
     int main(int argc, char *argv[])
    {
    getcontext(&Main);
    getcontext(&N1);
    getcontext(&N2);
    N1.uc_link=0;
    N1.uc_stack.ss_sp=malloc(MEM);
    N1.uc_stack.ss_size=MEM;
    N2.uc_link=0;
    N2.uc_stack.ss_sp=malloc(MEMS);
    N2.uc_stack.ss_size=MEMS;
    makecontext(&N1, fn1, 0);
    makecontext(&N2, fn2, 0);
    swapcontext(&Main,&N1);
    printf("completed\n");
    exit(0);
    }
        //Do something like this

        void fn1()
        {
        for(int i=0;i<=3;i++){
        cout<<i<<endl;
        swapcontext(&N1,&Man);
        }
        }

        void fn2()
        { 
        for(int i=4;i<=7;i++){
        cout<<i<<endl;
        if(i==7)
        swapcontext(&N2,&Main);
        else
        swapcontext(&N2,&Man);
        }


       void Manager()// void Manager(ucontext_t u)??? and makecontext(&Man,(void(*)())Manager,1,...)
        {
        //which ucontext transferred control ?
         queue <ucontext> q;
        push.active_context;
        ...
        swapcontext(&Man,&another_context);
        }

In General, you need to make a Manager in which there will be a queue, you need to find out which context is active and put it at the end of the queue, and pass the control to another context

AlexChek
  • 13
  • 2
  • 3
    1) define "context" in this, ahem, context. 2) post a [mcve]. Currently it's not clear what you are asking. – Jesper Juhl May 06 '19 at 17:23
  • 1
    Please [format](https://clang.llvm.org/docs/ClangFormat.html) your code nicely. What you have there currently is really unpleasant to read. – Jesper Juhl May 06 '19 at 17:35

2 Answers2

0
  1. Can I find out which context is currently active ?

This would be trivial with getcontext(), but what you actually want to find out is which context has been active before it activated the Manager. And you can't do that (unless the old context would store the information in a global variable).

  1. Can I pass in somehow a ucontext, from one function to another as an argument .

Since function arguments can be passed only on function entry to the Manager, and the Manager isn't re-entered at its start, but rather returns from swapcontext(), you can't do that.

What you could do to achieve the passing of control via the Manager is to let it determine which context to activate, e. g.

void Manager()
{
    ucontext_t *another_context = &N1;  // begin with N1
    for (;; another_context = another_context == &N1 ? &N2 : &N1)   // switch context
        swapcontext(&Man, another_context);
}

This can easily be extended for more than two contexts by using an array of ucontext_t instead of N1, N2.

Armali
  • 18,255
  • 14
  • 57
  • 171
  • 1
    Thank you very much, I will try to implement something similar. Is it possible to do it to someone through the queue? That is, the context from which the control was obtained was placed at the end, and the control was transferred to another, which would be at the beginning . PS: How to do something similar with an array? – AlexChek May 07 '19 at 14:04
  • Here's what the task looks like that I can't complete. After the control function is received, the Manager decides which work function to transfer control to; The decision is taken as follows: - the descriptor to the suspended work function is placed at the end of the descriptor queue; - the descriptor of the work function is retrieved from the beginning of the descriptor queue; - this function is transferred control. – AlexChek May 07 '19 at 19:39
  • @AlexChek - I wrote another answer which uses a queue of any number of contexts. To do something similar with an array would simply mean to place the contexts into an array instead and shift the elements or maintain head and tail indices - equivalent, just less elegant. – Armali May 08 '19 at 09:12
0

Is it possible to do it to someone through the queue? That is, the context from which the control was obtained was placed at the end, and the control was transferred to another, which would be at the beginning .

Actually, the Manager doesn't have to be a context, it can be a plain function. And since the queue has to be global anyway (so that main() can enqueue the execution contexts), Manager doesn't need any arguments passed. So the Manager and the execution functions can look like e. g.:

queue <ucontext *> q;
void Manager()
{
    ucontext_t *active_context = q.front(); // active context is at queue front
    q.pop();                                // remove active context from front
    q.push(active_context);                 // insert active context at the end
    swapcontext(active_context, q.front()); // switch to the new active context
}

void fn1()
{
    for (int i=0; i<=3; i++)
    {
        cout<<i<<endl;
        Manager();
    }
}

void fn2()
{ 
    for (int i=4; i<=7; i++)
    {
        cout<<i<<endl;
        Manager();
    }
}

The decision when to switch back to the Main context is removed from the functions - instead this is to be accomplished in main() by setting N1.uc_link = &Main; and the execution is started by:

    q.push(&N1);
    q.push(&N2);
    swapcontext(&Main, q.front());  // switch to first context
Armali
  • 18,255
  • 14
  • 57
  • 171