在suspend_freeze_processes()函数中调用了freeze_processes()函数,而freeze_processes()函数中又调用了try_to_freeze_tasks()来完成冻结任务。在冻结过程中,会判断当前进程是否有wake_lock,若有,则冻结失败,函数会放弃冻结。
static
{
struct
unsigned
unsigned
struct
u64
unsigned
unsigned
do_gettimeofday(&start);
end_time
do
todo
read_lock(&tasklist_lock);
do_each_thread(g,
if
continue;
if
continue;
if
todo++;
}
read_unlock(&tasklist_lock);
yield();
if
wakeup
break;
}
if
break;
}
do_gettimeofday(&end);
elapsed_csecs64
do_div(elapsed_csecs64,
elapsed_csecs
if
if(wakeup)
printk("\n");
printk(KERN_ERR
sig_only
}
else
printk("\n");
printk(KERN_ERR
"(%d
elapsed_csecs
show_state();
}
read_lock(&tasklist_lock);
do_each_thread(g,
task_lock(p);
if
printk(KERN_ERR
cancel_freezing(p);
task_unlock(p);
}
read_unlock(&tasklist_lock);
}
printk("(elapsed
elapsed_csecs
}
return
}
到现在,所有的进程(也包括workqueue/kthread)
回到enter_state()函数中,再冻结进程完成后,调用suspend_devices_and_enter()函数让外设进入休眠。该函数中,首先休眠串口(之后不能再显示log,解决方法为在kernel配置选项的cmd_line中,添加”no_console_suspend”选项),再通过device_suspend()函数调用各驱动的suspend函数。
当外设进入休眠后,suspend_ops->prepare()被调用,suspend_ops是板级的PM操作(本文中粉红色的函数,依赖于具体的平台),以s3c6410为例,其注册在linux_source/arch/arm/plat-s3c64xx/pm.c中,只定义了suspend_ops->enter()函数。
static
.enter=
.valid=
};
接下来,多CPU中的非启动CPU被关闭。
int
{
int
if
return
if
error
if
goto
}
suspend_console();
suspend_test_start();
error
if
printk(KERN_ERR
goto
}
suspend_test_finish("suspend
if
goto
if
error
if
goto
}
if
goto
error
if
suspend_enter(state);
enable_nonboot_cpus();
if
suspend_ops->finish();
suspend_test_start();
device_resume(PMSG_RESUME);
suspend_test_finish("resume
resume_console();
if
suspend_ops->end();
return
if
suspend_ops->recover();
goto
}
接下来suspend_enter()被调用,该函数首先关闭IRQ,然后调用device_power_down(),
static
{
int
device_pm_lock();
#ifdef
cpufreq_get_cpufreq_name(0);
strcpy(governor_name,
if(strnicmp(governor_name,
cpufreq_set_policy(0,
}
#endif
arch_suspend_disable_irqs();
BUG_ON(!irqs_disabled());
if
printk(KERN_ERR
goto
}
error
if
if
error
sysdev_resume();
}
device_power_up(PMSG_RESUME);
arch_suspend_enable_irqs();
#ifdef
if(strnicmp(governor_name,
cpufreq_set_policy(0,
}
#endif
BUG_ON(irqs_disabled());
device_pm_unlock();
return
}
在suspend_pos->enter()所对应的函数中,代码最终停止在pm_cpu_sleep();处。
static
{
s3c6410_pm_do_save(gpio_save,
s3c6410_pm_do_save(irq_save,
s3c6410_pm_do_save(core_save,
s3c6410_pm_do_save(sromc_save,
__raw_writel(__raw_readl(S3C_WAKEUP_STAT),
#ifdef
__raw_writel(0xffffff00,
__raw_writel(0xffffffff,
__raw_writel(0xffffffff,
__raw_writel(0xffffffff,
if
flush_cache_all();
pm_cpu_sleep();
}
cpu_init();
__raw_writel(s3c_eint_mask_val,
s3c6410_pm_do_restore_core(core_save,
s3c6410_pm_do_restore(sromc_save,
……
}