2

このカーネルコードでは、割り込みを無効にしてこのロック取得操作をアトミックにしますが、最後のelse条件が表示された場合、つまりロックが使用できない場合、スレッドはスリープ状態になり、スレッドがスリープ状態から戻った後にのみ割り込みが有効になります。私の質問は、このスレッドがスリープ状態から抜け出すまで、OS全体で割り込みが無効になるということです。

void Lock :: Acquisition()
{{
    IntStatus oldLevel = Interrupt-> SetLevel(IntOff); //割り込みを無効にして、次のステートメントをアトミックにします
    if(lockOwnerThread == currentThread)//要求しているスレッドがすでにロックを所有しているかどうかを確認する
    {{
        // printf( "SM:error:%sはすでにロックを所有しています\ n"、currentThread-> getName());
        DEBUG('z'、 "SM:error:%sはすでにロックを所有しています\ n"、currentThread-> getName());
        (void)割り込み-> SetLevel(oldLevel);
        戻る;
    }
    if(lockOwnerThread == NULL)
    {{
       lockOwnerThread = currentThread; //ロック所有者の船が現在のスレッドに与えられます
       DEBUG('z'、 "SM:ロック%sの所有権は%sに与えられます\ n"、name、currentThread-> getName());
    }
    そうしないと
    {{
        DEBUG('z'、 "SM:リクエストキューにスレッド%sを追加し、スリープ状態にします\ n"、currentThread-> getName());
        queueForLock-> Append((void *)currentThread); //ロックがビジーなので、スレッドをキューに追加します。
        currentThread-> Sleep(); //そして眠りにつく
    }
       (void)割り込み-> SetLevel(oldLevel); //割り込みを有効にします
 }

4

1 に答える 1

1

私は NACHOS を知りませんし、自分で推測することもありません。したがって、テストする必要があります。

考え方は単純です。この割り込みの有効化/無効化機能が現在のプロセス コンテキストに対してローカルである場合、 を呼び出したときに次のことが発生するはずですSleep(): プロセスは非実行としてマークされます。つまりscheduler、CPU 時間を与えると見なされるプロセスのリストから除外されます。次に、Sleep() 関数は、スケジューラに通常の作業 (実行するプロセスを見つける) を強制します。実行中のプロセスのリストが空でない場合、スケジューラは次に使用可能なプロセスを選択し、このプロセスへのコンテキスト スイッチを作成します。この後、割り込み管理の状態がこの新しいコンテキストから復元されます。

実行するプロセスがない場合、スケジューラはIdle loop状態に入り、通常は割り込みを有効にします。スケジューラーが実行されている間、スケジュールIdle loopするものを取得するまで、実行中のプロセスのキューをポーリングし続けます。

プロセスが再び実行中としてマークされると、プロセスは制御を取得します。これは、他のプロセスが呼び出された場合に発生する可能性がありますWakeUp()(または、APIが不明であると述べたように)

スケジューラがプロセスを選択して切り替えると、フラグがfalseに設定された通常の(システムの)コンテキストスイッチが実行されるため、割り込みが無効になっている呼び出しinterrupts enabledの後にatステートメントで実行が続行されます。Sleep()

上記の仮定が正しくなく、interrupts enabledフラグがグローバルである場合、次の 2 つの可能性があります。割り込みを処理できないためにシステムがハングするか、またはそのworkaroundような状況に備えているかのいずれかです。

だから、あなたは試す必要があります。最善の方法は、アクセスできる場合はもちろん、カーネル ソースを読むことです。))

于 2012-09-26T17:40:20.373 に答える