• [转]WM/WINCE代码研读系列之Power Management(5)


    下面是pNewPowerState->EnterState的具体内容
    pNewPowerState->EnterState

    {
         PmSetSystemPowerState_I(GetStateString(),0 ,0, TRUE);
         {
              if (((!_tcsicmp(szStateName,_T("suspend"))) || (dwStateHint==POWER_STATE_OFF)) &&(fInternal==TRUE))
              {
                       //将用户关闭系统的消息写入周日志里面
                       PMSQM_Set(PMSQM_DATAID_POWER_USER_SHUTDOWNS,1);
               }
     
               PlatformSetSystemPowerState
               {
                      
                        PmUpdateSystemPowerStatesIfChanged
                        RegReadSystemPowerState
     
                        //将PBT_TRANSITION消息发送给所有注册了相应电源管理通知事件的驱动
                        pbb.Message = PBT_TRANSITION;
                        pbb.Flags = pNewSystemPowerState->dwFlags;
                        pbb.Length = _tcslen(pNewSystemPowerState->pszName) + 1;
                        _tcsncpy(pbb.SystemPowerState,pNewSystemPowerState->pszName, pbb.Length);
                        pbb.Length *= sizeof(pbb.SystemPowerState[0]);
                        GenerateNotifications((PPOWER_BROADCAST) &pbb);
     
                        //更新所有Classes的设备的电源状态
                        UpdateAllDeviceStates();
                        {
                                 //从gpDeviceLists中遍历各个Device interface classes
                                 for(pdl = gpDeviceLists; pdl != NULL; pdl = pdl->pNext) 
                                 {
                                       UpdateClassDeviceStates(pdl);
                                        
                                             pds = pdl->pList;    //pdl中再遍历各个Device
                                             while(!fDeviceRemoved && pds != NULL) 
                                             {
                                                   UpdateDeviceState(pds)
                                                   pdsNext = pds->pNext;
                                              }
                                        }
                                 }
                         }
     
                    //下面就SUSPEND和Resuming这两种特殊情况分别讨论


                   //1.Suspended
                   if((dwNewStateFlags &(POWER_STATE_SUSPEND|POWER_STATE_OFF|
                                 POWER_STATE_CRITICAL|POWER_STATE_RESET)) != 0)
                          fSuspendSystem = TRUE;
                   GwesPowerDown() //关掉GWES
     
                   //关闭除了idBlockDevices Class的设备以外的所有设备电源状态。因为这个时候还要访问注册表,写文件。所以与此相关的idBlockDevices 的电源状态还应暂时不变.
                   for(pdl = gpDeviceLists;pdl != NULL;pdl = pdl->pNext)
                   {
                           if(*pdl->pGuid != idBlockDevices)
                           UpdateClassDeviceStates(pdl);
                    }
     
                   //这里会调用IOCTL_HAL_PRESUSPEND,在进入Suspended之前给OEM一个机会去设置一些东西。微软建议OEM实现IOCTL_HAL_PRESUSPEND时清掉唤醒标示。并且强制来一次线程调度
                    KernelIoControl(IOCTL_HAL_PRESUSPEND,NULL,0,NULL,0, NULL); 
                    iCurrentPriority = CeGetThreadPriority(GetCurrentThread());
                    CeSetThreadPriority(GetCurrentThread(),giPreSuspendPriority);
                    Sleep(0);
                    CeSetThreadPriority(GetCurrentThread(),iCurrentPriority);
     
                    //如果[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power]下有L"PageOutAllModules"则
                    if(gfPageOutAllModules)
                              PageOutModule(GetCurrentProcess(),PAGE_OUT_ALL_DEPENDENT_DLL);
                   //这个用来找出哪个驱动错误的使用了pageable机制
     
                    FileSystemPowerFunction(FSNOTIFY_POWER_OFF);  //关闭文件系统
     
                  //关闭block device的电源
                   pdl = GetDeviceListFromClass(&idBlockDevices);
                   UpdateClassDeviceStates(pdl);
     
                  //下面是重启的情况
                   if((dwNewStateFlags & POWER_STATE_RESET) != 0)
                   {
                           //如果是冷启动则CleanReBoot
                           if(_tcscmp(pszName, _T("coldreboot")) == 0)
                                  SetCleanRebootFlag();
     
                          //调用OEM去实现的IOCTL_HAL_REBOOT,这个函数不应该返回。
                           KernelLibIoControl((HANDLE)KMOD_OAL,IOCTL_HAL_REBOOT,NULL,0,NULL,0,NULL);
                   }
     
                  //设置标志位并调PowerOffSystem,这个函数最终会调到OEMPowerOff()
                   gfSystemSuspended = TRUE;
                   PowerOffSystem();
     
                   Sleep(0); //CPU唤醒后强制来此系统调度
                   gfSystemSuspended = FALSE; // clear the suspend flag
                   gfPasswordOn = 0;


                   //2. Resuming
                 //打开block device的电源
                  pdl = GetDeviceListFromClass(&idBlockDevices);
                  UpdateClassDeviceStates(pdl);
     
                 //打开文件系统
                  FileSystemPowerFunction(FSNOTIFY_POWER_ON);
                  //打开除了idBlockDevices Class的设备以外的所有设备电源状态
                  for(pdl = gpDeviceLists; pdl != NULL; pdl = pdl->pNext)
                  {
                        if(*pdl->pGuid != idBlockDevices)
                               UpdateClassDeviceStates(pdl);
                  }

                  gpfnGwesPowerUp(fWantStartupScreen); //唤醒GWES
     
                 //将PBT_RESUME消息发送给所有注册了相应电源管理通知事件的驱动
                  pbb.Message = PBT_RESUME;
                  pbb.Flags = 0;
                  pbb.Length = 0;
                  pbb.SystemPowerState[0] = 0;
                  GenerateNotifications((PPOWER_BROADCAST) &pbb);


             }
         }
     
         m_LastNewState = GetState();//更新电源状态标志
        //激活UserActivity事件
         m_dwEventArray[PM_USER_ACTIVITY_EVENT] = m_pPwrStateMgr->GetUserActivityTimer()->hevActive;
        //重新校正BacklightTimeout,SuspendTimeout,UserIdleTimeout这三个超时器
         m_pPwrStateMgr->ReAdjustTimeOuts();
    }

  • 相关阅读:
    LeetCode 2006 差的绝对值为K的数对数目
    web关键字驱动
    selenium 原理
    sched linux调度 CFS
    VMware linux虚拟机如何固定IP(亲测)
    linux centos + nginx +多版本php安装 实战(使用docker)
    如何设置linux 时区(只需一条命令)
    centos 安装 mongodb 只需三步
    生成包含常用扩展的docker phpfpm镜像含 php5.6 php7.1 php7.2 的dokcerfile(亲测可用202237)
    MySQL数据文件被恶意删除后的恢复
  • 原文地址:https://www.cnblogs.com/answer/p/1956261.html
Copyright © 2020-2023  润新知