我有个问题。我需要实现一个使用计时器和 SIGALRM 切换 ucontext 线程的程序,但是当我使用 evict_thread 函数切换线程时出现分段错误。我相信这是竞争条件的结果,因为它发生在程序执行期间的不同时间。这是我的 evict_thread
void evict_thread(int signal)
{
// Check that there is more than one thread in the queue
if ((int)list_length(runqueue) > 1)
{
// Remove the currently executing thread from the runqueue and store its id
int evict_thread_id = list_shift_int(runqueue);
// Place the thread at the back of the run queue
list_append_int(runqueue, evict_thread_id);
// Get the id of the thread that is now at the head of the run queue
int exec_thread_id = list_item_int(runqueue, 0);
// Set the start time for new thread to the current time
clock_gettime(CLOCK_REALTIME, &thread_table[exec_thread_id]->start);
printf("Switching context from %s to %s\n",
thread_table[evict_thread_id]->thread_name,
thread_table[exec_thread_id]->thread_name);
// Execute the thread at the head of the run queue
if (swapcontext(&thread_table[evict_thread_id]->context, &thread_table[exec_thread_id]->context) == -1)
{
perror("swapcontext failed\n");
printf("errno: %d.\n", errno);
return;
}
}
return;
}
上述函数的调用方式如下
// Set the SIGALRM
if (sigset(SIGALRM, evict_thread) == -1)
{
perror("sigset failed\n");
printf("errno: %d.\n", errno);
return;
}
// Initialize timer
thread_switcher.it_interval.tv_sec = 0;
thread_switcher.it_interval.tv_usec = quantum_size;
thread_switcher.it_value.tv_sec = 0;
thread_switcher.it_value.tv_usec = quantum_size;
setitimer(ITIMER_REAL, &thread_switcher, 0);
运行队列只是一个全局整数列表,它们是指向 ucontext 线程的全局指针表的索引。该列表是使用来自 libslack.org 的 C 通用实用程序库中的列表数据结构实现的
当我禁用计时器并让每个线程在切换上下文之前运行完成时,程序会正常运行,但是当线程在执行期间切换时,大约 80% 的时间会出现分段错误。
此外,当我尝试使用 gdb 回溯分段错误时,它说它发生在系统调用中。