我正在尝试实现用户级线程库,需要以循环方式调度线程。我目前正在尝试使用makecontext,getcontext和swapcontext为我创建的2个线程进行切换工作。使用带有ITIMER_PROF值的setitimer,并为sigaction分配一个处理程序,以便在生成SIGPROF信号时调度新线程。 但是,不调用信号处理程序,因此线程永远不会被调度。可能是什么原因?以下是代码的一些片段:
void userthread_init(long period){
/*long time_period = period;
//Includes all the code like initializing the timer and attaching the signal
// handler function "schedule()" to the signal SIGPROF.
// create a linked list of threads - each thread's context gets added to the list/updated in the list
// in userthread_create*/
struct itimerval it;
struct sigaction act;
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = &schedule;
sigemptyset(&act.sa_mask);
sigaction(SIGPROF,&act,NULL);
time_period = period;
it.it_interval.tv_sec = 4;
it.it_interval.tv_usec = period;
it.it_value.tv_sec = 1;
it.it_value.tv_usec = 100000;
setitimer(ITIMER_PROF, &it,NULL);
//for(;;);
}
上面的代码是初始化一个计时器并将处理程序计划附加到信号处理程序。我假设信号SIGPROF将被赋予上述函数,该函数将调用scheduler()函数。调度程序功能如下:
void schedule(int sig, siginfo_t *siginf, ucontext_t* context1){
printf("\nIn schedule");
ucontext_t *ucp = NULL;
ucp = malloc(sizeof(ucontext_t));
getcontext(ucp);
//ucp = &sched->context;
sched->context = *context1;
if(sched->next != NULL){
sched = sched->next;
}
else{
sched = first;
}
setcontext(&sched->context);
}
我有一个准备好的线程队列,其中存储了各自的上下文。每当执行setcontext指令时,每个线程都应该被调度。但是,不调用scheduler()!任何人都可以指出我的错误?
答案 0 :(得分:2)
查看代码后完全修改此答案。有几个问题:
当我添加while(1)循环时,我确实看到schedule()被调用并从线程2输出,但是线程1消失为胖空气(可能是因为未初始化的线程ID)。我认为你需要进行大量的代码清理。
以下是我的建议:
printf("\nMessage");
来电更改为printf("Message\n");
./test1
而不是运行valgrind ./test1
,它将突出显示内存损坏,内存泄漏,未初始化的读取等。我不能强调这一点; Valgrind很棒。你几乎那里,所以坚持下去 - 但请记住这三个简单的规则:
旧答案:
您应该检查任何系统调用的返回值。无论它是否有助于您找到答案,无论如何都应该这样做:)
检查sigaction()的返回值,如果为-1,则检查errno。 sigaction()可能由于某些原因而失败。如果您的信号处理程序没有被触发,则可能尚未设置它。
编辑:并确保检查setitimer()的返回值!
编辑2:只是想一想,你能尝试摆脱malloc()吗? malloc不是信号安全的。例如:像这样:
void schedule(int sig, siginfo_t *siginf, ucontext_t* context1){
printf("In schedule\n");
getcontext(&sched->context);
if(sched->next != NULL){
sched = sched->next;
}
else{
sched = first;
}
setcontext(&sched->context);
}
编辑3:根据this discussion,您不能在信号处理程序中使用printf()。您可以尝试使用write()调用替换它, async-signal safe:
// printf("In schedule\n");
const char message[] = "In schedule\n";
write( 1, message, sizeof( message ) );