のマニュアルページの文言に混乱していますarch_prctl(2)
。具体的には、次のように述べています。
64 ビット セグメント ベースのコンテキスト スイッチはかなり高価です。 カーネル 2.5 以降では、modify_ldt(2) で LDT を設定するか、set_thread_area(2) システム コールを使用して、セグメント セレクターを使用して 32 ビット ベースを設定する方が高速な代替手段になる場合があります。arch_prctl() は、4GB を超えるベースを設定する場合にのみ必要です。アドレス空間の最初の 2GB のメモリは、MAP_32BIT フラグを指定して mmap(2) を使用することで割り当てることができます。
これは、このシステム コールを使用するプロセスのコンテキスト スイッチがパフォーマンス ペナルティを受けることを意味するのでしょうか、それとも正確な意味は何ですか?
Linux カーネルのソースを調べたところ、4 GiB 未満のアドレスには LDT が使用され、4 GiB を超えるアドレスにはモデル固有のレジスタが使用されているようです。
case ARCH_SET_FS:
/* handle small bases via the GDT because that's faster to
switch. */
if (addr <= 0xffffffff) {
set_32bit_tls(task, FS_TLS, addr);
if (doit) {
load_TLS(&task->thread, cpu);
loadsegment(fs, FS_TLS_SEL);
}
task->thread.fsindex = FS_TLS_SEL;
task->thread.fs = 0;
} else {
task->thread.fsindex = 0;
task->thread.fs = addr;
if (doit) {
/* set the selector to 0 to not confuse
__switch_to */
loadsegment(fs, 0);
ret = wrmsrl_safe(MSR_FS_BASE, addr);
}
}
put_cpu();
break;
GDT を使用すると、レジスタに書き込むよりも高速になるのはなぜですか? また、FS と GS を更新する費用は、プロセスを切り替えるときにのみ支払われると思います。つまり、実行するプロセスがスケジュールされていないときに、システム コールを介してカーネルに入る追加費用はありませんか?