proc.c struct cpu* mycpu(void)
トップページ
jupiteroak.hatenablog.com
proc.c
https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L37
struct cpu* mycpu(void) { int apicid, i; if(readeflags()&FL_IF) panic("mycpu called with interrupts enabled\n"); apicid = lapicid(); // APIC IDs are not guaranteed to be contiguous. Maybe we should have // a reverse map, or reserve a register to store &cpus[i]. for (i = 0; i < ncpu; ++i) { if (cpus[i].apicid == apicid) return &cpus[i]; } panic("unknown apicid\n"); }
mycpu関数は、この関数を現在実行しているプロセッサに対応したcpu構造体を取得します。
戻り値 struct cpu* &cpus[i]
この関数を現在実行しているプロセッサに対応したcpu構造体のアドレスです。
cpu構造体について
cpu構造体は、そのcpu構造体に対応しているプロセッサについての情報を記録したデータ構造です。
1つのプロセッサにつき1つのcpu構造体が用意されています。
proc.h
// Per-CPU state struct cpu { uchar apicid; // Local APIC ID struct context *scheduler; // swtch() here to enter scheduler struct taskstate ts; // Used by x86 to find stack for interrupt struct segdesc gdt[NSEGS]; // x86 global descriptor table volatile uint started; // Has the CPU started? int ncli; // Depth of pushcli nesting. int intena; // Were interrupts enabled before pushcli? struct proc *proc; // The process running on this cpu or null };
処理の内容
- ハードウェア割り込みが無効化されていることを確認する
- この関数を実行しているプロセッサが持つLocal APIC IDを取得する
- 配列cpusを走査してプロセッサに対応したcpu構造体を取得する
- cpu構造体が見つからなかった場合はメッセージを出力する
ハードウェア割り込みが無効化されていることを確認する
if(readeflags()&FL_IF) panic("mycpu called with interrupts enabled\n");
readeflags関数を呼び出して取得したEFLFGSレジスタの値をFL_IF(#define FL_IF 0x0000 0200)を使ってマスク処理することにより、EFLFGSレジスタのIF(bit9 インターラプトエネーブルフラグ)の値を取り出しています。
readeflags()&FL_IFが真の場合→IFの値が1の場合→ハードウェア割り込みを有効化している場合は、panic関数を呼び出してメッセージを出力します。
readeflags()&FL_IFが偽の場合→IFの値が0の場合→ハードウェア割り込みを無効化している場合は、次の処理へ進みます。
この関数を実行しているプロセッサが持つLocal APIC IDを取得する
apicid = lapicid();
lapicid関数を呼び出して、この関数を実行しているプロセッサが持つLocal APIC IDレジスタからLocalAPIC IDを取得します。
このLocal APIC IDを用いてプロセッサの識別を行います。
配列cpusを走査してプロセッサに対応したcpu構造体を取得する
for (i = 0; i < ncpu; ++i) { if (cpus[i].apicid == apicid) return &cpus[i]; }
cpu構造体の配列cpusの中から、lapicid関数で取得したLocal APIC IDの値を持つcpu構造体を探し、そのcpu構造体のアドレスを戻り値として返します。
// Per-CPU state struct cpu { uchar apicid; // Local APIC ID struct context *scheduler; // swtch() here to enter scheduler struct taskstate ts; // Used by x86 to find stack for interrupt struct segdesc gdt[NSEGS]; // x86 global descriptor table volatile uint started; // Has the CPU started? int ncli; // Depth of pushcli nesting. int intena; // Were interrupts enabled before pushcli? struct proc *proc; // The process running on this cpu or null };
#define NCPU 8
struct cpu cpus[NCPU]
extern struct cpu cpus[NCPU];
cpu構造体が見つからなかった場合はメッセージを出力する
panic("unknown apicid\n");
lapicid関数で取得したLocal APIC IDの値を持つcpu構造体が見つからなかった場合は、panic関数を呼び出してメッセージを出力します。