Wakelock

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で取得)

コメント

タイトルとURLをコピーしました