关于s5pc110系统休眠的情景分析(2)

附:http://blogold.chinaunix.net/u/25572/showart_2533630.html 相关android的文章不错。

 

我们来分析enter_state这个函数,这个函数应该是一个重量级的函数,首先再次通过valid_state检测state的有效性,前面我们已经分析过
 这个检测方法通过全局的变量suspend_ops是否为空,其成员函数valid是否为空,以及调用成员函数valid的返回值来判断,s5pc110的平台 只接受PM_SUSPEND_MEM的suspend,获取互斥锁,同步文件系统之后, 调用suspend_prepare()函数,这个函数也定义在suspend.c中,做一些 进入suspend状态时的准备工作,我们分析这个函数
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 static int suspend_prepare(void)
 {
  int error;

  if (!suspend_ops || !suspend_ops->enter)
   return -EPERM;

  pm_prepare_console();

  error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
  if (error)
   goto Finish;

  error = usermodehelper_disable();
  if (error)
   goto Finish;

  error = suspend_freeze_processes();
  if (!error)
   return 0;

  suspend_thaw_processes();
  usermodehelper_enable();
  Finish:
  pm_notifier_call_chain(PM_POST_SUSPEND);
  pm_restore_console();
  return error;
 }
 我们看pm_notifier_call_chain(PM_SUSPEND_PREPARE),这里涉及到PM notifier的一个机制,关于这个机制,我们简单介绍一下
 pm在power/main.c中定义了一个pm_chain_head,用于pm在转换过程中的通知路径
 static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
 pm在休眠和唤醒的过程中会发出一些EVENTS,这些事件定义在notifier.h中
 /* Hibernation and suspend events */
 #define PM_HIBERNATION_PREPARE 0x0001 /* Going to hibernate */
 #define PM_POST_HIBERNATION 0x0002 /* Hibernation finished */
 #define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */
 #define PM_POST_SUSPEND  0x0004 /* Suspend finished */
 #define PM_RESTORE_PREPARE 0x0005 /* Going to restore a saved image */
 #define PM_POST_RESTORE  0x0006 /* Restore failed */
 
 如果哪个内核模块想得到这些EVENTS,就需要定义一个notifier_block, 并把它挂载到pm_chain_head上。为此,PM定义了挂载和卸载函数
 int register_pm_notifier(struct notifier_block *nb)
 {
  return blocking_notifier_chain_register(&pm_chain_head, nb);
 }
 EXPORT_SYMBOL_GPL(register_pm_notifier);

 int unregister_pm_notifier(struct notifier_block *nb)
 {
  return blocking_notifier_chain_unregister(&pm_chain_head, nb);
 }
 EXPORT_SYMBOL_GPL(unregister_pm_notifier);
 在PM休眠或者唤醒进行到某个特定阶段时,PM就会使用下面这个函数向链上所有的内核模块发送一个EVENT
 int pm_notifier_call_chain(unsigned long val)
 {
  return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
   == NOTIFY_BAD) ? -EINVAL : 0;
 }
 我们看到就是在suspend_prepare中调用了pm_notifier_call_chain(PM_SUSPEND_PREPARE)
 我们以s5pc110平台为例,看看触发了那些事件
 在文件drivers/char/apm-emulation.c中定义了apm_suspend_notifier
 因此pm_notifier_call_chain会触发apm_suspend_notifier的相应事件,这里执行apm_suspend_notifier的PM_SUSPEND_PREPARE分支

 下面执行函数usermodehelper_disable(),这个函数在kernel/kmod.c中
 int usermodehelper_disable(void)
 {
  long retval;

  usermodehelper_disabled = 1;
  smp_mb();
  /*
   * From now on call_usermodehelper_exec() won't start any new
   * helpers, so it is sufficient if running_helpers turns out to
   * be zero at one point (it may be increased later, but that
   * doesn't matter).
   */
  retval = wait_event_timeout(running_helpers_waitq,
     atomic_read(&running_helpers) == 0,
     RUNNING_HELPERS_TIMEOUT);
  if (retval)
   return 0;

  usermodehelper_disabled = 0;
  return -EAGAIN;
 }
 这个函数中主要是调用等待事件wait_event_timeo

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值