Как мне узнать, какой контекст активен? - PullRequest
0 голосов
/ 06 мая 2019

Есть 2 вопроса. 1. Могу ли я узнать, какой контекст в настоящее время активен?
2. Могу ли я как-то передать ucontext из одной функции в другую в качестве аргумента. Я хочу сделать что-то вроде этого.

    //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);
        }

В общем, вам нужно сделать менеджера, в котором будет очередь, вам нужно выяснить, какой контекст активен и поместить его в конец очереди, и передать управление в другой контекст

Ответы [ 2 ]

0 голосов
/ 08 мая 2019

Можно ли это сделать кому-то через очередь?То есть контекст, из которого был получен элемент управления, был помещен в конец, а элемент управления был передан другому, что будет в начале.

На самом деле, Manager не обязательно должен быть контекст , это может быть простая функция.И поскольку очередь все равно должна быть глобальной (чтобы main() могла ставить в очередь контексты выполнения), Manager не нуждается в передаваемых аргументах.Таким образом, Manager и исполнительные функции могут выглядеть следующим образом:

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();
    }
}

Решение о том, чтобы вернуться к контексту Main , удалено из функций - вместо этогоэто должно быть выполнено в main() путем установки N1.uc_link = &Main;, и выполнение начинается с:

    q.push(&N1);
    q.push(&N2);
    swapcontext(&Main, q.front());  // switch to first context
0 голосов
/ 07 мая 2019
  1. Могу ли я узнать, какой контекст в настоящее время активен?

Это будет тривиально с getcontext(), но на самом деле вы хотите выяснить, какойконтекст был активен до того, как активировал Manager .И вы не можете сделать это (если старый контекст не будет хранить информацию в глобальной переменной).

Могу ли я как-то передать ucontext из одной функции в другую в качестве аргумента.

Поскольку аргументы функции могут быть переданы только при входе функции в Manager и Manager не вводится повторно с самого начала, а скорее возвращается с swapcontext(), вы не можете этого сделать.

Что вы можете сделать, чтобы добиться прохожденияУправление с помощью Manager позволяет ему определить, какой контекст активировать, например,

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

. Это можно легко расширить для более чем двух контекстов, используя вместо этого массив ucontext_t.N1, N2.

...