高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先

Technote 1190

Power Manager 2.0



目次

節電への関心

スリープとスリープ解除に加えられた変更

デバイス省電力ハンドラ

Power Manager 2.0 に含まれる新しいルーチン

新しいスリープタイプ

スリープメッセージ

その他の新しいメッセージ

ネットワークアクティビティに対するスリープ解除

電源の追加

マイクロプロセッサの温度の取得

Power Manager Apple イベント

サーバモード

参考文献

Power Manager 2.0 は、より積極的な節電対策の実現を促進するために Mac OS に加えられたアップデートで、最新の Macintosh ハードウェアおよび NewWorld ROM アーキテクチャに組み込まれている新機能をサポートします。

Power Manager 2.0 は、すべての iMac、Blue & White G3、Power Mac G4 デスクトップ、「ブロンズキーボード」PowerBook G3 シリーズ、iBook、および今後発表されるポータブルおよびデスクトップで使用できます。

Power Manager 2.0 をサポートするために Mac OS にいくつかの内部的な変更が加えられると同時に、デベロッパが使用できるいくつかの新しい API も追加されました。したがって、このテクニカルノートでは、Power Manager 2.0 に含まれる新機能とアップデートされた機能の両方について説明します。Power Manager サービスの使用方法の詳細については、『Inside Macintosh: Devices』の「Power Manager」の章を参照してください。

このテクニカルノートは、これまでにポータブルマシンで実行されるアプリケーションの開発にかかわったことのあるアプリケーションデベロッパだけでなく、すべての Mac OS アプリケーションデベロッパを対象に書かれています。一方、PCI スロットへの電力の遮断をサポートする必要のあるデバイスドライバのデベロッパは、「Updating Drivers for PM 2.0」を参照してください。



節電への関心

新しい Power Manager は、PowerBook 固有のマネージャとしての性格が非常に弱まっています。実際、新しい Power Manager は、ポータブルマシンだけでなくデスクトップマシン (サポートされている機種にかぎり) でもポータブルマシン同様の省電力機能を実現し、将来の製品でも引き続き同様の動作を実行することになっています。つまり、書斎やオフィスから移動することのないコンピュータを含めて、すべてのコンピュータシステムで電力を効率的に使用することが時代の要請であるということです。

Mac OS 8.6 ではじめて使用できるようになった新しいナノカーネルの導入に伴い、ビジーでない、または CPU 時間を要求しないタスクのブロックが許可されるようになりました。その結果、プロセッサ (また、場合によってはマルチプロセッサ) は必要になるまで省電力状態に置くことができます。これにより、これまで以上の省電力が可能になり、このことが結果的にバッテリ寿命の大幅な向上を実現します。

新しい省電力機能を利用するため、アプリケーションおよびその他のソフトウェアは、次に示すいくつかの基本的なガイドラインにしたがうだけで、システムアイドルを適切に取り扱うことができるようになります。

WaitNextEvent

WaitNextEvent を呼び出すときにスリープ値としてゼロを使用しないでください。ゼロを使用すると、アプリケーションが CPU を独占してしまい、システムがアイドル状態にならなくなります。

VBL とタイムタスク

VBL および Time Manager タスクの使用を控えます。特に、これらが高い頻度で実行される場合は、その回数を減らしてください。使用されるタスクの数が多くなり、その頻度が高くなると、ほとんど必要のない命令を繰り返し実行するために、CPU の負荷がより大きくなります。

ポーリング/スピンルーピング

ループやスピンの中でイベントの待機を行わないようにします。Device Manager 呼び出しの中でスピンループを使用して、ioResult の変更を待たないでください。むしろ、Device Manager の中では、アイドル状態に悪影響を与えない PBWaitIOComplete という新しいルーチンを使用します。

   OSStatus PBWaitIOComplete(IOParamPtr ioPB, Duration timeout)

PBWaitIOComplete は、割り込み (ioResult の待機に影響を与える可能性のある割り込み) が発生するか、あらかじめ指定したタイムアウト値に達するまで、システムをアイドル状態にし続けます。タイムアウトになった場合、このルーチンは kMPTimeoutErr を返します。


Back to top

スリープとスリープ解除に加えられた変更

より積極的に節電要件を満たすため、スリープ/スリープ解除のプロセスが拡張され、可能な場合はスリープ時に PCI スロットに供給する電力を遮断する機能、「ディープスリープ」と呼ばれる新しい状態に入る機能などの、新しいハードウェアの機能を使用できるようになりました。ただし、全般的なプロセスはこれまで同様であり、いくつかのエントリが処理する必要のあるメッセージが追加されたことを除いて、スリープキューの使い方に変更は加えられていません。

ドライバサービスは、いくつかのサービスを提供できるようにアップデートされ、PCI (およびその他の) デバイスドライバがそれらのサービスを使用する場合、デバイスは伝統的なスリープキューよりも後の段階でスリープ/スリープ解除プロセスの電力を制御できるようになりました。これらの新しいサービスの使い方はクラシックなスリープキューの使い方に似ていますが、デバイス省電力ハンドラを呼び出すタイミングがクラシックなプロセスよりもずいぶん後になります。そのため、これらのサービスに対応したデバイスは電力が遮断される最後の瞬間までサービスを提供できるようになります。

注意:
伝統的なスリープキューの使い方については、『Inside Macintosh: Devices』の「Power Manager」の章を参照してください。



重要:
PCI スロットへの電力の遮断をサポートする必要のあるデバイスドライバのデベロッパは、このテクニカルノートとは別に「Updating Drivers for PM 2.0」というドキュメントを参照してください。




Back to top

デバイス省電力ハンドラ(Device Power Handlers)

デバイス省電力ハンドラは、Power Manager によって呼び出され、コンピュータに接続されているデバイスに代わって節電リクエストを処理するルーチンです。

Power Manager では、「デバイススリープキュー」と呼ばれる新しいローレベルのスリープキューを定義しています。デバイススリープキューは、スリーププロセスの最も遅い段階、およびスリープ解除プロセスの最も早い段階でスリープに関連する節電リクエストによって呼び出される複数の省電力ハンドラから構成されています。このキューは主として、デバイスドライバがスリープまたはスリープ解除イベントに応答して、それらの電力ステータスを設定するために用意されています。デバイススリープキューは、伝統的なスリープキューに送信されるメッセージと同じメッセージを受信し、また両方のキューは追加されたいくつかのメッセージを受信することができます (詳細については、後述の「新しいメッセージ」のセクションを参照してください)。

typedef pascal OSStatus (*PowerHandlerProcPtr)(UInt32  message,
		void * param,
		UInt32 refCon,
		RegEntryID * regEntryID);

これは、省電力ハンドラの定義です。パラメータ message は現在の節電リクエストです。param はメッセージ固有のパラメータで、現在のところ、kGetDevicePowerLevel および kSetDevicePowerLevel メッセージ、kGetPowerInfo および kGetWakeOnNetInfo メッセージに対してのみ使用されます。refCon は省電力ハンドラで使用するために指定します。登録時にこのパラメータに渡された値は、省電力ハンドラが呼び出されるたびに、その省電力ハンドラに返されます。最後のパラメータである regEntryID は省電力ハンドラが制御するデバイスで、省電力ハンドラが登録されたときに Power Manager に与えられたデバイスと同じデバイスです。

重要:
特定の節電メッセージを処理できない場合、すべての省電力ハンドラは kPowerMgtMessageNotHandled を返す必要があります。




Back to top

Power Manager 2.0 に含まれる新しいルーチン


AddDevicePowerHandler

AddDevicePowerHandler を使用すると、デバイススリープキューに省電力ハンドラを追加することができます。regEntryID は、対象となるデバイスの登録エントリ ID のアドレスです。なお、これは必ず必要なパラメータで、有効な regEntryID を指定する必要があります。handler は、対象となるデバイスに対して登録しようとしている省電力ハンドラです。これは、ルーチンディスクリプタではなく、PowerPC コードへのポインタです。省電力ハンドラを登録できるのは PowerPC コードのみであるため、ルーチンディスクリプタは必要ありません。refCon フィールドは内部的な目的に使用され、この値は節電リクエストが発行されるたびに返されることになります。deviceType は、デバイスのタイプを記述する文字列です。Power Manager では regEntryID パラメータに基づいてデバイスタイプを検索するため、大部分の省電力ハンドラではこのパラメータを使用する必要はありません。

   OSStatus AddDevicePowerHandler (RegEntryIDPtr regEntryID,
                    PowerHandlerProcPtr handler,
                    UInt32 refCon,
                    char * deviceType);

RemoveDevicePowerHandler

RemoveDevicePowerHandler を使用すると、省電力ハンドラをアンインストールすることができます。regEntryID は、省電力ハンドラが制御するデバイスに対応した登録エントリ ID です。

   OSStatus RemoveDevicePowerHandler (RegEntryIDPtr 
regEntryID);

GetDevicePowerLevel

GetDevicePowerLevel を使用すると、デバイスの省電力ハンドラに現在の省電力情報を問い合わせることができます。

   OSStatus GetDevicePowerLevel (RegEntryIDPtr regEntryID,
                    PowerLevel * devicePowerLevel);

SetDevicePowerLevel

SetDevicePowerLevel を使用すると、デバイスの省電力レベルを devicePowerLevel パラメータで指定するステータスに設定することができます。省電力レベルの定義と、GetDevicePowerLevel および SetDevicePowerLevel の使い方については、「Updating Drivers for PM 2.0」を参照してください。

    OSStatus SetDevicePowerLevel (RegEntryIDPtr regEntryID,
                    PowerLevel devicePowerLevel);


Back to top

新しいスリープタイプ

Power Manager 2.0 と、iBook およびそれ以降に発表されたマシンを含めた Apple 製の最新のハードウェアでは、スリープに関するいくつかのバリエーションが存在します。

シンプルスリープ

この形式のスリープは、伝統的な PowerBook のスリープとして知られているものです。大部分のマシンでは電源がオフになりますが、メモリはセルフリフレッシュモードに入っているため、マシンがスリープしている間もメモリの内容は失われません。

セーフスリープ

この形式のスリープはシンプルスリープに似ていますが、スリープに入ったときのメモリの内容を表すファイルがディスクに書き込まれる点が異なります。その結果、スリープ中に予期せぬ停電が発生しても、ユーザの作業コンテキストは次回の起動時に完全にリストアされます。現在、このスリープのバリエーションは、「メモリ」コントロールパネルの「仮想メモリ」が「入」になっている場合のみ使用できます。セーフスリープは、ユーザが「省エネルギー設定」コントロールパネルの「オプション設定」パネルで「スリープ中もメモリの内容を保持する」チェックボックスにチェックマークを入れたときに有効になります。

ディープスリープ

この形式のスリープでは、メモリの内容がディスクに書き込まれ、マシンの電源が完全にオフになります。ユーザが Power キーを押すと、保持されているメモリ内容がディスク上に存在するかどうかを判断した時点でマシンがブートし、メモリ内容がディスクに格納されている場合はメモリが再構築されて、あたかもそれまで単純なスリープ状態に入っていたかのようにマシンのスリープ状態が解除されます。

ディープスリープは、「メモリ」コントロールパネルの「仮想メモリ」が「入」になっている場合のみ使用できます。現在のところ、マシンがセーフスリープ状態に入っていて、その間に電力が失われたとき (マシンのスリープ中にバッテリの電源が完全に消耗したときなど) のみディープスリープに入ることになっています。

対象となるマシンでセーフまたはディープスリープがサポートされているかどうかを確認するには、PMFeatures ルーチンを使って、hasDeepSleep ビットがセットされているかどうかをチェックします。


Back to top

スリープメッセージ

Power Manager 2.0 では、使用可能なスリープのバリエーションが追加されたため、スリープキューおよびデバイススリープキューに送信されるメッセージのバリエーションも増加しました。

シンプルスリープのメッセージ

この場合、スリープキューのエントリとデバイススリープキューのエントリは、標準的なメッセージのセットを受信します。つまり、kSleepRequest (以前の sleepRequest) または kSleepDemand (以前の sleepDemand) と、スリープ解除時の kSleepWakeup (以前の sleepWakeup) です。これらのメッセージは以前同様に処理してください。また、Blue & White G3 マシンでは、これらのキューは、kDozeRequest、kDozeDemand、および kDozeWakeup というドーズメッセージを受信します。

セーフスリープのメッセージ

セーフスリープの場合は、前述の標準的なメッセージのセットも送信されますが、kSleepRequest または kSleepDemand よりも先に、スリープキューはそれぞれ kSuspendRequest または kSuspendDemand を受信します。スリープキューの場合、これらの新しいメッセージは、既存のメッセージに加えて送信されるだけでなく、既存のメッセージよりも前に送信されます。なぜ両方のメッセージが送信されるかといえば、レガシーソフトウェアが新しいメッセージを認識できず、その結果、差し迫ったスリープを適切に準備できない可能性があるためです。デバイススリープキューのエントリは、kSleepRequest または kSleepDemand メッセージの代わりに kSuspendRequest または kSuspendDemand メッセージを受信します。

スリープを解除するときに電力が失われていると、スリープキューは kSleepWakeup メッセージよりも前に新しく追加された kSuspendWakeup メッセージを受信します。デバイススリープキューのエントリは、マシンが電源オフの状態からのレジュームを行い、ディスクに保存されていたメモリの内容をリストアする場合に、kSuspendWakeup メッセージを受信します。通常のスリープから復帰する場合、両方のキューは kSleepWakeup メッセージを受信します。

非常に重要 !
伝統的なスリープキューに登録されているソフトウェアは、これらの追加メッセージに関係なく、自分自身のステータスを独自に保持する必要があります。たとえば、ソフトウェアが kSuspendDemand メッセージを受信し、kSleepDemand メッセージを受信するときに再度実行する必要のない活動の実行を続ける場合、シーケンスを適切に管理し、複数の活動を行わないようにすることはそのソフトウェアの責任です。デバイススリープシーケンスの場合、その中に登録されているエントリは 1 つのメッセージまたは他のメッセージのみを受信するため、このことは問題になりません。


スリープメッセージの例

新しいメッセージの複雑さを理解しやすくするため、以下の例を使って、それぞれのタイプのスリープに対するイベントの順序を説明します。ただし、ほとんどのソフトウェアでは、新しい Power Manager とともに正常に動作するようにスリープの処理方法を変更する必要はないという点に注意してください。というのも、通常、ほとんどのソフトウェアでは、セーフスリープ状態に入っているかどうかに配慮する必要はないためです。この場合は、『Inside Macintosh: Devices』に記載されているいくつかのガイドラインにしたがってください。新しいメッセージをいつ送信し、それらに対してどのように応答するかを理解していなければならないのは、デバイスドライバのデベロッパと、セーフスリープの場合に何らかの異なる動作を必要としているアプリケーションデベロッパのみです。

注意:
比較的古いデスクトップ (Blue & White G3 と iMac の一部) と、その他、通常のスリープ状態に入ることができないマシンでは、以下の例の「Sleep (スリープ)」を「Doze (ドーズ)」に置き換えてください (ただし、それらのマシンではセーフスリープを使用できないため、シンプルスリープの場合のみ)。たとえば、kSleepRequest は kDozeRequest になります。



シンプルスリープリクエスト (アイドルスリープ)

これは、ユーザが指定したスリープタイムアウトに達したときに送信されるメッセージのシーケンスです。

  1. スリープキューに kSleepRequest が送信されます。
  2. スリープキューの要素がリクエストを拒否すると、kSleepRevoke がスリープキューに送信され、スリープはアボートします。この後は、ステップ 10 に進みます。
  3. デバイススリープキューに kSleepRequest が送信されます。
  4. デバイススリープキューの要素がリクエストを拒否すると、kSleepRevoke がデバイススリープキューとスリープキューに送信され、スリープはアボートします。この後は、ステップ 10 に進みます。
  5. スリープキューに kSleepDemand が送信されます。
  6. デバイススリープキューに kSleepDemand が送信されます。
  7. マシンはスリープします。その後、スリープ解除イベントが発生します。
  8. デバイススリープキューに kSleepWakeup が送信されます。
  9. スリープキューに kSleepWakeup が送信されます。
  10. マシンのスリープが解除されます。

 

シンプルスリープデマンド (ユーザデマンドのスリープ)

これは、ユーザ (または電力不足の状態) によってスリープが開始されたときに送信されるメッセージのシーケンスです。

  1. スリープキューに kSleepDemand が送信されます。
  2. デバイススリープキューに kSleepRequest が送信されます。
  3. デバイススリープキューの要素がリクエストを拒否すると、kSleepRevoke がデバイススリープキューに送信され、kSleepWakeup がスリープキューに送信されて、スリープはアボートします。この後は、ステップ 7 に進みます。
  4. マシンはスリープします。その後、スリープ解除イベントが発生します。
  5. デバイススリープキューに kSleepWakeup が送信されます。
  6. スリープキューに kSleepWakeup が送信されます。
  7. マシンのスリープが解除されます。

     

セーフスリープリクエスト

これは、セーフスリープに対してユーザが指定したスリープタイムアウトに達したときに送信されるメッセージのシーケンスです

  1. スリープキューに kSuspendRequest が送信されます。
  2. スリープキューに kSleepRequest が送信されます。
  3. スリープキューの要素がリクエストを拒否すると、kSleepRevoke がスリープキューに送信され、スリープはアボートします。この後は、ステップ 14 に進みます。
  4. デバイススリープキューに kSuspendRequest が送信されます。
  5. デバイスキューの要素がリクエストを拒否すると、kSuspendRevoke がデバイススリープキューに送信され、kSleepRevoke がスリープキューに送信されて、スリープはアボートします。この後は、ステップ 14 に進みます。
  6. スリープキューに kSuspendDemand が送信されます。
  7. スリープキューに kSleepDemand が送信されます。
  8. デバイススリープキューに kSuspendDemand が送信されます。
  9. マシンはスリープします (この後で電力が失われる場合もあります)。その後、スリープ解除/電力回復イベントが発生します。
  10. 通常のスリープからスリープ解除を行う場合は、デバイススリープキューに kSleepWakeup が送信されます。この後は、ステップ 13 に進みます。
  11. 電源がオフになっている状態からスリープ解除を行う場合は、デバイススリープキューに kSuspendWakeup が送信されます。
  12. 電源がオフになっている状態からスリープ解除を行う場合は、スリープキューに kSuspendWakeup が送信されます。
  13. スリープキューに kSleepWakeup が送信されます。
  14. マシンのスリープが解除されます。

セーフスリープデマンド

これは、ユーザ (または電力不足の状態) によってセーフスリープが開始されたときに送信されるメッセージのシーケンスです。

  1. スリープキューに kSuspendDemand が送信されます。
  2. スリープキューに kSleepDemand が送信されます。
  3. デバイススリープキューに kSuspendRequest が送信されます。
  4. デバイススリープキューの要素がリクエストを拒否すると、kSleepRevoke がデバイススリープキューに送信され、kSleepWakeup がスリープキューに送信されて、スリープはアボートします。この後は、ステップ 11 に進みます。
  5. デバイススリープキューに kSuspendDemand が送信されます。
  6. マシンはスリープします (この後で電力が失われる場合もあります)。その後、スリープ解除/電力回復イベントが発生します。
  7. 通常のスリープからスリープ解除を行う場合は、デバイススリープキューに kSleepWakeup が送信されます。この後は、ステップ 10 に進みます。
  8. 電源がオフになっている状態からスリープ解除を行う場合は、デバイススリープキューに kSuspendWakeup が送信されます。
  9. 電源がオフになっている状態からスリープ解除を行う場合は、スリープキューに kSuspendWakeup が送信されます。
  10. スリープキューに kSleepWakeup が送信されます。
  11. マシンのスリープが解除されます。

注意:
オリジナルのスリープがリクエスト (アイドル) スリープであるかデマンド (ユーザ起動) スリープであるかに関係なく、常にリクエストがデバイススリープキューに送信されます。これは、デバイススリープキューのエントリが電力を管理するデバイスでは低電力スリープ (これは Power Macintosh G4 デスクトップで発生し、すべてのデバイスによってサポートされている場合、PCI スロットへの電力供給が遮断されます) がサポートされていない可能性もあるため、デバイススリープキューのエントリには常にスリープを拒否する機会が与えられなければならないからです。



Back to top

その他の新しいメッセージ

WakeToDoze

kWakeToDoze メッセージは、ネットワークまたはマシンのスリープ解除の原因 (ユーザ以外の) となったその他のリクエストにサービスを提供するために、マシンが特定の時点までにスリープ解除を行うことになっている場合、スリープキューとデバイススリープキューの両方に送信されます。大部分のスリープキューのエントリでは、このメッセージに対して個別に応答する必要はなく、noErr を返します。大部分のデバイススリープキューのエントリでは、kWakeToDoze メッセージを kSleepWakeup メッセージと同じ方法で取り扱う必要があります。つまり、このメッセージは常に処理し、無視してはいけないということです。一部のデバイス省電力ハンドラ、特にビデオデバイス (また、おそらくは大容量の記憶デバイスも) では、これとは異なる方法でリクエストに応答し、画面表示の回復やハードディスクドライブの回転を除き、最小限のスリープ解除タスクだけを実行します (必要がない場合)。

次に、kWakeToDoze に対して特に何もしないサンプルハンドラを示します。
                  
                  pascal OSStatus MyPowerHandler (UInt32 message,
	              void *param,
	              UInt32 refCon,
	              RegEntryID * regEntryID)
{
   switch (message)
   	{
   		case kWakeToDoze:
   		case kSleepWakeup:
   			WakeMyDevice ();
   			break;
 
   		case kDozeToFullWakeUp:
   		  // kWakeToDoze メッセージで完全にスリープ解除を
   		  // 行ったため無視することができる
   			break;
		:
   	}
}
                  
                  

次に、kWakeToDoze を異なる方法で処理するサンプルハンドラを示します。

                  
                  pascal OSStatus MyPowerHandler (UInt32 message,
	              void *param,
	              UInt32 refCon,
	              RegEntryID * regEntryID)
{
   switch (message)
   	{
   		case kWakeToDoze:
   			WakeMyDevicePartially();
   			break;
 
   		case kSleepWakeup:
   			WakeMyDevice ();
   			break;
 
   		case kDozeToFullWakeUp:
			WakeMyDeviceFromPartialState ();
   			break;
		:
   	}
}
                  
                  

 

DozeToFullWakeUp

マシンが中間的なドーズ状態にあるときにユーザが手動によるマシンのスリープ解除を選択した場合、kWakeToDoze メッセージに続いて kDozeToFullWakeUp メッセージが送信されます。このときも、大部分のエントリではこのメッセージの無視を選択できますが、kWakeToDoze メッセージに応答したエントリでは、デバイスを完全なスリープ解除状態に復帰させるために必要なすべてのステップを実行する必要があります。

マシンが中間的なスリープ解除状態 (ドーズ) にあるときに通常のスリープタイムアウトに達した場合、スリープキューのエントリは通常のスリープまたはサスペンドリクエストメッセージを受け取ることになり、その結果、マシンが完全なスリープ状態に戻るように、これらのメッセージを処理しなければなりません。

GetPowerLevel および GetPowerLevel

kGetPowerLevel および kSetPowerLevel メッセージは、新しいデバイススリープキューに含まれるエントリのみに送信されます。これらのメッセージは、デバイススリープキュー内の省電力ハンドラに対して、一部のソフトウェアがドライバサービスの GetDevicePowerLevel および SetDevicePowerLevel ルーチンを使って、それらが制御しているデバイスのステータスの変更を要求していることを通知するために使用します。省電力レベルの定義については、「Updating Drivers for PM 2.0」を参照してください。

DeviceInitiatedWake

kDeviceInitiatedWake メッセージはすべての省電力ハンドラに送信され、それらがスリープ解除の原因になったデバイスを制御しているかどうかを問い合わせます。大部分の省電力ハンドラはこのリクエストに応答しません。マシンのスリープ解除を行うことができるデバイスでは、そのデバイスがスリープ解除を開始したことと、kDeviceRequestsFullWake を使って完全なスリープ解除を行う必要があるか、kDeviceRequestsWakeToDoze を使って部分的なスリープ解除を行う必要があるかを示す適切な値を返すことで、このメッセージに応答する必要があります。これらの値は、省電力ハンドラ関数の param パラメータを介して返されることになります。

次に、制御するデバイスがスリープ解除の原因になったことを Power Manager に通知する関数のサンプルを示します。

	pascal OSStatus MyPowerHandler (UInt32 message,
	                void *param,
	                UInt32 refCon,
	                RegEntryID * regEntryID)
	{
	  OSStatus  status = kPowerMgtMessageNotHandled;
	  switch (message)
	  {
	    case kDeviceInitiatedWake:
	      *param = kDeviceDidNotWakeMachine;
	      if (IWokeTheMachine())
	        *param = kDeviceRequestsFullWake;
	      status = noErr;
	      break;
	    // その他の case を処理する
	  }
	  return err;
	}


Back to top

ネットワークアクティビティに対するスリープ解除

新しいハードウェア (iBook および Power Mac G4 を含む) には、「ネットワークスリープ解除」と呼ばれる新機能が用意されています。つまり、ユーザのオプション設定に基づいて、特定のタイプのネットワークアクティビティがスリープしているコンピュータのスリープ解除を行い、ネットワークリクエストに応答できるようにするということです。ユーザ (「省エネルギー設定」を介して) またはデベロッパは、ネットワークアクティビティによるマシンのスリープ解除に関して 2 つのオプションを指定することができます (後述の kWakeOnNetAdminAccessesBit および kWakeOnAllNetAccessesBit の値を使って)。kConfigSupportsWakeOnNetBit は、kGetWakeOnNetInfo 節電リクエストに応答して、ネットワークインタフェースカードに対する省電力ハンドラによってのみ使用されます。ただし、それらのカードがネットワークアクティビティに対するスリープ解除をサポートしている必要があります。

    // ネットワークアクティビティスリープ解除オプション
    enum
      {
      kConfigSupportsWakeOnNetBit   = 0, // 現在のインタフェース
 supports wake on network
      kWakeOnNetAdminAccessesBit    = 1, // ネットワーク管理者パケットによるスリープ解除
      kWakeOnAllNetAccessesBit      = 2, // 任意のパケットによるスリープ解除
      kUnmountServersBeforeSleepBit = 3, // サーバからの接続解除
                  
      kConfigSupportsWakeOnNetMask  = (1<<kConfigSupportsWakeOnNetBit),
      kWakeOnNetAdminAccessesMask   = (1<<kWakeOnNetAdminAccessesBit),
      kWakeOnAllNetAccessesMask     = (1<<kWakeOnAllNetAccessesBit)
      kUnmountServersBeforeSleepMask=
 (1<<kUnmountServersBeforeSleepBit);
      };

GetWakeOnNetworkOptions

GetWakeOnNetworkOptions は、システムがマシンのスリープ解除を許可されたと認識するネットワークアクセスのタイプを取得するために使用できます。

   OptionBits GetWakeOnNetworkOptions (void);
                    char * deviceType);

SetWakeOnNetworkOptions

SetWakeOnNetworkOptions は、サービスを提供するためにマシンのスリープ解除を許可することになるネットワークイベントをシステムに指示するために使用できます。ネットワークアクティビティに対するスリープ解除を無効にするには、ゼロに設定した kWakeOnNetAdminAccessesBit および kWakeOnAllNetAccessesBit を含む値を inOptions パラメータに渡します。

   OptionBits SetWakeOnNetworkOptions (OptionBits 
inOptions);

ネットワークドライバとネットワークアクティビティに対するスリープ解除

ネットワークインタフェースカードを制御するドライバでは、それらがシステムのスリープ解除を行うかどうかに関する問合せに応答できるように、省電力ハンドラを確実に Power Manager(Device Power Handlers 参照) に登録しておく必要があります。

現在選択されているネットワークデバイスで実際にネットワークアクティビティに対するスリープ解除がサポートされているかどうかを確認するため、kGetWakeOnNetInfo メッセージが送信されます。

スリープ解除時には、ネットワークデバイスの省電力ハンドラに kDeviceInitiatedWake メッセージが送信されます。このとき省電力ハンドラではメッセージに応答して、そのハンドラに対応するデバイスがシステムのスリープ解除の原因であるかどうかを示す結果を返す必要があります。省電力ハンドラは、リクエストに応えるためにシステムが完全にスリープ解除される場合は kDeviceRequestsWakeToFull を返し、リクエストに応えるためにシステムが部分的にのみスリープ解除される場合は kDeviceRequestsWakeToDoze を返す必要があります。部分的にスリープ解除されたシステムとは、完全な実行状態ではなく、ドーズ状態にあるシステムのことです。


Back to top

電源の追加

Power Manager 2.0 には、システムに電力を供給する AC、バッテリ、または UPS などの、いくつかのデバイスを制御して、それらと相互作用を行う機能が用意されています。このため Power Manager には、接続されているすべての電源の存在とステータスを通知して、特に、システムがバッテリまたはバックアップ電源 (UPS など) のみで動作しているかどうかなどの信頼できる重要情報をユーザに提供する必要があります。

Power Manager では、電源データ構造体 (単に「電源」とも呼ばれます) を介してこれらのデバイスの存在を認識します。

電源データ構造体

次に、電源のデータ構造体について説明します。

    struct PowerSourceParamBlock
    {
    PowerSourceID sourceID;             // Power Manager によって割り当てられたユニークな ID
    UInt16     sourceCapacityUsage;     // currentCapacity の使い方
    UInt32     sourceVersion;           // kVersionOnePowerSource を使用する
    OptionBits   sourceAttr;            // 属性 (詳細は後述)
    OptionBits   sourceFlags;           // フラグ (詳細は後述)
    UInt32     currentCapacity;         // ミリワットまたはパーセンテージで表した
                                        //  現在の容量
    UInt32     maxCapacity;             // ミリワット単位で表したフル容量
    UInt32     timeRemaining;           // ミリワット時単位で表した
                                        //  完全な電力消耗までに残された時間
    UInt32     timeToFullCharge;        // ミリワット時単位で表した
                                        //  充電に必要な時間
    UInt32     voltage;                 // ミリボルト単位の電圧
    SInt32     current;                 // ミリアンペア単位の電流
                                        // (電力消費時は負の数で、
                                        //  充電時は正の数)
    };

電源では、Power Manager が maxCapacity フィールドを基準として、電源の currentCapacity フィールドを解釈する方法を指定することができます。

次に、sourceCapacityUsage 定数の定義を示します。

 

    enum
    {
    kCapacityIsActual    = 0,           // 実際の単位で表現された容量
    kCapacityIsPercentOfMax = 1         // maxCapacity フィールドのパーセンテージとして
                                        // 表現された容量
    };

次の電源属性フラグを使用できます。

    enum
    {
    bSourceIsBattery   = 0,     // 電源はバッテリ
    bSourceIsAC     = 1,        // 電源は AC
    bSourceCanBeCharged = 2,    // 電源は充電可能
    bSourceIsUPS     = 3        // 電源は UPS
    };

次の電源ステータスフラグを使用できます。

    enum
    {
    bSourceIsAvailable  = 0,   // 電源はインストールされている
    bSourceIsCharging  = 1,   // 電源は充電中
    bChargerIsAttached  = 2,   // 充電器が接続されている
    };

AddPowerSource

AddPowerSource を呼び出すことで、Power Manager が監視する電源のリストに新しい電源を追加することができます。

    pascal OSStatus AddPowerSource (PowerSourceParamBlock * 
ioSource);

クライアントは、この電源の管理に使用できるユニークな PowerSourceID を受け取ります。ioSource は、電源を記述する情報を含んだパラメータブロックです。Power Manager では、電源の内部リストの中にこの情報のローカルコピーを保持します。

RemovePowerSource

デバイスの電源をもはや使用できなくなった場合は、RemovePowerSource を使って、リストからその電源を削除するように Power Manager に指示することができます。これにより、その電源は電力サマリ計算の対象外になります。

   pascal OSStatus RemovePowerSource (PowerSourceID 
inSourceID);

inSourceID は削除される電源の ID です。指定した PowerSourceID を持つ電源が Power Manager の電源リストの中で検出できない場合、このルーチンは kNoSuchPowerSource を返します。

UpdatePowerSource

UpdatePowerSource を呼び出すことで、電源のステータスに関する統計値 (電力消費量、残されている容量など) を更新することができます。電源情報を取得する方法は、それぞれのソフトウェアが内部的に決定します。

   pascal OSStatus UpdatePowerSource (PowerSourceParamBlock * 
ioSource);

ioSource には、電源に割り当てられている PowerSourceID を含めて、更新されることになる電源情報が含まれます。指定した PowerSourceID を持つ電源が Power Manager の電源リストの中で検出できない場合、このルーチンは kNoSuchPowerSource を返します。

単純な UPS 電源のサンプル

ユーザが、Power Manager とステータス情報のやり取りができる UPS をシステムに接続していると仮定します。UPS ドライバソフトウェアでは、その存在を示すために Power Manager に電源の登録を行わなければなりません。

static PowerSourceParamBlock mySource;
                  
void RegisterUPSSource (void)
{
    OSStatus  status = noErr;
 
    mySource.sourceCapacityUsage    = kCapacityIsActual;
    mySource.sourceAttr             = (1<<bSourceIsUPS)
                    | (1<<bSourceIsAC)
                    | (1<<bSourceIsBattery);
               // AC およびバッテリとともに UPS を登録する方法に注意
 
    mySource.sourceFlags            = (1<<bSourceIsAvailable);
    mySource.currentCapacity        = myCurrentCapacityInMilliWatts;
    mySource.maxCapacity            = myMaxCapacityInMilliWatts;
    mySource.timeRemaining          = secondsLeftToDischarge;
    mySource.timeToFullCharge       = secondsToFullChargeIfCharging;
    mySource.voltage                = myVoltageInMilliVolts;
    mySource.current                = -1234;
               // 電力を消費している場合は負の数
 
    status = AddPowerSource (&mySource);
               // エラーを処理する
}

AC 電源が削除されたとき、UPS はその周期的な更新時に次の変更を行って、ステータスを更新することができます。

  void UpdateUPSSource (void)
 {
    OSStatus  status = noErr;
                  
    // 更新されたデータを収集する
    if (NoACConnected())
      // AC 属性を削除していることに注意。これにより、Power Manager は、
      // 内部 AC を無視し、バッテリ電源が消耗しているかのように
      // 動作するように指示される
      mySource.sourceAttr &= ~(1<<bSourceIsAC);
                  
      mySource.currentCapacity     = myCurrentCapacityInMilliWatts;
      mySource.timeRemaining       = secondsLeftToDischarge;
      mySource.timeToFullCharge    = secondsToFullChargeIfCharging;
      mySource.voltage             = myVoltageInMilliVolts;
      mySource.current             = -1234; // 電力を消費している場合は負の数
                  
      status = UpdatePowerSource (&mySource);
      // エラーを処理する
 }

UPS が AC の不在を指定すると、AC の存在に関する内部的な読み込みデータが無効であることが Power Manager に通知され、Power Manager はあたかもバッテリが消耗しているかのようにシステムを取り扱うようになります。その結果、電力不足状態に陥ったシステムでは、バッテリ電源が消耗している PowerBook で行われるのと同じ省電力アクションが実行され、システムは低電力状態に置かれることになります。ディープスリープがサポートされている場合は、システムをディープスリープ状態にすることが試みられます。それが不可能な場合は、バッテリ電源を供給しないかぎり (デスクトップの場合のように)、システムは通常のスリープに入り、システムの電源はオフになります。なお、電力不足の状態になり、省電力アクションが開始される直前に、そのことを通知する Apple イベントがアクティブなプロセスに送信されます。これらのイベントの詳細については、後述の「Power Manager Apple イベント」を参照してください。


Back to top

マイクロプロセッサの温度の取得

Power Manager を使って、ボード上にあるマイクロプロセッサのコア温度を取得することができます。

   SInt32 GetCoreProcessorTemperature (MPCpuID inCpuID);

inCpuID パラメータは、Power Manager がコア温度を取得するプロセッサを指定します。この ID は MP API を使って取得できます (通常は、MPProcessors を呼び出してプロセッサカウントを取得した後、使用可能なプロセッサ全体にわたって MPGetNextCpuID を繰り返し実行します)。この方法は、ユニプロセッサシステムとマルチプロセッサシステムの両方で正常に動作します。

温度は摂氏で表現されます。温度を正しく取得できた場合、計測結果は正の値になります。計測結果が負の数の場合はエラーが返されています。

このルーチンは、対象となるハードウェアがコアプロセッサ温度のレポート機能をサポートしていなかったり、MP サービスが使用可能でないと、kCantReportProcessorTemperature を返します。


Back to top

Power Manager Apple イベント

Power Manager では、制限付きで Apple イベントがサポートされるようになりました。現在のところ、4 つのイベントのみが、ハイレベルイベントを認識可能なすべてのアクティブプロセスにブロードキャストされます。

節電イベントクラス

すべてのイベントは、kAEMacPowerMgtEvt というイベントクラスを使ってブロードキャストされます。

   enum
      {
      kAEMacPowerMgtEvt    = 'pmgt'
      }

節電イベント ID

次に、イベント ID の定義を示します。

    enum
      {
      kAEMacToWake            = 'wake',
      kAEMacLowPowerSaveData  = 'pmsd',
      kAEMacEmergencySleep    = 'emsl',
      kAEMacEmergencyShutdown = 'emsd'
      };

kAEMacToWake メッセージは、Macintosh のスリープが解除されるたびに送信されます。

kAEMacLowPowerSaveData メッセージは、Macintosh のメイン電源が停電になり、バックアップ電源も十分ではなく、近い将来スリープまたはシャットダウンを保証できなくなる可能性があるときに送信されます。アプリケーションでは、それらが提供しているサービスのステータスを保存するために必要な処理を実行する必要があります (必要な場合は、将来リストアできるように未保存の書類をテンポラリファイルに保存することで)。

重要:
この Apple イベントを処理するとき、ソフトウェアでは、ユーザからの入力を要求するアラートやダイアログのポスティングを避けてください。また、アラートやダイアログがどうしても必要な場合は、それらが必ず短時間でタイムアウトするようにしてください。これは、マシンが無人モードで実行されている可能性があり、OS の停電処理を完全に利用するためには、システムが確実にスリープまたは電源オフの状態に入ることができなければならないからです。


マシンのバックアップ電力が完全に消耗する直前には、2 つの緊急省電力アクション警告のいずれかがブロードキャストされます。どちらのメッセージが送信されるかは、対象となるマシンと、それがサポートしている機能によって異なります。

kAEMacEmergencySleep メッセージは、バックアップ電力が非常に残り少なくなって、コンピュータがスリープまたはディープスリープに入ろうとする直前に送信されます。このメッセージが送信されている間は、ユーザによる操作は許可されません。このイベントのブロードキャストが行われてから数秒以内に省電力アクションが実行されます。

kAEMacEmergencyShutdown メッセージは、バックアップ電力が非常に残り少なくなって、コンピュータがシャットダウンされようとする直前に送信されます。一部のモデル (Blue & White G3 や大部分の iMac など) では、スリープに入る代わりにシャットダウンが行われます。このメッセージが送信されている間、ユーザによる操作は許可されません。このイベントのブロードキャストが行われてから数秒以内に省電力アクションが実行されます。

重要:
ディープスリープがサポートされている特定の Macintosh のモデルの場合は、スリープまたはシャットダウンの代わりにディープスリープに入ります。あるモデルでディープスリープがサポートされていても、省電力アクションを実行する時点でそのオプションが使用可能でない場合、そのマシンは、バッテリがサポートされていればスリープに入り (iBook や PowerBook など)、そうでなければ電源がオフになります。ソフトウェアでは通常、kAEMacEmergencySleep と kAEMacEmergencyShutdown を同じものとして取り扱ってください。というのも、一方のメッセージがブロードキャストされていても、アクションが実行される時点でのシステムの性質により、実際にはもう一方の動作がインプリメントされる可能性があるためです。つまり、システムが kAEMacEmergencySleep メッセージをブロードキャストした場合でも、対象となるコンテキストでは、スリープの代わりに強制的なシャットダウンが行われる可能性があるということです。



Back to top

サーバモード

新しい Power Manager には、サーバモードのオペレーションを可能にする 2 つの新しいルーチンが用意されています。このモードはサーバ上で最も効果を発揮し、予期せぬ AC 電源の停電が発生した後で AC 電源が回復した場合にマシンが自動的に起動することを可能にします。

   pascal void EnableServerMode (Boolean inEnable);

EnableServerMode を使用すると、サーバモード機能の有効/無効を切り替えることができます。この機能が有効になっていると、AC 電源が供給されたとき (予期せぬ停電の後のみ) にマシンは自動的に起動するようになります。

   pascal Boolean IsServerModeEnabled (void);

IsServerModeEnabled を使用すると、サーバモードが現在有効になっているかどうかを判断することができます。戻り値の TRUE は機能が有効になっていることを意味し、FALSE は機能が有効でないことを意味します。


Back to top

参考文献


Back to top

ファイルのダウンロード

bluebook.gif Power Manager 2.0 DDK (Coming soon).


Back to top


Updated: 22-November-1999