2017-02-18 71 views
0

我正在构建一个先发制人的用户空间线程调度器,它使用一个定时器来中断线程并根据优先级在它们之间切换。但是,一旦线程中断,我似乎无法完成;只能再次启动它。我甚至有可能使用swapcontext?这个代码的结果应该允许itake5seconds()完成,只是反复循环“Hello”消息。如何使用swapcontext()恢复执行一个函数(而不是再次启动)?

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <time.h> 
#include <sys/time.h> 
#include <ucontext.h> 

static ucontext_t mainc, newthread; 

void itake5seconds() 
{ 
    puts("Hello. I take 5 seconds to run."); 
    sleep(5); 
    puts("And I'm done! Wasn't that nice?"); 
} 

void timer_handler(int signum) 
{ 
    puts("Doing some scheduler stuff."); 
    swapcontext(&mainc, &newthread); 
} 

int main(int argc, char* argv[]) 
{ 
    struct sigaction sa; 

    memset(&sa, 0, sizeof(sa)); 
    sa.sa_handler = &timer_handler; 
    sigaction(SIGALRM, &sa, NULL); 

    getcontext(&newthread); 
    newthread.uc_stack.ss_sp = malloc(5000); 
    newthread.uc_stack.ss_size = 5000; 
    newthread.uc_link = &mainc; 
    makecontext(&newthread, &itake5seconds, 0); 

    struct itimerval timer; 
    timer.it_value.tv_sec = 0; 
    timer.it_value.tv_usec = 500000; 
    timer.it_interval.tv_sec = 0; 
    timer.it_interval.tv_usec = 500000; 

    setitimer(ITIMER_REAL, &timer, NULL); 

    while(1); 

    return 0; 
} 

回答

0

您的代码正在调用信号处理函数(swapcontext)中的“不安全”函数。因此,你的程序的行为是“未定义的”。

man 7 signal

的信号处理函数必须非常小心,因为在别处处理可以在该程序的执行某任意点被中断。 POSIX具有“安全功能”的概念。如果信号中断不安全函数的执行,并且处理程序调用不安全的函数,那么程序的行为是不确定的。

请参阅Complete Context Control中的“SVID上下文处理示例”一节,了解如何使用信号处理程序进行处理。但基本上你会使用一个volatile int全局变量来标记你的信号处理程序被调用,而不是从正常的代码(即在信号处理的上下文中没有运行的代码)调用swapcontext

0

问题是我没有保存swapcontext()返回到它的第一个参数的当前执行上下文。

+0

你能提供更新后的代码给大家看吗? – Mike

相关问题