17以上の論理CPUでアプリが落ちる問題を調べて2000/XPのパッチ作った

16以上のプロセッサコアを利用できるシステムでMyDVDがクラッシュする - ThinkStation D10, D20, E20, S10, C20, C20x - Lenovo Support (JP)

Direct3Dライブラリーに内包する問題のため、16以上のプロセッサーが利用可能な場合にMyDVDがクラッシュします。 6コアのIntel
Xeon CPUを2個搭載したシステムでハイパースレッディングを有効にすると、システムに24コアあることになります。
このエラーはDirect3D仮想マシンでスレッドの数を制限することで解消できます。

16 を超える論理プロセッサが構成されているコンピューターで DirectX 9.0 アプリケーションがクラッシュする

以下のオペレーティング システムを搭載しているコンピューターで 16 を超える論理プロセッサを構成します。

  • Windows XP Service Pack 3 (SP3)
  • Windows Vista Service Pack 2 (SP2)
  • Windows Server 2008
  • Windows Server 2008 SP2
  • Windows 7
  • Windows Server 2008 R2

このコンピューターで DirectX 9.0 アプリケーションを実行すると、アプリケーションがクラッシュします。

たとえば、Microsoft Windows Media Player で音楽ファイルを再生する場合、Windows Media Player を終了しようとすると、アプリケーションがクラッシュします。

  1. [スタート] ボタンをクリックし、[プログラムとファイルの検索] ボックスに「regedit」と入力し、Enter キーを押します。
  2. 次のレジストリ サブキーを見つけてクリックします。
    HKEY_LOCAL_MACHINE\Software\Microsoft\Direct3D
  3. [編集] メニューの [新規] をポイントし、[DWORD 値] をクリックします。
  4. PSGPNumThreads」と入力し、Enter キーを押します。
  5. [PSGPNumThreads] を右クリックし、[修正] をクリックします。
  6. [値のデータ] ボックスに、使用するスレッドの数を入力して、[OK] をクリックします。
  7. コンピューターを再起動して、変更を適用します。

さて、これについて Windows XP(5.3.2600.5601 - 2008/5/13)のコードを見て見よう

          push    ebx
          push    esi
          push    edi
          push    00000000h
          push    SSZ4B678B88_DisableMT
          call    SUB_L4B74CD90
          add    esp,00000008h
          test    eax,eax
          jnz    L4B746210
          push    eax
          push    SSZ4B678B78_PSGPNumThreads
          call    SUB_L4B74CD90
//PSGPNumThreads のレジストリ読み取り
          add    esp,00000008h
          test    eax,eax
          mov    [ebp-04h],eax
          jnz    L4B7461FB
//値が0のときはプロセッサの数を数える
          lea    eax,[ebp-28h]
          push    eax
          call    [KERNEL32.dll!GetSystemInfo]
// 構造体 +14hなのでプロセッサの数(dwNumberOfProcessors)を取得
          mov    ecx,[ebp-14h]
          mov    ebx,[ebp+08h]
          mov    [ebx+00002BB0h],ecx
          jmp    L4B746220
 L4B7461FB:
//値が0以外の時は16以上ならば16になるように変更
          cmp    eax,00000010h
          jbe    L4B746205
          mov    eax,00000010h
 L4B746205:
          mov    edx,[ebp+08h]
          mov    [edx+00002BB0h],eax
          jmp    L4B74621D
 L4B746210:
// 値が0の場合は強制的に1
          mov    eax,[ebp+08h]
          mov    dword ptr [eax+00002BB0h],00000001h
 L4B74621D:
          mov    ebx,[ebp+08h]
 L4B746220:
          mov    ecx,[ebx+00002BB0h]
          imul    ecx,00001F70h
          push    00000004h
          push    00003000h
          add    ecx,0000001Fh
          push    ecx
          push    00000000h
          call    [KERNEL32.dll!VirtualAlloc]

それでは、Vista SP2(6.0.6002.18005 - 2009/4/11)のコードを見て見ましょう

          push    SSZ74B5A58C_PSGPNumThreads
          call    SUB_L74B510C5
          add    esp,00000008h
          cmp    eax,ebx
          mov    [ebp-04h],eax
          jnz    L74B5A2D5
          lea    eax,[ebp-28h]
          push    eax
          call    [KERNEL32.dll!GetSystemInfo]
// CPUの数を数えて直接代入している
          mov    ecx,[ebp-14h]
          mov    edi,[ebp+08h]
          mov    [edi+000018F0h],ecx
          jmp    L74B5A30C

どうやら同じようです

次、Windows 7 SP1(6.1.7601.17514 - 2010/11/20)

          push    SSZ75535DDC_PSGPNumThreads
          call    SUB_L7552C9F5
          add    esp,00000008h
          mov    [ebp-04h],eax
          cmp    eax,ebx
          jnz    L75535B2E
          lea    eax,[ebp-28h]
          push    eax
          call    [KERNEL32.dll!GetSystemInfo]
          mov    eax,[ebp-14h]
          cmp    eax,00000010h
          jbe    L75535B23
          mov    eax,00000010h

// 16以上のCPUが検出された場合 16に固定している
 L75535B23:
      &nb
sp;   mov    edi,[ebp+08h]
          mov    [edi+000018F0h],eax
          jmp    L75535B65

おや、なんと、コード上で16に制限する仕組みがありますよ?

というわけで、Windows Vista 死亡。

とりあえず、2000/XP向けにパッチ作成

          push    SSZ4B678B78_PSGPNumThreads
          call    SUB_L4B74CD90
          add    esp,00000008h
          test    eax,eax
          mov    [ebp-04h],eax
          jnz    L4B7461FB
          lea    eax,[ebp-28h]
          push    eax
          call    [KERNEL32.dll!GetSystemInfo]
          mov    eax,[ebp-14h]
          jmp    L4B7461FB
          nop

          mov    [ebx+00002BB0h],ecx
          jmp    L4B746220
 L4B7461FB:
          cmp    eax,00000010h
          jbe    L4B746205
          mov    eax,00000010h

これで、判定処理まで飛んで終わり。
どっちかというと、判定漏れのバグですね

WLU の Windows 2000/XP Multi Core(More than 16 processors)DirectX Hotfix(KB982485) でダウンロード可能

Win2000/XPは5コア以上のCPUをDirectXで扱うとクラッシュするバグがある

おすすめ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です