Wakelockとは
WakelockとはCPUがsuspend状態に入るのを止める仕組みです。(マルチコアであれば一部のCPU単体レベルではsuspendに入りますので、全てのCPU、Linuxがsuspendに入るのを止めるイメージです。)タブレット端末等では、CPUをsuspend状態に入れることで、消費電流を削減します。しかし、特定の条件(音楽再生中等)ではデバイスを動作させ続ける必要があります。このような際は、Wakelockによりスリープ状態への遷移を明示的に止める必要があります。
使い方
Wakelockは、照度センサデバイスドライバでは、以下に使用箇所があります。
kernel/mediatek/4.4/drivers/misc/mediatek/sensors-1.0/alsps/alsps.c
wakeup_source_init(&alsps_context_obj->ps_wake_lock, "ps_wake_lock");
この、wakeup_source_init関数は以下に定義されています。
kernel/mediatek/4.4/include/linux/pm_wakeup.h
kernel/mediatek/4.4/drivers/base/power/wakeup.c
static inline void wakeup_source_init(struct wakeup_source *ws,
const char *name)
これは、wakeup_sourceを初期化する関数です。第1引数にはstruct wakeup_source型のポインタを指定します。第2引数には任意の文字列を指定します。その他の、Wakelockに関する主要な関数には、以下のようなものがあります。
/**
* __pm_stay_awake - Notify the PM core of a wakeup event.
* @ws: Wakeup source object associated with the source of the event.
*
* It is safe to call this function from interrupt context.
*/
void __pm_stay_awake(struct wakeup_source *ws)
指定されたwakeup_sourceをアクティブにし、CPUがsuspend状態に入らないようにします。引数には、wakeup_source_initでも指定した、struct wakeup_source型のポインタを指定します。
/**
* __pm_relax - Notify the PM core that processing of a wakeup event has ended.
* @ws: Wakeup source object associated with the source of the event.
*
* Call this function for wakeup events whose processing started with calling
* __pm_stay_awake().
*
* It is safe to call it from interrupt context.
*/
void __pm_relax(struct wakeup_source *ws)
指定されたwakeup_sourceを非アクティブにし、CPUがsuspend状態に入ることができるようにします。引数には、wakeup_source_initでも指定した、struct wakeup_source型のポインタを指定します。
/**
* __pm_wakeup_event - Notify the PM core of a wakeup event.
* @ws: Wakeup source object associated with the event source.
* @msec: Anticipated event processing time (in milliseconds).
*
* Notify the PM core of a wakeup event whose source is @ws that will take
* approximately @msec milliseconds to be processed by the kernel. If @ws is
* not active, activate it. If @msec is nonzero, set up the @ws' timer to
* execute pm_wakeup_timer_fn() in future.
*
* It is safe to call this function from interrupt context.
*/
void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
指定されたwakeup_sourceをアクティブにし、指定したミリ秒数、CPUがsuspend状態に入らないようにします。第1引数には、wakeup_source_initでも指定した、struct wakeup_source型のポインタを指定します。第2引数には、アクティブにするミリ秒数を指定します。
最後に
英文の関数の説明に出てくるPMはLinuxのPowerManagerを示します。Wakelockを使用してPowerManagerに通知してないと思わぬ所でSleepに入り、処理が進まないことがあるので注意が必要です。反対に、むやみに使うと、CPUのsuspendを妨害し、消費電流で問題が起きることがあるので、注意が必要です。
Appendix. デバッグ関連
Wakelockの状態は/d/wakeup_sources
から確認可能です。(以下はbugreportから抜粋)
------ KERNEL WAKE SOURCES (/d/wakeup_sources) ------
name active_count event_count wakeup_count expire_count active_since total_time max_time last_change prevent_suspend_time
mem_disp_wakelock 0 0 0 0 0 0 0 16707 0
PowerManagerService.WakeLocks 4 4 0 0 27467 28240 27467 13552 0
WLAN rx_thread 469 469 0 0 0 61 0 40686 0
WLAN hif_thread 2418 2418 0 0 0 204 10 40687 0
WLAN tx_thread 1931 1931 0 0 0 69 0 40916 0
WLAN Timer 6 6 0 0 22118 28130 22118 18902 0
WLAN timeout 44 1956 0 44 0 18733 2739 40984 0
WLAN interrupt 0 0 0 0 0 0 0 8549 0
<省略>
mt_charger 0 0 0 0 0 0 0 128 0
usb 2 2 0 0 0 7 7 3403 0
ac 2 2 0 0 0 1 1 3398 0
charger 1 1 0 0 0 0 0 136 0
autosleep 0 0 0 0 0 0 0 52 0
deleted 0 0 0 0 0 0 0 0 0
主要な値の意味は以下になります。
active_count : wake_lockが有効になった回数
event_count : wake_lockを有効にしようとした回数(__pm_wakeup_eventの時間切れ前にもう一度呼ぶとこちらだけ増える)
active_since : いつからwake_lockが有効になっているか
total_time : wake_lock有効な合計時間
max_time : 1回のwake_lock有効における最大時間
尚、PowerManagerServiceは、前述のLinuxのPowerManagerでは無く、AOSP(Androidオープンソースプロジェクト)のPowerManagerになります。(AOSPより上位層のWakelockを取りまとめてKernelで取得)
コメント