Linux PM:wakeup count、wakelock、autosleep
在进行wakeup count、wakelock、autosleep之前,先参考《Linux电源管理(7)_Wakeup events framework (wowotech.net)》。
下面简单跟一下,wakeup count、wakelock、autosleep,及其使用方法。
1 PM初始化
PM子系统初始化:
pm_init
pm_start_workqueue
hibernate_image_size_init
hibernate_reserved_size_init
pm_states_init
kobject_create_and_add--创建/sys/power目录。
sys_create_groups--在/sys/power下创建一系列属性。
pm_print_times_init
pm_autosleep_init
wakeup_source_register--创建名为autosleep的wakeup source,在autosleep关键路径时,阻止系统睡眠。
alloc_ordered_workqueue--创建名为autosleep的有序workqueue,用于触发休眠动作。
PM suspend调试统计节点:
pm_debugfs_init
debugfs_create_file--创建suspend_stats节点。
查看/sys/kernel/debug/suspend_stats:
success: 1 fail: 0 failed_freeze: 0 failed_prepare: 0 failed_suspend: 0 failed_suspend_late: 0 failed_suspend_noirq: 0 failed_resume: 0 failed_resume_early: 0 failed_resume_noirq: 0 failures: last_failed_dev: last_failed_errno: 0 0 last_failed_step:
2 wakeup_count
关于wakeup_count参考《Linux电源管理(8)_Wakeup count功能 (wowotech.net)》。
获取wakeup_count:
cat /sys/power/wakeup_count
写入wakeup_count:
echo <count> > /sys/power/wakeup_count
如果写入的count和实际的wakeup_count不一致,则返回错误。
如果一致,说明可以操作/sys/power/state进行低功耗流程。
3 wakelock
关于wakelock参考《Linux电源管理(9)_wakelocks (wowotech.net)》。
3.1 wakelock使用方法
获取一个wakelock:
echo <lockname> > /sys/power/wake_lock
获取一个带超时的wakelock,超时后wakelock自动消失。时间单位是ns:
echo <lockname> <duration> > /sys/power/wake_unlock
查看当前生效的wakelock:
cat /sys/power/wake_lock
释放一个wakelock:
echo <lockname> > /sys/power/wake_unlock
查看非活跃wakelock:
cat /sys/power/wake_unlock
3.2 wakelock代码流程
wakelock获取代码流程:
wake_lock_show
pm_show_wakelocks--遍历wakelocks_tree,输出活跃的wakelock名称。
wake_lock_store
pm_wake_lock
->解析wakelock名称,以及是否有超时参数。
->wakelock_lookup_add--查找并添加wakelock。
->__pm_wakeup_event/__pm_stay_awake--保持唤醒一段时间,或者一直保持唤醒。
->wakelocks_lru_most_recent--加入wakelocks_lru_list。
wakelock释放代码流程:
wake_unlock_show
pm_show_wakelocks--遍历wakelocks_tree,输出非活跃wakelock名称。
wake_unlock_store
pm_wake_unlock
wakelock_lookup_add--查找,如果没找到不添加wakelock。
__pm_relax--找到wakelock后则释放。
wakelocks_lru_most_recent
wakelocks_gc--当释放wakelock时,不是立即销毁相关数据。而是启动一个work,保留last_time之后的WL_GC_TIME_SEC秒时间,默认为300秒。
schedule_work--调度wakelock_work。
__wakelocks_gc
wakeup_source_unregister--对于非active,并且在last_time超过WL_GC_TIME_SEC时间后开始回收资源。
rb_erase--从wakelocks_tree移除节点。
4 autosleep
关于autosleep参考《Linux电源管理(10)_autosleep (wowotech.net)》。
4.1 autosleep使用方法
对/sys/power/autosleep写入,触发sleep:
echo mem > /sys/power/autosleep
可能的值包括:freeze、standby、mem、disk、off。
4.2 autosleep代码流程
autosleep流程如下:
autosleep_show
pm_autosleep_state--获取autosleep_state值,根据状态从pm_states[]获取字符串。 autosleep_store decode_state--根据字符串匹配对应的state。 pm_autosleep_set_state __pm_stay_awake--获取autosleep wakesource。
__pm_relax--释放autosleep wakesource。
pm_wakeup_autosleep_enabled
queue_up_suspend_work
queue_work--将suspend_work放到autosleep_wq上。
try_to_suspend--根据autosleep_state进入hibernate或者suspemd。
hibernate
pm_suspend
queue_up_suspend_work--再次进行suspend队列。