私は問題があります。タイマーと 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 を使用してセグメンテーション違反をバックトレースしようとすると、システムコール内で発生したと表示されます。