Переключение стека вверх / вниз с помощью getcontext/setcontext
Я пытаюсь понять, будет ли getcontext/setcontext работать правильно в конкретном сценарии.
Я вижу, как setcontext() может быть использован для размотки стека обратно в определенное место в истории.
#include <stdio.h>
#include <ucontext.h>
int rollback = 0;
ucontext_t context;
void func(void)
{
setcontext(cp);
}
int main(void)
{
getcontext(&context);
if (rollback == 0)
{
printf("getcontext has been called\n");
rollback++;
func();
}
else
{
printf("setcontext has been called\n");
}
}
Но мне было интересно, если после отдыха вы можете вернуться к месту, которое было в будущем? Я полагаю, это зависит от getcontext()
call захватывает копию стека, и я не могу найти точные детали в документации.
#include <stdio.h>
#include <ucontext.h>
int rollback = 0;
int backToFuture = 0;
ucontext_t context;
ucontext_t futureContext;
void func(void)
{
// Some complex calc
if (some-condition)
{
getcontext(&futureContext); // After returning I want to come back
// here to carry on with my work.
if (backToFuture == 0)
{
setcontext(&context); // rewind to get stuff-done
}
}
// Finishe work
}
int main(void)
{
getcontext(&context);
if (rollback == 0)
{
printf("getcontext has been called\n");
rollback++;
func();
// eventually always return here.
}
else
{
printf("setcontext has been called\n");
// Do specialized work that needed to be done
// May involve function calls.
//
// I worry that anything the adds new stack frames
// will disrupt the saved state of futureContext
//
// But without detailed information I can not be sure
// if this is an allowed senario.
backToFuture = 1;
setcontext(&futureContext);
}
}
1 ответ
getcontext
не копирует стек, он только сбрасывает регистры (включая указатель стека) и небольшие данные контекста, такие как маска сигнала и т. д.
Когда вы спрыгиваете вниз по стеку, это лишает законной силы верхний контекст. Даже если вы не будете выполнять какие-либо вызовы функций, подумайте о обработчике сигналов, который может выполняться там. Если вы хотите прыгать между двумя стеками, вам нужно makecontext
,
Я добавил переменную, которая показывает, что ваш код неверен:
void func(void)
{
// Some complex calc
if (1)
{
volatile int neverChange = 1;
getcontext(&futureContext); // After returning I want to come back
// here to carry on with my work.
printf("neverchange = %d\n", neverChange);
if (backToFuture == 0)
{
setcontext(&context); // rewind to get stuff-done
}
}
// Finishe work
}
На моей машине это приводит к:
getcontext has been called
neverchange = 1
setcontext has been called
neverchange = 32767