2  * Copyright (c) 1998-2020 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29 #define IOKIT_ENABLE_SHARED_PTR 
  31 #include <libkern/c++/OSKext.h> 
  32 #include <libkern/c++/OSMetaClass.h> 
  33 #include <libkern/OSAtomic.h> 
  34 #include <libkern/OSDebug.h> 
  35 #include <IOKit/IOWorkLoop.h> 
  36 #include <IOKit/IOCommandGate.h> 
  37 #include <IOKit/IOTimerEventSource.h> 
  38 #include <IOKit/IOPlatformExpert.h> 
  39 #include <IOKit/IOCPU.h> 
  40 #include <IOKit/IOPlatformActions.h> 
  41 #include <IOKit/IOKitDebug.h> 
  42 #include <IOKit/IOTimeStamp.h> 
  43 #include <IOKit/pwr_mgt/IOPMlog.h> 
  44 #include <IOKit/pwr_mgt/RootDomain.h> 
  45 #include <IOKit/pwr_mgt/IOPMPrivate.h> 
  46 #include <IOKit/IODeviceTreeSupport.h> 
  47 #include <IOKit/IOMessage.h> 
  48 #include <IOKit/IOReturn.h> 
  49 #include <IOKit/IONVRAM.h> 
  50 #include "RootDomainUserClient.h" 
  51 #include "IOKit/pwr_mgt/IOPowerConnection.h" 
  52 #include "IOPMPowerStateQueue.h" 
  53 #include <IOKit/IOCatalogue.h> 
  54 #include <IOKit/IOReportMacros.h> 
  55 #include <IOKit/IOLib.h> 
  56 #include <IOKit/IOKitKeys.h> 
  57 #include <IOKit/IOUserServer.h> 
  58 #include "IOKitKernelInternal.h" 
  60 #include <IOKit/IOHibernatePrivate.h> 
  61 #endif /* HIBERNATION */ 
  62 #include <console/video_console.h> 
  63 #include <sys/syslog.h> 
  64 #include <sys/sysctl.h> 
  65 #include <sys/vnode.h> 
  66 #include <sys/vnode_internal.h> 
  67 #include <sys/fcntl.h> 
  69 #include <pexpert/protos.h> 
  70 #include <AssertMacros.h> 
  73 #include "IOServicePrivate.h"   // _IOServiceInterestNotifier 
  74 #include "IOServicePMPrivate.h" 
  76 #include <libkern/zlib.h> 
  77 #include <os/cpp_util.h> 
  78 #include <libkern/c++/OSBoundedArrayRef.h> 
  81 #include <mach/shared_region.h> 
  82 #include <kern/clock.h> 
  85 #if defined(__i386__) || defined(__x86_64__) 
  87 #include "IOPMrootDomainInternal.h" 
  88 const char *processor_to_datastring(const char *prefix
, processor_t target_processor
); 
  92 #define kIOPMrootDomainClass    "IOPMrootDomain" 
  93 #define LOG_PREFIX              "PMRD: " 
  97     do { kprintf(LOG_PREFIX x); IOLog(x); } while (false) 
 100     do { kprintf(LOG_PREFIX x); } while (false) 
 102 #if DEVELOPMENT || DEBUG 
 103 #define DEBUG_LOG(x...) do { \ 
 104     if (kIOLogPMRootDomain & gIOKitDebug) \ 
 105     kprintf(LOG_PREFIX x); \ 
 106     os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \ 
 109 #define DEBUG_LOG(x...) 
 112 #define DLOG(x...)  do { \ 
 113     if (kIOLogPMRootDomain & gIOKitDebug) \ 
 114         kprintf(LOG_PREFIX x); \ 
 116         os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \ 
 119 #define DMSG(x...)  do { \ 
 120     if (kIOLogPMRootDomain & gIOKitDebug) { \ 
 121         kprintf(LOG_PREFIX x); \ 
 128 #define CHECK_THREAD_CONTEXT 
 129 #ifdef  CHECK_THREAD_CONTEXT 
 130 static IOWorkLoop 
* gIOPMWorkLoop 
= NULL
; 
 131 #define ASSERT_GATED()                                      \ 
 133     if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \ 
 134         panic("RootDomain: not inside PM gate");            \ 
 138 #define ASSERT_GATED() 
 139 #endif /* CHECK_THREAD_CONTEXT */ 
 141 #define CAP_LOSS(c)  \ 
 142         (((_pendingCapability & (c)) == 0) && \ 
 143          ((_currentCapability & (c)) != 0)) 
 145 #define CAP_GAIN(c)  \ 
 146         (((_currentCapability & (c)) == 0) && \ 
 147          ((_pendingCapability & (c)) != 0)) 
 149 #define CAP_CHANGE(c)    \ 
 150         (((_currentCapability ^ _pendingCapability) & (c)) != 0) 
 152 #define CAP_CURRENT(c)  \ 
 153         ((_currentCapability & (c)) != 0) 
 155 #define CAP_HIGHEST(c)  \ 
 156         ((_highestCapability & (c)) != 0) 
 158 #define CAP_PENDING(c)  \ 
 159         ((_pendingCapability & (c)) != 0) 
 161 // rdar://problem/9157444 
 162 #if defined(__i386__) || defined(__x86_64__) 
 163 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY   20 
 166 // Event types for IOPMPowerStateQueue::submitPowerEvent() 
 168         kPowerEventFeatureChanged 
= 1,             // 1 
 169         kPowerEventReceivedPowerNotification
,      // 2 
 170         kPowerEventSystemBootCompleted
,            // 3 
 171         kPowerEventSystemShutdown
,                 // 4 
 172         kPowerEventUserDisabledSleep
,              // 5 
 173         kPowerEventRegisterSystemCapabilityClient
, // 6 
 174         kPowerEventRegisterKernelCapabilityClient
, // 7 
 175         kPowerEventPolicyStimulus
,                 // 8 
 176         kPowerEventAssertionCreate
,                // 9 
 177         kPowerEventAssertionRelease
,               // 10 
 178         kPowerEventAssertionSetLevel
,              // 11 
 179         kPowerEventQueueSleepWakeUUID
,             // 12 
 180         kPowerEventPublishSleepWakeUUID
,           // 13 
 181         kPowerEventSetDisplayPowerOn
,              // 14 
 182         kPowerEventPublishWakeType
,                // 15 
 183         kPowerEventAOTEvaluate                     
// 16 
 186 // For evaluatePolicy() 
 187 // List of stimuli that affects the root domain policy. 
 189         kStimulusDisplayWranglerSleep
,      // 0 
 190         kStimulusDisplayWranglerWake
,       // 1 
 191         kStimulusAggressivenessChanged
,     // 2 
 192         kStimulusDemandSystemSleep
,         // 3 
 193         kStimulusAllowSystemSleepChanged
,   // 4 
 194         kStimulusDarkWakeActivityTickle
,    // 5 
 195         kStimulusDarkWakeEntry
,             // 6 
 196         kStimulusDarkWakeReentry
,           // 7 
 197         kStimulusDarkWakeEvaluate
,          // 8 
 198         kStimulusNoIdleSleepPreventers
,     // 9 
 199         kStimulusEnterUserActiveState
,      // 10 
 200         kStimulusLeaveUserActiveState       
// 11 
 203 // Internal power state change reasons 
 204 // Must be less than kIOPMSleepReasonClamshell=101 
 206         kCPSReasonNone 
= 0,                 // 0 
 209         kCPSReasonIdleSleepPrevent
,         // 3 
 210         kCPSReasonIdleSleepAllow
,           // 4 
 211         kCPSReasonPowerOverride
,            // 5 
 212         kCPSReasonPowerDownCancel
,          // 6 
 213         kCPSReasonAOTExit
,                  // 7 
 214         kCPSReasonAdjustPowerState
,         // 8 
 215         kCPSReasonDarkWakeCannotSleep
,      // 9 
 216         kCPSReasonIdleSleepEnabled
,         // 10 
 217         kCPSReasonEvaluatePolicy
,           // 11 
 218         kCPSReasonSustainFullWake
,          // 12 
 219         kCPSReasonPMInternals 
= (kIOPMSleepReasonClamshell 
- 1) 
 223 IOReturn 
OSKextSystemSleepOrWake( UInt32 
); 
 225 extern "C" ppnum_t      
pmap_find_phys(pmap_t pmap
, addr64_t va
); 
 226 extern "C" addr64_t     
kvtophys(vm_offset_t va
); 
 227 extern "C" boolean_t    
kdp_has_polled_corefile(); 
 229 static void idleSleepTimerExpired( thread_call_param_t
, thread_call_param_t 
); 
 230 static void notifySystemShutdown( IOService 
* root
, uint32_t messageType 
); 
 231 static void handleAggressivesFunction( thread_call_param_t
, thread_call_param_t 
); 
 232 static void pmEventTimeStamp(uint64_t *recordTS
); 
 233 static void powerButtonUpCallout( thread_call_param_t
, thread_call_param_t 
); 
 234 static void powerButtonDownCallout( thread_call_param_t
, thread_call_param_t 
); 
 235 static OSPtr
<const OSSymbol
> copyKextIdentifierWithAddress(vm_address_t address
); 
 237 static int  IOPMConvertSecondsToCalendar(clock_sec_t secs
, IOPMCalendarStruct 
* dt
); 
 238 static clock_sec_t 
IOPMConvertCalendarToSeconds(const IOPMCalendarStruct 
* dt
); 
 239 #define YMDTF       "%04d/%02d/%d %02d:%02d:%02d" 
 240 #define YMDT(cal)   ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second 
 242 // "IOPMSetSleepSupported"  callPlatformFunction name 
 243 static OSSharedPtr
<const OSSymbol
>         sleepSupportedPEFunction
; 
 244 static OSSharedPtr
<const OSSymbol
>         sleepMessagePEFunction
; 
 245 static OSSharedPtr
<const OSSymbol
>         gIOPMWakeTypeUserKey
; 
 247 static OSSharedPtr
<const OSSymbol
>         gIOPMPSExternalConnectedKey
; 
 248 static OSSharedPtr
<const OSSymbol
>         gIOPMPSExternalChargeCapableKey
; 
 249 static OSSharedPtr
<const OSSymbol
>         gIOPMPSBatteryInstalledKey
; 
 250 static OSSharedPtr
<const OSSymbol
>         gIOPMPSIsChargingKey
; 
 251 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAtWarnLevelKey
; 
 252 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAtCriticalLevelKey
; 
 253 static OSSharedPtr
<const OSSymbol
>         gIOPMPSCurrentCapacityKey
; 
 254 static OSSharedPtr
<const OSSymbol
>         gIOPMPSMaxCapacityKey
; 
 255 static OSSharedPtr
<const OSSymbol
>         gIOPMPSDesignCapacityKey
; 
 256 static OSSharedPtr
<const OSSymbol
>         gIOPMPSTimeRemainingKey
; 
 257 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAmperageKey
; 
 258 static OSSharedPtr
<const OSSymbol
>         gIOPMPSVoltageKey
; 
 259 static OSSharedPtr
<const OSSymbol
>         gIOPMPSCycleCountKey
; 
 260 static OSSharedPtr
<const OSSymbol
>         gIOPMPSMaxErrKey
; 
 261 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterInfoKey
; 
 262 static OSSharedPtr
<const OSSymbol
>         gIOPMPSLocationKey
; 
 263 static OSSharedPtr
<const OSSymbol
>         gIOPMPSErrorConditionKey
; 
 264 static OSSharedPtr
<const OSSymbol
>         gIOPMPSManufacturerKey
; 
 265 static OSSharedPtr
<const OSSymbol
>         gIOPMPSManufactureDateKey
; 
 266 static OSSharedPtr
<const OSSymbol
>         gIOPMPSModelKey
; 
 267 static OSSharedPtr
<const OSSymbol
>         gIOPMPSSerialKey
; 
 268 static OSSharedPtr
<const OSSymbol
>         gIOPMPSLegacyBatteryInfoKey
; 
 269 static OSSharedPtr
<const OSSymbol
>         gIOPMPSBatteryHealthKey
; 
 270 static OSSharedPtr
<const OSSymbol
>         gIOPMPSHealthConfidenceKey
; 
 271 static OSSharedPtr
<const OSSymbol
>         gIOPMPSCapacityEstimatedKey
; 
 272 static OSSharedPtr
<const OSSymbol
>         gIOPMPSBatteryChargeStatusKey
; 
 273 static OSSharedPtr
<const OSSymbol
>         gIOPMPSBatteryTemperatureKey
; 
 274 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsKey
; 
 275 static OSSharedPtr
<const OSSymbol
>         gIOPMPSChargerConfigurationKey
; 
 276 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsIDKey
; 
 277 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsWattsKey
; 
 278 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsRevisionKey
; 
 279 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsSerialNumberKey
; 
 280 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsFamilyKey
; 
 281 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsAmperageKey
; 
 282 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsDescriptionKey
; 
 283 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsPMUConfigurationKey
; 
 284 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsSourceIDKey
; 
 285 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsErrorFlagsKey
; 
 286 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsSharedSourceKey
; 
 287 static OSSharedPtr
<const OSSymbol
>         gIOPMPSAdapterDetailsCloakedKey
; 
 288 static OSSharedPtr
<const OSSymbol
>         gIOPMPSInvalidWakeSecondsKey
; 
 289 static OSSharedPtr
<const OSSymbol
>         gIOPMPSPostChargeWaitSecondsKey
; 
 290 static OSSharedPtr
<const OSSymbol
>         gIOPMPSPostDishargeWaitSecondsKey
; 
 292 #define kIOSleepSupportedKey        "IOSleepSupported" 
 293 #define kIOPMSystemCapabilitiesKey  "System Capabilities" 
 294 #define kIOPMSystemDefaultOverrideKey   "SystemPowerProfileOverrideDict" 
 296 #define kIORequestWranglerIdleKey   "IORequestIdle" 
 297 #define kDefaultWranglerIdlePeriod  1000 // in milliseconds 
 299 #define kIOSleepWakeFailureString   "SleepWakeFailureString" 
 300 #define kIOEFIBootRomFailureKey     "wake-failure" 
 301 #define kIOSleepWakeFailurePanic    "SleepWakeFailurePanic" 
 303 #define kRD_AllPowerSources (kIOPMSupportedOnAC \ 
 304                            | kIOPMSupportedOnBatt \ 
 305                            | kIOPMSupportedOnUPS) 
 307 #define kLocalEvalClamshellCommand  (1 << 15) 
 308 #define kIdleSleepRetryInterval     (3 * 60) 
 310 #define DISPLAY_WRANGLER_PRESENT    (!NO_KERNEL_HID) 
 313         kWranglerPowerStateMin   
= 0, 
 314         kWranglerPowerStateSleep 
= 2, 
 315         kWranglerPowerStateDim   
= 3, 
 316         kWranglerPowerStateMax   
= 4 
 329 getPowerStateString( uint32_t state 
) 
 331 #define POWER_STATE(x) {(uint32_t) x, #x} 
 333         static const IONamedValue powerStates
[] = { 
 334                 POWER_STATE( OFF_STATE 
), 
 335                 POWER_STATE( RESTART_STATE 
), 
 336                 POWER_STATE( SLEEP_STATE 
), 
 337                 POWER_STATE( AOT_STATE 
), 
 338                 POWER_STATE( ON_STATE 
), 
 341         return IOFindNameForValue(state
, powerStates
); 
 344 #define ON_POWER        kIOPMPowerOn 
 345 #define RESTART_POWER   kIOPMRestart 
 346 #define SLEEP_POWER     kIOPMAuxPowerOn 
 348 static IOPMPowerState
 
 349     ourPowerStates
[NUM_POWER_STATES
] = 
 352             .capabilityFlags        
= 0, 
 353             .outputPowerCharacter   
= 0, 
 354             .inputPowerRequirement  
= 0 }, 
 356             .capabilityFlags        
= kIOPMRestartCapability
, 
 357             .outputPowerCharacter   
= kIOPMRestart
, 
 358             .inputPowerRequirement  
= RESTART_POWER 
}, 
 360             .capabilityFlags        
= kIOPMSleepCapability
, 
 361             .outputPowerCharacter   
= kIOPMSleep
, 
 362             .inputPowerRequirement  
= SLEEP_POWER 
}, 
 364             .capabilityFlags        
= kIOPMAOTCapability
, 
 365             .outputPowerCharacter   
= kIOPMAOTPower
, 
 366             .inputPowerRequirement  
= ON_POWER 
}, 
 368             .capabilityFlags        
= kIOPMPowerOn
, 
 369             .outputPowerCharacter   
= kIOPMPowerOn
, 
 370             .inputPowerRequirement  
= ON_POWER 
}, 
 373 #define kIOPMRootDomainWakeTypeSleepService     "SleepService" 
 374 #define kIOPMRootDomainWakeTypeMaintenance      "Maintenance" 
 375 #define kIOPMRootDomainWakeTypeSleepTimer       "SleepTimer" 
 376 #define kIOPMrootDomainWakeTypeLowBattery       "LowBattery" 
 377 #define kIOPMRootDomainWakeTypeUser             "User" 
 378 #define kIOPMRootDomainWakeTypeAlarm            "Alarm" 
 379 #define kIOPMRootDomainWakeTypeNetwork          "Network" 
 380 #define kIOPMRootDomainWakeTypeHIDActivity      "HID Activity" 
 381 #define kIOPMRootDomainWakeTypeNotification     "Notification" 
 382 #define kIOPMRootDomainWakeTypeHibernateError   "HibernateError" 
 384 // Special interest that entitles the interested client from receiving 
 385 // all system messages. Only used by powerd. 
 387 #define kIOPMSystemCapabilityInterest       "IOPMSystemCapabilityInterest" 
 389 // Entitlement required for root domain clients 
 390 #define kRootDomainEntitlementSetProperty   "com.apple.private.iokit.rootdomain-set-property" 
 392 #define WAKEEVENT_LOCK()        IOLockLock(wakeEventLock) 
 393 #define WAKEEVENT_UNLOCK()      IOLockUnlock(wakeEventLock) 
 398 #define AGGRESSIVES_LOCK()      IOLockLock(featuresDictLock) 
 399 #define AGGRESSIVES_UNLOCK()    IOLockUnlock(featuresDictLock) 
 401 #define kAggressivesMinValue    1 
 404 getAggressivenessTypeString( uint32_t type 
) 
 406 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x} 
 408         static const IONamedValue aggressivenessTypes
[] = { 
 409                 AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness 
), 
 410                 AGGRESSIVENESS_TYPE( kPMMinutesToDim 
), 
 411                 AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown 
), 
 412                 AGGRESSIVENESS_TYPE( kPMMinutesToSleep 
), 
 413                 AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings 
), 
 414                 AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed 
), 
 415                 AGGRESSIVENESS_TYPE( kPMPowerSource
), 
 416                 AGGRESSIVENESS_TYPE( kPMMotionSensor 
), 
 417                 AGGRESSIVENESS_TYPE( kPMLastAggressivenessType 
), 
 420         return IOFindNameForValue(type
, aggressivenessTypes
); 
 424         kAggressivesStateBusy           
= 0x01, 
 425         kAggressivesStateQuickSpindown  
= 0x02 
 428 struct AggressivesRecord 
{ 
 434 struct AggressivesRequest 
{ 
 439                 OSSharedPtr
<IOService
> service
; 
 440                 AggressivesRecord      record
; 
 445         kAggressivesRequestTypeService  
= 1, 
 446         kAggressivesRequestTypeRecord
 
 450         kAggressivesOptionSynchronous          
= 0x00000001, 
 451         kAggressivesOptionQuickSpindownEnable  
= 0x00000100, 
 452         kAggressivesOptionQuickSpindownDisable 
= 0x00000200, 
 453         kAggressivesOptionQuickSpindownMask    
= 0x00000300 
 457         kAggressivesRecordFlagModified         
= 0x00000001, 
 458         kAggressivesRecordFlagMinValue         
= 0x00000002 
 461 // System Sleep Preventers 
 464         kPMUserDisabledAllSleep 
= 1, 
 465         kPMSystemRestartBootingInProgress
, 
 466         kPMConfigPreventSystemSleep
, 
 467         kPMChildPreventSystemSleep
, 
 473 getSystemSleepPreventerString( uint32_t preventer 
) 
 475 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x} 
 476         static const IONamedValue systemSleepPreventers
[] = { 
 477                 SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep 
), 
 478                 SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress 
), 
 479                 SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep 
), 
 480                 SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep 
), 
 481                 SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion 
), 
 482                 SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported 
), 
 485         return IOFindNameForValue(preventer
, systemSleepPreventers
); 
 490         kDarkWakeFlagPromotionNone       
= 0x0000, 
 491         kDarkWakeFlagPromotionEarly      
= 0x0001, // promote before gfx clamp 
 492         kDarkWakeFlagPromotionLate       
= 0x0002, // promote after gfx clamp 
 493         kDarkWakeFlagPromotionMask       
= 0x0003, 
 494         kDarkWakeFlagAlarmIsDark         
= 0x0100, 
 495         kDarkWakeFlagAudioNotSuppressed  
= 0x0200, 
 496         kDarkWakeFlagUserWakeWorkaround  
= 0x1000 
 500 // The workaround for 9157444 is enabled at compile time using the 
 501 // DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY macro and is not represented below. 
 503         kClamshell_WAR_38378787 
= 0x00000001, 
 504         kClamshell_WAR_47715679 
= 0x00000002, 
 505         kClamshell_WAR_58009435 
= 0x00000004 
 508 // acceptSystemWakeEvents() 
 510         kAcceptSystemWakeEvents_Disable 
= 0, 
 511         kAcceptSystemWakeEvents_Enable
, 
 512         kAcceptSystemWakeEvents_Reenable
 
 515 static IOPMrootDomain 
* gRootDomain
; 
 516 static IORootParent 
*   gPatriarch
; 
 517 static IONotifier 
*     gSysPowerDownNotifier 
= NULL
; 
 518 static UInt32           gSleepOrShutdownPending 
= 0; 
 519 static UInt32           gWillShutdown 
= 0; 
 520 static UInt32           gPagingOff 
= 0; 
 521 static UInt32           gSleepWakeUUIDIsSet 
= false; 
 522 static uint32_t         gAggressivesState 
= 0; 
 523 uint32_t                gHaltTimeMaxLog
; 
 524 uint32_t                gHaltTimeMaxPanic
; 
 525 IOLock 
*                gHaltLogLock
; 
 526 static char *           gHaltLog
; 
 527 enum                  { kHaltLogSize 
= 2048 }; 
 528 static size_t           gHaltLogPos
; 
 529 static uint64_t         gHaltStartTime
; 
 530 static char             gKextNameBuf
[64]; 
 531 static size_t           gKextNamePos
; 
 532 static bool             gKextNameEnd
; 
 534 uuid_string_t bootsessionuuid_string
; 
 536 #if defined(XNU_TARGET_OS_OSX) 
 537 #if DISPLAY_WRANGLER_PRESENT 
 538 static uint32_t         gDarkWakeFlags 
= kDarkWakeFlagPromotionNone
; 
 540 // Enable temporary full wake promotion workarounds 
 541 static uint32_t         gDarkWakeFlags 
= kDarkWakeFlagUserWakeWorkaround
; 
 543 // Enable full wake promotion workarounds 
 544 static uint32_t         gDarkWakeFlags 
= kDarkWakeFlagUserWakeWorkaround
; 
 546 #else  /* !defined(XNU_TARGET_OS_OSX) */ 
 547 static uint32_t         gDarkWakeFlags 
= kDarkWakeFlagPromotionEarly
; 
 548 #endif /* !defined(XNU_TARGET_OS_OSX) */ 
 550 static uint32_t         gNoIdleFlag 
= 0; 
 551 static uint32_t         gSwdPanic 
= 1; 
 552 static uint32_t         gSwdSleepTimeout 
= 0; 
 553 static uint32_t         gSwdWakeTimeout 
= 0; 
 554 static uint32_t         gSwdSleepWakeTimeout 
= 0; 
 555 static PMStatsStruct    gPMStats
; 
 556 #if DEVELOPMENT || DEBUG 
 557 static uint32_t swd_panic_phase
; 
 560 static uint32_t         gClamshellFlags 
= 0 
 561 #if defined(__i386__) || defined(__x86_64__) 
 562     | kClamshell_WAR_58009435
 
 568 #if defined(__arm64__) 
 570 defaultSleepPolicyHandler(void *ctx
, const IOPMSystemSleepPolicyVariables 
*vars
, IOPMSystemSleepParameters 
*params
) 
 572         uint32_t sleepType 
= kIOPMSleepTypeDeepIdle
; 
 574         assert(vars
->signature 
== kIOPMSystemSleepPolicySignature
); 
 575         assert(vars
->version 
== kIOPMSystemSleepPolicyVersion
); 
 577         // Hibernation enabled and either user forced hibernate or low battery sleep 
 578         if ((vars
->hibernateMode 
& kIOHibernateModeOn
) && 
 579             (((vars
->hibernateMode 
& kIOHibernateModeSleep
) == 0) || 
 580             (vars
->sleepFactors 
& kIOPMSleepFactorBatteryLow
))) { 
 581                 sleepType 
= kIOPMSleepTypeHibernate
; 
 583         params
->version 
= kIOPMSystemSleepParametersVersion
; 
 584         params
->sleepType 
= sleepType
; 
 585         return kIOReturnSuccess
; 
 587 static IOPMSystemSleepPolicyHandler     gSleepPolicyHandler 
= &defaultSleepPolicyHandler
; 
 588 #else /* defined(__arm64__) */ 
 589 static IOPMSystemSleepPolicyHandler     gSleepPolicyHandler 
= NULL
; 
 590 #endif /* defined(__arm64__) */ 
 592 static IOPMSystemSleepPolicyVariables 
* gSleepPolicyVars 
= NULL
; 
 593 static void *                           gSleepPolicyTarget
; 
 596 struct timeval gIOLastSleepTime
; 
 597 struct timeval gIOLastWakeTime
; 
 598 AbsoluteTime gIOLastWakeAbsTime
; 
 599 AbsoluteTime gIOLastSleepAbsTime
; 
 601 struct timeval gIOLastUserSleepTime
; 
 603 static char gWakeReasonString
[128]; 
 604 static char gBootReasonString
[80]; 
 605 static char gShutdownReasonString
[80]; 
 606 static bool gWakeReasonSysctlRegistered 
= false; 
 607 static bool gBootReasonSysctlRegistered 
= false; 
 608 static bool gShutdownReasonSysctlRegistered 
= false; 
 609 static bool gWillShutdownSysctlRegistered 
= false; 
 610 static AbsoluteTime gUserActiveAbsTime
; 
 611 static AbsoluteTime gUserInactiveAbsTime
; 
 613 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION) 
 614 static bool gSpinDumpBufferFull 
= false; 
 618 vm_offset_t swd_zs_zmem
; 
 619 //size_t swd_zs_zsize; 
 620 size_t swd_zs_zoffset
; 
 621 #if defined(__i386__) || defined(__x86_64__) 
 622 IOCPU 
*currentShutdownTarget 
= NULL
; 
 625 static unsigned int     gPMHaltBusyCount
; 
 626 static unsigned int     gPMHaltIdleCount
; 
 627 static int              gPMHaltDepth
; 
 628 static uint32_t         gPMHaltMessageType
; 
 629 static IOLock 
*         gPMHaltLock  
= NULL
; 
 630 static OSSharedPtr
<OSArray
>        gPMHaltArray
; 
 631 static OSSharedPtr
<const OSSymbol
> gPMHaltClientAcknowledgeKey
; 
 632 static bool             gPMQuiesced
; 
 634 // Constants used as arguments to IOPMrootDomain::informCPUStateChange 
 635 #define kCPUUnknownIndex    9999999 
 642 OSSharedPtr
<const OSSymbol
> gIOPMStatsResponseTimedOut
; 
 643 OSSharedPtr
<const OSSymbol
> gIOPMStatsResponseCancel
; 
 644 OSSharedPtr
<const OSSymbol
> gIOPMStatsResponseSlow
; 
 645 OSSharedPtr
<const OSSymbol
> gIOPMStatsResponsePrompt
; 
 646 OSSharedPtr
<const OSSymbol
> gIOPMStatsDriverPSChangeSlow
; 
 648 #define kBadPMFeatureID     0 
 652  * Opaque handle passed to clients of registerPMSettingController() 
 654 class PMSettingHandle 
: public OSObject
 
 656         OSDeclareFinalStructors( PMSettingHandle 
); 
 657         friend class PMSettingObject
; 
 660         PMSettingObject 
*pmso
; 
 661         void free(void) APPLE_KEXT_OVERRIDE
; 
 666  * Internal object to track each PM setting controller 
 668 class PMSettingObject 
: public OSObject
 
 670         OSDeclareFinalStructors( PMSettingObject 
); 
 671         friend class IOPMrootDomain
; 
 674         queue_head_t                    calloutQueue
; 
 676         IOPMrootDomain                  
*parent
; 
 677         PMSettingHandle                 
*pmsh
; 
 678         IOPMSettingControllerCallback   func
; 
 681         uint32_t                        *publishedFeatureID
; 
 682         uint32_t                        settingCount
; 
 685         void free(void) APPLE_KEXT_OVERRIDE
; 
 688         static PMSettingObject 
*pmSettingObject( 
 689                 IOPMrootDomain                  
*parent_arg
, 
 690                 IOPMSettingControllerCallback   handler_arg
, 
 691                 OSObject                        
*target_arg
, 
 692                 uintptr_t                       refcon_arg
, 
 693                 uint32_t                        supportedPowerSources
, 
 694                 const OSSymbol                  
*settings
[], 
 695                 OSObject                        
**handle_obj
); 
 697         IOReturn 
dispatchPMSetting(const OSSymbol 
*type
, OSObject 
*object
); 
 698         void clientHandleFreed(void); 
 701 struct PMSettingCallEntry 
{ 
 706 #define PMSETTING_LOCK()    IOLockLock(settingsCtrlLock) 
 707 #define PMSETTING_UNLOCK()  IOLockUnlock(settingsCtrlLock) 
 708 #define PMSETTING_WAIT(p)   IOLockSleep(settingsCtrlLock, p, THREAD_UNINT) 
 709 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true) 
 713  * Internal helper object for logging trace points to RTC 
 714  * IOPMrootDomain and only IOPMrootDomain should instantiate 
 715  * exactly one of these. 
 718 typedef void (*IOPMTracePointHandler
)( 
 719         void * target
, uint32_t code
, uint32_t data 
); 
 721 class PMTraceWorker 
: public OSObject
 
 723         OSDeclareDefaultStructors(PMTraceWorker
); 
 725         typedef enum { kPowerChangeStart
, kPowerChangeCompleted 
} change_t
; 
 727         static OSPtr
<PMTraceWorker
> tracer( IOPMrootDomain 
* ); 
 728         void                        tracePCIPowerChange(change_t
, IOService 
*, uint32_t, uint32_t); 
 729         void                        tracePoint(uint8_t phase
); 
 730         void                        traceDetail(uint32_t detail
); 
 731         void                        traceComponentWakeProgress(uint32_t component
, uint32_t data
); 
 732         int                         recordTopLevelPCIDevice(IOService 
*); 
 733         void                        RTC_TRACE(void); 
 734         virtual bool                serialize(OSSerialize 
*s
) const APPLE_KEXT_OVERRIDE
; 
 736         IOPMTracePointHandler       tracePointHandler
; 
 737         void *                      tracePointTarget
; 
 738         uint64_t                    getPMStatusCode(); 
 739         uint8_t                     getTracePhase(); 
 740         uint32_t                    getTraceData(); 
 742         IOPMrootDomain              
*owner
; 
 743         IOLock                      
*pmTraceWorkerLock
; 
 744         OSSharedPtr
<OSArray
>         pciDeviceBitMappings
; 
 746         uint8_t                     addedToRegistry
; 
 748         uint32_t                    traceData32
; 
 749         uint8_t                     loginWindowData
; 
 750         uint8_t                     coreDisplayData
; 
 751         uint8_t                     coreGraphicsData
; 
 755  * PMAssertionsTracker 
 756  * Tracks kernel and user space PM assertions 
 758 class PMAssertionsTracker 
: public OSObject
 
 760         OSDeclareFinalStructors(PMAssertionsTracker
); 
 762         static PMAssertionsTracker  
*pmAssertionsTracker( IOPMrootDomain 
* ); 
 764         IOReturn                    
createAssertion(IOPMDriverAssertionType
, IOPMDriverAssertionLevel
, IOService 
*, const char *, IOPMDriverAssertionID 
*); 
 765         IOReturn                    
releaseAssertion(IOPMDriverAssertionID
); 
 766         IOReturn                    
setAssertionLevel(IOPMDriverAssertionID
, IOPMDriverAssertionLevel
); 
 767         IOReturn                    
setUserAssertionLevels(IOPMDriverAssertionType
); 
 769         OSSharedPtr
<OSArray
>        copyAssertionsArray(void); 
 770         IOPMDriverAssertionType     
getActivatedAssertions(void); 
 771         IOPMDriverAssertionLevel    
getAssertionLevel(IOPMDriverAssertionType
); 
 773         IOReturn                    
handleCreateAssertion(OSData 
*); 
 774         IOReturn                    
handleReleaseAssertion(IOPMDriverAssertionID
); 
 775         IOReturn                    
handleSetAssertionLevel(IOPMDriverAssertionID
, IOPMDriverAssertionLevel
); 
 776         IOReturn                    
handleSetUserAssertionLevels(void * arg0
); 
 777         void                        publishProperties(void); 
 778         void                        reportCPUBitAccounting(void); 
 782          * this should be treated as POD, as it's byte-copied around 
 783          * and we cannot rely on d'tor firing at the right time 
 786                 IOPMDriverAssertionID       id
; 
 787                 IOPMDriverAssertionType     assertionBits
; 
 788                 uint64_t                    createdTime
; 
 789                 uint64_t                    modifiedTime
; 
 790                 const OSSymbol              
*ownerString
; 
 791                 IOService                   
*ownerService
; 
 792                 uint64_t                    registryEntryID
; 
 793                 IOPMDriverAssertionLevel    level
; 
 794                 uint64_t                    assertCPUStartTime
; 
 795                 uint64_t                    assertCPUDuration
; 
 798         uint32_t                    tabulateProducerCount
; 
 799         uint32_t                    tabulateConsumerCount
; 
 801         uint64_t                    maxAssertCPUDuration
; 
 802         uint64_t                    maxAssertCPUEntryId
; 
 804         PMAssertStruct              
*detailsForID(IOPMDriverAssertionID
, int *); 
 806         void                        updateCPUBitAccounting(PMAssertStruct 
* assertStruct
); 
 808         IOPMrootDomain              
*owner
; 
 809         OSSharedPtr
<OSArray
>        assertionsArray
; 
 810         IOLock                      
*assertionsArrayLock
; 
 811         IOPMDriverAssertionID       issuingUniqueID 
__attribute__((aligned(8)));/* aligned for atomic access */ 
 812         IOPMDriverAssertionType     assertionsKernel
; 
 813         IOPMDriverAssertionType     assertionsUser
; 
 814         IOPMDriverAssertionType     assertionsCombined
; 
 817 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker
, OSObject
); 
 821  * Internal helper object for Shutdown/Restart notifications. 
 823 #define kPMHaltMaxWorkers   8 
 824 #define kPMHaltTimeoutMS    100 
 826 class PMHaltWorker 
: public OSObject
 
 828         OSDeclareFinalStructors( PMHaltWorker 
); 
 831         IOService 
*  service
;// service being worked on 
 832         AbsoluteTime startTime
; // time when work started 
 833         int          depth
;  // work on nubs at this PM-tree depth 
 834         int          visits
; // number of nodes visited (debug) 
 836         bool         timeout
;// service took too long 
 838         static  PMHaltWorker 
* worker( void ); 
 839         static  void main( void * arg
, wait_result_t waitResult 
); 
 840         static  void work( PMHaltWorker 
* me 
); 
 841         static  void checkTimeout( PMHaltWorker 
* me
, AbsoluteTime 
* now 
); 
 842         virtual void free( void ) APPLE_KEXT_OVERRIDE
; 
 845 OSDefineMetaClassAndFinalStructors( PMHaltWorker
, OSObject 
) 
 848 #define super IOService 
 849 OSDefineMetaClassAndFinalStructors(IOPMrootDomain
, IOService
) 
 852 IOPMRootDomainGetWillShutdown(void) 
 854         return gWillShutdown 
!= 0; 
 858 IOPMRootDomainWillShutdown(void) 
 860         if (OSCompareAndSwap(0, 1, &gWillShutdown
)) { 
 861                 IOService::willShutdown(); 
 862                 for (int i 
= 0; i 
< 100; i
++) { 
 863                         if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending
)) { 
 871 extern "C" IONotifier 
* 
 872 registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
) 
 874         return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref 
).detach(); 
 877 extern "C" IONotifier 
* 
 878 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
) 
 880         return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref 
).detach(); 
 884 acknowledgeSleepWakeNotification(void * PMrefcon
) 
 886         return gRootDomain
->allowPowerChange((unsigned long)PMrefcon 
); 
 890 vetoSleepWakeNotification(void * PMrefcon
) 
 892         return gRootDomain
->cancelPowerChange((unsigned long)PMrefcon 
); 
 896 rootDomainRestart( void ) 
 898         return gRootDomain
->restartSystem(); 
 902 rootDomainShutdown( void ) 
 904         return gRootDomain
->shutdownSystem(); 
 908 halt_log_putc(char c
) 
 910         if (gHaltLogPos 
>= (kHaltLogSize 
- 2)) { 
 913         gHaltLog
[gHaltLogPos
++] = c
; 
 917 _doprnt_log(const char     *fmt
, 
 923 halt_log(const char *fmt
, ...) 
 927         va_start(listp
, fmt
); 
 928         _doprnt_log(fmt
, &listp
, &halt_log_putc
, 16); 
 935 halt_log_enter(const char * what
, const void * pc
, uint64_t time
) 
 937         uint64_t nano
, millis
; 
 942         absolutetime_to_nanoseconds(time
, &nano
); 
 943         millis 
= nano 
/ NSEC_PER_MSEC
; 
 948         IOLockLock(gHaltLogLock
); 
 950                 halt_log("%s: %qd ms @ 0x%lx, ", what
, millis
, VM_KERNEL_UNSLIDE(pc
)); 
 951                 OSKext::printKextsInBacktrace((vm_offset_t 
*) &pc
, 1, &halt_log
, 
 952                     OSKext::kPrintKextsLock 
| OSKext::kPrintKextsUnslide 
| OSKext::kPrintKextsTerse
); 
 954                 halt_log("%s: %qd ms\n", what
, millis
); 
 957         gHaltLog
[gHaltLogPos
] = 0; 
 958         IOLockUnlock(gHaltLogLock
); 
 961 extern  uint32_t                           gFSState
; 
 964 IOSystemShutdownNotification(int stage
) 
 968         if (kIOSystemShutdownNotificationStageRootUnmount 
== stage
) { 
 969 #if defined(XNU_TARGET_OS_OSX) 
 970                 uint64_t nano
, millis
; 
 971                 startTime 
= mach_absolute_time(); 
 972                 IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC
); 
 973                 absolutetime_to_nanoseconds(mach_absolute_time() - startTime
, &nano
); 
 974                 millis 
= nano 
/ NSEC_PER_MSEC
; 
 975                 if (gHaltTimeMaxLog 
&& (millis 
>= gHaltTimeMaxLog
)) { 
 976                         printf("waitQuiet() for unmount %qd ms\n", millis
); 
 978 #endif /* defined(XNU_TARGET_OS_OSX) */ 
 982         if (kIOSystemShutdownNotificationTerminateDEXTs 
== stage
) { 
 983                 uint64_t nano
, millis
; 
 984                 startTime 
= mach_absolute_time(); 
 985                 IOServicePH::systemHalt(); 
 986                 absolutetime_to_nanoseconds(mach_absolute_time() - startTime
, &nano
); 
 987                 millis 
= nano 
/ NSEC_PER_MSEC
; 
 988                 if (true || (gHaltTimeMaxLog 
&& (millis 
>= gHaltTimeMaxLog
))) { 
 989                         printf("IOServicePH::systemHalt took %qd ms\n", millis
); 
 994         assert(kIOSystemShutdownNotificationStageProcessExit 
== stage
); 
 996         IOLockLock(gHaltLogLock
); 
 998                 gHaltLog 
= IONew(char, kHaltLogSize
); 
 999                 gHaltStartTime 
= mach_absolute_time(); 
1001                         halt_log_putc('\n'); 
1004         IOLockUnlock(gHaltLogLock
); 
1006         startTime 
= mach_absolute_time(); 
1007         IOPMRootDomainWillShutdown(); 
1008         halt_log_enter("IOPMRootDomainWillShutdown", NULL
, mach_absolute_time() - startTime
); 
1010         startTime 
= mach_absolute_time(); 
1011         IOHibernateSystemPostWake(true); 
1012         halt_log_enter("IOHibernateSystemPostWake", NULL
, mach_absolute_time() - startTime
); 
1014         if (OSCompareAndSwap(0, 1, &gPagingOff
)) { 
1015                 gRootDomain
->handlePlatformHaltRestart(kPEPagingOff
); 
1019 extern "C" int sync_internal(void); 
1022  *  A device is always in the highest power state which satisfies its driver, 
1023  *  its policy-maker, and any power children it has, but within the constraint 
1024  *  of the power state provided by its parent.  The driver expresses its desire by 
1025  *  calling changePowerStateTo(), the policy-maker expresses its desire by calling 
1026  *  changePowerStateToPriv(), and the children express their desires by calling 
1027  *  requestPowerDomainState(). 
1029  *  The Root Power Domain owns the policy for idle and demand sleep for the system. 
1030  *  It is a power-managed IOService just like the others in the system. 
1031  *  It implements several power states which map to what we see as Sleep and On. 
1033  *  The sleep policy is as follows: 
1034  *  1. Sleep is prevented if the case is open so that nobody will think the machine 
1035  *  is off and plug/unplug cards. 
1036  *  2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero. 
1037  *  3. System cannot Sleep if some object in the tree is in a power state marked 
1038  *  kIOPMPreventSystemSleep. 
1040  *  These three conditions are enforced using the "driver clamp" by calling 
1041  *  changePowerStateTo(). For example, if the case is opened, 
1042  *  changePowerStateTo(ON_STATE) is called to hold the system on regardless 
1043  *  of the desires of the children of the root or the state of the other clamp. 
1045  *  Demand Sleep is initiated by pressing the front panel power button, closing 
1046  *  the clamshell, or selecting the menu item. In this case the root's parent 
1047  *  actually initiates the power state change so that the root domain has no 
1048  *  choice and does not give applications the opportunity to veto the change. 
1050  *  Idle Sleep occurs if no objects in the tree are in a state marked 
1051  *  kIOPMPreventIdleSleep.  When this is true, the root's children are not holding 
1052  *  the root on, so it sets the "policy-maker clamp" by calling 
1053  *  changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires. 
1054  *  This timer is set for the difference between the sleep timeout slider and the 
1055  *  display dim timeout slider. When the timer expires, it releases its clamp and 
1056  *  now nothing is holding it awake, so it falls asleep. 
1058  *  Demand sleep is prevented when the system is booting.  When preferences are 
1059  *  transmitted by the loginwindow at the end of boot, a flag is cleared, 
1060  *  and this allows subsequent Demand Sleep. 
1063 //****************************************************************************** 
1066 IOPMrootDomain::construct( void ) 
1068         IOPMrootDomain  
*root
; 
1070         root 
= new IOPMrootDomain
; 
1078 //****************************************************************************** 
1079 // updateConsoleUsersCallout 
1081 //****************************************************************************** 
1084 updateConsoleUsersCallout(thread_call_param_t p0
, thread_call_param_t p1
) 
1086         IOPMrootDomain 
* rootDomain 
= (IOPMrootDomain 
*) p0
; 
1087         rootDomain
->updateConsoleUsers(); 
1091 IOPMrootDomain::updateConsoleUsers(void) 
1093         IOService::updateConsoleUsers(NULL
, kIOMessageSystemHasPoweredOn
); 
1094         if (tasksSuspended
) { 
1095                 tasksSuspended 
= FALSE
; 
1096                 updateTasksSuspend(); 
1101 IOPMrootDomain::updateTasksSuspend(void) 
1105         newSuspend 
= (tasksSuspended 
|| _aotTasksSuspended
); 
1106         if (newSuspend 
== tasksSuspendState
) { 
1109         tasksSuspendState 
= newSuspend
; 
1110         tasks_system_suspend(newSuspend
); 
1113 //****************************************************************************** 
1116 disk_sync_callout( thread_call_param_t p0
, thread_call_param_t p1 
) 
1118         IOPMrootDomain 
* rootDomain 
= (IOPMrootDomain 
*) p0
; 
1119         uint32_t    notifyRef  
= (uint32_t)(uintptr_t) p1
; 
1120         uint32_t    powerState 
= rootDomain
->getPowerState(); 
1122         DLOG("disk_sync_callout ps=%u\n", powerState
); 
1124         if (ON_STATE 
== powerState
) { 
1128                 // Block sleep until trim issued on previous wake path is completed. 
1129                 IOHibernateSystemPostWake(true); 
1134                 IOHibernateSystemPostWake(false); 
1136                 rootDomain
->sleepWakeDebugSaveSpinDumpFile(); 
1140         rootDomain
->allowPowerChange(notifyRef
); 
1141         DLOG("disk_sync_callout finish\n"); 
1144 //****************************************************************************** 
1146 computeDeltaTimeMS( const AbsoluteTime 
* startTime
, AbsoluteTime 
* elapsedTime 
) 
1148         AbsoluteTime    endTime
; 
1151         clock_get_uptime(&endTime
); 
1152         if (CMP_ABSOLUTETIME(&endTime
, startTime
) <= 0) { 
1155                 SUB_ABSOLUTETIME(&endTime
, startTime
); 
1156                 absolutetime_to_nanoseconds(endTime
, &nano
); 
1157                 *elapsedTime 
= endTime
; 
1160         return (UInt32
)(nano 
/ NSEC_PER_MSEC
); 
1163 //****************************************************************************** 
1166 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
 
1168         struct timeval 
*swt 
= (struct timeval 
*)arg1
; 
1169         struct proc 
*p 
= req
->p
; 
1171         if (p 
== kernproc
) { 
1172                 return sysctl_io_opaque(req
, swt
, sizeof(*swt
), NULL
); 
1173         } else if (proc_is64bit(p
)) { 
1174                 struct user64_timeval t 
= {}; 
1175                 t
.tv_sec 
= swt
->tv_sec
; 
1176                 t
.tv_usec 
= swt
->tv_usec
; 
1177                 return sysctl_io_opaque(req
, &t
, sizeof(t
), NULL
); 
1179                 struct user32_timeval t 
= {}; 
1180                 t
.tv_sec 
= (typeof(t
.tv_sec
))swt
->tv_sec
; 
1181                 t
.tv_usec 
= swt
->tv_usec
; 
1182                 return sysctl_io_opaque(req
, &t
, sizeof(t
), NULL
); 
1186 static SYSCTL_PROC(_kern
, OID_AUTO
, sleeptime
, 
1187     CTLTYPE_STRUCT 
| CTLFLAG_RD 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1188     &gIOLastUserSleepTime
, 0, sysctl_sleepwaketime
, "S,timeval", ""); 
1190 static SYSCTL_PROC(_kern
, OID_AUTO
, waketime
, 
1191     CTLTYPE_STRUCT 
| CTLFLAG_RD 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1192     &gIOLastWakeTime
, 0, sysctl_sleepwaketime
, "S,timeval", ""); 
1194 SYSCTL_QUAD(_kern
, OID_AUTO
, wake_abs_time
, CTLFLAG_RD 
| CTLFLAG_LOCKED
, &gIOLastWakeAbsTime
, ""); 
1195 SYSCTL_QUAD(_kern
, OID_AUTO
, sleep_abs_time
, CTLFLAG_RD 
| CTLFLAG_LOCKED
, &gIOLastSleepAbsTime
, ""); 
1196 SYSCTL_QUAD(_kern
, OID_AUTO
, useractive_abs_time
, CTLFLAG_RD 
| CTLFLAG_LOCKED
, &gUserActiveAbsTime
, ""); 
1197 SYSCTL_QUAD(_kern
, OID_AUTO
, userinactive_abs_time
, CTLFLAG_RD 
| CTLFLAG_LOCKED
, &gUserInactiveAbsTime
, ""); 
1200 sysctl_willshutdown SYSCTL_HANDLER_ARGS
 
1202         int new_value
, changed
, error
; 
1204         if (!gWillShutdownSysctlRegistered
) { 
1208         error 
= sysctl_io_number(req
, gWillShutdown
, sizeof(int), &new_value
, &changed
); 
1210                 if (!gWillShutdown 
&& (new_value 
== 1)) { 
1211                         IOPMRootDomainWillShutdown(); 
1219 static SYSCTL_PROC(_kern
, OID_AUTO
, willshutdown
, 
1220     CTLTYPE_INT 
| CTLFLAG_RW 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1221     NULL
, 0, sysctl_willshutdown
, "I", ""); 
1223 #if defined(XNU_TARGET_OS_OSX) 
1226 sysctl_progressmeterenable
 
1227 (__unused 
struct sysctl_oid 
*oidp
, __unused 
void *arg1
, __unused 
int arg2
, struct sysctl_req 
*req
) 
1230         int new_value
, changed
; 
1232         error 
= sysctl_io_number(req
, vc_progressmeter_enable
, sizeof(int), &new_value
, &changed
); 
1235                 vc_enable_progressmeter(new_value
); 
1242 sysctl_progressmeter
 
1243 (__unused 
struct sysctl_oid 
*oidp
, __unused 
void *arg1
, __unused 
int arg2
, struct sysctl_req 
*req
) 
1246         int new_value
, changed
; 
1248         error 
= sysctl_io_number(req
, vc_progressmeter_value
, sizeof(int), &new_value
, &changed
); 
1251                 vc_set_progressmeter(new_value
); 
1257 static SYSCTL_PROC(_kern
, OID_AUTO
, progressmeterenable
, 
1258     CTLTYPE_INT 
| CTLFLAG_RW 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1259     NULL
, 0, sysctl_progressmeterenable
, "I", ""); 
1261 static SYSCTL_PROC(_kern
, OID_AUTO
, progressmeter
, 
1262     CTLTYPE_INT 
| CTLFLAG_RW 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1263     NULL
, 0, sysctl_progressmeter
, "I", ""); 
1265 #endif /* defined(XNU_TARGET_OS_OSX) */ 
1270 sysctl_consoleoptions
 
1271 (__unused 
struct sysctl_oid 
*oidp
, __unused 
void *arg1
, __unused 
int arg2
, struct sysctl_req 
*req
) 
1276         error 
= sysctl_io_number(req
, vc_user_options
.options
, sizeof(uint32_t), &new_value
, &changed
); 
1279                 vc_user_options
.options 
= new_value
; 
1285 static SYSCTL_PROC(_kern
, OID_AUTO
, consoleoptions
, 
1286     CTLTYPE_INT 
| CTLFLAG_RW 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1287     NULL
, 0, sysctl_consoleoptions
, "I", ""); 
1291 sysctl_progressoptions SYSCTL_HANDLER_ARGS
 
1293         return sysctl_io_opaque(req
, &vc_user_options
, sizeof(vc_user_options
), NULL
); 
1296 static SYSCTL_PROC(_kern
, OID_AUTO
, progressoptions
, 
1297     CTLTYPE_STRUCT 
| CTLFLAG_RW 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED 
| CTLFLAG_ANYBODY
, 
1298     NULL
, 0, sysctl_progressoptions
, "S,vc_progress_user_options", ""); 
1302 sysctl_wakereason SYSCTL_HANDLER_ARGS
 
1304         char wr
[sizeof(gWakeReasonString
)]; 
1307         if (gRootDomain 
&& gWakeReasonSysctlRegistered
) { 
1308                 gRootDomain
->copyWakeReasonString(wr
, sizeof(wr
)); 
1313         return sysctl_io_string(req
, wr
, 0, 0, NULL
); 
1316 SYSCTL_PROC(_kern
, OID_AUTO
, wakereason
, 
1317     CTLTYPE_STRING 
| CTLFLAG_RD 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1318     NULL
, 0, sysctl_wakereason
, "A", "wakereason"); 
1321 sysctl_bootreason SYSCTL_HANDLER_ARGS
 
1323         if (!os_atomic_load(&gBootReasonSysctlRegistered
, acquire
)) { 
1327         return sysctl_io_string(req
, gBootReasonString
, 0, 0, NULL
); 
1330 SYSCTL_PROC(_kern
, OID_AUTO
, bootreason
, 
1331     CTLFLAG_RD 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1332     NULL
, 0, sysctl_bootreason
, "A", ""); 
1335 sysctl_shutdownreason SYSCTL_HANDLER_ARGS
 
1337         char sr
[sizeof(gShutdownReasonString
)]; 
1340         if (gRootDomain 
&& gShutdownReasonSysctlRegistered
) { 
1341                 gRootDomain
->copyShutdownReasonString(sr
, sizeof(sr
)); 
1346         return sysctl_io_string(req
, sr
, 0, 0, NULL
); 
1349 SYSCTL_PROC(_kern
, OID_AUTO
, shutdownreason
, 
1350     CTLTYPE_STRING 
| CTLFLAG_RD 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1351     NULL
, 0, sysctl_shutdownreason
, "A", "shutdownreason"); 
1354 sysctl_targettype SYSCTL_HANDLER_ARGS
 
1357         OSSharedPtr
<OSObject
>  obj
; 
1362         root 
= IOService::getServiceRoot(); 
1363         if (root 
&& (obj 
= root
->copyProperty(gIODTTargetTypeKey
))) { 
1364                 if ((data 
= OSDynamicCast(OSData
, obj
.get()))) { 
1365                         strlcpy(tt
, (const char *) data
->getBytesNoCopy(), sizeof(tt
)); 
1368         return sysctl_io_string(req
, tt
, 0, 0, NULL
); 
1371 SYSCTL_PROC(_hw
, OID_AUTO
, targettype
, 
1372     CTLTYPE_STRING 
| CTLFLAG_RD 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1373     NULL
, 0, sysctl_targettype
, "A", "targettype"); 
1375 static SYSCTL_INT(_debug
, OID_AUTO
, noidle
, CTLFLAG_RW
, &gNoIdleFlag
, 0, ""); 
1376 static SYSCTL_INT(_debug
, OID_AUTO
, swd_sleep_timeout
, CTLFLAG_RW
, &gSwdSleepTimeout
, 0, ""); 
1377 static SYSCTL_INT(_debug
, OID_AUTO
, swd_wake_timeout
, CTLFLAG_RW
, &gSwdWakeTimeout
, 0, ""); 
1378 static SYSCTL_INT(_debug
, OID_AUTO
, swd_timeout
, CTLFLAG_RW
, &gSwdSleepWakeTimeout
, 0, ""); 
1379 static SYSCTL_INT(_debug
, OID_AUTO
, swd_panic
, CTLFLAG_RW
, &gSwdPanic
, 0, ""); 
1380 #if DEVELOPMENT || DEBUG 
1381 static SYSCTL_INT(_debug
, OID_AUTO
, swd_panic_phase
, CTLFLAG_RW
, &swd_panic_phase
, 0, ""); 
1382 #if defined(XNU_TARGET_OS_OSX) 
1383 static SYSCTL_INT(_debug
, OID_AUTO
, clamshell
, CTLFLAG_RW
, &gClamshellFlags
, 0, ""); 
1384 static SYSCTL_INT(_debug
, OID_AUTO
, darkwake
, CTLFLAG_RW
, &gDarkWakeFlags
, 0, ""); 
1385 #endif /* defined(XNU_TARGET_OS_OSX) */ 
1386 #endif /* DEVELOPMENT || DEBUG */ 
1388 //****************************************************************************** 
1392 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
 
1394         if (NULL 
== gRootDomain
) { 
1397         if (NULL 
== gRootDomain
->_aotMetrics
) { 
1400         return sysctl_io_opaque(req
, gRootDomain
->_aotMetrics
, sizeof(IOPMAOTMetrics
), NULL
); 
1403 static SYSCTL_PROC(_kern
, OID_AUTO
, aotmetrics
, 
1404     CTLTYPE_STRUCT 
| CTLFLAG_RD 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED 
| CTLFLAG_ANYBODY
, 
1405     NULL
, 0, sysctl_aotmetrics
, "S,IOPMAOTMetrics", ""); 
1409 update_aotmode(uint32_t mode
) 
1413         if (!gIOPMWorkLoop
) { 
1416         result 
= gIOPMWorkLoop
->runActionBlock(^IOReturn (void) { 
1417                 unsigned int oldCount
; 
1419                 if (mode 
&& !gRootDomain
->_aotMetrics
) { 
1420                         gRootDomain
->_aotMetrics 
= IONewZero(IOPMAOTMetrics
, 1); 
1421                         if (!gRootDomain
->_aotMetrics
) { 
1426                 oldCount 
= gRootDomain
->idleSleepPreventersCount(); 
1427                 gRootDomain
->_aotMode 
= (mode 
& kIOPMAOTModeMask
); 
1428                 gRootDomain
->updatePreventIdleSleepListInternal(NULL
, false, oldCount
); 
1436 (__unused 
struct sysctl_oid 
*oidp
, __unused 
void *arg1
, __unused 
int arg2
, struct sysctl_req 
*req
) 
1441         if (NULL 
== gRootDomain
) { 
1444         error 
= sysctl_io_number(req
, gRootDomain
->_aotMode
, sizeof(uint32_t), &new_value
, &changed
); 
1445         if (changed 
&& gIOPMWorkLoop
) { 
1446                 error 
= update_aotmode(new_value
); 
1452 static SYSCTL_PROC(_kern
, OID_AUTO
, aotmodebits
, 
1453     CTLTYPE_INT 
| CTLFLAG_RW 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1454     NULL
, 0, sysctl_aotmodebits
, "I", ""); 
1458 (__unused 
struct sysctl_oid 
*oidp
, __unused 
void *arg1
, __unused 
int arg2
, struct sysctl_req 
*req
) 
1463         if (NULL 
== gRootDomain
) { 
1466         error 
= sysctl_io_number(req
, gRootDomain
->_aotMode
, sizeof(uint32_t), &new_value
, &changed
); 
1467         if (changed 
&& gIOPMWorkLoop
) { 
1469                         new_value 
= kIOPMAOTModeDefault
; // & ~kIOPMAOTModeRespectTimers; 
1471                 error 
= update_aotmode(new_value
); 
1477 static SYSCTL_PROC(_kern
, OID_AUTO
, aotmode
, 
1478     CTLTYPE_INT 
| CTLFLAG_RW 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED 
| CTLFLAG_ANYBODY
, 
1479     NULL
, 0, sysctl_aotmode
, "I", ""); 
1481 //****************************************************************************** 
1483 static OSSharedPtr
<const OSSymbol
> gIOPMSettingAutoWakeCalendarKey
; 
1484 static OSSharedPtr
<const OSSymbol
> gIOPMSettingAutoWakeSecondsKey
; 
1485 static OSSharedPtr
<const OSSymbol
> gIOPMSettingAutoPowerCalendarKey
; 
1486 static OSSharedPtr
<const OSSymbol
> gIOPMSettingAutoPowerSecondsKey
; 
1487 static OSSharedPtr
<const OSSymbol
> gIOPMSettingDebugWakeRelativeKey
; 
1488 static OSSharedPtr
<const OSSymbol
> gIOPMSettingDebugPowerRelativeKey
; 
1489 static OSSharedPtr
<const OSSymbol
> gIOPMSettingMaintenanceWakeCalendarKey
; 
1490 static OSSharedPtr
<const OSSymbol
> gIOPMSettingSleepServiceWakeCalendarKey
; 
1491 static OSSharedPtr
<const OSSymbol
> gIOPMSettingSilentRunningKey
; 
1492 static OSSharedPtr
<const OSSymbol
> gIOPMUserTriggeredFullWakeKey
; 
1493 static OSSharedPtr
<const OSSymbol
> gIOPMUserIsActiveKey
; 
1494 static OSSharedPtr
<const OSSymbol
> gIOPMSettingLowLatencyAudioModeKey
; 
1496 //****************************************************************************** 
1499 //****************************************************************************** 
1501 #define kRootDomainSettingsCount           20 
1502 #define kRootDomainNoPublishSettingsCount  4 
1505 IOPMrootDomain::start( IOService 
* nub 
) 
1507         OSSharedPtr
<OSIterator
>      psIterator
; 
1508         OSSharedPtr
<OSDictionary
>    tmpDict
; 
1513         gIOPMSettingAutoWakeCalendarKey 
= OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey
); 
1514         gIOPMSettingAutoWakeSecondsKey 
= OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey
); 
1515         gIOPMSettingAutoPowerCalendarKey 
= OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey
); 
1516         gIOPMSettingAutoPowerSecondsKey 
= OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey
); 
1517         gIOPMSettingDebugWakeRelativeKey 
= OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey
); 
1518         gIOPMSettingDebugPowerRelativeKey 
= OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey
); 
1519         gIOPMSettingMaintenanceWakeCalendarKey 
= OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey
); 
1520         gIOPMSettingSleepServiceWakeCalendarKey 
= OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey
); 
1521         gIOPMSettingSilentRunningKey 
= OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey
); 
1522         gIOPMUserTriggeredFullWakeKey 
= OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey
); 
1523         gIOPMUserIsActiveKey 
= OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey
); 
1524         gIOPMSettingLowLatencyAudioModeKey 
= OSSymbol::withCStringNoCopy(kIOPMSettingLowLatencyAudioModeKey
); 
1526         gIOPMStatsResponseTimedOut 
= OSSymbol::withCString(kIOPMStatsResponseTimedOut
); 
1527         gIOPMStatsResponseCancel 
= OSSymbol::withCString(kIOPMStatsResponseCancel
); 
1528         gIOPMStatsResponseSlow 
= OSSymbol::withCString(kIOPMStatsResponseSlow
); 
1529         gIOPMStatsResponsePrompt 
= OSSymbol::withCString(kIOPMStatsResponsePrompt
); 
1530         gIOPMStatsDriverPSChangeSlow 
= OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow
); 
1532         sleepSupportedPEFunction 
= OSSymbol::withCString("IOPMSetSleepSupported"); 
1533         sleepMessagePEFunction 
= OSSymbol::withCString("IOPMSystemSleepMessage"); 
1534         gIOPMWakeTypeUserKey 
= OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser
); 
1536         OSSharedPtr
<const OSSymbol
> settingsArr
[kRootDomainSettingsCount
] = 
1538                 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey
), 
1539                 gIOPMSettingAutoWakeSecondsKey
, 
1540                 gIOPMSettingAutoPowerSecondsKey
, 
1541                 gIOPMSettingAutoWakeCalendarKey
, 
1542                 gIOPMSettingAutoPowerCalendarKey
, 
1543                 gIOPMSettingDebugWakeRelativeKey
, 
1544                 gIOPMSettingDebugPowerRelativeKey
, 
1545                 OSSymbol::withCString(kIOPMSettingWakeOnRingKey
), 
1546                 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
), 
1547                 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey
), 
1548                 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey
), 
1549                 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey
), 
1550                 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey
), 
1551                 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey
), 
1552                 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey
), 
1553                 OSSymbol::withCString(kIOPMStateConsoleShutdown
), 
1554                 OSSymbol::withCString(kIOPMSettingProModeControl
), 
1555                 OSSymbol::withCString(kIOPMSettingProModeDefer
), 
1556                 gIOPMSettingSilentRunningKey
, 
1557                 gIOPMSettingLowLatencyAudioModeKey
, 
1560         OSSharedPtr
<const OSSymbol
> noPublishSettingsArr
[kRootDomainNoPublishSettingsCount
] = 
1562                 OSSymbol::withCString(kIOPMSettingProModeControl
), 
1563                 OSSymbol::withCString(kIOPMSettingProModeDefer
), 
1564                 gIOPMSettingSilentRunningKey
, 
1565                 gIOPMSettingLowLatencyAudioModeKey
, 
1568 #if DEVELOPMENT || DEBUG 
1569 #if defined(XNU_TARGET_OS_OSX) 
1570         PE_parse_boot_argn("darkwake", &gDarkWakeFlags
, sizeof(gDarkWakeFlags
)); 
1571         PE_parse_boot_argn("clamshell", &gClamshellFlags
, sizeof(gClamshellFlags
)); 
1572 #endif /* defined(XNU_TARGET_OS_OSX) */ 
1573 #endif /* DEVELOPMENT || DEBUG */ 
1575         PE_parse_boot_argn("noidle", &gNoIdleFlag
, sizeof(gNoIdleFlag
)); 
1576         PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout
, sizeof(gSwdSleepTimeout
)); 
1577         PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout
, sizeof(gSwdWakeTimeout
)); 
1578         PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout
, sizeof(gSwdSleepWakeTimeout
)); 
1579         PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic
, sizeof(gHaltTimeMaxPanic
)); 
1580         PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog
, sizeof(gHaltTimeMaxLog
)); 
1582         queue_init(&aggressivesQueue
); 
1583         aggressivesThreadCall 
= thread_call_allocate(handleAggressivesFunction
, this); 
1584         aggressivesData 
= OSData::withCapacity( 
1585                 sizeof(AggressivesRecord
) * (kPMLastAggressivenessType 
+ 4)); 
1587         featuresDictLock 
= IOLockAlloc(); 
1588         settingsCtrlLock 
= IOLockAlloc(); 
1589         wakeEventLock 
= IOLockAlloc(); 
1590         gHaltLogLock 
= IOLockAlloc(); 
1591         setPMRootDomain(this); 
1593         extraSleepTimer 
= thread_call_allocate( 
1594                 idleSleepTimerExpired
, 
1595                 (thread_call_param_t
) this); 
1597         powerButtonDown 
= thread_call_allocate( 
1598                 powerButtonDownCallout
, 
1599                 (thread_call_param_t
) this); 
1601         powerButtonUp 
= thread_call_allocate( 
1602                 powerButtonUpCallout
, 
1603                 (thread_call_param_t
) this); 
1605         diskSyncCalloutEntry 
= thread_call_allocate( 
1607                 (thread_call_param_t
) this); 
1608         updateConsoleUsersEntry 
= thread_call_allocate( 
1609                 &updateConsoleUsersCallout
, 
1610                 (thread_call_param_t
) this); 
1612 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 
1613         fullWakeThreadCall 
= thread_call_allocate_with_options( 
1614                 OSMemberFunctionCast(thread_call_func_t
, this, 
1615                 &IOPMrootDomain::fullWakeDelayedWork
), 
1616                 (thread_call_param_t
) this, THREAD_CALL_PRIORITY_KERNEL
, 
1617                 THREAD_CALL_OPTIONS_ONCE
); 
1620         setProperty(kIOSleepSupportedKey
, true); 
1622         bzero(&gPMStats
, sizeof(gPMStats
)); 
1624         pmTracer 
= PMTraceWorker::tracer(this); 
1626         pmAssertions 
= PMAssertionsTracker::pmAssertionsTracker(this); 
1628         userDisabledAllSleep 
= false; 
1629         systemBooting 
= true; 
1630         idleSleepEnabled 
= false; 
1632         idleSleepTimerPending 
= false; 
1634         clamshellClosed 
= false; 
1635         clamshellExists 
= false; 
1636 #if DISPLAY_WRANGLER_PRESENT 
1637         clamshellDisabled 
= true; 
1639         clamshellDisabled 
= false; 
1641         clamshellIgnoreClose 
= false; 
1642         acAdaptorConnected 
= true; 
1643         clamshellSleepDisableMask 
= 0; 
1644         gWakeReasonString
[0] = '\0'; 
1646         // Initialize to user active. 
1647         // Will never transition to user inactive w/o wrangler. 
1648         fullWakeReason 
= kFullWakeReasonLocalUser
; 
1649         userIsActive 
= userWasActive 
= true; 
1650         clock_get_uptime(&gUserActiveAbsTime
); 
1651         setProperty(gIOPMUserIsActiveKey
.get(), kOSBooleanTrue
); 
1653         // Set the default system capabilities at boot. 
1654         _currentCapability 
= kIOPMSystemCapabilityCPU      
| 
1655             kIOPMSystemCapabilityGraphics 
| 
1656             kIOPMSystemCapabilityAudio    
| 
1657             kIOPMSystemCapabilityNetwork
; 
1659         _pendingCapability 
= _currentCapability
; 
1660         _desiredCapability 
= _currentCapability
; 
1661         _highestCapability 
= _currentCapability
; 
1662         setProperty(kIOPMSystemCapabilitiesKey
, _currentCapability
, 64); 
1664         queuedSleepWakeUUIDString 
= NULL
; 
1665         initializeBootSessionUUID(); 
1666         pmStatsAppResponses     
= OSArray::withCapacity(5); 
1667         _statsNameKey           
= OSSymbol::withCString(kIOPMStatsNameKey
); 
1668         _statsPIDKey            
= OSSymbol::withCString(kIOPMStatsPIDKey
); 
1669         _statsTimeMSKey         
= OSSymbol::withCString(kIOPMStatsTimeMSKey
); 
1670         _statsResponseTypeKey   
= OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey
); 
1671         _statsMessageTypeKey    
= OSSymbol::withCString(kIOPMStatsMessageTypeKey
); 
1672         _statsPowerCapsKey      
= OSSymbol::withCString(kIOPMStatsPowerCapabilityKey
); 
1673         assertOnWakeSecs        
= -1;// Invalid value to prevent updates 
1675         pmStatsLock 
= IOLockAlloc(); 
1676         idxPMCPUClamshell 
= kCPUUnknownIndex
; 
1677         idxPMCPULimitedPower 
= kCPUUnknownIndex
; 
1679         tmpDict 
= OSDictionary::withCapacity(1); 
1680         setProperty(kRootDomainSupportedFeatures
, tmpDict
.get()); 
1682         // Set a default "SystemPowerProfileOverrideDict" for platform 
1683         // drivers without any overrides. 
1684         if (!propertyExists(kIOPMSystemDefaultOverrideKey
)) { 
1685                 tmpDict 
= OSDictionary::withCapacity(1); 
1686                 setProperty(kIOPMSystemDefaultOverrideKey
, tmpDict
.get()); 
1689         settingsCallbacks 
= OSDictionary::withCapacity(1); 
1691         // Create a list of the valid PM settings that we'll relay to 
1692         // interested clients in setProperties() => setPMSetting() 
1693         allowedPMSettings 
= OSArray::withObjects( 
1694                 (const OSObject 
**)settingsArr
, 
1695                 kRootDomainSettingsCount
, 
1698         // List of PM settings that should not automatically publish itself 
1699         // as a feature when registered by a listener. 
1700         noPublishPMSettings 
= OSArray::withObjects( 
1701                 (const OSObject 
**)noPublishSettingsArr
, 
1702                 kRootDomainNoPublishSettingsCount
, 
1705         fPMSettingsDict 
= OSDictionary::withCapacity(5); 
1706         preventIdleSleepList 
= OSSet::withCapacity(8); 
1707         preventSystemSleepList 
= OSSet::withCapacity(2); 
1709         PMinit(); // creates gIOPMWorkLoop 
1710         gIOPMWorkLoop 
= getIOPMWorkloop(); 
1712         // Create IOPMPowerStateQueue used to queue external power 
1713         // events, and to handle those events on the PM work loop. 
1714         pmPowerStateQueue 
= IOPMPowerStateQueue::PMPowerStateQueue( 
1715                 this, OSMemberFunctionCast(IOEventSource::Action
, this, 
1716                 &IOPMrootDomain::dispatchPowerEvent
)); 
1717         gIOPMWorkLoop
->addEventSource(pmPowerStateQueue
); 
1720         _aotTimerES 
= IOTimerEventSource::timerEventSource(this, 
1721             OSMemberFunctionCast(IOTimerEventSource::Action
, 
1722             this, &IOPMrootDomain::aotEvaluate
)); 
1723         gIOPMWorkLoop
->addEventSource(_aotTimerES
.get()); 
1725         // create our power parent 
1726         gPatriarch 
= new IORootParent
; 
1728         gPatriarch
->attach(this); 
1729         gPatriarch
->start(this); 
1730         gPatriarch
->addPowerChild(this); 
1732         registerPowerDriver(this, ourPowerStates
, NUM_POWER_STATES
); 
1733         changePowerStateWithTagToPriv(ON_STATE
, kCPSReasonInit
); 
1735         // install power change handler 
1736         gSysPowerDownNotifier 
= registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, NULL
); 
1738 #if DISPLAY_WRANGLER_PRESENT 
1739         wranglerIdleSettings 
= OSDictionary::withCapacity(1); 
1740         OSSharedPtr
<OSNumber
> wranglerIdlePeriod 
= OSNumber::withNumber(kDefaultWranglerIdlePeriod
, 32); 
1742         if (wranglerIdleSettings 
&& wranglerIdlePeriod
) { 
1743                 wranglerIdleSettings
->setObject(kIORequestWranglerIdleKey
, 
1744                     wranglerIdlePeriod
.get()); 
1747 #endif /* DISPLAY_WRANGLER_PRESENT */ 
1749         lowLatencyAudioNotifierDict       
= OSDictionary::withCapacity(2); 
1750         lowLatencyAudioNotifyStateSym     
= OSSymbol::withCString("LowLatencyAudioNotifyState"); 
1751         lowLatencyAudioNotifyTimestampSym 
= OSSymbol::withCString("LowLatencyAudioNotifyTimestamp"); 
1752         lowLatencyAudioNotifyStateVal     
= OSNumber::withNumber(0ull, 32); 
1753         lowLatencyAudioNotifyTimestampVal 
= OSNumber::withNumber(0ull, 64); 
1755         if (lowLatencyAudioNotifierDict 
&& lowLatencyAudioNotifyStateSym 
&& lowLatencyAudioNotifyTimestampSym 
&& 
1756             lowLatencyAudioNotifyStateVal 
&& lowLatencyAudioNotifyTimestampVal
) { 
1757                 lowLatencyAudioNotifierDict
->setObject(lowLatencyAudioNotifyStateSym
.get(), lowLatencyAudioNotifyStateVal
.get()); 
1758                 lowLatencyAudioNotifierDict
->setObject(lowLatencyAudioNotifyTimestampSym
.get(), lowLatencyAudioNotifyTimestampVal
.get()); 
1761         OSSharedPtr
<const OSSymbol
> ucClassName 
= OSSymbol::withCStringNoCopy("RootDomainUserClient"); 
1762         setProperty(gIOUserClientClassKey
, const_cast<OSObject 
*>(static_cast<const OSObject 
*>(ucClassName
.get()))); 
1764         // IOBacklightDisplay can take a long time to load at boot, or it may 
1765         // not load at all if you're booting with clamshell closed. We publish 
1766         // 'DisplayDims' here redundantly to get it published early and at all. 
1767         OSSharedPtr
<OSDictionary
> matching
; 
1768         matching 
= serviceMatching("IOPMPowerSource"); 
1769         psIterator 
= getMatchingServices(matching
.get()); 
1771         if (psIterator 
&& psIterator
->getNextObject()) { 
1772                 // There's at least one battery on the system, so we publish 
1773                 // 'DisplayDims' support for the LCD. 
1774                 publishFeature("DisplayDims"); 
1777         // read swd_panic boot-arg 
1778         PE_parse_boot_argn("swd_panic", &gSwdPanic
, sizeof(gSwdPanic
)); 
1779         gWillShutdownSysctlRegistered 
= true; 
1782 #if defined(__arm64__) 
1783 #endif /* defined(__arm64__) */ 
1784         IOHibernateSystemInit(this); 
1787         registerService();                  // let clients find us 
1792 //****************************************************************************** 
1795 // Receive a setProperty call 
1796 // The "System Boot" property means the system is completely booted. 
1797 //****************************************************************************** 
1800 IOPMrootDomain::setProperties( OSObject 
* props_obj 
) 
1802         IOReturn        return_value 
= kIOReturnSuccess
; 
1803         OSDictionary    
*dict 
= OSDynamicCast(OSDictionary
, props_obj
); 
1804         OSBoolean       
*b 
= NULL
; 
1806         const OSSymbol  
*key 
= NULL
; 
1807         OSObject        
*obj 
= NULL
; 
1808         OSSharedPtr
<OSCollectionIterator
> iter
; 
1811                 return kIOReturnBadArgument
; 
1814         bool clientEntitled 
= false; 
1816                 OSSharedPtr
<OSObject
> obj 
= IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty
); 
1817                 clientEntitled 
= (obj 
== kOSBooleanTrue
); 
1820         if (!clientEntitled
) { 
1821                 const char * errorSuffix 
= NULL
; 
1823                 // IOPMSchedulePowerEvent() clients may not be entitled, but must be root. 
1824                 // That API can set 6 possible keys that are checked below. 
1825                 if ((dict
->getCount() == 1) && 
1826                     (dict
->getObject(gIOPMSettingAutoWakeSecondsKey
.get()) || 
1827                     dict
->getObject(gIOPMSettingAutoPowerSecondsKey
.get()) || 
1828                     dict
->getObject(gIOPMSettingAutoWakeCalendarKey
.get()) || 
1829                     dict
->getObject(gIOPMSettingAutoPowerCalendarKey
.get()) || 
1830                     dict
->getObject(gIOPMSettingDebugWakeRelativeKey
.get()) || 
1831                     dict
->getObject(gIOPMSettingDebugPowerRelativeKey
.get()))) { 
1832                         return_value 
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
); 
1833                         if (return_value 
!= kIOReturnSuccess
) { 
1834                                 errorSuffix 
= "privileged"; 
1837                         return_value 
= kIOReturnNotPermitted
; 
1838                         errorSuffix 
= "entitled"; 
1841                 if (return_value 
!= kIOReturnSuccess
) { 
1842                         OSSharedPtr
<OSString
> procName(IOCopyLogNameForPID(proc_selfpid()), OSNoRetain
); 
1843                         DLOG("%s failed, process %s is not %s\n", __func__
, 
1844                             procName 
? procName
->getCStringNoCopy() : "", errorSuffix
); 
1845                         return return_value
; 
1849         OSSharedPtr
<const OSSymbol
> publish_simulated_battery_string    
= OSSymbol::withCString("SoftwareSimulatedBatteries"); 
1850         OSSharedPtr
<const OSSymbol
> boot_complete_string                
= OSSymbol::withCString("System Boot Complete"); 
1851         OSSharedPtr
<const OSSymbol
> sys_shutdown_string                 
= OSSymbol::withCString("System Shutdown"); 
1852         OSSharedPtr
<const OSSymbol
> stall_halt_string                   
= OSSymbol::withCString("StallSystemAtHalt"); 
1853         OSSharedPtr
<const OSSymbol
> battery_warning_disabled_string     
= OSSymbol::withCString("BatteryWarningsDisabled"); 
1854         OSSharedPtr
<const OSSymbol
> idle_seconds_string                 
= OSSymbol::withCString("System Idle Seconds"); 
1855         OSSharedPtr
<const OSSymbol
> sleepdisabled_string                
= OSSymbol::withCString("SleepDisabled"); 
1856         OSSharedPtr
<const OSSymbol
> ondeck_sleepwake_uuid_string        
= OSSymbol::withCString(kIOPMSleepWakeUUIDKey
); 
1857         OSSharedPtr
<const OSSymbol
> loginwindow_progress_string         
= OSSymbol::withCString(kIOPMLoginWindowProgressKey
); 
1858         OSSharedPtr
<const OSSymbol
> coredisplay_progress_string         
= OSSymbol::withCString(kIOPMCoreDisplayProgressKey
); 
1859         OSSharedPtr
<const OSSymbol
> coregraphics_progress_string        
= OSSymbol::withCString(kIOPMCoreGraphicsProgressKey
); 
1860 #if DEBUG || DEVELOPMENT 
1861         OSSharedPtr
<const OSSymbol
> clamshell_close_string              
= OSSymbol::withCString("IOPMTestClamshellClose"); 
1862         OSSharedPtr
<const OSSymbol
> clamshell_open_string               
= OSSymbol::withCString("IOPMTestClamshellOpen"); 
1863         OSSharedPtr
<const OSSymbol
> ac_detach_string                    
= OSSymbol::withCString("IOPMTestACDetach"); 
1864         OSSharedPtr
<const OSSymbol
> ac_attach_string                    
= OSSymbol::withCString("IOPMTestACAttach"); 
1865         OSSharedPtr
<const OSSymbol
> desktopmode_set_string              
= OSSymbol::withCString("IOPMTestDesktopModeSet"); 
1866         OSSharedPtr
<const OSSymbol
> desktopmode_remove_string           
= OSSymbol::withCString("IOPMTestDesktopModeRemove"); 
1870         OSSharedPtr
<const OSSymbol
> hibernatemode_string                
= OSSymbol::withCString(kIOHibernateModeKey
); 
1871         OSSharedPtr
<const OSSymbol
> hibernatefile_string                
= OSSymbol::withCString(kIOHibernateFileKey
); 
1872         OSSharedPtr
<const OSSymbol
> hibernatefilemin_string             
= OSSymbol::withCString(kIOHibernateFileMinSizeKey
); 
1873         OSSharedPtr
<const OSSymbol
> hibernatefilemax_string             
= OSSymbol::withCString(kIOHibernateFileMaxSizeKey
); 
1874         OSSharedPtr
<const OSSymbol
> hibernatefreeratio_string           
= OSSymbol::withCString(kIOHibernateFreeRatioKey
); 
1875         OSSharedPtr
<const OSSymbol
> hibernatefreetime_string            
= OSSymbol::withCString(kIOHibernateFreeTimeKey
); 
1878         iter 
= OSCollectionIterator::withCollection(dict
); 
1880                 return_value 
= kIOReturnNoMemory
; 
1884         while ((key 
= (const OSSymbol 
*) iter
->getNextObject()) && 
1885             (obj 
= dict
->getObject(key
))) { 
1886                 if (key
->isEqualTo(publish_simulated_battery_string
.get())) { 
1887                         if (OSDynamicCast(OSBoolean
, obj
)) { 
1888                                 publishResource(key
, kOSBooleanTrue
); 
1890                 } else if (key
->isEqualTo(idle_seconds_string
.get())) { 
1891                         if ((n 
= OSDynamicCast(OSNumber
, obj
))) { 
1892                                 setProperty(key
, n
); 
1893                                 idleSeconds 
= n
->unsigned32BitValue(); 
1895                 } else if (key
->isEqualTo(boot_complete_string
.get())) { 
1896                         pmPowerStateQueue
->submitPowerEvent(kPowerEventSystemBootCompleted
); 
1897                 } else if (key
->isEqualTo(sys_shutdown_string
.get())) { 
1898                         if ((b 
= OSDynamicCast(OSBoolean
, obj
))) { 
1899                                 pmPowerStateQueue
->submitPowerEvent(kPowerEventSystemShutdown
, (void *) b
); 
1901                 } else if (key
->isEqualTo(battery_warning_disabled_string
.get())) { 
1902                         setProperty(key
, obj
); 
1905                 else if (key
->isEqualTo(hibernatemode_string
.get()) || 
1906                     key
->isEqualTo(hibernatefilemin_string
.get()) || 
1907                     key
->isEqualTo(hibernatefilemax_string
.get()) || 
1908                     key
->isEqualTo(hibernatefreeratio_string
.get()) || 
1909                     key
->isEqualTo(hibernatefreetime_string
.get())) { 
1910                         if ((n 
= OSDynamicCast(OSNumber
, obj
))) { 
1911                                 setProperty(key
, n
); 
1913                 } else if (key
->isEqualTo(hibernatefile_string
.get())) { 
1914                         OSString 
* str 
= OSDynamicCast(OSString
, obj
); 
1916                                 setProperty(key
, str
); 
1920                 else if (key
->isEqualTo(sleepdisabled_string
.get())) { 
1921                         if ((b 
= OSDynamicCast(OSBoolean
, obj
))) { 
1922                                 setProperty(key
, b
); 
1923                                 pmPowerStateQueue
->submitPowerEvent(kPowerEventUserDisabledSleep
, (void *) b
); 
1925                 } else if (key
->isEqualTo(ondeck_sleepwake_uuid_string
.get())) { 
1927                         pmPowerStateQueue
->submitPowerEvent(kPowerEventQueueSleepWakeUUID
, (void *)obj
); 
1928                 } else if (key
->isEqualTo(loginwindow_progress_string
.get())) { 
1929                         if (pmTracer 
&& (n 
= OSDynamicCast(OSNumber
, obj
))) { 
1930                                 uint32_t data 
= n
->unsigned32BitValue(); 
1931                                 pmTracer
->traceComponentWakeProgress(kIOPMLoginWindowProgress
, data
); 
1932                                 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMLoginWindowProgress
, data
); 
1934                 } else if (key
->isEqualTo(coredisplay_progress_string
.get())) { 
1935                         if (pmTracer 
&& (n 
= OSDynamicCast(OSNumber
, obj
))) { 
1936                                 uint32_t data 
= n
->unsigned32BitValue(); 
1937                                 pmTracer
->traceComponentWakeProgress(kIOPMCoreDisplayProgress
, data
); 
1938                                 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMCoreDisplayProgress
, data
); 
1940                 } else if (key
->isEqualTo(coregraphics_progress_string
.get())) { 
1941                         if (pmTracer 
&& (n 
= OSDynamicCast(OSNumber
, obj
))) { 
1942                                 uint32_t data 
= n
->unsigned32BitValue(); 
1943                                 pmTracer
->traceComponentWakeProgress(kIOPMCoreGraphicsProgress
, data
); 
1944                                 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMCoreGraphicsProgress
, data
); 
1946                 } else if (key
->isEqualTo(kIOPMDeepSleepEnabledKey
) || 
1947                     key
->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey
) || 
1948                     key
->isEqualTo(kIOPMAutoPowerOffEnabledKey
) || 
1949                     key
->isEqualTo(stall_halt_string
.get())) { 
1950                         if ((b 
= OSDynamicCast(OSBoolean
, obj
))) { 
1951                                 setProperty(key
, b
); 
1953                 } else if (key
->isEqualTo(kIOPMDeepSleepDelayKey
) || 
1954                     key
->isEqualTo(kIOPMDeepSleepTimerKey
) || 
1955                     key
->isEqualTo(kIOPMAutoPowerOffDelayKey
) || 
1956                     key
->isEqualTo(kIOPMAutoPowerOffTimerKey
)) { 
1957                         if ((n 
= OSDynamicCast(OSNumber
, obj
))) { 
1958                                 setProperty(key
, n
); 
1960                 } else if (key
->isEqualTo(kIOPMUserWakeAlarmScheduledKey
)) { 
1961                         if (kOSBooleanTrue 
== obj
) { 
1962                                 OSBitOrAtomic(kIOPMAlarmBitCalendarWake
, &_userScheduledAlarmMask
); 
1964                                 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake
, &_userScheduledAlarmMask
); 
1966                         DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask
); 
1968 #if DEBUG || DEVELOPMENT 
1969                 else if (key
->isEqualTo(clamshell_close_string
.get())) { 
1970                         DLOG("SetProperties: setting clamshell close\n"); 
1971                         UInt32 msg 
= kIOPMClamshellClosed
; 
1972                         pmPowerStateQueue
->submitPowerEvent(kPowerEventReceivedPowerNotification
, (void *)(uintptr_t)msg
); 
1973                 } else if (key
->isEqualTo(clamshell_open_string
.get())) { 
1974                         DLOG("SetProperties: setting clamshell open\n"); 
1975                         UInt32 msg 
= kIOPMClamshellOpened
; 
1976                         pmPowerStateQueue
->submitPowerEvent(kPowerEventReceivedPowerNotification
, (void *)(uintptr_t)msg
); 
1977                 } else if (key
->isEqualTo(ac_detach_string
.get())) { 
1978                         DLOG("SetProperties: setting ac detach\n"); 
1979                         UInt32 msg 
= kIOPMSetACAdaptorConnected
; 
1980                         pmPowerStateQueue
->submitPowerEvent(kPowerEventReceivedPowerNotification
, (void *)(uintptr_t)msg
); 
1981                 } else if (key
->isEqualTo(ac_attach_string
.get())) { 
1982                         DLOG("SetProperties: setting ac attach\n"); 
1983                         UInt32 msg 
= kIOPMSetACAdaptorConnected 
| kIOPMSetValue
; 
1984                         pmPowerStateQueue
->submitPowerEvent(kPowerEventReceivedPowerNotification
, (void *)(uintptr_t)msg
); 
1985                 } else if (key
->isEqualTo(desktopmode_set_string
.get())) { 
1986                         DLOG("SetProperties: setting desktopmode"); 
1987                         UInt32 msg 
= kIOPMSetDesktopMode 
| kIOPMSetValue
; 
1988                         pmPowerStateQueue
->submitPowerEvent(kPowerEventReceivedPowerNotification
, (void *)(uintptr_t)msg
); 
1989                 } else if (key
->isEqualTo(desktopmode_remove_string
.get())) { 
1990                         DLOG("SetProperties: removing desktopmode\n"); 
1991                         UInt32 msg 
= kIOPMSetDesktopMode
; 
1992                         pmPowerStateQueue
->submitPowerEvent(kPowerEventReceivedPowerNotification
, (void *)(uintptr_t)msg
); 
1995                 // Relay our allowed PM settings onto our registered PM clients 
1996                 else if ((allowedPMSettings
->getNextIndexOfObject(key
, 0) != (unsigned int) -1)) { 
1997                         return_value 
= setPMSetting(key
, obj
); 
1998                         if (kIOReturnSuccess 
!= return_value
) { 
2002                         DLOG("setProperties(%s) not handled\n", key
->getCStringNoCopy()); 
2007         return return_value
; 
2011 // MARK: Aggressiveness 
2013 //****************************************************************************** 
2014 // setAggressiveness 
2016 // Override IOService::setAggressiveness() 
2017 //****************************************************************************** 
2020 IOPMrootDomain::setAggressiveness( 
2022         unsigned long   value 
) 
2024         return setAggressiveness( type
, value
, 0 ); 
2028  * Private setAggressiveness() with an internal options argument. 
2031 IOPMrootDomain::setAggressiveness( 
2033         unsigned long   value
, 
2034         IOOptionBits    options 
) 
2036         AggressivesRequest 
*    entry
; 
2037         AggressivesRequest 
*    request
; 
2040         if ((type 
> UINT_MAX
) || (value 
> UINT_MAX
)) { 
2041                 return kIOReturnBadArgument
; 
2044         if (type 
== kPMMinutesToDim 
|| type 
== kPMMinutesToSleep
) { 
2045                 DLOG("setAggressiveness(%x) %s = %u\n", 
2046                     (uint32_t) options
, getAggressivenessTypeString((uint32_t) type
), (uint32_t) value
); 
2048                 DEBUG_LOG("setAggressiveness(%x) %s = %u\n", 
2049                     (uint32_t) options
, getAggressivenessTypeString((uint32_t) type
), (uint32_t) value
); 
2052         request 
= IONew(AggressivesRequest
, 1); 
2054                 return kIOReturnNoMemory
; 
2057         memset(request
, 0, sizeof(*request
)); 
2058         request
->options  
= options
; 
2059         request
->dataType 
= kAggressivesRequestTypeRecord
; 
2060         request
->data
.record
.type  
= (uint32_t) type
; 
2061         request
->data
.record
.value 
= (uint32_t) value
; 
2065         // Update disk quick spindown flag used by getAggressiveness(). 
2066         // Never merge requests with quick spindown flags set. 
2068         if (options 
& kAggressivesOptionQuickSpindownEnable
) { 
2069                 gAggressivesState 
|= kAggressivesStateQuickSpindown
; 
2070         } else if (options 
& kAggressivesOptionQuickSpindownDisable
) { 
2071                 gAggressivesState 
&= ~kAggressivesStateQuickSpindown
; 
2073                 // Coalesce requests with identical aggressives types. 
2074                 // Deal with callers that calls us too "aggressively". 
2076                 queue_iterate(&aggressivesQueue
, entry
, AggressivesRequest 
*, chain
) 
2078                         if ((entry
->dataType 
== kAggressivesRequestTypeRecord
) && 
2079                             (entry
->data
.record
.type 
== type
) && 
2080                             ((entry
->options 
& kAggressivesOptionQuickSpindownMask
) == 0)) { 
2081                                 entry
->data
.record
.value 
= (uint32_t) value
; 
2089                 queue_enter(&aggressivesQueue
, request
, AggressivesRequest 
*, chain
); 
2092         AGGRESSIVES_UNLOCK(); 
2095                 IODelete(request
, AggressivesRequest
, 1); 
2098         if (options 
& kAggressivesOptionSynchronous
) { 
2099                 handleAggressivesRequests(); // not truly synchronous 
2101                 thread_call_enter(aggressivesThreadCall
); 
2104         return kIOReturnSuccess
; 
2107 //****************************************************************************** 
2108 // getAggressiveness 
2110 // Override IOService::setAggressiveness() 
2111 // Fetch the aggressiveness factor with the given type. 
2112 //****************************************************************************** 
2115 IOPMrootDomain::getAggressiveness( 
2117         unsigned long * outLevel 
) 
2122         if (!outLevel 
|| (type 
> UINT_MAX
)) { 
2123                 return kIOReturnBadArgument
; 
2128         // Disk quick spindown in effect, report value = 1 
2130         if ((gAggressivesState 
& kAggressivesStateQuickSpindown
) && 
2131             (type 
== kPMMinutesToSpinDown
)) { 
2132                 value  
= kAggressivesMinValue
; 
2136         // Consult the pending request queue. 
2139                 AggressivesRequest 
* entry
; 
2141                 queue_iterate(&aggressivesQueue
, entry
, AggressivesRequest 
*, chain
) 
2143                         if ((entry
->dataType 
== kAggressivesRequestTypeRecord
) && 
2144                             (entry
->data
.record
.type 
== type
) && 
2145                             ((entry
->options 
& kAggressivesOptionQuickSpindownMask
) == 0)) { 
2146                                 value  
= entry
->data
.record
.value
; 
2153         // Consult the backend records. 
2155         if (!source 
&& aggressivesData
) { 
2156                 AggressivesRecord 
* record
; 
2159                 count  
= aggressivesData
->getLength() / sizeof(AggressivesRecord
); 
2160                 record 
= (AggressivesRecord 
*) aggressivesData
->getBytesNoCopy(); 
2162                 for (i 
= 0; i 
< count
; i
++, record
++) { 
2163                         if (record
->type 
== type
) { 
2164                                 value  
= record
->value
; 
2171         AGGRESSIVES_UNLOCK(); 
2174                 *outLevel 
= (unsigned long) value
; 
2175                 return kIOReturnSuccess
; 
2177                 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type
); 
2178                 *outLevel 
= 0; // default return = 0, driver may not check for error 
2179                 return kIOReturnInvalid
; 
2183 //****************************************************************************** 
2184 // joinAggressiveness 
2186 // Request from IOService to join future aggressiveness broadcasts. 
2187 //****************************************************************************** 
2190 IOPMrootDomain::joinAggressiveness( 
2191         IOService 
* service 
) 
2193         AggressivesRequest 
*    request
; 
2195         if (!service 
|| (service 
== this)) { 
2196                 return kIOReturnBadArgument
; 
2199         DEBUG_LOG("joinAggressiveness %s %p\n", service
->getName(), OBFUSCATE(service
)); 
2201         request 
= IONew(AggressivesRequest
, 1); 
2203                 return kIOReturnNoMemory
; 
2206         memset(request
, 0, sizeof(*request
)); 
2207         request
->dataType 
= kAggressivesRequestTypeService
; 
2208         request
->data
.service
.reset(service
, OSRetain
); // released by synchronizeAggressives() 
2211         queue_enter(&aggressivesQueue
, request
, AggressivesRequest 
*, chain
); 
2212         AGGRESSIVES_UNLOCK(); 
2214         thread_call_enter(aggressivesThreadCall
); 
2216         return kIOReturnSuccess
; 
2219 //****************************************************************************** 
2220 // handleAggressivesRequests 
2222 // Backend thread processes all incoming aggressiveness requests in the queue. 
2223 //****************************************************************************** 
2226 handleAggressivesFunction( 
2227         thread_call_param_t param1
, 
2228         thread_call_param_t param2 
) 
2231                 ((IOPMrootDomain 
*) param1
)->handleAggressivesRequests(); 
2236 IOPMrootDomain::handleAggressivesRequests( void ) 
2238         AggressivesRecord 
*     start
; 
2239         AggressivesRecord 
*     record
; 
2240         AggressivesRequest 
*    request
; 
2241         queue_head_t            joinedQueue
; 
2245         bool                    pingSelf 
= false; 
2249         if ((gAggressivesState 
& kAggressivesStateBusy
) || !aggressivesData 
|| 
2250             queue_empty(&aggressivesQueue
)) { 
2254         gAggressivesState 
|= kAggressivesStateBusy
; 
2255         count 
= aggressivesData
->getLength() / sizeof(AggressivesRecord
); 
2256         start 
= (AggressivesRecord 
*) aggressivesData
->getBytesNoCopy(); 
2260                 queue_init(&joinedQueue
); 
2263                         // Remove request from the incoming queue in FIFO order. 
2264                         queue_remove_first(&aggressivesQueue
, request
, AggressivesRequest 
*, chain
); 
2265                         switch (request
->dataType
) { 
2266                         case kAggressivesRequestTypeRecord
: 
2267                                 // Update existing record if found. 
2269                                 for (i 
= 0, record 
= start
; i 
< count
; i
++, record
++) { 
2270                                         if (record
->type 
== request
->data
.record
.type
) { 
2273                                                 if (request
->options 
& kAggressivesOptionQuickSpindownEnable
) { 
2274                                                         if ((record
->flags 
& kAggressivesRecordFlagMinValue
) == 0) { 
2276                                                                 record
->flags 
|= (kAggressivesRecordFlagMinValue 
| 
2277                                                                     kAggressivesRecordFlagModified
); 
2278                                                                 DLOG("disk spindown accelerated, was %u min\n", 
2281                                                 } else if (request
->options 
& kAggressivesOptionQuickSpindownDisable
) { 
2282                                                         if (record
->flags 
& kAggressivesRecordFlagMinValue
) { 
2284                                                                 record
->flags 
|= kAggressivesRecordFlagModified
; 
2285                                                                 record
->flags 
&= ~kAggressivesRecordFlagMinValue
; 
2286                                                                 DLOG("disk spindown restored to %u min\n", 
2289                                                 } else if (record
->value 
!= request
->data
.record
.value
) { 
2290                                                         record
->value 
= request
->data
.record
.value
; 
2291                                                         if ((record
->flags 
& kAggressivesRecordFlagMinValue
) == 0) { 
2293                                                                 record
->flags 
|= kAggressivesRecordFlagModified
; 
2300                                 // No matching record, append a new record. 
2302                                     ((request
->options 
& kAggressivesOptionQuickSpindownDisable
) == 0)) { 
2303                                         AggressivesRecord   newRecord
; 
2305                                         newRecord
.flags 
= kAggressivesRecordFlagModified
; 
2306                                         newRecord
.type  
= request
->data
.record
.type
; 
2307                                         newRecord
.value 
= request
->data
.record
.value
; 
2308                                         if (request
->options 
& kAggressivesOptionQuickSpindownEnable
) { 
2309                                                 newRecord
.flags 
|= kAggressivesRecordFlagMinValue
; 
2310                                                 DLOG("disk spindown accelerated\n"); 
2313                                         aggressivesData
->appendBytes(&newRecord
, sizeof(newRecord
)); 
2315                                         // OSData may have switched to another (larger) buffer. 
2316                                         count 
= aggressivesData
->getLength() / sizeof(AggressivesRecord
); 
2317                                         start 
= (AggressivesRecord 
*) aggressivesData
->getBytesNoCopy(); 
2321                                 // Finished processing the request, release it. 
2322                                 IODelete(request
, AggressivesRequest
, 1); 
2325                         case kAggressivesRequestTypeService
: 
2326                                 // synchronizeAggressives() will free request. 
2327                                 queue_enter(&joinedQueue
, request
, AggressivesRequest 
*, chain
); 
2331                                 panic("bad aggressives request type %x\n", request
->dataType
); 
2334                 } while (!queue_empty(&aggressivesQueue
)); 
2336                 // Release the lock to perform work, with busy flag set. 
2337                 if (!queue_empty(&joinedQueue
) || broadcast
) { 
2338                         AGGRESSIVES_UNLOCK(); 
2339                         if (!queue_empty(&joinedQueue
)) { 
2340                                 synchronizeAggressives(&joinedQueue
, start
, count
); 
2343                                 broadcastAggressives(start
, count
); 
2348                 // Remove the modified flag from all records. 
2349                 for (i 
= 0, record 
= start
; i 
< count
; i
++, record
++) { 
2350                         if ((record
->flags 
& kAggressivesRecordFlagModified
) && 
2351                             ((record
->type 
== kPMMinutesToDim
) || 
2352                             (record
->type 
== kPMMinutesToSleep
))) { 
2356                         record
->flags 
&= ~kAggressivesRecordFlagModified
; 
2359                 // Check the incoming queue again since new entries may have been 
2360                 // added while lock was released above. 
2361         } while (!queue_empty(&aggressivesQueue
)); 
2363         gAggressivesState 
&= ~kAggressivesStateBusy
; 
2366         AGGRESSIVES_UNLOCK(); 
2368         // Root domain is interested in system and display sleep slider changes. 
2369         // Submit a power event to handle those changes on the PM work loop. 
2371         if (pingSelf 
&& pmPowerStateQueue
) { 
2372                 pmPowerStateQueue
->submitPowerEvent( 
2373                         kPowerEventPolicyStimulus
, 
2374                         (void *) kStimulusAggressivenessChanged 
); 
2378 //****************************************************************************** 
2379 // synchronizeAggressives 
2381 // Push all known aggressiveness records to one or more IOService. 
2382 //****************************************************************************** 
2385 IOPMrootDomain::synchronizeAggressives( 
2386         queue_head_t 
*              joinedQueue
, 
2387         const AggressivesRecord 
*   array
, 
2390         OSSharedPtr
<IOService
>      service
; 
2391         AggressivesRequest 
*        request
; 
2392         const AggressivesRecord 
*   record
; 
2393         IOPMDriverCallEntry         callEntry
; 
2397         while (!queue_empty(joinedQueue
)) { 
2398                 queue_remove_first(joinedQueue
, request
, AggressivesRequest 
*, chain
); 
2399                 if (request
->dataType 
== kAggressivesRequestTypeService
) { 
2400                         // retained by joinAggressiveness(), so take ownership 
2401                         service 
= os::move(request
->data
.service
); 
2406                 IODelete(request
, AggressivesRequest
, 1); 
2410                         if (service
->assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetAggressive
)) { 
2411                                 for (i 
= 0, record 
= array
; i 
< count
; i
++, record
++) { 
2412                                         value 
= record
->value
; 
2413                                         if (record
->flags 
& kAggressivesRecordFlagMinValue
) { 
2414                                                 value 
= kAggressivesMinValue
; 
2417                                         _LOG("synchronizeAggressives 0x%x = %u to %s\n", 
2418                                             record
->type
, value
, service
->getName()); 
2419                                         service
->setAggressiveness(record
->type
, value
); 
2421                                 service
->deassertPMDriverCall(&callEntry
); 
2427 //****************************************************************************** 
2428 // broadcastAggressives 
2430 // Traverse PM tree and call setAggressiveness() for records that have changed. 
2431 //****************************************************************************** 
2434 IOPMrootDomain::broadcastAggressives( 
2435         const AggressivesRecord 
*   array
, 
2438         OSSharedPtr
<IORegistryIterator
> iter
; 
2439         IORegistryEntry                
*entry
; 
2440         OSSharedPtr
<IORegistryEntry
>    child
; 
2441         IOPowerConnection              
*connect
; 
2443         const AggressivesRecord        
*record
; 
2444         IOPMDriverCallEntry             callEntry
; 
2448         iter 
= IORegistryIterator::iterateOver( 
2449                 this, gIOPowerPlane
, kIORegistryIterateRecursively
); 
2452                         // !! reset the iterator 
2454                         while ((entry 
= iter
->getNextObject())) { 
2455                                 connect 
= OSDynamicCast(IOPowerConnection
, entry
); 
2456                                 if (!connect 
|| !connect
->getReadyFlag()) { 
2460                                 child 
= connect
->copyChildEntry(gIOPowerPlane
); 
2462                                         if ((service 
= OSDynamicCast(IOService
, child
.get()))) { 
2463                                                 if (service
->assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetAggressive
)) { 
2464                                                         for (i 
= 0, record 
= array
; i 
< count
; i
++, record
++) { 
2465                                                                 if (record
->flags 
& kAggressivesRecordFlagModified
) { 
2466                                                                         value 
= record
->value
; 
2467                                                                         if (record
->flags 
& kAggressivesRecordFlagMinValue
) { 
2468                                                                                 value 
= kAggressivesMinValue
; 
2470                                                                         _LOG("broadcastAggressives %x = %u to %s\n", 
2471                                                                             record
->type
, value
, service
->getName()); 
2472                                                                         service
->setAggressiveness(record
->type
, value
); 
2475                                                         service
->deassertPMDriverCall(&callEntry
); 
2480                 }while (!entry 
&& !iter
->isValid()); 
2484 //***************************************** 
2485 // stackshot on power button press 
2486 // *************************************** 
2488 powerButtonDownCallout(thread_call_param_t us
, thread_call_param_t 
) 
2490         /* Power button pressed during wake 
2493         DEBUG_LOG("Powerbutton: down. Taking stackshot\n"); 
2494         ((IOPMrootDomain 
*)us
)->takeStackshot(false); 
2498 powerButtonUpCallout(thread_call_param_t us
, thread_call_param_t
) 
2500         /* Power button released. 
2501          * Delete any stackshot data 
2503         DEBUG_LOG("PowerButton: up callout. Delete stackshot\n"); 
2504         ((IOPMrootDomain 
*)us
)->deleteStackshot(); 
2506 //************************************************************************* 
2510 // MARK: System Sleep 
2512 //****************************************************************************** 
2513 // startIdleSleepTimer 
2515 //****************************************************************************** 
2518 IOPMrootDomain::startIdleSleepTimer( uint32_t inSeconds 
) 
2520         AbsoluteTime deadline
; 
2524                 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag
); 
2528                 clock_interval_to_deadline(inSeconds
, kSecondScale
, &deadline
); 
2529                 thread_call_enter_delayed(extraSleepTimer
, deadline
); 
2530                 idleSleepTimerPending 
= true; 
2532                 thread_call_enter(extraSleepTimer
); 
2534         DLOG("idle timer set for %u seconds\n", inSeconds
); 
2537 //****************************************************************************** 
2538 // cancelIdleSleepTimer 
2540 //****************************************************************************** 
2543 IOPMrootDomain::cancelIdleSleepTimer( void ) 
2546         if (idleSleepTimerPending
) { 
2547                 DLOG("idle timer cancelled\n"); 
2548                 thread_call_cancel(extraSleepTimer
); 
2549                 idleSleepTimerPending 
= false; 
2551                 if (!assertOnWakeSecs 
&& gIOLastWakeAbsTime
) { 
2553                         clock_usec_t    microsecs
; 
2554                         clock_get_uptime(&now
); 
2555                         SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
); 
2556                         absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
); 
2557                         if (assertOnWakeReport
) { 
2558                                 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
); 
2559                                 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
); 
2565 //****************************************************************************** 
2566 // idleSleepTimerExpired 
2568 //****************************************************************************** 
2571 idleSleepTimerExpired( 
2572         thread_call_param_t us
, thread_call_param_t 
) 
2574         ((IOPMrootDomain 
*)us
)->handleSleepTimerExpiration(); 
2577 //****************************************************************************** 
2578 // handleSleepTimerExpiration 
2580 // The time between the sleep idle timeout and the next longest one has elapsed. 
2581 // It's time to sleep. Start that by removing the clamp that's holding us awake. 
2582 //****************************************************************************** 
2585 IOPMrootDomain::handleSleepTimerExpiration( void ) 
2587         if (!gIOPMWorkLoop
->inGate()) { 
2588                 gIOPMWorkLoop
->runAction( 
2589                         OSMemberFunctionCast(IOWorkLoop::Action
, this, 
2590                         &IOPMrootDomain::handleSleepTimerExpiration
), 
2595         DLOG("sleep timer expired\n"); 
2598         idleSleepTimerPending 
= false; 
2599         setQuickSpinDownTimeout(); 
2600         adjustPowerState(true); 
2603 //****************************************************************************** 
2604 // getTimeToIdleSleep 
2606 // Returns number of seconds left before going into idle sleep. 
2607 // Caller has to make sure that idle sleep is allowed at the time of calling 
2609 //****************************************************************************** 
2612 IOPMrootDomain::getTimeToIdleSleep( void ) 
2614         AbsoluteTime    now
, lastActivityTime
; 
2616         uint32_t        minutesSinceUserInactive 
= 0; 
2617         uint32_t        sleepDelay 
= 0; 
2619         if (!idleSleepEnabled
) { 
2623         if (userActivityTime
) { 
2624                 lastActivityTime 
= userActivityTime
; 
2626                 lastActivityTime 
= userBecameInactiveTime
; 
2629         // Ignore any lastActivityTime that predates the last system wake. 
2630         // The goal is to avoid a sudden idle sleep right after a dark wake 
2631         // due to sleepDelay=0 computed below. The alternative 60s minimum 
2632         // timeout should be large enough to allow dark wake to complete, 
2633         // at which point the idle timer will be promptly cancelled. 
2634         clock_get_uptime(&now
); 
2635         if ((CMP_ABSOLUTETIME(&lastActivityTime
, &gIOLastWakeAbsTime
) >= 0) && 
2636             (CMP_ABSOLUTETIME(&now
, &lastActivityTime
) > 0)) { 
2637                 SUB_ABSOLUTETIME(&now
, &lastActivityTime
); 
2638                 absolutetime_to_nanoseconds(now
, &nanos
); 
2639                 minutesSinceUserInactive 
= nanos 
/ (60000000000ULL); 
2641                 if (minutesSinceUserInactive 
>= sleepSlider
) { 
2644                         sleepDelay 
= sleepSlider 
- minutesSinceUserInactive
; 
2647                 DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n", 
2648                     lastActivityTime
, now
, gIOLastWakeAbsTime
); 
2649                 sleepDelay 
= sleepSlider
; 
2652         DLOG("user inactive %u min, time to idle sleep %u min\n", 
2653             minutesSinceUserInactive
, sleepDelay
); 
2655         return sleepDelay 
* 60; 
2658 //****************************************************************************** 
2659 // setQuickSpinDownTimeout 
2661 //****************************************************************************** 
2664 IOPMrootDomain::setQuickSpinDownTimeout( void ) 
2668                 kPMMinutesToSpinDown
, 0, kAggressivesOptionQuickSpindownEnable 
); 
2671 //****************************************************************************** 
2672 // restoreUserSpinDownTimeout 
2674 //****************************************************************************** 
2677 IOPMrootDomain::restoreUserSpinDownTimeout( void ) 
2681                 kPMMinutesToSpinDown
, 0, kAggressivesOptionQuickSpindownDisable 
); 
2684 //****************************************************************************** 
2687 //****************************************************************************** 
2691 IOPMrootDomain::sleepSystem( void ) 
2693         return sleepSystemOptions(NULL
); 
2698 IOPMrootDomain::sleepSystemOptions( OSDictionary 
*options 
) 
2700         OSObject 
*obj 
= NULL
; 
2701         OSString 
*reason 
= NULL
; 
2702         /* sleepSystem is a public function, and may be called by any kernel driver. 
2703          * And that's bad - drivers should sleep the system by calling 
2704          * receivePowerNotification() instead. Drivers should not use sleepSystem. 
2706          * Note that user space app calls to IOPMSleepSystem() will also travel 
2707          * this code path and thus be correctly identified as software sleeps. 
2710         if (options 
&& options
->getObject("OSSwitch")) { 
2711                 // Log specific sleep cause for OS Switch hibernation 
2712                 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate
); 
2715         if (options 
&& (obj 
= options
->getObject("Sleep Reason"))) { 
2716                 reason 
= OSDynamicCast(OSString
, obj
); 
2717                 if (reason 
&& reason
->isEqualTo(kIOPMDarkWakeThermalEmergencyKey
)) { 
2718                         return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency
); 
2720                 if (reason 
&& reason
->isEqualTo(kIOPMNotificationWakeExitKey
)) { 
2721                         return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit
); 
2725         return privateSleepSystem( kIOPMSleepReasonSoftware
); 
2730 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason 
) 
2732         /* Called from both gated and non-gated context */ 
2734         if (!checkSystemSleepEnabled() || !pmPowerStateQueue
) { 
2735                 return kIOReturnNotPermitted
; 
2738         pmPowerStateQueue
->submitPowerEvent( 
2739                 kPowerEventPolicyStimulus
, 
2740                 (void *) kStimulusDemandSystemSleep
, 
2743         return kIOReturnSuccess
; 
2746 //****************************************************************************** 
2749 // This overrides powerChangeDone in IOService. 
2750 //****************************************************************************** 
2752 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState 
) 
2754 #if !__i386__ && !__x86_64__ 
2755         uint64_t    timeSinceReset 
= 0; 
2758         unsigned long      newState
; 
2760         clock_usec_t       microsecs
; 
2761         uint32_t           lastDebugWakeSeconds
; 
2762         clock_sec_t        adjWakeTime
; 
2763         IOPMCalendarStruct nowCalendar
; 
2766         newState 
= getPowerState(); 
2767         DLOG("PowerChangeDone: %s->%s\n", 
2768             getPowerStateString((uint32_t) previousPowerState
), getPowerStateString((uint32_t) getPowerState())); 
2770         if (previousPowerState 
== newState
) { 
2774         notifierThread 
= current_thread(); 
2775         switch (getPowerState()) { 
2777                 if (kPMCalendarTypeInvalid 
!= _aotWakeTimeCalendar
.selector
) { 
2780                         PEGetUTCTimeOfDay(&secs
, µsecs
); 
2783                         if ((kIOPMAOTModeRespectTimers 
& _aotMode
) && (_calendarWakeAlarmUTC 
< _aotWakeTimeUTC
)) { 
2784                                 IOLog("use _calendarWakeAlarmUTC\n"); 
2785                                 adjWakeTime 
= _calendarWakeAlarmUTC
; 
2786                         } else if (_aotExit 
|| (kIOPMWakeEventAOTExitFlags 
& _aotPendingFlags
)) { 
2787                                 IOLog("accelerate _aotWakeTime for exit\n"); 
2789                         } else if (kIOPMDriverAssertionLevelOn 
== getPMAssertionLevel(kIOPMDriverAssertionCPUBit
)) { 
2790                                 IOLog("accelerate _aotWakeTime for assertion\n"); 
2794                                 IOPMConvertSecondsToCalendar(adjWakeTime
, &_aotWakeTimeCalendar
); 
2797                         IOPMConvertSecondsToCalendar(secs
, &nowCalendar
); 
2798                         IOLog("aotSleep at " YMDTF 
" sched: " YMDTF 
"\n", YMDT(&nowCalendar
), YMDT(&_aotWakeTimeCalendar
)); 
2800                         IOReturn __unused ret 
= setMaintenanceWakeCalendar(&_aotWakeTimeCalendar
); 
2801                         assert(kIOReturnSuccess 
== ret
); 
2803                 if (_aotLastWakeTime
) { 
2804                         _aotMetrics
->totalTime 
+= mach_absolute_time() - _aotLastWakeTime
; 
2805                         if (_aotMetrics
->sleepCount 
&& (_aotMetrics
->sleepCount 
<= kIOPMAOTMetricsKernelWakeCountMax
)) { 
2806                                 strlcpy(&_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount 
- 1][0], 
2808                                     sizeof(_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
])); 
2811                 _aotPendingFlags 
&= ~kIOPMWakeEventAOTPerCycleFlags
; 
2812                 if (_aotTimerScheduled
) { 
2813                         _aotTimerES
->cancelTimeout(); 
2814                         _aotTimerScheduled 
= false; 
2816                 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable
); 
2818                 // re-enable this timer for next sleep 
2819                 cancelIdleSleepTimer(); 
2821                 if (clamshellExists
) { 
2822 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 
2823                         if (gClamshellFlags 
& kClamshell_WAR_58009435
) { 
2824                                 // Disable clamshell sleep until system has completed full wake. 
2825                                 // This prevents a system sleep request (due to a clamshell close) 
2826                                 // from being queued until the end of system full wake - even if 
2827                                 // other clamshell disable bits outside of our control is wrong. 
2828                                 setClamShellSleepDisable(true, kClamshellSleepDisableInternal
); 
2832                         // Log the last known clamshell state before system sleep 
2833                         DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n", 
2834                             clamshellClosed
, clamshellDisabled
, clamshellSleepDisableMask
, 
2835                             desktopMode
, acAdaptorConnected
); 
2838                 clock_get_calendar_absolute_and_microtime(&secs
, µsecs
, &now
); 
2840                 gIOLastSleepTime
.tv_sec  
= secs
; 
2841                 gIOLastSleepTime
.tv_usec 
= microsecs
; 
2842                 if (!_aotLastWakeTime
) { 
2843                         gIOLastUserSleepTime 
= gIOLastSleepTime
; 
2846                 gIOLastWakeTime
.tv_sec 
= 0; 
2847                 gIOLastWakeTime
.tv_usec 
= 0; 
2848                 gIOLastSleepAbsTime 
= now
; 
2850                 if (wake2DarkwakeDelay 
&& sleepDelaysReport
) { 
2851                         clock_sec_t     wake2DarkwakeSecs
, darkwake2SleepSecs
; 
2852                         // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition 
2854                         SUB_ABSOLUTETIME(&now
, &ts_sleepStart
); 
2855                         absolutetime_to_microtime(now
, &darkwake2SleepSecs
, µsecs
); 
2856                         absolutetime_to_microtime(wake2DarkwakeDelay
, &wake2DarkwakeSecs
, µsecs
); 
2857                         HISTREPORT_TALLYVALUE(sleepDelaysReport
, 
2858                             (int64_t)(wake2DarkwakeSecs 
+ darkwake2SleepSecs
)); 
2860                         DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs
, (unsigned long)darkwake2SleepSecs
); 
2861                         wake2DarkwakeDelay 
= 0; 
2864                 LOG("System %sSleep\n", gIOHibernateState 
? "Safe" : ""); 
2866                 IOHibernateSystemHasSlept(); 
2868                 evaluateSystemSleepPolicyFinal(); 
2870                 LOG("System Sleep\n"); 
2872                 if (thermalWarningState
) { 
2873                         OSSharedPtr
<const OSSymbol
> event 
= OSSymbol::withCString(kIOPMThermalLevelWarningKey
); 
2875                                 systemPowerEventOccurred(event
.get(), kIOPMThermalLevelUnknown
); 
2878                 assertOnWakeSecs 
= 0; 
2879                 lowBatteryCondition 
= false; 
2880                 thermalEmergencyState 
= false; 
2882 #if DEVELOPMENT || DEBUG 
2883                 extern int g_should_log_clock_adjustments
; 
2884                 if (g_should_log_clock_adjustments
) { 
2885                         clock_sec_t  secs 
= 0; 
2886                         clock_usec_t microsecs 
= 0; 
2887                         uint64_t now_b 
= mach_absolute_time(); 
2891                         PEGetUTCTimeOfDay(&secs
, µsecs
); 
2893                         uint64_t now_a 
= mach_absolute_time(); 
2894                         os_log(OS_LOG_DEFAULT
, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n", 
2895                             __func__
, (unsigned long)secs
, microsecs
, now_b
, now_a
); 
2899                 getPlatform()->sleepKernel(); 
2901                 // The CPU(s) are off at this point, 
2902                 // Code will resume execution here upon wake. 
2904                 clock_get_uptime(&gIOLastWakeAbsTime
); 
2905                 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime
); 
2906                 _highestCapability 
= 0; 
2909                 IOHibernateSystemWake(); 
2912                 // sleep transition complete 
2913                 gSleepOrShutdownPending 
= 0; 
2915                 // trip the reset of the calendar clock 
2916                 clock_wakeup_calendar(); 
2917                 clock_get_calendar_microtime(&secs
, µsecs
); 
2918                 gIOLastWakeTime
.tv_sec  
= secs
; 
2919                 gIOLastWakeTime
.tv_usec 
= microsecs
; 
2922                 if (_aotWakeTimeCalendar
.selector 
!= kPMCalendarTypeInvalid
) { 
2923                         _aotWakeTimeCalendar
.selector 
= kPMCalendarTypeInvalid
; 
2926                         PEGetUTCTimeOfDay(&secs
, µsecs
); 
2927                         IOPMConvertSecondsToCalendar(secs
, &nowCalendar
); 
2928                         IOLog("aotWake at " YMDTF 
" sched: " YMDTF 
"\n", YMDT(&nowCalendar
), YMDT(&_aotWakeTimeCalendar
)); 
2929                         _aotMetrics
->sleepCount
++; 
2930                         _aotLastWakeTime 
= gIOLastWakeAbsTime
; 
2931                         if (_aotMetrics
->sleepCount 
<= kIOPMAOTMetricsKernelWakeCountMax
) { 
2932                                 _aotMetrics
->kernelSleepTime
[_aotMetrics
->sleepCount 
- 1] 
2933                                         = (((uint64_t) gIOLastSleepTime
.tv_sec
) << 10) + (gIOLastSleepTime
.tv_usec 
/ 1000); 
2934                                 _aotMetrics
->kernelWakeTime
[_aotMetrics
->sleepCount 
- 1] 
2935                                         = (((uint64_t) gIOLastWakeTime
.tv_sec
) << 10) + (gIOLastWakeTime
.tv_usec 
/ 1000); 
2939                                 if (_aotWakeTimeUTC 
<= secs
) { 
2940                                         _aotTestTime 
= _aotTestTime 
+ _aotTestInterval
; 
2942                                 setWakeTime(_aotTestTime
); 
2947                 LOG("System %sWake\n", gIOHibernateState 
? "SafeSleep " : ""); 
2950                 lastSleepReason 
= 0; 
2952                 lastDebugWakeSeconds    
= _debugWakeSeconds
; 
2953                 _debugWakeSeconds       
= 0; 
2954                 _scheduledAlarmMask     
= 0; 
2955                 _nextScheduledAlarmType 
= NULL
; 
2957                 darkWakeExit            
= false; 
2958                 darkWakePowerClamped    
= false; 
2959                 darkWakePostTickle      
= false; 
2960                 darkWakeHibernateError  
= false; 
2961                 darkWakeToSleepASAP     
= true; 
2962                 darkWakeLogClamp        
= true; 
2963                 sleepTimerMaintenance   
= false; 
2964                 sleepToStandby          
= false; 
2965                 wranglerTickled         
= false; 
2966                 userWasActive           
= false; 
2967                 isRTCAlarmWake          
= false; 
2968                 clamshellIgnoreClose    
= false; 
2969                 fullWakeReason 
= kFullWakeReasonNone
; 
2971 #if defined(__i386__) || defined(__x86_64__) 
2972                 kdebugTrace(kPMLogSystemWake
, 0, 0, 0); 
2974                 OSSharedPtr
<OSObject
> wakeTypeProp   
= copyProperty(kIOPMRootDomainWakeTypeKey
); 
2975                 OSSharedPtr
<OSObject
> wakeReasonProp 
= copyProperty(kIOPMRootDomainWakeReasonKey
); 
2976                 OSString 
* wakeType 
= OSDynamicCast(OSString
, wakeTypeProp
.get()); 
2977                 OSString 
* wakeReason 
= OSDynamicCast(OSString
, wakeReasonProp
.get()); 
2979                 if (wakeReason 
&& (wakeReason
->getLength() >= 2) && 
2980                     gWakeReasonString
[0] == '\0') { 
2982                         // Until the platform driver can claim its wake reasons 
2983                         strlcat(gWakeReasonString
, wakeReason
->getCStringNoCopy(), 
2984                             sizeof(gWakeReasonString
)); 
2985                         if (!gWakeReasonSysctlRegistered
) { 
2986                                 gWakeReasonSysctlRegistered 
= true; 
2991                 if (wakeType 
&& wakeType
->isEqualTo(kIOPMrootDomainWakeTypeLowBattery
)) { 
2992                         lowBatteryCondition 
= true; 
2993                         darkWakeMaintenance 
= true; 
2996                         OSSharedPtr
<OSObject
> hibOptionsProp 
= copyProperty(kIOHibernateOptionsKey
); 
2997                         OSNumber 
* hibOptions 
= OSDynamicCast(  OSNumber
, hibOptionsProp
.get()); 
2998                         if (hibernateAborted 
|| ((hibOptions 
&& 
2999                             !(hibOptions
->unsigned32BitValue() & kIOHibernateOptionDarkWake
)))) { 
3000                                 // Hibernate aborted, or EFI brought up graphics 
3001                                 darkWakeExit 
= true; 
3002                                 if (hibernateAborted
) { 
3003                                         DLOG("Hibernation aborted\n"); 
3005                                         DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions
->unsigned32BitValue()); 
3010                                     wakeType
->isEqualTo(kIOPMRootDomainWakeTypeUser
) || 
3011                                     wakeType
->isEqualTo(kIOPMRootDomainWakeTypeAlarm
))) { 
3012                                 // User wake or RTC alarm 
3013                                 darkWakeExit 
= true; 
3014                                 if (wakeType
->isEqualTo(kIOPMRootDomainWakeTypeAlarm
)) { 
3015                                         isRTCAlarmWake 
= true; 
3017                         } else if (wakeType 
&& 
3018                             wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer
)) { 
3019                                 // SMC standby timer trumps SleepX 
3020                                 darkWakeMaintenance 
= true; 
3021                                 sleepTimerMaintenance 
= true; 
3022                         } else if ((lastDebugWakeSeconds 
!= 0) && 
3023                             ((gDarkWakeFlags 
& kDarkWakeFlagAlarmIsDark
) == 0)) { 
3024                                 // SleepX before maintenance 
3025                                 darkWakeExit 
= true; 
3026                         } else if (wakeType 
&& 
3027                             wakeType
->isEqualTo(kIOPMRootDomainWakeTypeMaintenance
)) { 
3028                                 darkWakeMaintenance 
= true; 
3029                         } else if (wakeType 
&& 
3030                             wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepService
)) { 
3031                                 darkWakeMaintenance 
= true; 
3032                                 darkWakeSleepService 
= true; 
3034                                 if (kIOHibernateStateWakingFromHibernate 
== gIOHibernateState
) { 
3035                                         sleepToStandby 
= true; 
3038                         } else if (wakeType 
&& 
3039                             wakeType
->isEqualTo(kIOPMRootDomainWakeTypeHibernateError
)) { 
3040                                 darkWakeMaintenance 
= true; 
3041                                 darkWakeHibernateError 
= true; 
3043                                 // Unidentified wake source, resume to full wake if debug 
3044                                 // alarm is pending. 
3046                                 if (lastDebugWakeSeconds 
&& 
3047                                     (!wakeReason 
|| wakeReason
->isEqualTo(""))) { 
3048                                         darkWakeExit 
= true; 
3054                         darkWakeToSleepASAP 
= false; 
3055                         fullWakeReason 
= kFullWakeReasonLocalUser
; 
3057                 } else if (displayPowerOnRequested 
&& checkSystemCanSustainFullWake()) { 
3058                         handleSetDisplayPowerOn(true); 
3059                 } else if (!darkWakeMaintenance
) { 
3060                         // Early/late tickle for non-maintenance wake. 
3061                         if ((gDarkWakeFlags 
& kDarkWakeFlagPromotionMask
) != kDarkWakeFlagPromotionNone
) { 
3062                                 darkWakePostTickle 
= true; 
3065 #else   /* !__i386__ && !__x86_64__ */ 
3066                 timeSinceReset 
= ml_get_time_since_reset(); 
3067                 kdebugTrace(kPMLogSystemWake
, 0, (uintptr_t)(timeSinceReset 
>> 32), (uintptr_t) timeSinceReset
); 
3069                 if ((gDarkWakeFlags 
& kDarkWakeFlagPromotionMask
) == kDarkWakeFlagPromotionEarly
) { 
3070                         wranglerTickled 
= true; 
3071                         fullWakeReason 
= kFullWakeReasonLocalUser
; 
3072                         requestUserActive(this, "Full wake on dark wake promotion boot-arg"); 
3073                 } else if ((lastDebugWakeSeconds 
!= 0) && !(gDarkWakeFlags 
& kDarkWakeFlagAlarmIsDark
)) { 
3074                         isRTCAlarmWake 
= true; 
3075                         fullWakeReason 
= kFullWakeReasonLocalUser
; 
3076                         requestUserActive(this, "RTC debug alarm"); 
3079                         OSSharedPtr
<OSObject
> hibOptionsProp 
= copyProperty(kIOHibernateOptionsKey
); 
3080                         OSNumber 
* hibOptions 
= OSDynamicCast(OSNumber
, hibOptionsProp
.get()); 
3081                         if (hibOptions 
&& !(hibOptions
->unsigned32BitValue() & kIOHibernateOptionDarkWake
)) { 
3082                                 fullWakeReason 
= kFullWakeReasonLocalUser
; 
3083                                 requestUserActive(this, "hibernate user wake"); 
3088                 // stay awake for at least 30 seconds 
3089                 startIdleSleepTimer(30); 
3093                 thread_call_enter(updateConsoleUsersEntry
); 
3095                 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake
); 
3098 #if !__i386__ && !__x86_64__ 
3102                 DLOG("Force re-evaluating aggressiveness\n"); 
3103                 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */ 
3104                 pmPowerStateQueue
->submitPowerEvent( 
3105                         kPowerEventPolicyStimulus
, 
3106                         (void *) kStimulusNoIdleSleepPreventers 
); 
3108                 // After changing to ON_STATE, invalidate any previously queued 
3109                 // request to change to a state less than ON_STATE. This isn't 
3110                 // necessary for AOT_STATE or if the device has only one running 
3111                 // state since the changePowerStateToPriv() issued at the tail 
3112                 // end of SLEEP_STATE case should take care of that. 
3113                 if (getPowerState() == ON_STATE
) { 
3114                         changePowerStateWithTagToPriv(ON_STATE
, kCPSReasonWake
); 
3118 #endif /* !__i386__ && !__x86_64__ */ 
3120         notifierThread 
= NULL
; 
3123 //****************************************************************************** 
3124 // requestPowerDomainState 
3126 // Extend implementation in IOService. Running on PM work loop thread. 
3127 //****************************************************************************** 
3130 IOPMrootDomain::requestPowerDomainState( 
3131         IOPMPowerFlags      childDesire
, 
3132         IOPowerConnection 
* childConnection
, 
3133         unsigned long       specification 
) 
3135         // Idle and system sleep prevention flags affects driver desire. 
3136         // Children desire are irrelevant so they are cleared. 
3138         return super::requestPowerDomainState(0, childConnection
, specification
); 
3143 makeSleepPreventersListLog(const OSSharedPtr
<OSSet
> &preventers
, char *buf
, size_t buf_size
) 
3145         if (!preventers
->getCount()) { 
3149         char *buf_iter 
= buf 
+ strlen(buf
); 
3150         char *buf_end 
= buf 
+ buf_size
; 
3152         OSSharedPtr
<OSCollectionIterator
> iterator 
= OSCollectionIterator::withCollection(preventers
.get()); 
3153         OSObject 
*obj 
= NULL
; 
3155         while ((obj 
= iterator
->getNextObject())) { 
3156                 IOService 
*srv 
= OSDynamicCast(IOService
, obj
); 
3157                 if (buf_iter 
< buf_end
) { 
3158                         buf_iter 
+= snprintf(buf_iter
, buf_end 
- buf_iter
, " %s", srv
->getName()); 
3160                         DLOG("Print buffer exhausted for sleep preventers list\n"); 
3166 //****************************************************************************** 
3167 // updatePreventIdleSleepList 
3169 // Called by IOService on PM work loop. 
3170 // Returns true if PM policy recognized the driver's desire to prevent idle 
3171 // sleep and updated the list of idle sleep preventers. Returns false otherwise 
3172 //****************************************************************************** 
3175 IOPMrootDomain::updatePreventIdleSleepList( 
3176         IOService 
* service
, bool addNotRemove
) 
3178         unsigned int oldCount
; 
3180         oldCount 
= idleSleepPreventersCount(); 
3181         return updatePreventIdleSleepListInternal(service
, addNotRemove
, oldCount
); 
3185 IOPMrootDomain::updatePreventIdleSleepListInternal( 
3186         IOService 
* service
, bool addNotRemove
, unsigned int oldCount
) 
3188         unsigned int newCount
; 
3192 #if defined(XNU_TARGET_OS_OSX) 
3193         // Only the display wrangler and no-idle-sleep kernel assertions 
3194         // can prevent idle sleep. The kIOPMPreventIdleSleep capability flag 
3195         // reported by drivers in their power state table is ignored. 
3196         if (service 
&& (service 
!= wrangler
) && (service 
!= this)) { 
3203                         preventIdleSleepList
->setObject(service
); 
3204                         DLOG("Added %s to idle sleep preventers list (Total %u)\n", 
3205                             service
->getName(), preventIdleSleepList
->getCount()); 
3206                 } else if (preventIdleSleepList
->member(service
)) { 
3207                         preventIdleSleepList
->removeObject(service
); 
3208                         DLOG("Removed %s from idle sleep preventers list (Total %u)\n", 
3209                             service
->getName(), preventIdleSleepList
->getCount()); 
3212                 if (preventIdleSleepList
->getCount()) { 
3213                         char buf
[256] = "Idle Sleep Preventers:"; 
3214                         makeSleepPreventersListLog(preventIdleSleepList
, buf
, sizeof(buf
)); 
3219         newCount 
= idleSleepPreventersCount(); 
3221         if ((oldCount 
== 0) && (newCount 
!= 0)) { 
3222                 // Driver added to empty prevent list. 
3223                 // Update the driver desire to prevent idle sleep. 
3224                 // Driver desire does not prevent demand sleep. 
3226                 changePowerStateWithTagTo(getRUN_STATE(), kCPSReasonIdleSleepPrevent
); 
3227         } else if ((oldCount 
!= 0) && (newCount 
== 0)) { 
3228                 // Last driver removed from prevent list. 
3229                 // Drop the driver clamp to allow idle sleep. 
3231                 changePowerStateWithTagTo(SLEEP_STATE
, kCPSReasonIdleSleepAllow
); 
3232                 evaluatePolicy( kStimulusNoIdleSleepPreventers 
); 
3234         messageClient(kIOPMMessageIdleSleepPreventers
, systemCapabilityNotifier
.get(), 
3235             &newCount
, sizeof(newCount
)); 
3237 #if defined(XNU_TARGET_OS_OSX) 
3238         if (addNotRemove 
&& (service 
== wrangler
) && !checkSystemCanSustainFullWake()) { 
3239                 DLOG("Cannot cancel idle sleep\n"); 
3240                 return false; // do not idle-cancel 
3247 //****************************************************************************** 
3249 //****************************************************************************** 
3252 IOPMrootDomain::startSpinDump(uint32_t spindumpKind
) 
3254         messageClients(kIOPMMessageLaunchBootSpinDump
, (void *)(uintptr_t)spindumpKind
); 
3257 //****************************************************************************** 
3258 // preventSystemSleepListUpdate 
3260 // Called by IOService on PM work loop. 
3261 //****************************************************************************** 
3264 IOPMrootDomain::updatePreventSystemSleepList( 
3265         IOService 
* service
, bool addNotRemove 
) 
3267         unsigned int oldCount
, newCount
; 
3270         if (this == service
) { 
3274         oldCount 
= preventSystemSleepList
->getCount(); 
3276                 preventSystemSleepList
->setObject(service
); 
3277                 DLOG("Added %s to system sleep preventers list (Total %u)\n", 
3278                     service
->getName(), preventSystemSleepList
->getCount()); 
3279                 if (!assertOnWakeSecs 
&& gIOLastWakeAbsTime
) { 
3281                         clock_usec_t    microsecs
; 
3282                         clock_get_uptime(&now
); 
3283                         SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
); 
3284                         absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
); 
3285                         if (assertOnWakeReport
) { 
3286                                 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
); 
3287                                 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
); 
3290         } else if (preventSystemSleepList
->member(service
)) { 
3291                 preventSystemSleepList
->removeObject(service
); 
3292                 DLOG("Removed %s from system sleep preventers list (Total %u)\n", 
3293                     service
->getName(), preventSystemSleepList
->getCount()); 
3295                 if ((oldCount 
!= 0) && (preventSystemSleepList
->getCount() == 0)) { 
3296                         // Lost all system sleep preventers. 
3297                         // Send stimulus if system sleep was blocked, and is in dark wake. 
3298                         evaluatePolicy( kStimulusDarkWakeEvaluate 
); 
3302         newCount 
= preventSystemSleepList
->getCount(); 
3304                 char buf
[256] = "System Sleep Preventers:"; 
3305                 makeSleepPreventersListLog(preventSystemSleepList
, buf
, sizeof(buf
)); 
3309         messageClient(kIOPMMessageSystemSleepPreventers
, systemCapabilityNotifier
.get(), 
3310             &newCount
, sizeof(newCount
)); 
3314 IOPMrootDomain::copySleepPreventersList(OSArray 
**idleSleepList
, OSArray 
**systemSleepList
) 
3316         OSSharedPtr
<OSCollectionIterator
> iterator
; 
3317         OSObject    
*object 
= NULL
; 
3318         OSSharedPtr
<OSArray
>     array
; 
3320         if (!gIOPMWorkLoop
->inGate()) { 
3321                 gIOPMWorkLoop
->runAction( 
3322                         OSMemberFunctionCast(IOWorkLoop::Action
, this, 
3323                         &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList
), 
3324                         this, (void *)idleSleepList
, (void *)systemSleepList
); 
3328         if (idleSleepList 
&& preventIdleSleepList 
&& (preventIdleSleepList
->getCount() != 0)) { 
3329                 iterator 
= OSCollectionIterator::withCollection(preventIdleSleepList
.get()); 
3330                 array 
= OSArray::withCapacity(5); 
3332                 if (iterator 
&& array
) { 
3333                         while ((object 
= iterator
->getNextObject())) { 
3334                                 IOService 
*service 
= OSDynamicCast(IOService
, object
); 
3336                                         OSSharedPtr
<const OSSymbol
> name 
= service
->copyName(); 
3338                                                 array
->setObject(name
.get()); 
3343                 *idleSleepList 
= array
.detach(); 
3346         if (systemSleepList 
&& preventSystemSleepList 
&& (preventSystemSleepList
->getCount() != 0)) { 
3347                 iterator 
= OSCollectionIterator::withCollection(preventSystemSleepList
.get()); 
3348                 array 
= OSArray::withCapacity(5); 
3350                 if (iterator 
&& array
) { 
3351                         while ((object 
= iterator
->getNextObject())) { 
3352                                 IOService 
*service 
= OSDynamicCast(IOService
, object
); 
3354                                         OSSharedPtr
<const OSSymbol
> name 
= service
->copyName(); 
3356                                                 array
->setObject(name
.get()); 
3361                 *systemSleepList 
= array
.detach(); 
3366 IOPMrootDomain::copySleepPreventersListWithID(OSArray 
**idleSleepList
, OSArray 
**systemSleepList
) 
3368         OSSharedPtr
<OSCollectionIterator
> iterator
; 
3369         OSObject    
*object 
= NULL
; 
3370         OSSharedPtr
<OSArray
>     array
; 
3372         if (!gIOPMWorkLoop
->inGate()) { 
3373                 gIOPMWorkLoop
->runAction( 
3374                         OSMemberFunctionCast(IOWorkLoop::Action
, this, 
3375                         &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID
), 
3376                         this, (void *)idleSleepList
, (void *)systemSleepList
); 
3380         if (idleSleepList 
&& preventIdleSleepList 
&& (preventIdleSleepList
->getCount() != 0)) { 
3381                 iterator 
= OSCollectionIterator::withCollection(preventIdleSleepList
.get()); 
3382                 array 
= OSArray::withCapacity(5); 
3384                 if (iterator 
&& array
) { 
3385                         while ((object 
= iterator
->getNextObject())) { 
3386                                 IOService 
*service 
= OSDynamicCast(IOService
, object
); 
3388                                         OSSharedPtr
<OSDictionary
> dict 
= OSDictionary::withCapacity(2); 
3389                                         OSSharedPtr
<const OSSymbol
> name 
= service
->copyName(); 
3390                                         OSSharedPtr
<OSNumber
> id 
= OSNumber::withNumber(service
->getRegistryEntryID(), 64); 
3391                                         if (dict 
&& name 
&& id
) { 
3392                                                 dict
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, id
.get()); 
3393                                                 dict
->setObject(kIOPMDriverAssertionOwnerStringKey
, name
.get()); 
3394                                                 array
->setObject(dict
.get()); 
3399                 *idleSleepList 
= array
.detach(); 
3402         if (systemSleepList 
&& preventSystemSleepList 
&& (preventSystemSleepList
->getCount() != 0)) { 
3403                 iterator 
= OSCollectionIterator::withCollection(preventSystemSleepList
.get()); 
3404                 array 
= OSArray::withCapacity(5); 
3406                 if (iterator 
&& array
) { 
3407                         while ((object 
= iterator
->getNextObject())) { 
3408                                 IOService 
*service 
= OSDynamicCast(IOService
, object
); 
3410                                         OSSharedPtr
<OSDictionary
> dict 
= OSDictionary::withCapacity(2); 
3411                                         OSSharedPtr
<const OSSymbol
> name 
= service
->copyName(); 
3412                                         OSSharedPtr
<OSNumber
> id 
= OSNumber::withNumber(service
->getRegistryEntryID(), 64); 
3413                                         if (dict 
&& name 
&& id
) { 
3414                                                 dict
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, id
.get()); 
3415                                                 dict
->setObject(kIOPMDriverAssertionOwnerStringKey
, name
.get()); 
3416                                                 array
->setObject(dict
.get()); 
3421                 *systemSleepList 
= array
.detach(); 
3425 //****************************************************************************** 
3428 // Override the superclass implementation to send a different message type. 
3429 //****************************************************************************** 
3432 IOPMrootDomain::tellChangeDown( unsigned long stateNum 
) 
3434         DLOG("tellChangeDown %s->%s\n", 
3435             getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
)); 
3437         if (SLEEP_STATE 
== stateNum
) { 
3438                 // Legacy apps were already told in the full->dark transition 
3439                 if (!ignoreTellChangeDown
) { 
3440                         tracePoint( kIOPMTracePointSleepApplications 
); 
3442                         tracePoint( kIOPMTracePointSleepPriorityClients 
); 
3446         if (!ignoreTellChangeDown
) { 
3447                 userActivityAtSleep 
= userActivityCount
; 
3448                 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep
); 
3450                 if (SLEEP_STATE 
== stateNum
) { 
3451                         hibernateAborted 
= false; 
3453                         // Direct callout into OSKext so it can disable kext unloads 
3454                         // during sleep/wake to prevent deadlocks. 
3455                         OSKextSystemSleepOrWake( kIOMessageSystemWillSleep 
); 
3457                         IOService::updateConsoleUsers(NULL
, kIOMessageSystemWillSleep
); 
3459                         // Two change downs are sent by IOServicePM. Ignore the 2nd. 
3460                         // But tellClientsWithResponse() must be called for both. 
3461                         ignoreTellChangeDown 
= true; 
3465         return super::tellClientsWithResponse( kIOMessageSystemWillSleep 
); 
3468 //****************************************************************************** 
3471 // Override the superclass implementation to send a different message type. 
3472 // This must be idle sleep since we don't ask during any other power change. 
3473 //****************************************************************************** 
3476 IOPMrootDomain::askChangeDown( unsigned long stateNum 
) 
3478         DLOG("askChangeDown %s->%s\n", 
3479             getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
)); 
3481         // Don't log for dark wake entry 
3482         if (kSystemTransitionSleep 
== _systemTransitionType
) { 
3483                 tracePoint( kIOPMTracePointSleepApplications 
); 
3486         return super::tellClientsWithResponse( kIOMessageCanSystemSleep 
); 
3489 //****************************************************************************** 
3490 // askChangeDownDone 
3492 // An opportunity for root domain to cancel the power transition, 
3493 // possibily due to an assertion created by powerd in response to 
3494 // kIOMessageCanSystemSleep. 
3497 //   full -> dark wake transition 
3498 //     1. Notify apps and powerd with kIOMessageCanSystemSleep 
3499 //     2. askChangeDownDone() 
3500 //   dark -> sleep transition 
3501 //     1. Notify powerd with kIOMessageCanSystemSleep 
3502 //     2. askChangeDownDone() 
3505 //   full -> dark wake transition 
3506 //     1. Notify powerd with kIOMessageCanSystemSleep 
3507 //     2. askChangeDownDone() 
3508 //   dark -> sleep transition 
3509 //     1. Notify powerd with kIOMessageCanSystemSleep 
3510 //     2. askChangeDownDone() 
3511 //****************************************************************************** 
3514 IOPMrootDomain::askChangeDownDone( 
3515         IOPMPowerChangeFlags 
* inOutChangeFlags
, bool * cancel 
) 
3517         DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n", 
3518             *inOutChangeFlags
, *cancel
, 
3519             _systemTransitionType
, 
3520             _currentCapability
, _pendingCapability
); 
3522         if ((false == *cancel
) && (kSystemTransitionSleep 
== _systemTransitionType
)) { 
3523                 // Dark->Sleep transition. 
3524                 // Check if there are any deny sleep assertions. 
3525                 // lastSleepReason already set by handleOurPowerChangeStart() 
3527                 if (!checkSystemCanSleep(lastSleepReason
)) { 
3528                         // Cancel dark wake to sleep transition. 
3529                         // Must re-scan assertions upon entering dark wake. 
3532                         DLOG("cancel dark->sleep\n"); 
3534                 if (_aotMode 
&& (kPMCalendarTypeInvalid 
!= _aotWakeTimeCalendar
.selector
)) { 
3535                         uint64_t now 
= mach_continuous_time(); 
3536                         if (((now 
+ _aotWakePreWindow
) >= _aotWakeTimeContinuous
) 
3537                             && (now 
< (_aotWakeTimeContinuous 
+ _aotWakePostWindow
))) { 
3539                                 IOLog("AOT wake window cancel: %qd, %qd\n", now
, _aotWakeTimeContinuous
); 
3545 //****************************************************************************** 
3546 // systemDidNotSleep 
3548 // Work common to both canceled or aborted sleep. 
3549 //****************************************************************************** 
3552 IOPMrootDomain::systemDidNotSleep( void ) 
3554         // reset console lock state 
3555         thread_call_enter(updateConsoleUsersEntry
); 
3557         if (idleSleepEnabled
) { 
3559 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 
3560                         startIdleSleepTimer(kIdleSleepRetryInterval
); 
3562                         startIdleSleepTimer(idleSeconds
); 
3564                 } else if (!userIsActive
) { 
3565                         // Manually start the idle sleep timer besides waiting for 
3566                         // the user to become inactive. 
3567                         startIdleSleepTimer(kIdleSleepRetryInterval
); 
3571         preventTransitionToUserActive(false); 
3572         IOService::setAdvisoryTickleEnable( true ); 
3574         // After idle revert and cancel, send a did-change message to powerd 
3575         // to balance the previous will-change message. Kernel clients do not 
3576         // need this since sleep cannot be canceled once they are notified. 
3578         if (toldPowerdCapWillChange 
&& systemCapabilityNotifier 
&& 
3579             (_pendingCapability 
!= _currentCapability
) && 
3580             ((_systemMessageClientMask 
& kSystemMessageClientPowerd
) != 0)) { 
3581                 // Differs from a real capability gain change where notifyRef != 0, 
3582                 // but it is zero here since no response is expected. 
3584                 IOPMSystemCapabilityChangeParameters params
; 
3586                 bzero(¶ms
, sizeof(params
)); 
3587                 params
.fromCapabilities 
= _pendingCapability
; 
3588                 params
.toCapabilities 
= _currentCapability
; 
3589                 params
.changeFlags 
= kIOPMSystemCapabilityDidChange
; 
3591                 DLOG("MESG cap %x->%x did change\n", 
3592                     params
.fromCapabilities
, params
.toCapabilities
); 
3593                 messageClient(kIOMessageSystemCapabilityChange
, systemCapabilityNotifier
.get(), 
3594                     ¶ms
, sizeof(params
)); 
3598 //****************************************************************************** 
3601 // Notify registered applications and kernel clients that we are not dropping 
3604 // We override the superclass implementation so we can send a different message 
3605 // type to the client or application being notified. 
3607 // This must be a vetoed idle sleep, since no other power change can be vetoed. 
3608 //****************************************************************************** 
3611 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum 
) 
3613         DLOG("tellNoChangeDown %s->%s\n", 
3614             getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
)); 
3616         // Sleep canceled, clear the sleep trace point. 
3617         tracePoint(kIOPMTracePointSystemUp
); 
3619         systemDidNotSleep(); 
3620         return tellClients( kIOMessageSystemWillNotSleep 
); 
3623 //****************************************************************************** 
3626 // Notify registered applications and kernel clients that we are raising power. 
3628 // We override the superclass implementation so we can send a different message 
3629 // type to the client or application being notified. 
3630 //****************************************************************************** 
3633 IOPMrootDomain::tellChangeUp( unsigned long stateNum 
) 
3635         DLOG("tellChangeUp %s->%s\n", 
3636             getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
)); 
3638         ignoreTellChangeDown 
= false; 
3640         if (stateNum 
== ON_STATE
) { 
3641                 // Direct callout into OSKext so it can disable kext unloads 
3642                 // during sleep/wake to prevent deadlocks. 
3643                 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn 
); 
3645                 // Notify platform that sleep was cancelled or resumed. 
3646                 getPlatform()->callPlatformFunction( 
3647                         sleepMessagePEFunction
.get(), false, 
3648                         (void *)(uintptr_t) kIOMessageSystemHasPoweredOn
, 
3651                 if (getPowerState() == ON_STATE
) { 
3652                         // Sleep was cancelled by idle cancel or revert 
3653                         if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) { 
3654                                 // rdar://problem/50363791 
3655                                 // If system is in dark wake and sleep is cancelled, do not 
3656                                 // send SystemWillPowerOn/HasPoweredOn messages to kernel 
3657                                 // priority clients. They haven't yet seen a SystemWillSleep 
3658                                 // message before the cancellation. So make sure the kernel 
3659                                 // client bit is cleared in _systemMessageClientMask before 
3660                                 // invoking the tellClients() below. This bit may have been 
3661                                 // set by handleOurPowerChangeStart() anticipating a successful 
3662                                 // sleep and setting the filter mask ahead of time allows the 
3663                                 // SystemWillSleep message to go through. 
3664                                 _systemMessageClientMask 
&= ~kSystemMessageClientKernel
; 
3667                         systemDidNotSleep(); 
3668                         tellClients( kIOMessageSystemWillPowerOn 
); 
3671                 tracePoint( kIOPMTracePointWakeApplications 
); 
3672                 tellClients( kIOMessageSystemHasPoweredOn 
); 
3676 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \ 
3677     (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \ 
3678      ((params)->fromCapabilities & (flag)) && \ 
3679      (((params)->toCapabilities & (flag)) == 0)) 
3681 #define CAP_DID_CHANGE_TO_ON(params, flag) \ 
3682     (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \ 
3683      ((params)->toCapabilities & (flag)) && \ 
3684      (((params)->fromCapabilities & (flag)) == 0)) 
3686 #define CAP_DID_CHANGE_TO_OFF(params, flag) \ 
3687     (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \ 
3688      ((params)->fromCapabilities & (flag)) && \ 
3689      (((params)->toCapabilities & (flag)) == 0)) 
3691 #define CAP_WILL_CHANGE_TO_ON(params, flag) \ 
3692     (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \ 
3693      ((params)->toCapabilities & (flag)) && \ 
3694      (((params)->fromCapabilities & (flag)) == 0)) 
3696 //****************************************************************************** 
3697 // sysPowerDownHandler 
3699 // Perform a vfs sync before system sleep. 
3700 //****************************************************************************** 
3703 IOPMrootDomain::sysPowerDownHandler( 
3704         void * target
, void * refCon
, 
3705         UInt32 messageType
, IOService 
* service
, 
3706         void * messageArgs
, vm_size_t argSize 
) 
3708         static UInt32 lastSystemMessageType 
= 0; 
3711         DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType
)); 
3713         // rdar://problem/50363791 
3714         // Sanity check to make sure the SystemWill/Has message types are 
3715         // received in the expected order for all kernel priority clients. 
3716         if (messageType 
== kIOMessageSystemWillSleep 
|| 
3717             messageType 
== kIOMessageSystemWillPowerOn 
|| 
3718             messageType 
== kIOMessageSystemHasPoweredOn
) { 
3719                 switch (messageType
) { 
3720                 case kIOMessageSystemWillPowerOn
: 
3721                         assert(lastSystemMessageType 
== kIOMessageSystemWillSleep
); 
3723                 case kIOMessageSystemHasPoweredOn
: 
3724                         assert(lastSystemMessageType 
== kIOMessageSystemWillPowerOn
); 
3728                 lastSystemMessageType 
= messageType
; 
3732                 return kIOReturnUnsupported
; 
3735         if (messageType 
== kIOMessageSystemCapabilityChange
) { 
3736                 IOPMSystemCapabilityChangeParameters 
* params 
= 
3737                     (IOPMSystemCapabilityChangeParameters 
*) messageArgs
; 
3739                 // Interested applications have been notified of an impending power 
3740                 // change and have acked (when applicable). 
3741                 // This is our chance to save whatever state we can before powering 
3743                 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c, 
3746                 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n", 
3747                     params
->fromCapabilities
, params
->toCapabilities
, 
3748                     params
->changeFlags
); 
3750                 if (CAP_WILL_CHANGE_TO_OFF(params
, kIOPMSystemCapabilityCPU
)) { 
3751                         // We will ack within 20 seconds 
3752                         params
->maxWaitForReply 
= 20 * 1000 * 1000; 
3755                         gRootDomain
->evaluateSystemSleepPolicyEarly(); 
3757                         // add in time we could spend freeing pages 
3758                         if (gRootDomain
->hibernateMode 
&& !gRootDomain
->hibernateDisabled
) { 
3759                                 params
->maxWaitForReply 
= kCapabilityClientMaxWait
; 
3761                         DLOG("sysPowerDownHandler max wait %d s\n", 
3762                             (int) (params
->maxWaitForReply 
/ 1000 / 1000)); 
3765                         // Notify platform that sleep has begun, after the early 
3766                         // sleep policy evaluation. 
3767                         getPlatform()->callPlatformFunction( 
3768                                 sleepMessagePEFunction
.get(), false, 
3769                                 (void *)(uintptr_t) kIOMessageSystemWillSleep
, 
3772                         if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending 
)) { 
3773                                 // Purposely delay the ack and hope that shutdown occurs quickly. 
3774                                 // Another option is not to schedule the thread and wait for 
3776                                 AbsoluteTime deadline
; 
3777                                 clock_interval_to_deadline( 30, kSecondScale
, &deadline 
); 
3778                                 thread_call_enter1_delayed( 
3779                                         gRootDomain
->diskSyncCalloutEntry
, 
3780                                         (thread_call_param_t
)(uintptr_t) params
->notifyRef
, 
3784                                         gRootDomain
->diskSyncCalloutEntry
, 
3785                                         (thread_call_param_t
)(uintptr_t) params
->notifyRef
); 
3789                 else if (CAP_DID_CHANGE_TO_ON(params
, kIOPMSystemCapabilityCPU
)) { 
3790                         // We will ack within 110 seconds 
3791                         params
->maxWaitForReply 
= 110 * 1000 * 1000; 
3794                                 gRootDomain
->diskSyncCalloutEntry
, 
3795                                 (thread_call_param_t
)(uintptr_t) params
->notifyRef
); 
3798                 ret 
= kIOReturnSuccess
; 
3804 //****************************************************************************** 
3805 // handleQueueSleepWakeUUID 
3807 // Called from IOPMrootDomain when we're initiating a sleep, 
3808 // or indirectly from PM configd when PM decides to clear the UUID. 
3809 // PM clears the UUID several minutes after successful wake from sleep, 
3810 // so that we might associate App spindumps with the immediately previous 
3813 // @param   obj has a retain on it. We're responsible for releasing that retain. 
3814 //****************************************************************************** 
3817 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject 
*obj
) 
3819         OSSharedPtr
<OSString
>    str
; 
3821         if (kOSBooleanFalse 
== obj
) { 
3822                 handlePublishSleepWakeUUID(false); 
3824                 str
.reset(OSDynamicCast(OSString
, obj
), OSNoRetain
); 
3826                         // This branch caches the UUID for an upcoming sleep/wake 
3827                         queuedSleepWakeUUIDString 
= str
; 
3828                         DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString
->getCStringNoCopy()); 
3832 //****************************************************************************** 
3833 // handlePublishSleepWakeUUID 
3835 // Called from IOPMrootDomain when we're initiating a sleep, 
3836 // or indirectly from PM configd when PM decides to clear the UUID. 
3837 // PM clears the UUID several minutes after successful wake from sleep, 
3838 // so that we might associate App spindumps with the immediately previous 
3840 //****************************************************************************** 
3843 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish 
) 
3848          * Clear the current UUID 
3850         if (gSleepWakeUUIDIsSet
) { 
3851                 DLOG("SleepWake UUID cleared\n"); 
3853                 gSleepWakeUUIDIsSet 
= false; 
3855                 removeProperty(kIOPMSleepWakeUUIDKey
); 
3856                 messageClients(kIOPMMessageSleepWakeUUIDChange
, kIOPMMessageSleepWakeUUIDCleared
); 
3860          * Optionally, publish a new UUID 
3862         if (queuedSleepWakeUUIDString 
&& shouldPublish
) { 
3863                 OSSharedPtr
<OSString
> publishThisUUID
; 
3865                 publishThisUUID 
= queuedSleepWakeUUIDString
; 
3867                 if (publishThisUUID
) { 
3868                         setProperty(kIOPMSleepWakeUUIDKey
, publishThisUUID
.get()); 
3871                 gSleepWakeUUIDIsSet 
= true; 
3872                 messageClients(kIOPMMessageSleepWakeUUIDChange
, kIOPMMessageSleepWakeUUIDSet
); 
3874                 queuedSleepWakeUUIDString
.reset(); 
3878 //****************************************************************************** 
3879 // IOPMGetSleepWakeUUIDKey 
3881 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key. 
3882 // To get the full key -- a C string -- the buffer must large enough for 
3883 // the end-of-string character. 
3884 // The key is expected to be an UUID string 
3885 //****************************************************************************** 
3888 IOPMCopySleepWakeUUIDKey(char *buffer
, size_t buf_len
) 
3890         if (!gSleepWakeUUIDIsSet
) { 
3894         if (buffer 
!= NULL
) { 
3895                 OSSharedPtr
<OSString
> string 
= 
3896                     OSDynamicPtrCast
<OSString
>(gRootDomain
->copyProperty(kIOPMSleepWakeUUIDKey
)); 
3901                         strlcpy(buffer
, string
->getCStringNoCopy(), buf_len
); 
3908 //****************************************************************************** 
3909 // lowLatencyAudioNotify 
3911 // Used to send an update about low latency audio activity to interested 
3912 // clients. To keep the overhead minimal the OSDictionary used here 
3913 // is initialized at boot. 
3914 //****************************************************************************** 
3917 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time
, boolean_t state
) 
3919         if (lowLatencyAudioNotifierDict 
&& lowLatencyAudioNotifyStateSym 
&& lowLatencyAudioNotifyTimestampSym 
&& 
3920             lowLatencyAudioNotifyStateVal 
&& lowLatencyAudioNotifyTimestampVal
) { 
3921                 lowLatencyAudioNotifyTimestampVal
->setValue(time
); 
3922                 lowLatencyAudioNotifyStateVal
->setValue(state
); 
3923                 setPMSetting(gIOPMSettingLowLatencyAudioModeKey
.get(), lowLatencyAudioNotifierDict
.get()); 
3925                 DLOG("LowLatencyAudioNotify error\n"); 
3930 //****************************************************************************** 
3931 // IOPMrootDomainRTNotifier 
3933 // Used by performance controller to update the timestamp and state associated 
3934 // with low latency audio activity in the system. 
3935 //****************************************************************************** 
3938 IOPMrootDomainRTNotifier(uint64_t time
, boolean_t state
) 
3940         gRootDomain
->lowLatencyAudioNotify(time
, state
); 
3944 //****************************************************************************** 
3945 // initializeBootSessionUUID 
3947 // Initialize the boot session uuid at boot up and sets it into registry. 
3948 //****************************************************************************** 
3951 IOPMrootDomain::initializeBootSessionUUID(void) 
3954         uuid_string_t   new_uuid_string
; 
3956         uuid_generate(new_uuid
); 
3957         uuid_unparse_upper(new_uuid
, new_uuid_string
); 
3958         memcpy(bootsessionuuid_string
, new_uuid_string
, sizeof(uuid_string_t
)); 
3960         setProperty(kIOPMBootSessionUUIDKey
, new_uuid_string
); 
3963 //****************************************************************************** 
3964 // Root domain uses the private and tagged changePowerState methods for 
3965 // tracking and logging purposes. 
3966 //****************************************************************************** 
3968 #define REQUEST_TAG_TO_REASON(x)        ((uint16_t)x) 
3971 nextRequestTag( IOPMRequestTag tag 
) 
3973         static SInt16 msb16 
= 1; 
3974         uint16_t id 
= OSAddAtomic16(1, &msb16
); 
3975         return ((uint32_t)id 
<< 16) | REQUEST_TAG_TO_REASON(tag
); 
3978 // TODO: remove this shim function and exported symbol 
3980 IOPMrootDomain::changePowerStateTo( unsigned long ordinal 
) 
3982         return changePowerStateWithTagTo(ordinal
, kCPSReasonNone
); 
3985 // TODO: remove this shim function and exported symbol 
3987 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal 
) 
3989         return changePowerStateWithTagToPriv(ordinal
, kCPSReasonNone
); 
3993 IOPMrootDomain::changePowerStateWithOverrideTo( 
3994         IOPMPowerStateIndex ordinal
, IOPMRequestTag reason 
) 
3996         uint32_t tag 
= nextRequestTag(reason
); 
3997         DLOG("%s(%s, %x)\n", __FUNCTION__
, getPowerStateString((uint32_t) ordinal
), tag
); 
3999         if ((ordinal 
!= ON_STATE
) && (ordinal 
!= AOT_STATE
) && (ordinal 
!= SLEEP_STATE
)) { 
4000                 return kIOReturnUnsupported
; 
4003         return super::changePowerStateWithOverrideTo(ordinal
, tag
); 
4007 IOPMrootDomain::changePowerStateWithTagTo( 
4008         IOPMPowerStateIndex ordinal
, IOPMRequestTag reason 
) 
4010         uint32_t tag 
= nextRequestTag(reason
); 
4011         DLOG("%s(%s, %x)\n", __FUNCTION__
, getPowerStateString((uint32_t) ordinal
), tag
); 
4013         if ((ordinal 
!= ON_STATE
) && (ordinal 
!= AOT_STATE
) && (ordinal 
!= SLEEP_STATE
)) { 
4014                 return kIOReturnUnsupported
; 
4017         return super::changePowerStateWithTagTo(ordinal
, tag
); 
4021 IOPMrootDomain::changePowerStateWithTagToPriv( 
4022         IOPMPowerStateIndex ordinal
, IOPMRequestTag reason 
) 
4024         uint32_t tag 
= nextRequestTag(reason
); 
4025         DLOG("%s(%s, %x)\n", __FUNCTION__
, getPowerStateString((uint32_t) ordinal
), tag
); 
4027         if ((ordinal 
!= ON_STATE
) && (ordinal 
!= AOT_STATE
) && (ordinal 
!= SLEEP_STATE
)) { 
4028                 return kIOReturnUnsupported
; 
4031         return super::changePowerStateWithTagToPriv(ordinal
, tag
); 
4034 //****************************************************************************** 
4037 //****************************************************************************** 
4040 IOPMrootDomain::activitySinceSleep(void) 
4042         return userActivityCount 
!= userActivityAtSleep
; 
4046 IOPMrootDomain::abortHibernation(void) 
4049         // don't allow hibernation to be aborted on ARM due to user activity 
4050         // since once ApplePMGR decides we're hibernating, we can't turn back 
4051         // see: <rdar://problem/63848862> Tonga ApplePMGR diff quiesce path support 
4054         bool ret 
= activitySinceSleep(); 
4056         if (ret 
&& !hibernateAborted 
&& checkSystemCanSustainFullWake()) { 
4057                 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount
, userActivityAtSleep
); 
4058                 hibernateAborted 
= true; 
4065 hibernate_should_abort(void) 
4068                 return gRootDomain
->abortHibernation(); 
4074 //****************************************************************************** 
4075 // willNotifyPowerChildren 
4077 // Called after all interested drivers have all acknowledged the power change, 
4078 // but before any power children is informed. Dispatched though a thread call, 
4079 // so it is safe to perform work that might block on a sleeping disk. PM state 
4080 // machine (not thread) will block w/o timeout until this function returns. 
4081 //****************************************************************************** 
4084 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState 
) 
4086         OSSharedPtr
<OSDictionary
> dict
; 
4087         OSSharedPtr
<OSNumber
> secs
; 
4089         if (SLEEP_STATE 
== newPowerState
) { 
4090                 notifierThread 
= current_thread(); 
4091                 if (!tasksSuspended
) { 
4092                         AbsoluteTime deadline
; 
4093                         tasksSuspended 
= TRUE
; 
4094                         updateTasksSuspend(); 
4096                         clock_interval_to_deadline(10, kSecondScale
, &deadline
); 
4097 #if defined(XNU_TARGET_OS_OSX) 
4098                         vm_pageout_wait(AbsoluteTime_to_scalar(&deadline
)); 
4099 #endif /* defined(XNU_TARGET_OS_OSX) */ 
4102                 _aotReadyToFullWake 
= false; 
4104                 if (_aotLingerTime
) { 
4106                         IOLog("aot linger no return\n"); 
4107                         clock_absolutetime_interval_to_deadline(_aotLingerTime
, &deadline
); 
4108                         clock_delay_until(deadline
); 
4113                         _aotWakeTimeCalendar
.selector 
= kPMCalendarTypeInvalid
; 
4115                                 bzero(_aotMetrics
, sizeof(IOPMAOTMetrics
)); 
4117                 } else if (!_aotNow 
&& !_debugWakeSeconds
) { 
4120                         _aotPendingFlags   
= 0; 
4121                         _aotTasksSuspended 
= true; 
4122                         _aotLastWakeTime   
= 0; 
4123                         bzero(_aotMetrics
, sizeof(IOPMAOTMetrics
)); 
4124                         if (kIOPMAOTModeCycle 
& _aotMode
) { 
4125                                 clock_interval_to_absolutetime_interval(60, kSecondScale
, &_aotTestInterval
); 
4126                                 _aotTestTime 
= mach_continuous_time() + _aotTestInterval
; 
4127                                 setWakeTime(_aotTestTime
); 
4129                         uint32_t lingerSecs
; 
4130                         if (!PE_parse_boot_argn("aotlinger", &lingerSecs
, sizeof(lingerSecs
))) { 
4133                         clock_interval_to_absolutetime_interval(lingerSecs
, kSecondScale
, &_aotLingerTime
); 
4134                         clock_interval_to_absolutetime_interval(2000, kMillisecondScale
, &_aotWakePreWindow
); 
4135                         clock_interval_to_absolutetime_interval(1100, kMillisecondScale
, &_aotWakePostWindow
); 
4139                 IOHibernateSystemSleep(); 
4140                 IOHibernateIOKitSleep(); 
4142                 if (gRootDomain
->activitySinceSleep()) { 
4143                         dict 
= OSDictionary::withCapacity(1); 
4144                         secs 
= OSNumber::withNumber(1, 32); 
4147                                 dict
->setObject(gIOPMSettingDebugWakeRelativeKey
.get(), secs
.get()); 
4148                                 gRootDomain
->setProperties(dict
.get()); 
4149                                 MSG("Reverting sleep with relative wake\n"); 
4153                 notifierThread 
= NULL
; 
4157 //****************************************************************************** 
4158 // willTellSystemCapabilityDidChange 
4160 // IOServicePM calls this from OurChangeTellCapabilityDidChange() when root 
4161 // domain is raising its power state, immediately after notifying interested 
4162 // drivers and power children. 
4163 //****************************************************************************** 
4166 IOPMrootDomain::willTellSystemCapabilityDidChange( void ) 
4168         if ((_systemTransitionType 
== kSystemTransitionWake
) && 
4169             !CAP_GAIN(kIOPMSystemCapabilityGraphics
)) { 
4170                 // After powering up drivers, dark->full promotion on the current wake 
4171                 // transition is no longer possible. That is because the next machine 
4172                 // state will issue the system capability change messages. 
4173                 // The darkWakePowerClamped flag may already be set if the system has 
4174                 // at least one driver that was power clamped due to dark wake. 
4175                 // This function sets the darkWakePowerClamped flag in case there 
4176                 // is no power-clamped driver in the system. 
4178                 // Last opportunity to exit dark wake using: 
4179                 // requestFullWake( kFullWakeReasonLocalUser ); 
4181                 if (!darkWakePowerClamped
) { 
4182                         if (darkWakeLogClamp
) { 
4186                                 clock_get_uptime(&now
); 
4187                                 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
); 
4188                                 absolutetime_to_nanoseconds(now
, &nsec
); 
4189                                 DLOG("dark wake promotion disabled at %u ms\n", 
4190                                     ((int)((nsec
) / NSEC_PER_MSEC
))); 
4192                         darkWakePowerClamped 
= true; 
4197 //****************************************************************************** 
4198 // sleepOnClamshellClosed 
4200 // contains the logic to determine if the system should sleep when the clamshell 
4202 //****************************************************************************** 
4205 IOPMrootDomain::shouldSleepOnClamshellClosed( void ) 
4207         if (!clamshellExists
) { 
4211         DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n", 
4212             clamshellClosed
, clamshellDisabled
, clamshellSleepDisableMask
, desktopMode
, acAdaptorConnected
); 
4214         return !clamshellDisabled 
&& !(desktopMode 
&& acAdaptorConnected
) && !clamshellSleepDisableMask
; 
4218 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void ) 
4220         // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell 
4221         // closed && battery 
4222         if (!clamshellExists
) { 
4226         DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n", 
4227             clamshellClosed
, clamshellDisabled
, clamshellSleepDisableMask
, desktopMode
, acAdaptorConnected
); 
4229         return !acAdaptorConnected 
&& !clamshellSleepDisableMask
; 
4233 IOPMrootDomain::sendClientClamshellNotification( void ) 
4235         /* Only broadcast clamshell alert if clamshell exists. */ 
4236         if (!clamshellExists
) { 
4240         setProperty(kAppleClamshellStateKey
, 
4241             clamshellClosed 
? kOSBooleanTrue 
: kOSBooleanFalse
); 
4243         setProperty(kAppleClamshellCausesSleepKey
, 
4244             shouldSleepOnClamshellClosed() ? kOSBooleanTrue 
: kOSBooleanFalse
); 
4246         /* Argument to message is a bitfiel of 
4247          *      ( kClamshellStateBit | kClamshellSleepBit ) 
4249         messageClients(kIOPMMessageClamshellStateChange
, 
4250             (void *)(uintptr_t) ((clamshellClosed 
? kClamshellStateBit 
: 0) 
4251             | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit 
: 0))); 
4254 //****************************************************************************** 
4255 // getSleepSupported 
4258 //****************************************************************************** 
4261 IOPMrootDomain::getSleepSupported( void ) 
4263         return platformSleepSupport
; 
4266 //****************************************************************************** 
4267 // setSleepSupported 
4270 //****************************************************************************** 
4273 IOPMrootDomain::setSleepSupported( IOOptionBits flags 
) 
4275         DLOG("setSleepSupported(%x)\n", (uint32_t) flags
); 
4276         OSBitOrAtomic(flags
, &platformSleepSupport
); 
4279 //****************************************************************************** 
4280 // setClamShellSleepDisable 
4282 //****************************************************************************** 
4285 IOPMrootDomain::setClamShellSleepDisable( bool disable
, uint32_t bitmask 
) 
4289         // User client calls this in non-gated context 
4290         if (gIOPMWorkLoop
->inGate() == false) { 
4291                 gIOPMWorkLoop
->runAction( 
4292                         OSMemberFunctionCast(IOWorkLoop::Action
, this, 
4293                         &IOPMrootDomain::setClamShellSleepDisable
), 
4295                         (void *) disable
, (void *)(uintptr_t) bitmask
); 
4299         oldMask 
= clamshellSleepDisableMask
; 
4301                 clamshellSleepDisableMask 
|= bitmask
; 
4303                 clamshellSleepDisableMask 
&= ~bitmask
; 
4305         DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask
, clamshellSleepDisableMask
); 
4307         if (clamshellExists 
&& clamshellClosed 
&& 
4308             (clamshellSleepDisableMask 
!= oldMask
) && 
4309             (clamshellSleepDisableMask 
== 0)) { 
4310                 handlePowerNotification(kLocalEvalClamshellCommand
); 
4314 //****************************************************************************** 
4318 //****************************************************************************** 
4321 IOPMrootDomain::wakeFromDoze( void ) 
4323         // Preserve symbol for familes (IOUSBFamily and IOGraphics) 
4326 //****************************************************************************** 
4329 // Record the earliest scheduled RTC alarm to determine whether a RTC wake 
4330 // should be a dark wake or a full wake. Both Maintenance and SleepService 
4331 // alarms are dark wake, while AutoWake (WakeByCalendarDate) and DebugWake 
4332 // (WakeRelativeToSleep) should trigger a full wake. Scheduled power-on 
4333 // PMSettings are ignored. 
4335 // Caller serialized using settingsCtrlLock. 
4336 //****************************************************************************** 
4339 IOPMrootDomain::recordRTCAlarm( 
4340         const OSSymbol  
*type
, 
4343         uint32_t previousAlarmMask 
= _scheduledAlarmMask
; 
4345         if (type 
== gIOPMSettingDebugWakeRelativeKey
) { 
4346                 OSNumber 
* n 
= OSDynamicCast(OSNumber
, object
); 
4348                         // Debug wake has highest scheduling priority so it overrides any 
4349                         // pre-existing alarm. 
4350                         uint32_t debugSecs 
= n
->unsigned32BitValue(); 
4351                         _nextScheduledAlarmType
.reset(type
, OSRetain
); 
4352                         _nextScheduledAlarmUTC 
= debugSecs
; 
4354                         _debugWakeSeconds 
= debugSecs
; 
4355                         OSBitOrAtomic(kIOPMAlarmBitDebugWake
, &_scheduledAlarmMask
); 
4356                         DLOG("next alarm (%s) in %u secs\n", 
4357                             type
->getCStringNoCopy(), debugSecs
); 
4359         } else if ((type 
== gIOPMSettingAutoWakeCalendarKey
.get()) || 
4360             (type 
== gIOPMSettingMaintenanceWakeCalendarKey
.get()) || 
4361             (type 
== gIOPMSettingSleepServiceWakeCalendarKey
.get())) { 
4362                 OSData 
* data 
= OSDynamicCast(OSData
, object
); 
4363                 if (data 
&& (data
->getLength() == sizeof(IOPMCalendarStruct
))) { 
4364                         const IOPMCalendarStruct 
* cs
; 
4365                         bool replaceNextAlarm 
= false; 
4368                         cs 
= (const IOPMCalendarStruct 
*) data
->getBytesNoCopy(); 
4369                         secs 
= IOPMConvertCalendarToSeconds(cs
); 
4370                         DLOG("%s " YMDTF 
"\n", type
->getCStringNoCopy(), YMDT(cs
)); 
4372                         // Update the next scheduled alarm type 
4373                         if ((_nextScheduledAlarmType 
== NULL
) || 
4374                             ((_nextScheduledAlarmType 
!= gIOPMSettingDebugWakeRelativeKey
) && 
4375                             (secs 
< _nextScheduledAlarmUTC
))) { 
4376                                 replaceNextAlarm 
= true; 
4379                         if (type 
== gIOPMSettingAutoWakeCalendarKey
.get()) { 
4381                                         _calendarWakeAlarmUTC 
= IOPMConvertCalendarToSeconds(cs
); 
4382                                         OSBitOrAtomic(kIOPMAlarmBitCalendarWake
, &_scheduledAlarmMask
); 
4384                                         // TODO: can this else-block be removed? 
4385                                         _calendarWakeAlarmUTC 
= 0; 
4386                                         OSBitAndAtomic(~kIOPMAlarmBitCalendarWake
, &_scheduledAlarmMask
); 
4389                         if (type 
== gIOPMSettingMaintenanceWakeCalendarKey
.get()) { 
4390                                 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake
, &_scheduledAlarmMask
); 
4392                         if (type 
== gIOPMSettingSleepServiceWakeCalendarKey
.get()) { 
4393                                 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake
, &_scheduledAlarmMask
); 
4396                         if (replaceNextAlarm
) { 
4397                                 _nextScheduledAlarmType
.reset(type
, OSRetain
); 
4398                                 _nextScheduledAlarmUTC 
= secs
; 
4399                                 DLOG("next alarm (%s) " YMDTF 
"\n", type
->getCStringNoCopy(), YMDT(cs
)); 
4404         if (_scheduledAlarmMask 
!= previousAlarmMask
) { 
4405                 DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask
); 
4412 //****************************************************************************** 
4415 // Adds a new feature to the supported features dictionary 
4416 //****************************************************************************** 
4419 IOPMrootDomain::publishFeature( const char * feature 
) 
4421         publishFeature(feature
, kRD_AllPowerSources
, NULL
); 
4424 //****************************************************************************** 
4425 // publishFeature (with supported power source specified) 
4427 // Adds a new feature to the supported features dictionary 
4428 //****************************************************************************** 
4431 IOPMrootDomain::publishFeature( 
4432         const char *feature
, 
4433         uint32_t supportedWhere
, 
4434         uint32_t *uniqueFeatureID
) 
4436         static uint16_t       next_feature_id 
= 500; 
4438         OSSharedPtr
<OSNumber
> new_feature_data
; 
4439         OSNumber             
*existing_feature 
= NULL
; 
4440         OSArray              
*existing_feature_arr_raw 
= NULL
; 
4441         OSSharedPtr
<OSArray
>  existing_feature_arr
; 
4442         OSObject             
*osObj 
= NULL
; 
4443         uint32_t              feature_value 
= 0; 
4445         supportedWhere 
&= kRD_AllPowerSources
; // mask off any craziness! 
4447         if (!supportedWhere
) { 
4448                 // Feature isn't supported anywhere! 
4452         if (next_feature_id 
> 5000) { 
4453                 // Far, far too many features! 
4457         if (featuresDictLock
) { 
4458                 IOLockLock(featuresDictLock
); 
4461         OSSharedPtr
<OSObject
> origFeaturesProp 
= copyProperty(kRootDomainSupportedFeatures
); 
4462         OSDictionary 
*origFeatures 
= OSDynamicCast(OSDictionary
, origFeaturesProp
.get()); 
4463         OSSharedPtr
<OSDictionary
> features
; 
4465         // Create new features dict if necessary 
4467                 features 
= OSDictionary::withDictionary(origFeatures
); 
4469                 features 
= OSDictionary::withCapacity(1); 
4472         // Create OSNumber to track new feature 
4474         next_feature_id 
+= 1; 
4475         if (uniqueFeatureID
) { 
4476                 // We don't really mind if the calling kext didn't give us a place 
4477                 // to stash their unique id. Many kexts don't plan to unload, and thus 
4478                 // have no need to remove themselves later. 
4479                 *uniqueFeatureID 
= next_feature_id
; 
4482         feature_value 
= (uint32_t)next_feature_id
; 
4483         feature_value 
<<= 16; 
4484         feature_value 
+= supportedWhere
; 
4486         new_feature_data 
= OSNumber::withNumber( 
4487                 (unsigned long long)feature_value
, 32); 
4489         // Does features object already exist? 
4490         if ((osObj 
= features
->getObject(feature
))) { 
4491                 if ((existing_feature 
= OSDynamicCast(OSNumber
, osObj
))) { 
4492                         // We need to create an OSArray to hold the now 2 elements. 
4493                         existing_feature_arr 
= OSArray::withObjects( 
4494                                 (const OSObject 
**)&existing_feature
, 1, 2); 
4495                 } else if ((existing_feature_arr_raw 
= OSDynamicCast(OSArray
, osObj
))) { 
4496                         // Add object to existing array 
4497                         existing_feature_arr 
= OSArray::withArray( 
4498                                 existing_feature_arr_raw
, 
4499                                 existing_feature_arr_raw
->getCount() + 1); 
4502                 if (existing_feature_arr
) { 
4503                         existing_feature_arr
->setObject(new_feature_data
.get()); 
4504                         features
->setObject(feature
, existing_feature_arr
.get()); 
4507                 // The easy case: no previously existing features listed. We simply 
4508                 // set the OSNumber at key 'feature' and we're on our way. 
4509                 features
->setObject(feature
, new_feature_data
.get()); 
4512         setProperty(kRootDomainSupportedFeatures
, features
.get()); 
4514         if (featuresDictLock
) { 
4515                 IOLockUnlock(featuresDictLock
); 
4518         // Notify EnergySaver and all those in user space so they might 
4519         // re-populate their feature specific UI 
4520         if (pmPowerStateQueue
) { 
4521                 pmPowerStateQueue
->submitPowerEvent( kPowerEventFeatureChanged 
); 
4525 //****************************************************************************** 
4526 // removePublishedFeature 
4528 // Removes previously published feature 
4529 //****************************************************************************** 
4532 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID 
) 
4534         IOReturn                ret 
= kIOReturnError
; 
4535         uint32_t                feature_value 
= 0; 
4536         uint16_t                feature_id 
= 0; 
4537         bool                    madeAChange 
= false; 
4539         OSSymbol                
*dictKey 
= NULL
; 
4540         OSSharedPtr
<OSCollectionIterator
>    dictIterator
; 
4541         OSArray                 
*arrayMember  
= NULL
; 
4542         OSNumber                
*numberMember 
= NULL
; 
4543         OSObject                
*osObj        
= NULL
; 
4544         OSNumber                
*osNum        
= NULL
; 
4545         OSSharedPtr
<OSArray
>    arrayMemberCopy
; 
4547         if (kBadPMFeatureID 
== removeFeatureID
) { 
4548                 return kIOReturnNotFound
; 
4551         if (featuresDictLock
) { 
4552                 IOLockLock(featuresDictLock
); 
4555         OSSharedPtr
<OSObject
> origFeaturesProp 
= copyProperty(kRootDomainSupportedFeatures
); 
4556         OSDictionary 
*origFeatures 
= OSDynamicCast(OSDictionary
, origFeaturesProp
.get()); 
4557         OSSharedPtr
<OSDictionary
> features
; 
4560                 // Any modifications to the dictionary are made to the copy to prevent 
4561                 // races & crashes with userland clients. Dictionary updated 
4562                 // automically later. 
4563                 features 
= OSDictionary::withDictionary(origFeatures
); 
4566                 ret 
= kIOReturnNotFound
; 
4570         // We iterate 'features' dictionary looking for an entry tagged 
4571         // with 'removeFeatureID'. If found, we remove it from our tracking 
4572         // structures and notify the OS via a general interest message. 
4574         dictIterator 
= OSCollectionIterator::withCollection(features
.get()); 
4575         if (!dictIterator
) { 
4579         while ((dictKey 
= OSDynamicCast(OSSymbol
, dictIterator
->getNextObject()))) { 
4580                 osObj 
= features
->getObject(dictKey
); 
4582                 // Each Feature is either tracked by an OSNumber 
4583                 if (osObj 
&& (numberMember 
= OSDynamicCast(OSNumber
, osObj
))) { 
4584                         feature_value 
= numberMember
->unsigned32BitValue(); 
4585                         feature_id 
= (uint16_t)(feature_value 
>> 16); 
4587                         if (feature_id 
== (uint16_t)removeFeatureID
) { 
4589                                 features
->removeObject(dictKey
); 
4594                         // Or tracked by an OSArray of OSNumbers 
4595                 } else if (osObj 
&& (arrayMember 
= OSDynamicCast(OSArray
, osObj
))) { 
4596                         unsigned int arrayCount 
= arrayMember
->getCount(); 
4598                         for (unsigned int i 
= 0; i 
< arrayCount
; i
++) { 
4599                                 osNum 
= OSDynamicCast(OSNumber
, arrayMember
->getObject(i
)); 
4604                                 feature_value 
= osNum
->unsigned32BitValue(); 
4605                                 feature_id 
= (uint16_t)(feature_value 
>> 16); 
4607                                 if (feature_id 
== (uint16_t)removeFeatureID
) { 
4609                                         if (1 == arrayCount
) { 
4610                                                 // If the array only contains one element, remove 
4612                                                 features
->removeObject(dictKey
); 
4614                                                 // Otherwise remove the element from a copy of the array. 
4615                                                 arrayMemberCopy 
= OSArray::withArray(arrayMember
); 
4616                                                 if (arrayMemberCopy
) { 
4617                                                         arrayMemberCopy
->removeObject(i
); 
4618                                                         features
->setObject(dictKey
, arrayMemberCopy
.get()); 
4630                 ret 
= kIOReturnSuccess
; 
4632                 setProperty(kRootDomainSupportedFeatures
, features
.get()); 
4634                 // Notify EnergySaver and all those in user space so they might 
4635                 // re-populate their feature specific UI 
4636                 if (pmPowerStateQueue
) { 
4637                         pmPowerStateQueue
->submitPowerEvent( kPowerEventFeatureChanged 
); 
4640                 ret 
= kIOReturnNotFound
; 
4644         if (featuresDictLock
) { 
4645                 IOLockUnlock(featuresDictLock
); 
4650 //****************************************************************************** 
4651 // publishPMSetting (private) 
4653 // Should only be called by PMSettingObject to publish a PM Setting as a 
4654 // supported feature. 
4655 //****************************************************************************** 
4658 IOPMrootDomain::publishPMSetting( 
4659         const OSSymbol 
* feature
, uint32_t where
, uint32_t * featureID 
) 
4661         if (noPublishPMSettings 
&& 
4662             (noPublishPMSettings
->getNextIndexOfObject(feature
, 0) != (unsigned int)-1)) { 
4663                 // Setting found in noPublishPMSettings array 
4664                 *featureID 
= kBadPMFeatureID
; 
4669                 feature
->getCStringNoCopy(), where
, featureID
); 
4672 //****************************************************************************** 
4673 // setPMSetting (private) 
4675 // Internal helper to relay PM settings changes from user space to individual 
4676 // drivers. Should be called only by IOPMrootDomain::setProperties. 
4677 //****************************************************************************** 
4680 IOPMrootDomain::setPMSetting( 
4681         const OSSymbol  
*type
, 
4684         PMSettingCallEntry  
*entries 
= NULL
; 
4685         OSSharedPtr
<OSArray
>    chosen
; 
4686         const OSArray       
*array
; 
4687         PMSettingObject     
*pmso
; 
4688         thread_t            thisThread
; 
4689         int                 i
, j
, count
, capacity
; 
4694                 return kIOReturnBadArgument
; 
4699         // Update settings dict so changes are visible from copyPMSetting(). 
4700         fPMSettingsDict
->setObject(type
, object
); 
4702         // Prep all PMSetting objects with the given 'type' for callout. 
4703         array 
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(type
)); 
4704         if (!array 
|| ((capacity 
= array
->getCount()) == 0)) { 
4708         // Array to retain PMSetting objects targeted for callout. 
4709         chosen 
= OSArray::withCapacity(capacity
); 
4711                 goto unlock_exit
; // error 
4713         entries 
= IONew(PMSettingCallEntry
, capacity
); 
4715                 goto unlock_exit
; // error 
4717         memset(entries
, 0, sizeof(PMSettingCallEntry
) * capacity
); 
4719         thisThread 
= current_thread(); 
4721         for (i 
= 0, j 
= 0; i 
< capacity
; i
++) { 
4722                 pmso 
= (PMSettingObject 
*) array
->getObject(i
); 
4723                 if (pmso
->disabled
) { 
4726                 entries
[j
].thread 
= thisThread
; 
4727                 queue_enter(&pmso
->calloutQueue
, &entries
[j
], PMSettingCallEntry 
*, link
); 
4728                 chosen
->setObject(pmso
); 
4738         // Call each pmso in the chosen array. 
4739         for (i 
= 0; i 
< count
; i
++) { 
4740                 pmso 
= (PMSettingObject 
*) chosen
->getObject(i
); 
4741                 ret 
= pmso
->dispatchPMSetting(type
, object
); 
4742                 if (ret 
== kIOReturnSuccess
) { 
4743                         // At least one setting handler was successful 
4745 #if DEVELOPMENT || DEBUG 
4747                         // Log the handler and kext that failed 
4748                         OSSharedPtr
<const OSSymbol
> kextName 
= copyKextIdentifierWithAddress((vm_address_t
) pmso
->func
); 
4750                                 DLOG("PMSetting(%s) error 0x%x from %s\n", 
4751                                     type
->getCStringNoCopy(), ret
, kextName
->getCStringNoCopy()); 
4758         for (i 
= 0; i 
< count
; i
++) { 
4759                 pmso 
= (PMSettingObject 
*) chosen
->getObject(i
); 
4760                 queue_remove(&pmso
->calloutQueue
, &entries
[i
], PMSettingCallEntry 
*, link
); 
4761                 if (pmso
->waitThread
) { 
4762                         PMSETTING_WAKEUP(pmso
); 
4767                 recordRTCAlarm(type
, object
); 
4773                 IODelete(entries
, PMSettingCallEntry
, capacity
); 
4776         return kIOReturnSuccess
; 
4779 //****************************************************************************** 
4780 // copyPMSetting (public) 
4782 // Allows kexts to safely read setting values, without being subscribed to 
4784 //****************************************************************************** 
4786 OSSharedPtr
<OSObject
> 
4787 IOPMrootDomain::copyPMSetting( 
4788         OSSymbol 
*whichSetting
) 
4790         OSSharedPtr
<OSObject
> obj
; 
4792         if (!whichSetting
) { 
4797         obj
.reset(fPMSettingsDict
->getObject(whichSetting
), OSRetain
); 
4803 //****************************************************************************** 
4804 // registerPMSettingController (public) 
4806 // direct wrapper to registerPMSettingController with uint32_t power source arg 
4807 //****************************************************************************** 
4810 IOPMrootDomain::registerPMSettingController( 
4811         const OSSymbol 
*                settings
[], 
4812         IOPMSettingControllerCallback   func
, 
4817         return registerPMSettingController( 
4819                 (kIOPMSupportedOnAC 
| kIOPMSupportedOnBatt 
| kIOPMSupportedOnUPS
), 
4820                 func
, target
, refcon
, handle
); 
4823 //****************************************************************************** 
4824 // registerPMSettingController (public) 
4826 // Kexts may register for notifications when a particular setting is changed. 
4827 // A list of settings is available in IOPM.h. 
4829 //  * settings - An OSArray containing OSSymbols. Caller should populate this 
4830 //          array with a list of settings caller wants notifications from. 
4831 //  * func - A C function callback of the type IOPMSettingControllerCallback 
4832 //  * target - caller may provide an OSObject *, which PM will pass as an 
4833 //          target to calls to "func" 
4834 //  * refcon - caller may provide an void *, which PM will pass as an 
4835 //          argument to calls to "func" 
4836 //  * handle - This is a return argument. We will populate this pointer upon 
4837 //          call success. Hold onto this and pass this argument to 
4838 //          IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext 
4840 //      kIOReturnSuccess on success 
4841 //****************************************************************************** 
4844 IOPMrootDomain::registerPMSettingController( 
4845         const OSSymbol 
*                settings
[], 
4846         uint32_t                        supportedPowerSources
, 
4847         IOPMSettingControllerCallback   func
, 
4852         PMSettingObject 
*pmso 
= NULL
; 
4853         OSObject        
*pmsh 
= NULL
; 
4856         if (NULL 
== settings 
|| 
4859                 return kIOReturnBadArgument
; 
4862         pmso 
= PMSettingObject::pmSettingObject( 
4863                 (IOPMrootDomain 
*) this, func
, target
, 
4864                 refcon
, supportedPowerSources
, settings
, &pmsh
); 
4868                 return kIOReturnInternalError
; 
4872         for (i 
= 0; settings
[i
]; i
++) { 
4873                 OSSharedPtr
<OSArray
> newList
; 
4874                 OSArray 
*list 
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(settings
[i
])); 
4876                         // New array of callbacks for this setting 
4877                         newList 
= OSArray::withCapacity(1); 
4878                         settingsCallbacks
->setObject(settings
[i
], newList
.get()); 
4879                         list 
= newList
.get(); 
4882                 // Add caller to the callback list 
4883                 list
->setObject(pmso
); 
4887         // Return handle to the caller, the setting object is private. 
4890         return kIOReturnSuccess
; 
4893 //****************************************************************************** 
4894 // deregisterPMSettingObject (private) 
4896 // Only called from PMSettingObject. 
4897 //****************************************************************************** 
4900 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject 
* pmso 
) 
4902         thread_t                thisThread 
= current_thread(); 
4903         PMSettingCallEntry      
*callEntry
; 
4904         OSSharedPtr
<OSCollectionIterator
>    iter
; 
4912         pmso
->disabled 
= true; 
4914         // Wait for all callout threads to finish. 
4917                 queue_iterate(&pmso
->calloutQueue
, callEntry
, PMSettingCallEntry 
*, link
) 
4919                         if (callEntry
->thread 
!= thisThread
) { 
4925                         assert(NULL 
== pmso
->waitThread
); 
4926                         pmso
->waitThread 
= thisThread
; 
4927                         PMSETTING_WAIT(pmso
); 
4928                         pmso
->waitThread 
= NULL
; 
4932         // Search each PM settings array in the kernel. 
4933         iter 
= OSCollectionIterator::withCollection(settingsCallbacks
.get()); 
4935                 while ((sym 
= OSDynamicCast(OSSymbol
, iter
->getNextObject()))) { 
4936                         array 
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(sym
)); 
4937                         index 
= array
->getNextIndexOfObject(pmso
, 0); 
4939                                 array
->removeObject(index
); 
4949 //****************************************************************************** 
4950 // informCPUStateChange 
4952 // Call into PM CPU code so that CPU power savings may dynamically adjust for 
4953 // running on battery, with the lid closed, etc. 
4955 // informCPUStateChange is a no-op on non x86 systems 
4956 // only x86 has explicit support in the IntelCPUPowerManagement kext 
4957 //****************************************************************************** 
4960 IOPMrootDomain::informCPUStateChange( 
4964 #if defined(__i386__) || defined(__x86_64__) 
4966         pmioctlVariableInfo_t varInfoStruct
; 
4968         const char          *varNameStr 
= NULL
; 
4969         int32_t             *varIndex   
= NULL
; 
4971         if (kInformAC 
== type
) { 
4972                 varNameStr 
= kIOPMRootDomainBatPowerCString
; 
4973                 varIndex 
= &idxPMCPULimitedPower
; 
4974         } else if (kInformLid 
== type
) { 
4975                 varNameStr 
= kIOPMRootDomainLidCloseCString
; 
4976                 varIndex 
= &idxPMCPUClamshell
; 
4981         // Set the new value! 
4982         // pmCPUControl will assign us a new ID if one doesn't exist yet 
4983         bzero(&varInfoStruct
, sizeof(pmioctlVariableInfo_t
)); 
4984         varInfoStruct
.varID         
= *varIndex
; 
4985         varInfoStruct
.varType       
= vBool
; 
4986         varInfoStruct
.varInitValue  
= value
; 
4987         varInfoStruct
.varCurValue   
= value
; 
4988         strlcpy((char *)varInfoStruct
.varName
, 
4989             (const char *)varNameStr
, 
4990             sizeof(varInfoStruct
.varName
)); 
4993         pmCPUret 
= pmCPUControl( PMIOCSETVARINFO
, (void *)&varInfoStruct 
); 
4995         // pmCPU only assigns numerical id's when a new varName is specified 
4997             && (*varIndex 
== kCPUUnknownIndex
)) { 
4998                 // pmCPUControl has assigned us a new variable ID. 
4999                 // Let's re-read the structure we just SET to learn that ID. 
5000                 pmCPUret 
= pmCPUControl( PMIOCGETVARNAMEINFO
, (void *)&varInfoStruct 
); 
5002                 if (0 == pmCPUret
) { 
5003                         // Store it in idxPMCPUClamshell or idxPMCPULimitedPower 
5004                         *varIndex 
= varInfoStruct
.varID
; 
5010 #endif /* __i386__ || __x86_64__ */ 
5014 // MARK: Deep Sleep Policy 
5018 //****************************************************************************** 
5019 // evaluateSystemSleepPolicy 
5020 //****************************************************************************** 
5022 #define kIOPlatformSystemSleepPolicyKey     "IOPlatformSystemSleepPolicy" 
5026         kIOPMSleepFlagHibernate         
= 0x00000001, 
5027         kIOPMSleepFlagSleepTimerEnable  
= 0x00000002 
5030 struct IOPMSystemSleepPolicyEntry 
{ 
5031         uint32_t    factorMask
; 
5032         uint32_t    factorBits
; 
5033         uint32_t    sleepFlags
; 
5034         uint32_t    wakeEvents
; 
5035 } __attribute__((packed
)); 
5037 struct IOPMSystemSleepPolicyTable 
{ 
5040         uint16_t    entryCount
; 
5041         IOPMSystemSleepPolicyEntry  entries
[]; 
5042 } __attribute__((packed
)); 
5045         kIOPMSleepAttributeHibernateSetup   
= 0x00000001, 
5046         kIOPMSleepAttributeHibernateSleep   
= 0x00000002 
5050 getSleepTypeAttributes( uint32_t sleepType 
) 
5052         static const uint32_t sleepTypeAttributes
[kIOPMSleepTypeLast
] = 
5057                 /* safesleep */ kIOPMSleepAttributeHibernateSetup
, 
5058                 /* hibernate */ kIOPMSleepAttributeHibernateSetup 
| kIOPMSleepAttributeHibernateSleep
, 
5059                 /* standby   */ kIOPMSleepAttributeHibernateSetup 
| kIOPMSleepAttributeHibernateSleep
, 
5060                 /* poweroff  */ kIOPMSleepAttributeHibernateSetup 
| kIOPMSleepAttributeHibernateSleep
, 
5064         if (sleepType 
>= kIOPMSleepTypeLast
) { 
5068         return sleepTypeAttributes
[sleepType
]; 
5072 IOPMrootDomain::evaluateSystemSleepPolicy( 
5073         IOPMSystemSleepParameters 
* params
, int sleepPhase
, uint32_t * hibMode 
) 
5075 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x} 
5077         static const IONamedValue factorValues
[] = { 
5078                 SLEEP_FACTOR( SleepTimerWake 
), 
5079                 SLEEP_FACTOR( LidOpen 
), 
5080                 SLEEP_FACTOR( ACPower 
), 
5081                 SLEEP_FACTOR( BatteryLow 
), 
5082                 SLEEP_FACTOR( StandbyNoDelay 
), 
5083                 SLEEP_FACTOR( StandbyForced 
), 
5084                 SLEEP_FACTOR( StandbyDisabled 
), 
5085                 SLEEP_FACTOR( USBExternalDevice 
), 
5086                 SLEEP_FACTOR( BluetoothHIDDevice 
), 
5087                 SLEEP_FACTOR( ExternalMediaMounted 
), 
5088                 SLEEP_FACTOR( ThunderboltDevice 
), 
5089                 SLEEP_FACTOR( RTCAlarmScheduled 
), 
5090                 SLEEP_FACTOR( MagicPacketWakeEnabled 
), 
5091                 SLEEP_FACTOR( HibernateForced 
), 
5092                 SLEEP_FACTOR( AutoPowerOffDisabled 
), 
5093                 SLEEP_FACTOR( AutoPowerOffForced 
), 
5094                 SLEEP_FACTOR( ExternalDisplay 
), 
5095                 SLEEP_FACTOR( NetworkKeepAliveActive 
), 
5096                 SLEEP_FACTOR( LocalUserActivity 
), 
5097                 SLEEP_FACTOR( HibernateFailed 
), 
5098                 SLEEP_FACTOR( ThermalWarning 
), 
5099                 SLEEP_FACTOR( DisplayCaptured 
), 
5103         const IOPMSystemSleepPolicyTable 
* pt
; 
5104         OSSharedPtr
<OSObject
>  prop
; 
5105         OSData 
*    policyData
; 
5106         uint64_t    currentFactors 
= 0; 
5107         char        currentFactorsBuf
[512]; 
5108         uint32_t    standbyDelay   
= 0; 
5109         uint32_t    powerOffDelay  
= 0; 
5110         uint32_t    powerOffTimer  
= 0; 
5111         uint32_t    standbyTimer  
= 0; 
5113         bool        standbyEnabled
; 
5114         bool        powerOffEnabled
; 
5117         // Get platform's sleep policy table 
5118         if (!gSleepPolicyHandler
) { 
5119                 prop 
= getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey
); 
5125         // Fetch additional settings 
5126         standbyEnabled 
= (getSleepOption(kIOPMDeepSleepDelayKey
, &standbyDelay
) 
5127             && propertyHasValue(kIOPMDeepSleepEnabledKey
, kOSBooleanTrue
)); 
5128         powerOffEnabled 
= (getSleepOption(kIOPMAutoPowerOffDelayKey
, &powerOffDelay
) 
5129             && propertyHasValue(kIOPMAutoPowerOffEnabledKey
, kOSBooleanTrue
)); 
5130         if (!getSleepOption(kIOPMAutoPowerOffTimerKey
, &powerOffTimer
)) { 
5131                 powerOffTimer 
= powerOffDelay
; 
5133         if (!getSleepOption(kIOPMDeepSleepTimerKey
, &standbyTimer
)) { 
5134                 standbyTimer 
= standbyDelay
; 
5137         DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n", 
5138             sleepPhase
, standbyEnabled
, standbyDelay
, standbyTimer
, 
5139             powerOffEnabled
, powerOffDelay
, powerOffTimer
, *hibMode
); 
5141         currentFactorsBuf
[0] = 0; 
5142         // pmset level overrides 
5143         if ((*hibMode 
& kIOHibernateModeOn
) == 0) { 
5144                 if (!gSleepPolicyHandler
) { 
5145                         standbyEnabled  
= false; 
5146                         powerOffEnabled 
= false; 
5148         } else if (!(*hibMode 
& kIOHibernateModeSleep
)) { 
5149                 // Force hibernate (i.e. mode 25) 
5150                 // If standby is enabled, force standy. 
5151                 // If poweroff is enabled, force poweroff. 
5152                 if (standbyEnabled
) { 
5153                         currentFactors 
|= kIOPMSleepFactorStandbyForced
; 
5154                 } else if (powerOffEnabled
) { 
5155                         currentFactors 
|= kIOPMSleepFactorAutoPowerOffForced
; 
5157                         currentFactors 
|= kIOPMSleepFactorHibernateForced
; 
5161         // Current factors based on environment and assertions 
5162         if (sleepTimerMaintenance
) { 
5163                 currentFactors 
|= kIOPMSleepFactorSleepTimerWake
; 
5165         if (standbyEnabled 
&& sleepToStandby 
&& !gSleepPolicyHandler
) { 
5166                 currentFactors 
|= kIOPMSleepFactorSleepTimerWake
; 
5168         if (!clamshellClosed
) { 
5169                 currentFactors 
|= kIOPMSleepFactorLidOpen
; 
5171         if (acAdaptorConnected
) { 
5172                 currentFactors 
|= kIOPMSleepFactorACPower
; 
5174         if (lowBatteryCondition
) { 
5176                 getSleepOption(kIOHibernateModeKey
, &hibernateMode
); 
5177                 if ((hibernateMode 
& kIOHibernateModeOn
) == 0) { 
5178                         DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n"); 
5180                         currentFactors 
|= kIOPMSleepFactorBatteryLow
; 
5183         if (!standbyDelay 
|| !standbyTimer
) { 
5184                 currentFactors 
|= kIOPMSleepFactorStandbyNoDelay
; 
5186         if (standbyNixed 
|| !standbyEnabled
) { 
5187                 currentFactors 
|= kIOPMSleepFactorStandbyDisabled
; 
5190                 currentFactors 
|= kIOPMSleepFactorLocalUserActivity
; 
5191                 currentFactors 
&= ~kIOPMSleepFactorSleepTimerWake
; 
5193         if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit
) != 
5194             kIOPMDriverAssertionLevelOff
) { 
5195                 currentFactors 
|= kIOPMSleepFactorUSBExternalDevice
; 
5197         if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit
) != 
5198             kIOPMDriverAssertionLevelOff
) { 
5199                 currentFactors 
|= kIOPMSleepFactorBluetoothHIDDevice
; 
5201         if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit
) != 
5202             kIOPMDriverAssertionLevelOff
) { 
5203                 currentFactors 
|= kIOPMSleepFactorExternalMediaMounted
; 
5205         if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5
) != 
5206             kIOPMDriverAssertionLevelOff
) { 
5207                 currentFactors 
|= kIOPMSleepFactorThunderboltDevice
; 
5209         if (_scheduledAlarmMask 
!= 0) { 
5210                 currentFactors 
|= kIOPMSleepFactorRTCAlarmScheduled
; 
5212         if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit
) != 
5213             kIOPMDriverAssertionLevelOff
) { 
5214                 currentFactors 
|= kIOPMSleepFactorMagicPacketWakeEnabled
; 
5216 #define TCPKEEPALIVE 1 
5218         if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit
) != 
5219             kIOPMDriverAssertionLevelOff
) { 
5220                 currentFactors 
|= kIOPMSleepFactorNetworkKeepAliveActive
; 
5223         if (!powerOffEnabled
) { 
5224                 currentFactors 
|= kIOPMSleepFactorAutoPowerOffDisabled
; 
5227                 currentFactors 
|= kIOPMSleepFactorExternalDisplay
; 
5229         if (userWasActive
) { 
5230                 currentFactors 
|= kIOPMSleepFactorLocalUserActivity
; 
5232         if (darkWakeHibernateError 
&& !CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) { 
5233                 currentFactors 
|= kIOPMSleepFactorHibernateFailed
; 
5235         if (thermalWarningState
) { 
5236                 currentFactors 
|= kIOPMSleepFactorThermalWarning
; 
5239         for (int factorBit 
= 0; factorBit 
< (8 * sizeof(uint32_t)); factorBit
++) { 
5240                 uint32_t factor 
= 1 << factorBit
; 
5241                 if (factor 
& currentFactors
) { 
5242                         strlcat(currentFactorsBuf
, ", ", sizeof(currentFactorsBuf
)); 
5243                         strlcat(currentFactorsBuf
, IOFindNameForValue(factor
, factorValues
), sizeof(currentFactorsBuf
)); 
5246         DLOG("sleep factors 0x%llx%s\n", currentFactors
, currentFactorsBuf
); 
5248         if (gSleepPolicyHandler
) { 
5249                 uint32_t    savedHibernateMode
; 
5252                 if (!gSleepPolicyVars
) { 
5253                         gSleepPolicyVars 
= IONew(IOPMSystemSleepPolicyVariables
, 1); 
5254                         if (!gSleepPolicyVars
) { 
5257                         bzero(gSleepPolicyVars
, sizeof(*gSleepPolicyVars
)); 
5259                 gSleepPolicyVars
->signature 
= kIOPMSystemSleepPolicySignature
; 
5260                 gSleepPolicyVars
->version   
= kIOPMSystemSleepPolicyVersion
; 
5261                 gSleepPolicyVars
->currentCapability 
= _currentCapability
; 
5262                 gSleepPolicyVars
->highestCapability 
= _highestCapability
; 
5263                 gSleepPolicyVars
->sleepFactors      
= currentFactors
; 
5264                 gSleepPolicyVars
->sleepReason       
= lastSleepReason
; 
5265                 gSleepPolicyVars
->sleepPhase        
= sleepPhase
; 
5266                 gSleepPolicyVars
->standbyDelay      
= standbyDelay
; 
5267                 gSleepPolicyVars
->standbyTimer      
= standbyTimer
; 
5268                 gSleepPolicyVars
->poweroffDelay     
= powerOffDelay
; 
5269                 gSleepPolicyVars
->scheduledAlarms   
= _scheduledAlarmMask 
| _userScheduledAlarmMask
; 
5270                 gSleepPolicyVars
->poweroffTimer     
= powerOffTimer
; 
5272                 if (kIOPMSleepPhase0 
== sleepPhase
) { 
5273                         // preserve hibernateMode 
5274                         savedHibernateMode 
= gSleepPolicyVars
->hibernateMode
; 
5275                         gSleepPolicyVars
->hibernateMode 
= *hibMode
; 
5276                 } else if (kIOPMSleepPhase1 
== sleepPhase
) { 
5277                         // use original hibernateMode for phase2 
5278                         gSleepPolicyVars
->hibernateMode 
= *hibMode
; 
5281                 result 
= gSleepPolicyHandler(gSleepPolicyTarget
, gSleepPolicyVars
, params
); 
5283                 if (kIOPMSleepPhase0 
== sleepPhase
) { 
5284                         // restore hibernateMode 
5285                         gSleepPolicyVars
->hibernateMode 
= savedHibernateMode
; 
5288                 if ((result 
!= kIOReturnSuccess
) || 
5289                     (kIOPMSleepTypeInvalid 
== params
->sleepType
) || 
5290                     (params
->sleepType 
>= kIOPMSleepTypeLast
) || 
5291                     (kIOPMSystemSleepParametersVersion 
!= params
->version
)) { 
5292                         MSG("sleep policy handler error\n"); 
5296                 if ((getSleepTypeAttributes(params
->sleepType
) & 
5297                     kIOPMSleepAttributeHibernateSetup
) && 
5298                     ((*hibMode 
& kIOHibernateModeOn
) == 0)) { 
5299                         *hibMode 
|= (kIOHibernateModeOn 
| kIOHibernateModeSleep
); 
5302                 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n", 
5303                     params
->version
, params
->sleepType
, params
->sleepFlags
, 
5304                     params
->ecWakeEvents
, params
->ecWakeTimer
, params
->ecPoweroffTimer
); 
5309         // Policy table is meaningless without standby enabled 
5310         if (!standbyEnabled
) { 
5314         // Validate the sleep policy table 
5315         policyData 
= OSDynamicCast(OSData
, prop
.get()); 
5316         if (!policyData 
|| (policyData
->getLength() <= sizeof(IOPMSystemSleepPolicyTable
))) { 
5320         pt 
= (const IOPMSystemSleepPolicyTable 
*) policyData
->getBytesNoCopy(); 
5321         if ((pt
->signature 
!= kIOPMSystemSleepPolicySignature
) || 
5322             (pt
->version 
!= 1) || (0 == pt
->entryCount
)) { 
5326         if (((policyData
->getLength() - sizeof(IOPMSystemSleepPolicyTable
)) != 
5327             (sizeof(IOPMSystemSleepPolicyEntry
) * pt
->entryCount
))) { 
5331         for (uint32_t i 
= 0; i 
< pt
->entryCount
; i
++) { 
5332                 const IOPMSystemSleepPolicyEntry 
* entry 
= &pt
->entries
[i
]; 
5333                 mismatch 
= (((uint32_t)currentFactors 
^ entry
->factorBits
) & entry
->factorMask
); 
5335                 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n", 
5336                     entry
->factorMask
, entry
->factorBits
, 
5337                     entry
->sleepFlags
, entry
->wakeEvents
, mismatch
); 
5342                 DLOG("^ found match\n"); 
5345                 params
->version 
= kIOPMSystemSleepParametersVersion
; 
5346                 params
->reserved1 
= 1; 
5347                 if (entry
->sleepFlags 
& kIOPMSleepFlagHibernate
) { 
5348                         params
->sleepType 
= kIOPMSleepTypeStandby
; 
5350                         params
->sleepType 
= kIOPMSleepTypeNormalSleep
; 
5353                 params
->ecWakeEvents 
= entry
->wakeEvents
; 
5354                 if (entry
->sleepFlags 
& kIOPMSleepFlagSleepTimerEnable
) { 
5355                         if (kIOPMSleepPhase2 
== sleepPhase
) { 
5356                                 clock_sec_t now_secs 
= gIOLastSleepTime
.tv_sec
; 
5358                                 if (!_standbyTimerResetSeconds 
|| 
5359                                     (now_secs 
<= _standbyTimerResetSeconds
)) { 
5360                                         // Reset standby timer adjustment 
5361                                         _standbyTimerResetSeconds 
= now_secs
; 
5362                                         DLOG("standby delay %u, reset %u\n", 
5363                                             standbyDelay
, (uint32_t) _standbyTimerResetSeconds
); 
5364                                 } else if (standbyDelay
) { 
5365                                         // Shorten the standby delay timer 
5366                                         clock_sec_t elapsed 
= now_secs 
- _standbyTimerResetSeconds
; 
5367                                         if (standbyDelay 
> elapsed
) { 
5368                                                 standbyDelay 
-= elapsed
; 
5370                                                 standbyDelay 
= 1; // must be > 0 
5372                                         DLOG("standby delay %u, elapsed %u\n", 
5373                                             standbyDelay
, (uint32_t) elapsed
); 
5376                         params
->ecWakeTimer 
= standbyDelay
; 
5377                 } else if (kIOPMSleepPhase2 
== sleepPhase
) { 
5378                         // A sleep that does not enable the sleep timer will reset 
5379                         // the standby delay adjustment. 
5380                         _standbyTimerResetSeconds 
= 0; 
5389 static IOPMSystemSleepParameters gEarlySystemSleepParams
; 
5392 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void ) 
5394         // Evaluate early (priority interest phase), before drivers sleep. 
5396         DLOG("%s\n", __FUNCTION__
); 
5397         removeProperty(kIOPMSystemSleepParametersKey
); 
5399         // Full wake resets the standby timer delay adjustment 
5400         if (_highestCapability 
& kIOPMSystemCapabilityGraphics
) { 
5401                 _standbyTimerResetSeconds 
= 0; 
5404         hibernateDisabled 
= false; 
5406         getSleepOption(kIOHibernateModeKey
, &hibernateMode
); 
5408         // Save for late evaluation if sleep is aborted 
5409         bzero(&gEarlySystemSleepParams
, sizeof(gEarlySystemSleepParams
)); 
5411         if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams
, kIOPMSleepPhase1
, 
5413                 if (!hibernateRetry 
&& 
5414                     ((getSleepTypeAttributes(gEarlySystemSleepParams
.sleepType
) & 
5415                     kIOPMSleepAttributeHibernateSetup
) == 0)) { 
5416                         // skip hibernate setup 
5417                         hibernateDisabled 
= true; 
5421         // Publish IOPMSystemSleepType 
5422         uint32_t sleepType 
= gEarlySystemSleepParams
.sleepType
; 
5423         if (sleepType 
== kIOPMSleepTypeInvalid
) { 
5425                 sleepType 
= kIOPMSleepTypeNormalSleep
; 
5426                 if (hibernateMode 
& kIOHibernateModeOn
) { 
5427                         sleepType 
= (hibernateMode 
& kIOHibernateModeSleep
) ? 
5428                             kIOPMSleepTypeSafeSleep 
: kIOPMSleepTypeHibernate
; 
5430         } else if ((sleepType 
== kIOPMSleepTypeStandby
) && 
5431             (gEarlySystemSleepParams
.ecPoweroffTimer
)) { 
5432                 // report the lowest possible sleep state 
5433                 sleepType 
= kIOPMSleepTypePowerOff
; 
5436         setProperty(kIOPMSystemSleepTypeKey
, sleepType
, 32); 
5440 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void ) 
5442         IOPMSystemSleepParameters   params
; 
5443         OSSharedPtr
<OSData
>         paramsData
; 
5445         // Evaluate sleep policy after sleeping drivers but before platform sleep. 
5447         DLOG("%s\n", __FUNCTION__
); 
5449         bzero(¶ms
, sizeof(params
)); 
5451         if (evaluateSystemSleepPolicy(¶ms
, kIOPMSleepPhase2
, &hibernateMode
)) { 
5452                 if ((kIOPMSleepTypeStandby 
== params
.sleepType
) 
5453                     && gIOHibernateStandbyDisabled 
&& gSleepPolicyVars
 
5454                     && (!((kIOPMSleepFactorStandbyForced 
| kIOPMSleepFactorAutoPowerOffForced 
| kIOPMSleepFactorHibernateForced
) 
5455                     & gSleepPolicyVars
->sleepFactors
))) { 
5456                         standbyNixed 
= true; 
5460                     || ((hibernateDisabled 
|| hibernateAborted
) && 
5461                     (getSleepTypeAttributes(params
.sleepType
) & 
5462                     kIOPMSleepAttributeHibernateSetup
))) { 
5463                         // Final evaluation picked a state requiring hibernation, 
5464                         // but hibernate isn't going to proceed. Arm a short sleep using 
5465                         // the early non-hibernate sleep parameters. 
5466                         bcopy(&gEarlySystemSleepParams
, ¶ms
, sizeof(params
)); 
5467                         params
.sleepType 
= kIOPMSleepTypeAbortedSleep
; 
5468                         params
.ecWakeTimer 
= 1; 
5472                                 // Set hibernateRetry flag to force hibernate setup on the 
5474                                 hibernateRetry 
= true; 
5476                         DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n", 
5477                             params
.ecWakeTimer
, hibernateDisabled
, hibernateAborted
, standbyNixed
); 
5479                         hibernateRetry 
= false; 
5482                 if (kIOPMSleepTypeAbortedSleep 
!= params
.sleepType
) { 
5483                         resetTimers 
= false; 
5486                 paramsData 
= OSData::withBytes(¶ms
, sizeof(params
)); 
5488                         setProperty(kIOPMSystemSleepParametersKey
, paramsData
.get()); 
5491                 if (getSleepTypeAttributes(params
.sleepType
) & 
5492                     kIOPMSleepAttributeHibernateSleep
) { 
5493                         // Disable sleep to force hibernation 
5494                         gIOHibernateMode 
&= ~kIOHibernateModeSleep
; 
5500 IOPMrootDomain::getHibernateSettings( 
5501         uint32_t *  hibernateModePtr
, 
5502         uint32_t *  hibernateFreeRatio
, 
5503         uint32_t *  hibernateFreeTime 
) 
5505         // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly() 
5506         // has updated the hibernateDisabled flag. 
5508         bool ok 
= getSleepOption(kIOHibernateModeKey
, hibernateModePtr
); 
5509         getSleepOption(kIOHibernateFreeRatioKey
, hibernateFreeRatio
); 
5510         getSleepOption(kIOHibernateFreeTimeKey
, hibernateFreeTime
); 
5511         if (hibernateDisabled
) { 
5512                 *hibernateModePtr 
= 0; 
5513         } else if (gSleepPolicyHandler
) { 
5514                 *hibernateModePtr 
= hibernateMode
; 
5516         DLOG("hibernateMode 0x%x\n", *hibernateModePtr
); 
5521 IOPMrootDomain::getSleepOption( const char * key
, uint32_t * option 
) 
5523         OSSharedPtr
<OSObject
>       optionsProp
; 
5524         OSDictionary 
*              optionsDict
; 
5525         OSSharedPtr
<OSObject
>       obj
; 
5529         optionsProp 
= copyProperty(kRootDomainSleepOptionsKey
); 
5530         optionsDict 
= OSDynamicCast(OSDictionary
, optionsProp
.get()); 
5533                 obj
.reset(optionsDict
->getObject(key
), OSRetain
); 
5536                 obj 
= copyProperty(key
); 
5539                 if ((num 
= OSDynamicCast(OSNumber
, obj
.get()))) { 
5540                         *option 
= num
->unsigned32BitValue(); 
5542                 } else if (OSDynamicCast(OSBoolean
, obj
.get())) { 
5543                         *option 
= (obj 
== kOSBooleanTrue
) ? 1 : 0; 
5550 #endif /* HIBERNATION */ 
5553 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType
, uint32_t * standbyTimer 
) 
5556         IOPMSystemSleepParameters   params
; 
5557         uint32_t                    hibMode 
= 0; 
5560         if (gIOPMWorkLoop
->inGate() == false) { 
5561                 IOReturn ret 
= gIOPMWorkLoop
->runAction( 
5562                         OSMemberFunctionCast(IOWorkLoop::Action
, this, 
5563                         &IOPMrootDomain::getSystemSleepType
), 
5565                         (void *) sleepType
, (void *) standbyTimer
); 
5569         getSleepOption(kIOHibernateModeKey
, &hibMode
); 
5570         bzero(¶ms
, sizeof(params
)); 
5572         ok 
= evaluateSystemSleepPolicy(¶ms
, kIOPMSleepPhase0
, &hibMode
); 
5574                 *sleepType 
= params
.sleepType
; 
5575                 if (!getSleepOption(kIOPMDeepSleepTimerKey
, standbyTimer
) && 
5576                     !getSleepOption(kIOPMDeepSleepDelayKey
, standbyTimer
)) { 
5577                         DLOG("Standby delay is not set\n"); 
5580                 return kIOReturnSuccess
; 
5584         return kIOReturnUnsupported
; 
5588 // MARK: Shutdown and Restart 
5590 //****************************************************************************** 
5591 // handlePlatformHaltRestart 
5593 //****************************************************************************** 
5595 // Phases while performing shutdown/restart 
5598         kNotifyPriorityClients      
= 0x10, 
5599         kNotifyPowerPlaneDrivers    
= 0x20, 
5600         kNotifyHaltRestartAction    
= 0x30, 
5605 struct HaltRestartApplierContext 
{ 
5606         IOPMrootDomain 
*    RootDomain
; 
5607         unsigned long       PowerState
; 
5608         IOPMPowerFlags      PowerFlags
; 
5611         const char *        LogString
; 
5612         shutdownPhase_t     phase
; 
5614         IOServiceInterestHandler    handler
; 
5618 shutdownPhase2String(shutdownPhase_t phase
) 
5622                 return "Notifications completed"; 
5623         case kNotifyPriorityClients
: 
5624                 return "Notifying priority clients"; 
5625         case kNotifyPowerPlaneDrivers
: 
5626                 return "Notifying power plane drivers"; 
5627         case kNotifyHaltRestartAction
: 
5628                 return "Notifying HaltRestart action handlers"; 
5630                 return "Quiescing PM"; 
5637 platformHaltRestartApplier( OSObject 
* object
, void * context 
) 
5639         IOPowerStateChangeNotification  notify
; 
5640         HaltRestartApplierContext 
*     ctx
; 
5641         AbsoluteTime                    startTime
, elapsedTime
; 
5644         ctx 
= (HaltRestartApplierContext 
*) context
; 
5646         _IOServiceInterestNotifier 
* notifier
; 
5647         notifier 
= OSDynamicCast(_IOServiceInterestNotifier
, object
); 
5648         memset(¬ify
, 0, sizeof(notify
)); 
5649         notify
.powerRef    
= (void *)(uintptr_t)ctx
->Counter
; 
5650         notify
.returnValue 
= 0; 
5651         notify
.stateNumber 
= ctx
->PowerState
; 
5652         notify
.stateFlags  
= ctx
->PowerFlags
; 
5655                 ctx
->handler 
= notifier
->handler
; 
5658         clock_get_uptime(&startTime
); 
5659         ctx
->RootDomain
->messageClient( ctx
->MessageType
, object
, (void *)¬ify 
); 
5660         deltaTime 
= computeDeltaTimeMS(&startTime
, &elapsedTime
); 
5662         if ((deltaTime 
> kPMHaltTimeoutMS
) && notifier
) { 
5663                 LOG("%s handler %p took %u ms\n", 
5664                     ctx
->LogString
, OBFUSCATE(notifier
->handler
), deltaTime
); 
5665                 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier
->handler
, elapsedTime
); 
5668         ctx
->handler 
= NULL
; 
5673 quiescePowerTreeCallback( void * target
, void * param 
) 
5675         IOLockLock(gPMHaltLock
); 
5677         thread_wakeup(param
); 
5678         IOLockUnlock(gPMHaltLock
); 
5682 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type 
) 
5684         AbsoluteTime                startTime
, elapsedTime
; 
5687         memset(&gHaltRestartCtx
, 0, sizeof(gHaltRestartCtx
)); 
5688         gHaltRestartCtx
.RootDomain 
= this; 
5690         clock_get_uptime(&startTime
); 
5693         case kPEUPSDelayHaltCPU
: 
5694                 gHaltRestartCtx
.PowerState  
= OFF_STATE
; 
5695                 gHaltRestartCtx
.MessageType 
= kIOMessageSystemWillPowerOff
; 
5696                 gHaltRestartCtx
.LogString   
= "PowerOff"; 
5700                 gHaltRestartCtx
.PowerState  
= RESTART_STATE
; 
5701                 gHaltRestartCtx
.MessageType 
= kIOMessageSystemWillRestart
; 
5702                 gHaltRestartCtx
.LogString   
= "Restart"; 
5706                 gHaltRestartCtx
.PowerState  
= ON_STATE
; 
5707                 gHaltRestartCtx
.MessageType 
= kIOMessageSystemPagingOff
; 
5708                 gHaltRestartCtx
.LogString   
= "PagingOff"; 
5709                 IOService::updateConsoleUsers(NULL
, kIOMessageSystemPagingOff
); 
5711                 IOHibernateSystemRestart(); 
5719         gHaltRestartCtx
.phase 
= kNotifyPriorityClients
; 
5720         // Notify legacy clients 
5721         applyToInterested(gIOPriorityPowerStateInterest
, platformHaltRestartApplier
, &gHaltRestartCtx
); 
5723         // For normal shutdown, turn off File Server Mode. 
5724         if (kPEHaltCPU 
== pe_type
) { 
5725                 OSSharedPtr
<const OSSymbol
> setting 
= OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
); 
5726                 OSSharedPtr
<OSNumber
> num 
= OSNumber::withNumber((unsigned long long) 0, 32); 
5727                 if (setting 
&& num
) { 
5728                         setPMSetting(setting
.get(), num
.get()); 
5732         if (kPEPagingOff 
!= pe_type
) { 
5733                 gHaltRestartCtx
.phase 
= kNotifyPowerPlaneDrivers
; 
5734                 // Notify in power tree order 
5735                 notifySystemShutdown(this, gHaltRestartCtx
.MessageType
); 
5738         gHaltRestartCtx
.phase 
= kNotifyHaltRestartAction
; 
5739 #if defined(XNU_TARGET_OS_OSX) 
5740         IOCPURunPlatformHaltRestartActions(pe_type
); 
5741 #else /* !defined(XNU_TARGET_OS_OSX) */ 
5742         if (kPEPagingOff 
!= pe_type
) { 
5743                 IOCPURunPlatformHaltRestartActions(pe_type
); 
5745 #endif /* !defined(XNU_TARGET_OS_OSX) */ 
5747         // Wait for PM to quiesce 
5748         if ((kPEPagingOff 
!= pe_type
) && gPMHaltLock
) { 
5749                 gHaltRestartCtx
.phase 
= kQuiescePM
; 
5750                 AbsoluteTime quiesceTime 
= mach_absolute_time(); 
5752                 IOLockLock(gPMHaltLock
); 
5753                 gPMQuiesced 
= false; 
5754                 if (quiescePowerTree(this, &quiescePowerTreeCallback
, &gPMQuiesced
) == 
5756                         while (!gPMQuiesced
) { 
5757                                 IOLockSleep(gPMHaltLock
, &gPMQuiesced
, THREAD_UNINT
); 
5760                 IOLockUnlock(gPMHaltLock
); 
5761                 deltaTime 
= computeDeltaTimeMS(&quiesceTime
, &elapsedTime
); 
5762                 DLOG("PM quiesce took %u ms\n", deltaTime
); 
5763                 halt_log_enter("Quiesce", NULL
, elapsedTime
); 
5765         gHaltRestartCtx
.phase 
= kNotifyDone
; 
5767         deltaTime 
= computeDeltaTimeMS(&startTime
, &elapsedTime
); 
5768         LOG("%s all drivers took %u ms\n", gHaltRestartCtx
.LogString
, deltaTime
); 
5770         halt_log_enter(gHaltRestartCtx
.LogString
, NULL
, elapsedTime
); 
5772         deltaTime 
= computeDeltaTimeMS(&gHaltStartTime
, &elapsedTime
); 
5773         LOG("%s total %u ms\n", gHaltRestartCtx
.LogString
, deltaTime
); 
5775         if (gHaltLog 
&& gHaltTimeMaxLog 
&& (deltaTime 
>= gHaltTimeMaxLog
)) { 
5776                 printf("%s total %d ms:%s\n", gHaltRestartCtx
.LogString
, deltaTime
, gHaltLog
); 
5779         checkShutdownTimeout(); 
5783 IOPMrootDomain::checkShutdownTimeout() 
5785         AbsoluteTime   elapsedTime
; 
5786         uint32_t deltaTime 
= computeDeltaTimeMS(&gHaltStartTime
, &elapsedTime
); 
5788         if (gHaltTimeMaxPanic 
&& (deltaTime 
>= gHaltTimeMaxPanic
)) { 
5795 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs
) 
5798                 if ((gHaltRestartCtx
.phase 
== kNotifyPriorityClients
) && gHaltRestartCtx
.handler
) { 
5799                         halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx
.handler
, mach_absolute_time() - gHaltStartTime
); 
5801                 panic("%s timed out in phase '%s'. Total %d ms:%s", 
5802                     gHaltRestartCtx
.LogString
, shutdownPhase2String(gHaltRestartCtx
.phase
), timeoutInMs
, gHaltLog
); 
5804                 panic("%s timed out in phase \'%s\'. Total %d ms", 
5805                     gHaltRestartCtx
.LogString
, shutdownPhase2String(gHaltRestartCtx
.phase
), timeoutInMs
); 
5809 //****************************************************************************** 
5812 //****************************************************************************** 
5815 IOPMrootDomain::shutdownSystem( void ) 
5817         return kIOReturnUnsupported
; 
5820 //****************************************************************************** 
5823 //****************************************************************************** 
5826 IOPMrootDomain::restartSystem( void ) 
5828         return kIOReturnUnsupported
; 
5832 // MARK: System Capability 
5834 //****************************************************************************** 
5835 // tagPowerPlaneService 
5837 // Running on PM work loop thread. 
5838 //****************************************************************************** 
5841 IOPMrootDomain::tagPowerPlaneService( 
5842         IOService 
*         service
, 
5843         IOPMActions 
*       actions
, 
5844         IOPMPowerStateIndex maxPowerState 
) 
5848         memset(actions
, 0, sizeof(*actions
)); 
5849         actions
->target 
= this; 
5851         if (service 
== this) { 
5852                 actions
->actionPowerChangeStart 
= 
5853                     OSMemberFunctionCast( 
5854                         IOPMActionPowerChangeStart
, this, 
5855                         &IOPMrootDomain::handleOurPowerChangeStart
); 
5857                 actions
->actionPowerChangeDone 
= 
5858                     OSMemberFunctionCast( 
5859                         IOPMActionPowerChangeDone
, this, 
5860                         &IOPMrootDomain::handleOurPowerChangeDone
); 
5862                 actions
->actionPowerChangeOverride 
= 
5863                     OSMemberFunctionCast( 
5864                         IOPMActionPowerChangeOverride
, this, 
5865                         &IOPMrootDomain::overrideOurPowerChange
); 
5869 #if DISPLAY_WRANGLER_PRESENT 
5870         if (NULL 
!= service
->metaCast("IODisplayWrangler")) { 
5871                 // XXX should this really retain? 
5872                 wrangler
.reset(service
, OSRetain
); 
5873                 wrangler
->registerInterest(gIOGeneralInterest
, 
5874                     &displayWranglerNotification
, this, NULL
); 
5876                 // found the display wrangler, check for any display assertions already created 
5877                 if (pmAssertions
->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit
) { 
5878                         DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n"); 
5879                         wrangler
->setIgnoreIdleTimer( true ); 
5881                 flags 
|= kPMActionsFlagIsDisplayWrangler
; 
5883 #endif /* DISPLAY_WRANGLER_PRESENT */ 
5885         if (service
->propertyExists("IOPMStrictTreeOrder")) { 
5886                 flags 
|= kPMActionsFlagIsGraphicsDriver
; 
5888         if (service
->propertyExists("IOPMUnattendedWakePowerState")) { 
5889                 flags 
|= kPMActionsFlagIsAudioDriver
; 
5892         OSSharedPtr
<OSObject
> prop 
= service
->copyProperty(kIOPMDarkWakeMaxPowerStateKey
); 
5894                 OSNumber 
* num 
= OSDynamicCast(OSNumber
, prop
.get()); 
5896                         actions
->darkWakePowerState 
= num
->unsigned32BitValue(); 
5897                         if (actions
->darkWakePowerState 
< maxPowerState
) { 
5898                                 flags 
|= kPMActionsFlagHasDarkWakePowerState
; 
5903         // Find the power connection object that is a child of the PCI host 
5904         // bridge, and has a graphics/audio device attached below. Mark the 
5905         // power branch for delayed child notifications. 
5908                 IORegistryEntry 
* child  
= service
; 
5909                 IORegistryEntry 
* parent 
= child
->getParentEntry(gIOPowerPlane
); 
5911                 while (child 
!= this) { 
5912                         if (child
->propertyHasValue("IOPCITunnelled", kOSBooleanTrue
)) { 
5913                                 // Skip delaying notifications and clamping power on external graphics and audio devices. 
5914                                 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service
->getRegistryEntryID(), flags
); 
5918                         if ((parent 
== pciHostBridgeDriver
) || 
5920                                 if (OSDynamicCast(IOPowerConnection
, child
)) { 
5921                                         IOPowerConnection 
* conn 
= (IOPowerConnection 
*) child
; 
5922                                         conn
->delayChildNotification 
= true; 
5923                                         DLOG("delayChildNotification for 0x%llx\n", conn
->getRegistryEntryID()); 
5928                         parent 
= child
->getParentEntry(gIOPowerPlane
); 
5933                 DLOG("%s tag flags %x\n", service
->getName(), flags
); 
5934                 actions
->flags 
|= flags
; 
5935                 actions
->actionPowerChangeOverride 
= 
5936                     OSMemberFunctionCast( 
5937                         IOPMActionPowerChangeOverride
, this, 
5938                         &IOPMrootDomain::overridePowerChangeForService
); 
5940                 if (flags 
& kPMActionsFlagIsDisplayWrangler
) { 
5941                         actions
->actionActivityTickle 
= 
5942                             OSMemberFunctionCast( 
5943                                 IOPMActionActivityTickle
, this, 
5944                                 &IOPMrootDomain::handleActivityTickleForDisplayWrangler
); 
5946                         actions
->actionUpdatePowerClient 
= 
5947                             OSMemberFunctionCast( 
5948                                 IOPMActionUpdatePowerClient
, this, 
5949                                 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler
); 
5954         // Locate the first PCI host bridge for PMTrace. 
5955         if (!pciHostBridgeDevice 
&& service
->metaCast("IOPCIBridge")) { 
5956                 IOService 
* provider 
= service
->getProvider(); 
5957                 if (OSDynamicCast(IOPlatformDevice
, provider
) && 
5958                     provider
->inPlane(gIODTPlane
)) { 
5959                         pciHostBridgeDevice
.reset(provider
, OSNoRetain
); 
5960                         pciHostBridgeDriver
.reset(service
, OSNoRetain
); 
5961                         DLOG("PMTrace found PCI host bridge %s->%s\n", 
5962                             provider
->getName(), service
->getName()); 
5966         // Tag top-level PCI devices. The order of PMinit() call does not 
5967         // change across boots and is used as the PCI bit number. 
5968         if (pciHostBridgeDevice 
&& service
->metaCast("IOPCIDevice")) { 
5969                 // Would prefer to check built-in property, but tagPowerPlaneService() 
5970                 // is called before pciDevice->registerService(). 
5971                 IORegistryEntry 
* parent 
= service
->getParentEntry(gIODTPlane
); 
5972                 if ((parent 
== pciHostBridgeDevice
) && service
->propertyExists("acpi-device")) { 
5973                         int bit 
= pmTracer
->recordTopLevelPCIDevice( service 
); 
5975                                 // Save the assigned bit for fast lookup. 
5976                                 actions
->flags 
|= (bit 
& kPMActionsPCIBitNumberMask
); 
5978                                 actions
->actionPowerChangeStart 
= 
5979                                     OSMemberFunctionCast( 
5980                                         IOPMActionPowerChangeStart
, this, 
5981                                         &IOPMrootDomain::handlePowerChangeStartForPCIDevice
); 
5983                                 actions
->actionPowerChangeDone 
= 
5984                                     OSMemberFunctionCast( 
5985                                         IOPMActionPowerChangeDone
, this, 
5986                                         &IOPMrootDomain::handlePowerChangeDoneForPCIDevice
); 
5992 //****************************************************************************** 
5993 // PM actions for root domain 
5994 //****************************************************************************** 
5997 IOPMrootDomain::overrideOurPowerChange( 
5998         IOService 
*             service
, 
5999         IOPMActions 
*           actions
, 
6000         const IOPMRequest 
*     request
, 
6001         IOPMPowerStateIndex 
*   inOutPowerState
, 
6002         IOPMPowerChangeFlags 
*  inOutChangeFlags 
) 
6004         uint32_t changeFlags 
= *inOutChangeFlags
; 
6005         uint32_t desiredPowerState 
= (uint32_t) *inOutPowerState
; 
6006         uint32_t currentPowerState 
= (uint32_t) getPowerState(); 
6008         if (request
->getTag() == 0) { 
6009                 // Set a tag for any request that originates from IOServicePM 
6010                 (const_cast<IOPMRequest 
*>(request
))->fTag 
= nextRequestTag(kCPSReasonPMInternals
); 
6013         DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n", 
6014             getPowerStateString(currentPowerState
), 
6015             getPowerStateString(desiredPowerState
), 
6016             _currentCapability
, changeFlags
, 
6020 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 
6022          * ASBM send lowBattery notifications every 1 second until the device 
6023          * enters hibernation. This queues up multiple sleep requests. 
6024          * After the device wakes from hibernation, none of these previously 
6025          * queued sleep requests are valid. 
6026          * lowBattteryCondition variable is set when ASBM notifies rootDomain 
6027          * and is cleared at the very last point in sleep. 
6028          * Any attempt to sleep with reason kIOPMSleepReasonLowPower without 
6029          * lowBatteryCondition is invalid 
6031         if (REQUEST_TAG_TO_REASON(request
->getTag()) == kIOPMSleepReasonLowPower
) { 
6032                 if (!lowBatteryCondition
) { 
6033                         DLOG("Duplicate lowBattery sleep"); 
6034                         *inOutChangeFlags 
|= kIOPMNotDone
; 
6040         if ((AOT_STATE 
== desiredPowerState
) && (ON_STATE 
== currentPowerState
)) { 
6041                 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT) 
6042                 *inOutChangeFlags 
|= kIOPMNotDone
; 
6046         if (changeFlags 
& kIOPMParentInitiated
) { 
6047                 // Root parent is permanently pegged at max power, 
6048                 // a parent initiated power change is unexpected. 
6049                 *inOutChangeFlags 
|= kIOPMNotDone
; 
6053         if (desiredPowerState 
< currentPowerState
) { 
6054                 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) { 
6055                         // Root domain is dropping power state from ON->SLEEP. 
6056                         // If system is in full wake, first enter dark wake by 
6057                         // converting the power drop to a capability change. 
6058                         // Once in dark wake, transition to sleep state ASAP. 
6060                         darkWakeToSleepASAP 
= true; 
6062                         // Drop graphics and audio capability 
6063                         _desiredCapability 
&= ~( 
6064                                 kIOPMSystemCapabilityGraphics 
| 
6065                                 kIOPMSystemCapabilityAudio
); 
6067                         // Convert to capability change (ON->ON) 
6068                         *inOutPowerState 
= getRUN_STATE(); 
6069                         *inOutChangeFlags 
|= kIOPMSynchronize
; 
6071                         // Revert device desire from SLEEP to ON 
6072                         changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride
); 
6074                         // System is already in dark wake, ok to drop power state. 
6075                         // Broadcast root power down to entire tree. 
6076                         *inOutChangeFlags 
|= kIOPMRootChangeDown
; 
6078         } else if (desiredPowerState 
> currentPowerState
) { 
6079                 if ((_currentCapability 
& kIOPMSystemCapabilityCPU
) == 0) { 
6080                         // Broadcast power up when waking from sleep, but not for the 
6081                         // initial power change at boot by checking for cpu capability. 
6082                         *inOutChangeFlags 
|= kIOPMRootChangeUp
; 
6088 IOPMrootDomain::handleOurPowerChangeStart( 
6089         IOService 
*             service
, 
6090         IOPMActions 
*           actions
, 
6091         const IOPMRequest 
*     request
, 
6092         IOPMPowerStateIndex     newPowerState
, 
6093         IOPMPowerChangeFlags 
*  inOutChangeFlags 
) 
6095         IOPMRequestTag requestTag 
= request
->getTag(); 
6096         IOPMRequestTag sleepReason
; 
6098         uint32_t changeFlags        
= *inOutChangeFlags
; 
6099         uint32_t currentPowerState  
= (uint32_t) getPowerState(); 
6100         bool     publishSleepReason 
= false; 
6102         // Check if request has a valid sleep reason 
6103         sleepReason 
= REQUEST_TAG_TO_REASON(requestTag
); 
6104         if (sleepReason 
< kIOPMSleepReasonClamshell
) { 
6105                 sleepReason 
= kIOPMSleepReasonIdle
; 
6108         _systemTransitionType    
= kSystemTransitionNone
; 
6109         _systemMessageClientMask 
= 0; 
6110         capabilityLoss           
= false; 
6111         toldPowerdCapWillChange  
= false; 
6113         // Emergency notifications may arrive after the initial sleep request 
6114         // has been queued. Override the sleep reason so powerd and others can 
6115         // treat this as an emergency sleep. 
6116         if (lowBatteryCondition
) { 
6117                 sleepReason 
= kIOPMSleepReasonLowPower
; 
6118         } else if (thermalEmergencyState
) { 
6119                 sleepReason 
= kIOPMSleepReasonThermalEmergency
; 
6122         // 1. Explicit capability change. 
6123         if (changeFlags 
& kIOPMSynchronize
) { 
6124                 if (newPowerState 
== ON_STATE
) { 
6125                         if (changeFlags 
& kIOPMSyncNoChildNotify
) { 
6126                                 _systemTransitionType 
= kSystemTransitionNewCapClient
; 
6128                                 _systemTransitionType 
= kSystemTransitionCapability
; 
6132         // 2. Going to sleep (cancellation still possible). 
6133         else if (newPowerState 
< currentPowerState
) { 
6134                 _systemTransitionType 
= kSystemTransitionSleep
; 
6136         // 3. Woke from (idle or demand) sleep. 
6137         else if (!systemBooting 
&& 
6138             (changeFlags 
& kIOPMSelfInitiated
) && 
6139             (newPowerState 
> currentPowerState
)) { 
6140                 _systemTransitionType 
= kSystemTransitionWake
; 
6141                 _desiredCapability 
= kIOPMSystemCapabilityCPU 
| kIOPMSystemCapabilityNetwork
; 
6143                 // Early exit from dark wake to full (e.g. LID open) 
6144                 if (kFullWakeReasonNone 
!= fullWakeReason
) { 
6145                         _desiredCapability 
|= ( 
6146                                 kIOPMSystemCapabilityGraphics 
| 
6147                                 kIOPMSystemCapabilityAudio
); 
6149 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 
6150                         if (fullWakeReason 
== kFullWakeReasonLocalUser
) { 
6151                                 darkWakeExit 
= true; 
6152                                 darkWakeToSleepASAP 
= false; 
6153                                 setProperty(kIOPMRootDomainWakeTypeKey
, isRTCAlarmWake 
? 
6154                                     kIOPMRootDomainWakeTypeAlarm 
: kIOPMRootDomainWakeTypeUser
); 
6159                 IOHibernateSetWakeCapabilities(_desiredCapability
); 
6163         // Update pending wake capability at the beginning of every 
6164         // state transition (including synchronize). This will become 
6165         // the current capability at the end of the transition. 
6167         if (kSystemTransitionSleep 
== _systemTransitionType
) { 
6168                 _pendingCapability 
= 0; 
6169                 capabilityLoss 
= true; 
6170         } else if (kSystemTransitionNewCapClient 
!= _systemTransitionType
) { 
6171                 _pendingCapability 
= _desiredCapability 
| 
6172                     kIOPMSystemCapabilityCPU 
| 
6173                     kIOPMSystemCapabilityNetwork
; 
6175                 if (_pendingCapability 
& kIOPMSystemCapabilityGraphics
) { 
6176                         _pendingCapability 
|= kIOPMSystemCapabilityAudio
; 
6179                 if ((kSystemTransitionCapability 
== _systemTransitionType
) && 
6180                     (_pendingCapability 
== _currentCapability
)) { 
6181                         // Cancel the PM state change. 
6182                         _systemTransitionType 
= kSystemTransitionNone
; 
6183                         *inOutChangeFlags 
|= kIOPMNotDone
; 
6185                 if (__builtin_popcount(_pendingCapability
) < 
6186                     __builtin_popcount(_currentCapability
)) { 
6187                         capabilityLoss 
= true; 
6191         // 1. Capability change. 
6192         if (kSystemTransitionCapability 
== _systemTransitionType
) { 
6193                 // Dark to Full transition. 
6194                 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) { 
6195                         tracePoint( kIOPMTracePointDarkWakeExit 
); 
6197 #if defined(XNU_TARGET_OS_OSX) 
6198                         // rdar://problem/65627936 
6199                         // When a dark->full wake promotion is scheduled before an ON->SLEEP 
6200                         // power state drop, invalidate any request to drop power state already 
6201                         // in the queue, including the override variant, unless full wake cannot 
6202                         // be sustained. Any power state drop queued after this SustainFullWake 
6203                         // request will not be affected. 
6204                         if (checkSystemCanSustainFullWake()) { 
6205                                 changePowerStateWithOverrideTo(getRUN_STATE(), kCPSReasonSustainFullWake
); 
6209                         willEnterFullWake(); 
6212                 // Full to Dark transition. 
6213                 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) { 
6214                         // Clear previous stats 
6215                         IOLockLock(pmStatsLock
); 
6216                         if (pmStatsAppResponses
) { 
6217                                 pmStatsAppResponses 
= OSArray::withCapacity(5); 
6219                         IOLockUnlock(pmStatsLock
); 
6221                         tracePoint( kIOPMTracePointDarkWakeEntry 
); 
6222                         *inOutChangeFlags 
|= kIOPMSyncTellPowerDown
; 
6223                         _systemMessageClientMask 
= kSystemMessageClientPowerd 
| 
6224                             kSystemMessageClientLegacyApp
; 
6227                         // Prevent user active transitions before notifying clients 
6228                         // that system will sleep. 
6229                         preventTransitionToUserActive(true); 
6231                         IOService::setAdvisoryTickleEnable( false ); 
6233                         // Publish the sleep reason for full to dark wake 
6234                         publishSleepReason 
= true; 
6235                         lastSleepReason 
= fullToDarkReason 
= sleepReason
; 
6237                         // Publish a UUID for the Sleep --> Wake cycle 
6238                         handlePublishSleepWakeUUID(true); 
6239                         if (sleepDelaysReport
) { 
6240                                 clock_get_uptime(&ts_sleepStart
); 
6241                                 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart
); 
6244                         darkWakeExit 
= false; 
6248         else if (kSystemTransitionSleep 
== _systemTransitionType
) { 
6249                 // Beginning of a system sleep transition. 
6250                 // Cancellation is still possible. 
6251                 tracePoint( kIOPMTracePointSleepStarted 
); 
6253                 _systemMessageClientMask 
= kSystemMessageClientAll
; 
6254                 if ((_currentCapability 
& kIOPMSystemCapabilityGraphics
) == 0) { 
6255                         _systemMessageClientMask 
&= ~kSystemMessageClientLegacyApp
; 
6257                 if ((_highestCapability 
& kIOPMSystemCapabilityGraphics
) == 0) { 
6258                         // Kernel priority clients are only notified on the initial 
6259                         // transition to full wake, so don't notify them unless system 
6260                         // has gained graphics capability since the last system wake. 
6261                         _systemMessageClientMask 
&= ~kSystemMessageClientKernel
; 
6263                         // System was in full wake, but the downwards power transition is driven 
6264                         // by a request that originates from IOServicePM, so it isn't tagged with 
6265                         // a valid system sleep reason. 
6266                         if (REQUEST_TAG_TO_REASON(requestTag
) == kCPSReasonPMInternals
) { 
6267                                 // Publish the same reason for full to dark 
6268                                 sleepReason 
= fullToDarkReason
; 
6272                 gIOHibernateState 
= 0; 
6275                 // Record the reason for dark wake back to sleep 
6276                 // System may not have ever achieved full wake 
6278                 publishSleepReason 
= true; 
6279                 lastSleepReason 
= sleepReason
; 
6280                 if (sleepDelaysReport
) { 
6281                         clock_get_uptime(&ts_sleepStart
); 
6282                         DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart
); 
6286         else if (kSystemTransitionWake 
== _systemTransitionType
) { 
6287                 tracePoint( kIOPMTracePointWakeWillPowerOnClients 
); 
6288                 // Clear stats about sleep 
6290                 if (AOT_STATE 
== newPowerState
) { 
6291                         _pendingCapability 
= 0; 
6294                 if (AOT_STATE 
== currentPowerState
) { 
6295                         // Wake events are no longer accepted after waking to AOT_STATE. 
6296                         // Re-enable wake event acceptance to append wake events claimed 
6297                         // during the AOT to ON_STATE transition. 
6298                         acceptSystemWakeEvents(kAcceptSystemWakeEvents_Reenable
); 
6301                 if (_pendingCapability 
& kIOPMSystemCapabilityGraphics
) { 
6302                         willEnterFullWake(); 
6306         // The only location where the sleep reason is published. At this point 
6307         // sleep can still be cancelled, but sleep reason should be published 
6308         // early for logging purposes. 
6310         if (publishSleepReason
) { 
6311                 static const char * IOPMSleepReasons
[] = 
6313                         kIOPMClamshellSleepKey
, 
6314                         kIOPMPowerButtonSleepKey
, 
6315                         kIOPMSoftwareSleepKey
, 
6316                         kIOPMOSSwitchHibernationKey
, 
6318                         kIOPMLowPowerSleepKey
, 
6319                         kIOPMThermalEmergencySleepKey
, 
6320                         kIOPMMaintenanceSleepKey
, 
6321                         kIOPMSleepServiceExitKey
, 
6322                         kIOPMDarkWakeThermalEmergencyKey
, 
6323                         kIOPMNotificationWakeExitKey
 
6326                 // Record sleep cause in IORegistry 
6327                 uint32_t reasonIndex 
= sleepReason 
- kIOPMSleepReasonClamshell
; 
6328                 if (reasonIndex 
< sizeof(IOPMSleepReasons
) / sizeof(IOPMSleepReasons
[0])) { 
6329                         DLOG("sleep reason %s\n", IOPMSleepReasons
[reasonIndex
]); 
6330                         setProperty(kRootDomainSleepReasonKey
, IOPMSleepReasons
[reasonIndex
]); 
6334         if ((kSystemTransitionNone 
!= _systemTransitionType
) && 
6335             (kSystemTransitionNewCapClient 
!= _systemTransitionType
)) { 
6336                 _systemStateGeneration
++; 
6337                 systemDarkWake 
= false; 
6339                 DLOG("=== START (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n", 
6340                     getPowerStateString(currentPowerState
), 
6341                     getPowerStateString((uint32_t) newPowerState
), 
6342                     _currentCapability
, _pendingCapability
, 
6343                     *inOutChangeFlags
, _systemStateGeneration
, _systemMessageClientMask
, 
6347         if ((AOT_STATE 
== newPowerState
) && (SLEEP_STATE 
!= currentPowerState
)) { 
6348                 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState
)); 
6350         if (_aotNow 
&& (ON_STATE 
== newPowerState
)) { 
6352                 aotShouldExit(false, true); 
6359 IOPMrootDomain::handleOurPowerChangeDone( 
6360         IOService 
*             service
, 
6361         IOPMActions 
*           actions
, 
6362         const IOPMRequest 
*     request
, 
6363         IOPMPowerStateIndex     oldPowerState
, 
6364         IOPMPowerChangeFlags    changeFlags 
) 
6366         if (kSystemTransitionNewCapClient 
== _systemTransitionType
) { 
6367                 _systemTransitionType 
= kSystemTransitionNone
; 
6371         if (_systemTransitionType 
!= kSystemTransitionNone
) { 
6372                 uint32_t currentPowerState 
= (uint32_t) getPowerState(); 
6374                 if (changeFlags 
& kIOPMNotDone
) { 
6375                         // Power down was cancelled or vetoed. 
6376                         _pendingCapability 
= _currentCapability
; 
6377                         lastSleepReason 
= 0; 
6379                         // When sleep is cancelled or reverted, don't report 
6380                         // the target (lower) power state as the previous state. 
6381                         oldPowerState 
= currentPowerState
; 
6383                         if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
) && 
6384                             CAP_CURRENT(kIOPMSystemCapabilityCPU
)) { 
6385 #if defined(XNU_TARGET_OS_OSX) 
6386                                 pmPowerStateQueue
->submitPowerEvent( 
6387                                         kPowerEventPolicyStimulus
, 
6388                                         (void *) kStimulusDarkWakeReentry
, 
6389                                         _systemStateGeneration 
); 
6390 #else /* !defined(XNU_TARGET_OS_OSX) */ 
6391                                 // On embedded, there are no factors that can prolong a 
6392                                 // "darkWake" when a power down is vetoed. We need to 
6393                                 // promote to "fullWake" at least once so that factors 
6394                                 // that prevent idle sleep can assert themselves if required 
6395                                 pmPowerStateQueue
->submitPowerEvent( 
6396                                         kPowerEventPolicyStimulus
, 
6397                                         (void *) kStimulusDarkWakeActivityTickle
); 
6398 #endif /* !defined(XNU_TARGET_OS_OSX) */ 
6401                         // Revert device desire to max. 
6402                         changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel
); 
6404                         // Send message on dark wake to full wake promotion. 
6405                         // tellChangeUp() handles the normal SLEEP->ON case. 
6407                         if (kSystemTransitionCapability 
== _systemTransitionType
) { 
6408                                 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) { 
6409                                         lastSleepReason 
= 0; // stop logging wrangler tickles 
6410                                         tellClients(kIOMessageSystemHasPoweredOn
); 
6412                                 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) { 
6413                                         // Going dark, reset full wake state 
6414                                         // userIsActive will be cleared by wrangler powering down 
6415                                         fullWakeReason 
= kFullWakeReasonNone
; 
6417                                         if (ts_sleepStart
) { 
6418                                                 clock_get_uptime(&wake2DarkwakeDelay
); 
6419                                                 SUB_ABSOLUTETIME(&wake2DarkwakeDelay
, &ts_sleepStart
); 
6420                                                 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay
); 
6426                         // Reset state after exiting from dark wake. 
6428                         if (CAP_GAIN(kIOPMSystemCapabilityGraphics
) || 
6429                             CAP_LOSS(kIOPMSystemCapabilityCPU
)) { 
6430                                 darkWakeMaintenance 
= false; 
6431                                 darkWakeToSleepASAP 
= false; 
6432                                 pciCantSleepValid   
= false; 
6433                                 darkWakeSleepService 
= false; 
6435                                 if (CAP_LOSS(kIOPMSystemCapabilityCPU
)) { 
6436                                         // Remove the influence of display power assertion 
6437                                         // before next system wake. 
6439                                                 wrangler
->changePowerStateForRootDomain( 
6440                                                         kWranglerPowerStateMin 
); 
6442                                         removeProperty(gIOPMUserTriggeredFullWakeKey
.get()); 
6446                         // Entered dark mode. 
6448                         if (((_pendingCapability 
& kIOPMSystemCapabilityGraphics
) == 0) && 
6449                             (_pendingCapability 
& kIOPMSystemCapabilityCPU
)) { 
6450                                 // Queue an evaluation of whether to remain in dark wake, 
6451                                 // and for how long. This serves the purpose of draining 
6452                                 // any assertions from the queue. 
6454                                 pmPowerStateQueue
->submitPowerEvent( 
6455                                         kPowerEventPolicyStimulus
, 
6456                                         (void *) kStimulusDarkWakeEntry
, 
6457                                         _systemStateGeneration 
); 
6461                 DLOG("=== FINISH (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n", 
6462                     getPowerStateString((uint32_t) oldPowerState
), getPowerStateString(currentPowerState
), 
6463                     _currentCapability
, _pendingCapability
, 
6464                     changeFlags
, _systemStateGeneration
, _systemMessageClientMask
, 
6467                 if ((currentPowerState 
== ON_STATE
) && pmAssertions
) { 
6468                         pmAssertions
->reportCPUBitAccounting(); 
6471                 if (_pendingCapability 
& kIOPMSystemCapabilityGraphics
) { 
6473 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 
6474                         if (clamshellExists 
&& fullWakeThreadCall
) { 
6475                                 AbsoluteTime deadline
; 
6476                                 clock_interval_to_deadline(DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
, kSecondScale
, &deadline
); 
6477                                 thread_call_enter_delayed(fullWakeThreadCall
, deadline
); 
6480                 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU
)) { 
6484                 // Update current system capability. 
6485                 if (_currentCapability 
!= _pendingCapability
) { 
6486                         _currentCapability 
= _pendingCapability
; 
6489                 // Update highest system capability. 
6491                 _highestCapability 
|= _currentCapability
; 
6493                 if (darkWakePostTickle 
&& 
6494                     (kSystemTransitionWake 
== _systemTransitionType
) && 
6495                     (gDarkWakeFlags 
& kDarkWakeFlagPromotionMask
) == 
6496                     kDarkWakeFlagPromotionLate
) { 
6497                         darkWakePostTickle 
= false; 
6499                 } else if (darkWakeExit
) { 
6500                         requestFullWake( kFullWakeReasonLocalUser 
); 
6503                 // Reset tracepoint at completion of capability change, 
6504                 // completion of wake transition, and aborted sleep transition. 
6506                 if ((_systemTransitionType 
== kSystemTransitionCapability
) || 
6507                     (_systemTransitionType 
== kSystemTransitionWake
) || 
6508                     ((_systemTransitionType 
== kSystemTransitionSleep
) && 
6509                     (changeFlags 
& kIOPMNotDone
))) { 
6510                         setProperty(kIOPMSystemCapabilitiesKey
, _currentCapability
, 64); 
6511                         tracePoint( kIOPMTracePointSystemUp 
); 
6514                 _systemTransitionType 
= kSystemTransitionNone
; 
6515                 _systemMessageClientMask 
= 0; 
6516                 toldPowerdCapWillChange  
= false; 
6518                 darkWakeLogClamp 
= false; 
6520                 if (lowBatteryCondition
) { 
6521                         privateSleepSystem(kIOPMSleepReasonLowPower
); 
6522                 } else if (thermalEmergencyState
) { 
6523                         privateSleepSystem(kIOPMSleepReasonThermalEmergency
); 
6524                 } else if ((fullWakeReason 
== kFullWakeReasonDisplayOn
) && !displayPowerOnRequested
) { 
6525                         // Request for full wake is removed while system is waking up to full wake 
6526                         DLOG("DisplayOn fullwake request is removed\n"); 
6527                         handleSetDisplayPowerOn(false); 
6530                 if ((gClamshellFlags 
& kClamshell_WAR_47715679
) && isRTCAlarmWake
) { 
6531                         pmPowerStateQueue
->submitPowerEvent( 
6532                                 kPowerEventReceivedPowerNotification
, (void *)(uintptr_t) kLocalEvalClamshellCommand 
); 
6537 //****************************************************************************** 
6538 // PM actions for graphics and audio. 
6539 //****************************************************************************** 
6542 IOPMrootDomain::overridePowerChangeForService( 
6543         IOService 
*             service
, 
6544         IOPMActions 
*           actions
, 
6545         const IOPMRequest 
*     request
, 
6546         IOPMPowerStateIndex 
*   inOutPowerState
, 
6547         IOPMPowerChangeFlags 
*  inOutChangeFlags 
) 
6549         uint32_t powerState  
= (uint32_t) *inOutPowerState
; 
6550         uint32_t changeFlags 
= (uint32_t) *inOutChangeFlags
; 
6551         const uint32_t actionFlags 
= actions
->flags
; 
6553         if (kSystemTransitionNone 
== _systemTransitionType
) { 
6554                 // Not in midst of a system transition. 
6555                 // Do not set kPMActionsStatePowerClamped. 
6556         } else if ((actions
->state 
& kPMActionsStatePowerClamped
) == 0) { 
6557                 bool enableClamp 
= false; 
6559                 // For most drivers, enable the clamp during ON->Dark transition 
6560                 // which has the kIOPMSynchronize flag set in changeFlags. 
6561                 if ((actionFlags 
& kPMActionsFlagIsDisplayWrangler
) && 
6562                     ((_pendingCapability 
& kIOPMSystemCapabilityGraphics
) == 0) && 
6563                     (changeFlags 
& kIOPMSynchronize
)) { 
6565                 } else if ((actionFlags 
& kPMActionsFlagIsAudioDriver
) && 
6566                     ((gDarkWakeFlags 
& kDarkWakeFlagAudioNotSuppressed
) == 0) && 
6567                     ((_pendingCapability 
& kIOPMSystemCapabilityAudio
) == 0) && 
6568                     (changeFlags 
& kIOPMSynchronize
)) { 
6570                 } else if ((actionFlags 
& kPMActionsFlagHasDarkWakePowerState
) && 
6571                     ((_pendingCapability 
& kIOPMSystemCapabilityGraphics
) == 0) && 
6572                     (changeFlags 
& kIOPMSynchronize
)) { 
6574                 } else if ((actionFlags 
& kPMActionsFlagIsGraphicsDriver
) && 
6575                     (_systemTransitionType 
== kSystemTransitionSleep
)) { 
6576                         // For graphics drivers, clamp power when entering 
6577                         // system sleep. Not when dropping to dark wake. 
6582                         actions
->state 
|= kPMActionsStatePowerClamped
; 
6583                         DLOG("power clamp enabled %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n", 
6584                             service
->getName(), service
->getRegistryEntryID(), 
6585                             _pendingCapability
, powerState
, changeFlags
); 
6587         } else if ((actions
->state 
& kPMActionsStatePowerClamped
) != 0) { 
6588                 bool disableClamp 
= false; 
6590                 if ((actionFlags 
& ( 
6591                             kPMActionsFlagIsDisplayWrangler 
| 
6592                             kPMActionsFlagIsGraphicsDriver
)) && 
6593                     (_pendingCapability 
& kIOPMSystemCapabilityGraphics
)) { 
6594                         disableClamp 
= true; 
6595                 } else if ((actionFlags 
& kPMActionsFlagIsAudioDriver
) && 
6596                     (_pendingCapability 
& kIOPMSystemCapabilityAudio
)) { 
6597                         disableClamp 
= true; 
6598                 } else if ((actionFlags 
& kPMActionsFlagHasDarkWakePowerState
) && 
6599                     (_pendingCapability 
& kIOPMSystemCapabilityGraphics
)) { 
6600                         disableClamp 
= true; 
6604                         actions
->state 
&= ~kPMActionsStatePowerClamped
; 
6605                         DLOG("power clamp removed %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n", 
6606                             service
->getName(), service
->getRegistryEntryID(), 
6607                             _pendingCapability
, powerState
, changeFlags
); 
6611         if (actions
->state 
& kPMActionsStatePowerClamped
) { 
6612                 uint32_t maxPowerState 
= 0; 
6614                 // Determine the max power state allowed when clamp is enabled 
6615                 if (changeFlags 
& (kIOPMDomainDidChange 
| kIOPMDomainWillChange
)) { 
6616                         // Parent intiated power state changes 
6617                         if ((service
->getPowerState() > maxPowerState
) && 
6618                             (actionFlags 
& kPMActionsFlagIsDisplayWrangler
)) { 
6621                                 // Remove lingering effects of any tickle before entering 
6622                                 // dark wake. It will take a new tickle to return to full 
6623                                 // wake, so the existing tickle state is useless. 
6625                                 if (changeFlags 
& kIOPMDomainDidChange
) { 
6626                                         *inOutChangeFlags 
|= kIOPMExpireIdleTimer
; 
6628                         } else if (actionFlags 
& kPMActionsFlagIsGraphicsDriver
) { 
6630                         } else if (actionFlags 
& kPMActionsFlagHasDarkWakePowerState
) { 
6631                                 maxPowerState 
= actions
->darkWakePowerState
; 
6634                         // Deny all self-initiated changes when power is limited. 
6635                         // Wrangler tickle should never defeat the limiter. 
6636                         maxPowerState 
= service
->getPowerState(); 
6639                 if (powerState 
> maxPowerState
) { 
6640                         DLOG("power clamped %s %qx, ps %u->%u, cflags 0x%x)\n", 
6641                             service
->getName(), service
->getRegistryEntryID(), 
6642                             powerState
, maxPowerState
, changeFlags
); 
6643                         *inOutPowerState 
= maxPowerState
; 
6645                         if (darkWakePostTickle 
&& 
6646                             (actionFlags 
& kPMActionsFlagIsDisplayWrangler
) && 
6647                             (changeFlags 
& kIOPMDomainWillChange
) && 
6648                             ((gDarkWakeFlags 
& kDarkWakeFlagPromotionMask
) == 
6649                             kDarkWakeFlagPromotionEarly
)) { 
6650                                 darkWakePostTickle 
= false; 
6655                 if (!darkWakePowerClamped 
&& (changeFlags 
& kIOPMDomainDidChange
)) { 
6656                         if (darkWakeLogClamp
) { 
6660                                 clock_get_uptime(&now
); 
6661                                 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
); 
6662                                 absolutetime_to_nanoseconds(now
, &nsec
); 
6663                                 DLOG("dark wake power clamped after %u ms\n", 
6664                                     ((int)((nsec
) / NSEC_PER_MSEC
))); 
6666                         darkWakePowerClamped 
= true; 
6672 IOPMrootDomain::handleActivityTickleForDisplayWrangler( 
6673         IOService 
*     service
, 
6674         IOPMActions 
*   actions 
) 
6676 #if DISPLAY_WRANGLER_PRESENT 
6677         // Warning: Not running in PM work loop context - don't modify state !!! 
6678         // Trap tickle directed to IODisplayWrangler while running with graphics 
6679         // capability suppressed. 
6681         assert(service 
== wrangler
); 
6683         clock_get_uptime(&userActivityTime
); 
6684         bool aborting 
= ((lastSleepReason 
== kIOPMSleepReasonIdle
) 
6685             || (lastSleepReason 
== kIOPMSleepReasonMaintenance
) 
6686             || (lastSleepReason 
== kIOPMSleepReasonSoftware
)); 
6688                 userActivityCount
++; 
6689                 DLOG("display wrangler tickled1 %d lastSleepReason %d\n", 
6690                     userActivityCount
, lastSleepReason
); 
6693         if (!darkWakeExit 
&& ((_pendingCapability 
& kIOPMSystemCapabilityGraphics
) == 0)) { 
6694                 DLOG("display wrangler tickled\n"); 
6695                 if (kIOLogPMRootDomain 
& gIOKitDebug
) { 
6696                         OSReportWithBacktrace("Dark wake display tickle"); 
6698                 if (pmPowerStateQueue
) { 
6699                         pmPowerStateQueue
->submitPowerEvent( 
6700                                 kPowerEventPolicyStimulus
, 
6701                                 (void *) kStimulusDarkWakeActivityTickle
, 
6702                                 true /* set wake type */ ); 
6705 #endif /* DISPLAY_WRANGLER_PRESENT */ 
6709 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler( 
6710         IOService 
*             service
, 
6711         IOPMActions 
*           actions
, 
6712         const OSSymbol 
*        powerClient
, 
6713         IOPMPowerStateIndex     oldPowerState
, 
6714         IOPMPowerStateIndex     newPowerState 
) 
6716 #if DISPLAY_WRANGLER_PRESENT 
6717         assert(service 
== wrangler
); 
6719         // This function implements half of the user active detection 
6720         // by monitoring changes to the display wrangler's device desire. 
6722         // User becomes active when either: 
6723         // 1. Wrangler's DeviceDesire increases to max, but wrangler is already 
6724         //    in max power state. This desire change in absence of a power state 
6725         //    change is detected within. This handles the case when user becomes 
6726         //    active while the display is already lit by setDisplayPowerOn(). 
6728         // 2. Power state change to max, and DeviceDesire is also at max. 
6729         //    Handled by displayWranglerNotification(). 
6731         // User becomes inactive when DeviceDesire drops to sleep state or below. 
6733         DLOG("wrangler %s (ps %u, %u->%u)\n", 
6734             powerClient
->getCStringNoCopy(), 
6735             (uint32_t) service
->getPowerState(), 
6736             (uint32_t) oldPowerState
, (uint32_t) newPowerState
); 
6738         if (powerClient 
== gIOPMPowerClientDevice
) { 
6739                 if ((newPowerState 
> oldPowerState
) && 
6740                     (newPowerState 
== kWranglerPowerStateMax
) && 
6741                     (service
->getPowerState() == kWranglerPowerStateMax
)) { 
6742                         evaluatePolicy( kStimulusEnterUserActiveState 
); 
6743                 } else if ((newPowerState 
< oldPowerState
) && 
6744                     (newPowerState 
<= kWranglerPowerStateSleep
)) { 
6745                         evaluatePolicy( kStimulusLeaveUserActiveState 
); 
6749         if (newPowerState 
<= kWranglerPowerStateSleep
) { 
6750                 evaluatePolicy( kStimulusDisplayWranglerSleep 
); 
6751         } else if (newPowerState 
== kWranglerPowerStateMax
) { 
6752                 evaluatePolicy( kStimulusDisplayWranglerWake 
); 
6754 #endif /* DISPLAY_WRANGLER_PRESENT */ 
6757 //****************************************************************************** 
6758 // User active state management 
6759 //****************************************************************************** 
6762 IOPMrootDomain::preventTransitionToUserActive( bool prevent 
) 
6764 #if DISPLAY_WRANGLER_PRESENT 
6765         _preventUserActive 
= prevent
; 
6766         if (wrangler 
&& !_preventUserActive
) { 
6767                 // Allowing transition to user active, but the wrangler may have 
6768                 // already powered ON in case of sleep cancel/revert. Poll the 
6769                 // same conditions checked for in displayWranglerNotification() 
6770                 // to bring the user active state up to date. 
6772                 if ((wrangler
->getPowerState() == kWranglerPowerStateMax
) && 
6773                     (wrangler
->getPowerStateForClient(gIOPMPowerClientDevice
) == 
6774                     kWranglerPowerStateMax
)) { 
6775                         evaluatePolicy( kStimulusEnterUserActiveState 
); 
6778 #endif /* DISPLAY_WRANGLER_PRESENT */ 
6781 //****************************************************************************** 
6782 // Approve usage of delayed child notification by PM. 
6783 //****************************************************************************** 
6786 IOPMrootDomain::shouldDelayChildNotification( 
6787         IOService 
* service 
) 
6789         if ((kFullWakeReasonNone 
== fullWakeReason
) && 
6790             (kSystemTransitionWake 
== _systemTransitionType
)) { 
6791                 DLOG("%s: delay child notify\n", service
->getName()); 
6797 //****************************************************************************** 
6798 // PM actions for PCI device. 
6799 //****************************************************************************** 
6802 IOPMrootDomain::handlePowerChangeStartForPCIDevice( 
6803         IOService 
*             service
, 
6804         IOPMActions 
*           actions
, 
6805         const IOPMRequest 
*     request
, 
6806         IOPMPowerStateIndex     powerState
, 
6807         IOPMPowerChangeFlags 
*  inOutChangeFlags 
) 
6809         pmTracer
->tracePCIPowerChange( 
6810                 PMTraceWorker::kPowerChangeStart
, 
6811                 service
, *inOutChangeFlags
, 
6812                 (actions
->flags 
& kPMActionsPCIBitNumberMask
)); 
6816 IOPMrootDomain::handlePowerChangeDoneForPCIDevice( 
6817         IOService 
*             service
, 
6818         IOPMActions 
*           actions
, 
6819         const IOPMRequest 
*     request
, 
6820         IOPMPowerStateIndex     powerState
, 
6821         IOPMPowerChangeFlags    changeFlags 
) 
6823         pmTracer
->tracePCIPowerChange( 
6824                 PMTraceWorker::kPowerChangeCompleted
, 
6825                 service
, changeFlags
, 
6826                 (actions
->flags 
& kPMActionsPCIBitNumberMask
)); 
6829 //****************************************************************************** 
6832 // Override IOService::registerInterest() for root domain clients. 
6833 //****************************************************************************** 
6835 class IOPMServiceInterestNotifier 
: public _IOServiceInterestNotifier
 
6837         friend class IOPMrootDomain
; 
6838         OSDeclareDefaultStructors(IOPMServiceInterestNotifier
); 
6841         uint32_t        ackTimeoutCnt
; 
6842         uint32_t        msgType
;        // Message pending ack 
6844         uint32_t        maxMsgDelayMS
; 
6845         uint32_t        maxAckDelayMS
; 
6846         uint64_t        msgAbsTime
; 
6849         OSSharedPtr
<const OSSymbol
> identifier
; 
6850         OSSharedPtr
<const OSSymbol
> clientName
; 
6853 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier
, _IOServiceInterestNotifier
) 
6855 OSSharedPtr
<IONotifier
> 
6856 IOPMrootDomain::registerInterest( 
6857         const OSSymbol 
* typeOfInterest
, 
6858         IOServiceInterestHandler handler
, 
6859         void * target
, void * ref 
) 
6861         IOPMServiceInterestNotifier
* notifier
; 
6862         bool            isSystemCapabilityClient
; 
6863         bool            isKernelCapabilityClient
; 
6864         IOReturn        rc 
= kIOReturnError
; 
6866         isSystemCapabilityClient 
= typeOfInterest 
&& 
6867             typeOfInterest
->isEqualTo(kIOPMSystemCapabilityInterest
); 
6869         isKernelCapabilityClient 
= typeOfInterest 
&& 
6870             typeOfInterest
->isEqualTo(gIOPriorityPowerStateInterest
); 
6872         if (isSystemCapabilityClient
) { 
6873                 typeOfInterest 
= gIOAppPowerStateInterest
; 
6876         notifier 
= new IOPMServiceInterestNotifier
; 
6881         if (notifier
->init()) { 
6882                 rc  
= super::registerInterestForNotifier(notifier
, typeOfInterest
, handler
, target
, ref
); 
6884         if (rc 
!= kIOReturnSuccess
) { 
6888         notifier
->ackTimeoutCnt 
= 0; 
6890         if (pmPowerStateQueue
) { 
6891                 if (isSystemCapabilityClient
) { 
6893                         if (pmPowerStateQueue
->submitPowerEvent( 
6894                                     kPowerEventRegisterSystemCapabilityClient
, notifier
) == false) { 
6895                                 notifier
->release(); 
6899                 if (isKernelCapabilityClient
) { 
6901                         if (pmPowerStateQueue
->submitPowerEvent( 
6902                                     kPowerEventRegisterKernelCapabilityClient
, notifier
) == false) { 
6903                                 notifier
->release(); 
6908         OSSharedPtr
<OSData
> data
; 
6909         uint8_t *uuid 
= NULL
; 
6910         OSSharedPtr
<OSKext
> kext 
= OSKext::lookupKextWithAddress((vm_address_t
)handler
); 
6912                 data 
= kext
->copyUUID(); 
6914         if (data 
&& (data
->getLength() == sizeof(uuid_t
))) { 
6915                 uuid 
= (uint8_t *)(data
->getBytesNoCopy()); 
6917                 notifier
->uuid0 
= ((uint64_t)(uuid
[0]) << 56) | ((uint64_t)(uuid
[1]) << 48) | ((uint64_t)(uuid
[2]) << 40) | 
6918                     ((uint64_t)(uuid
[3]) << 32) | ((uint64_t)(uuid
[4]) << 24) | ((uint64_t)(uuid
[5]) << 16) | 
6919                     ((uint64_t)(uuid
[6]) << 8) | (uuid
[7]); 
6920                 notifier
->uuid1 
= ((uint64_t)(uuid
[8]) << 56) | ((uint64_t)(uuid
[9]) << 48) | ((uint64_t)(uuid
[10]) << 40) | 
6921                     ((uint64_t)(uuid
[11]) << 32) | ((uint64_t)(uuid
[12]) << 24) | ((uint64_t)(uuid
[13]) << 16) | 
6922                     ((uint64_t)(uuid
[14]) << 8) | (uuid
[15]); 
6924                 notifier
->identifier 
= copyKextIdentifierWithAddress((vm_address_t
) handler
); 
6926         return OSSharedPtr
<IOPMServiceInterestNotifier
>(notifier
, OSNoRetain
); 
6929 //****************************************************************************** 
6930 // systemMessageFilter 
6932 //****************************************************************************** 
6935 IOPMrootDomain::systemMessageFilter( 
6936         void * object
, void * arg1
, void * arg2
, void * arg3 
) 
6938         const IOPMInterestContext 
* context 
= (const IOPMInterestContext 
*) arg1
; 
6939         bool  isCapMsg 
= (context
->messageType 
== kIOMessageSystemCapabilityChange
); 
6940         bool  isCapClient 
= false; 
6942         IOPMServiceInterestNotifier 
*notifier
; 
6944         notifier 
= OSDynamicCast(IOPMServiceInterestNotifier
, (OSObject 
*)object
); 
6947                 if ((kSystemTransitionNewCapClient 
== _systemTransitionType
) && 
6948                     (!isCapMsg 
|| !_joinedCapabilityClients 
|| 
6949                     !_joinedCapabilityClients
->containsObject((OSObject 
*) object
))) { 
6953                 // Capability change message for app and kernel clients. 
6957                         if ((context
->notifyType 
== kNotifyPriority
) || 
6958                             (context
->notifyType 
== kNotifyCapabilityChangePriority
)) { 
6962                         // powerd's systemCapabilityNotifier 
6963                         if ((context
->notifyType 
== kNotifyCapabilityChangeApps
) && 
6964                             (object 
== (void *) systemCapabilityNotifier
.get())) { 
6970                         IOPMSystemCapabilityChangeParameters 
* capArgs 
= 
6971                             (IOPMSystemCapabilityChangeParameters 
*) arg2
; 
6973                         if (kSystemTransitionNewCapClient 
== _systemTransitionType
) { 
6974                                 capArgs
->fromCapabilities 
= 0; 
6975                                 capArgs
->toCapabilities 
= _currentCapability
; 
6976                                 capArgs
->changeFlags 
= 0; 
6978                                 capArgs
->fromCapabilities 
= _currentCapability
; 
6979                                 capArgs
->toCapabilities 
= _pendingCapability
; 
6981                                 if (context
->isPreChange
) { 
6982                                         capArgs
->changeFlags 
= kIOPMSystemCapabilityWillChange
; 
6984                                         capArgs
->changeFlags 
= kIOPMSystemCapabilityDidChange
; 
6987                                 if ((object 
== (void *) systemCapabilityNotifier
.get()) && 
6988                                     context
->isPreChange
) { 
6989                                         toldPowerdCapWillChange 
= true; 
6993                         // Capability change messages only go to the PM configd plugin. 
6994                         // Wait for response post-change if capabilitiy is increasing. 
6995                         // Wait for response pre-change if capability is decreasing. 
6997                         if ((context
->notifyType 
== kNotifyCapabilityChangeApps
) && arg3 
&& 
6998                             ((capabilityLoss 
&& context
->isPreChange
) || 
6999                             (!capabilityLoss 
&& !context
->isPreChange
))) { 
7000                                 // app has not replied yet, wait for it 
7001                                 *((OSObject 
**) arg3
) = kOSBooleanFalse
; 
7008                 // Capability client will always see kIOMessageCanSystemSleep, 
7009                 // even for demand sleep. It will also have a chance to veto 
7010                 // sleep one last time after all clients have responded to 
7011                 // kIOMessageSystemWillSleep 
7013                 if ((kIOMessageCanSystemSleep 
== context
->messageType
) || 
7014                     (kIOMessageSystemWillNotSleep 
== context
->messageType
)) { 
7015                         if (object 
== (OSObject 
*) systemCapabilityNotifier
.get()) { 
7020                         // Not idle sleep, don't ask apps. 
7021                         if (context
->changeFlags 
& kIOPMSkipAskPowerDown
) { 
7026                 if (kIOPMMessageLastCallBeforeSleep 
== context
->messageType
) { 
7027                         if ((object 
== (OSObject 
*) systemCapabilityNotifier
.get()) && 
7028                             CAP_HIGHEST(kIOPMSystemCapabilityGraphics
) && 
7029                             (fullToDarkReason 
== kIOPMSleepReasonIdle
)) { 
7035                 // Reject capability change messages for legacy clients. 
7036                 // Reject legacy system sleep messages for capability client. 
7038                 if (isCapMsg 
|| (object 
== (OSObject 
*) systemCapabilityNotifier
.get())) { 
7042                 // Filter system sleep messages. 
7044                 if ((context
->notifyType 
== kNotifyApps
) && 
7045                     (_systemMessageClientMask 
& kSystemMessageClientLegacyApp
)) { 
7050                                         if (notifier
->ackTimeoutCnt 
>= 3) { 
7051                                                 *((OSObject 
**) arg3
) = kOSBooleanFalse
; 
7053                                                 *((OSObject 
**) arg3
) = kOSBooleanTrue
; 
7057                 } else if ((context
->notifyType 
== kNotifyPriority
) && 
7058                     (_systemMessageClientMask 
& kSystemMessageClientKernel
)) { 
7063         if (allow 
&& isCapMsg 
&& _joinedCapabilityClients
) { 
7064                 _joinedCapabilityClients
->removeObject((OSObject 
*) object
); 
7065                 if (_joinedCapabilityClients
->getCount() == 0) { 
7066                         DLOG("destroyed capability client set %p\n", 
7067                             OBFUSCATE(_joinedCapabilityClients
.get())); 
7068                         _joinedCapabilityClients
.reset(); 
7072                 notifier
->msgType 
= context
->messageType
; 
7078 //****************************************************************************** 
7079 // setMaintenanceWakeCalendar 
7081 //****************************************************************************** 
7084 IOPMrootDomain::setMaintenanceWakeCalendar( 
7085         const IOPMCalendarStruct 
* calendar 
) 
7087         OSSharedPtr
<OSData
> data
; 
7091                 return kIOReturnBadArgument
; 
7094         data 
= OSData::withBytes((void *) calendar
, sizeof(*calendar
)); 
7096                 return kIOReturnNoMemory
; 
7099         if (kPMCalendarTypeMaintenance 
== calendar
->selector
) { 
7100                 ret 
= setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey
.get(), data
.get()); 
7101         } else if (kPMCalendarTypeSleepService 
== calendar
->selector
) { 
7102                 ret 
= setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey
.get(), data
.get()); 
7109 // MARK: Display Wrangler 
7111 //****************************************************************************** 
7112 // displayWranglerNotification 
7114 // Handle the notification when the IODisplayWrangler changes power state. 
7115 //****************************************************************************** 
7118 IOPMrootDomain::displayWranglerNotification( 
7119         void * target
, void * refCon
, 
7120         UInt32 messageType
, IOService 
* service
, 
7121         void * messageArgument
, vm_size_t argSize 
) 
7123 #if DISPLAY_WRANGLER_PRESENT 
7124         IOPMPowerStateIndex                 displayPowerState
; 
7125         IOPowerStateChangeNotification 
*    params 
= 
7126             (IOPowerStateChangeNotification 
*) messageArgument
; 
7128         if ((messageType 
!= kIOMessageDeviceWillPowerOff
) && 
7129             (messageType 
!= kIOMessageDeviceHasPoweredOn
)) { 
7130                 return kIOReturnUnsupported
; 
7135                 return kIOReturnUnsupported
; 
7138         displayPowerState 
= params
->stateNumber
; 
7139         DLOG("wrangler %s ps %d\n", 
7140             getIOMessageString(messageType
), (uint32_t) displayPowerState
); 
7142         switch (messageType
) { 
7143         case kIOMessageDeviceWillPowerOff
: 
7144                 // Display wrangler has dropped power due to display idle 
7145                 // or force system sleep. 
7147                 // 4 Display ON             kWranglerPowerStateMax 
7148                 // 3 Display Dim            kWranglerPowerStateDim 
7149                 // 2 Display Sleep          kWranglerPowerStateSleep 
7150                 // 1 Not visible to user 
7151                 // 0 Not visible to user    kWranglerPowerStateMin 
7153                 if (displayPowerState 
<= kWranglerPowerStateSleep
) { 
7154                         gRootDomain
->evaluatePolicy( kStimulusDisplayWranglerSleep 
); 
7158         case kIOMessageDeviceHasPoweredOn
: 
7159                 // Display wrangler has powered on due to user activity 
7160                 // or wake from sleep. 
7162                 if (kWranglerPowerStateMax 
== displayPowerState
) { 
7163                         gRootDomain
->evaluatePolicy( kStimulusDisplayWranglerWake 
); 
7165                         // See comment in handleUpdatePowerClientForDisplayWrangler 
7166                         if (service
->getPowerStateForClient(gIOPMPowerClientDevice
) == 
7167                             kWranglerPowerStateMax
) { 
7168                                 gRootDomain
->evaluatePolicy( kStimulusEnterUserActiveState 
); 
7173 #endif /* DISPLAY_WRANGLER_PRESENT */ 
7174         return kIOReturnUnsupported
; 
7177 //****************************************************************************** 
7180 //****************************************************************************** 
7183 IOPMrootDomain::updateUserActivity( void ) 
7185 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 
7186         clock_get_uptime(&userActivityTime
); 
7187         bool aborting 
=  ((lastSleepReason 
== kIOPMSleepReasonSoftware
) 
7188             || (lastSleepReason 
== kIOPMSleepReasonIdle
) 
7189             || (lastSleepReason 
== kIOPMSleepReasonMaintenance
)); 
7191                 userActivityCount
++; 
7192                 DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount
, lastSleepReason
); 
7197 IOPMrootDomain::reportUserInput( void ) 
7200                 wrangler
->activityTickle(0, 0); 
7202 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 
7203         // Update user activity 
7204         updateUserActivity(); 
7206         if (!darkWakeExit 
&& ((_pendingCapability 
& kIOPMSystemCapabilityGraphics
) == 0)) { 
7207                 // update user active abs time 
7208                 clock_get_uptime(&gUserActiveAbsTime
); 
7209                 pmPowerStateQueue
->submitPowerEvent( 
7210                         kPowerEventPolicyStimulus
, 
7211                         (void *) kStimulusDarkWakeActivityTickle
, 
7212                         true /* set wake type */ ); 
7218 IOPMrootDomain::requestUserActive(IOService 
*device
, const char *reason
) 
7220 #if DISPLAY_WRANGLER_PRESENT 
7222                 wrangler
->activityTickle(0, 0); 
7226                 DLOG("requestUserActive: device is null\n"); 
7229         OSSharedPtr
<const OSSymbol
> deviceName 
= device
->copyName(); 
7230         uint64_t registryID 
= device
->getRegistryEntryID(); 
7232         if (!deviceName 
|| !registryID
) { 
7233                 DLOG("requestUserActive: no device name or registry entry\n"); 
7236         const char *name 
= deviceName
->getCStringNoCopy(); 
7238         snprintf(payload
, sizeof(payload
), "%s:%s", name
, reason
); 
7239         DLOG("requestUserActive from %s (0x%llx) for %s\n", name
, registryID
, reason
); 
7240         messageClient(kIOPMMessageRequestUserActive
, systemCapabilityNotifier
.get(), (void *)payload
, sizeof(payload
)); 
7244 //****************************************************************************** 
7245 // latchDisplayWranglerTickle 
7246 //****************************************************************************** 
7249 IOPMrootDomain::latchDisplayWranglerTickle( bool latch 
) 
7251 #if DISPLAY_WRANGLER_PRESENT 
7253                 if (!(_currentCapability 
& kIOPMSystemCapabilityGraphics
) && 
7254                     !(_pendingCapability 
& kIOPMSystemCapabilityGraphics
) && 
7255                     !checkSystemCanSustainFullWake()) { 
7256                         // Currently in dark wake, and not transitioning to full wake. 
7257                         // Full wake is unsustainable, so latch the tickle to prevent 
7258                         // the display from lighting up momentarily. 
7259                         wranglerTickled 
= true; 
7261                         wranglerTickled 
= false; 
7263         } else if (wranglerTickled 
&& checkSystemCanSustainFullWake()) { 
7264                 wranglerTickled 
= false; 
7266                 pmPowerStateQueue
->submitPowerEvent( 
7267                         kPowerEventPolicyStimulus
, 
7268                         (void *) kStimulusDarkWakeActivityTickle 
); 
7271         return wranglerTickled
; 
7272 #else  /* ! DISPLAY_WRANGLER_PRESENT */ 
7274 #endif /* ! DISPLAY_WRANGLER_PRESENT */ 
7277 //****************************************************************************** 
7278 // setDisplayPowerOn 
7280 // For root domain user client 
7281 //****************************************************************************** 
7284 IOPMrootDomain::setDisplayPowerOn( uint32_t options 
) 
7286         pmPowerStateQueue
->submitPowerEvent( kPowerEventSetDisplayPowerOn
, 
7287             (void *) NULL
, options 
); 
7291 // MARK: System PM Policy 
7293 //****************************************************************************** 
7294 // checkSystemSleepAllowed 
7296 //****************************************************************************** 
7299 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options
, 
7300     uint32_t     sleepReason 
) 
7304         // Conditions that prevent idle and demand system sleep. 
7307                 if (userDisabledAllSleep
) { 
7308                         err 
= kPMUserDisabledAllSleep
; // 1. user-space sleep kill switch 
7312                 if (systemBooting 
|| systemShutdown 
|| gWillShutdown
) { 
7313                         err 
= kPMSystemRestartBootingInProgress
; // 2. restart or shutdown in progress 
7321                 // Conditions above pegs the system at full wake. 
7322                 // Conditions below prevent system sleep but does not prevent 
7323                 // dark wake, and must be called from gated context. 
7326                 err 
= kPMConfigPreventSystemSleep
;    // 3. config does not support sleep 
7330                 if (lowBatteryCondition 
|| thermalWarningState 
|| thermalEmergencyState
) { 
7331                         break; // always sleep on low battery or when in thermal warning/emergency state 
7334                 if (sleepReason 
== kIOPMSleepReasonDarkWakeThermalEmergency
) { 
7335                         break; // always sleep on dark wake thermal emergencies 
7338                 if (preventSystemSleepList
->getCount() != 0) { 
7339                         err 
= kPMChildPreventSystemSleep
; // 4. child prevent system sleep clamp 
7343                 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit 
) == 
7344                     kIOPMDriverAssertionLevelOn
) { 
7345                         err 
= kPMCPUAssertion
; // 5. CPU assertion 
7349                 if (pciCantSleepValid
) { 
7350                         if (pciCantSleepFlag
) { 
7351                                 err 
= kPMPCIUnsupported
; // 6. PCI card does not support PM (cached) 
7354                 } else if (sleepSupportedPEFunction 
&& 
7355                     CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) { 
7357                         OSBitAndAtomic(~kPCICantSleep
, &platformSleepSupport
); 
7358                         ret 
= getPlatform()->callPlatformFunction( 
7359                                 sleepSupportedPEFunction
.get(), false, 
7360                                 NULL
, NULL
, NULL
, NULL
); 
7361                         pciCantSleepValid 
= true; 
7362                         pciCantSleepFlag  
= false; 
7363                         if ((platformSleepSupport 
& kPCICantSleep
) || 
7364                             ((ret 
!= kIOReturnSuccess
) && (ret 
!= kIOReturnUnsupported
))) { 
7365                                 err 
= 6; // 6. PCI card does not support PM 
7366                                 pciCantSleepFlag 
= true; 
7373                 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err
)); 
7380 IOPMrootDomain::checkSystemSleepEnabled( void ) 
7382         return checkSystemSleepAllowed(0, 0); 
7386 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason 
) 
7389         return checkSystemSleepAllowed(1, sleepReason
); 
7392 //****************************************************************************** 
7393 // checkSystemCanSustainFullWake 
7394 //****************************************************************************** 
7397 IOPMrootDomain::checkSystemCanSustainFullWake( void ) 
7399         if (lowBatteryCondition 
|| thermalWarningState 
|| thermalEmergencyState
) { 
7400                 // Low battery wake, or received a low battery notification 
7401                 // while system is awake. This condition will persist until 
7402                 // the following wake. 
7406         if (clamshellExists 
&& clamshellClosed 
&& !clamshellSleepDisableMask
) { 
7407                 // Graphics state is unknown and external display might not be probed. 
7408                 // Do not incorporate state that requires graphics to be in max power 
7409                 // such as desktopMode or clamshellDisabled. 
7411                 if (!acAdaptorConnected
) { 
7412                         DLOG("full wake check: no AC\n"); 
7419 //****************************************************************************** 
7421 //****************************************************************************** 
7426 IOPMrootDomain::mustHibernate( void ) 
7428         return lowBatteryCondition 
|| thermalWarningState
; 
7431 #endif /* HIBERNATION */ 
7433 //****************************************************************************** 
7435 //****************************************************************************** 
7437 // Tables for accumulated days in year by month, latter used for leap years 
7439 static const unsigned int daysbymonth
[] = 
7440 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; 
7442 static const unsigned int lydaysbymonth
[] = 
7443 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; 
7446 IOPMConvertSecondsToCalendar(clock_sec_t secs
, IOPMCalendarStruct 
* dt
) 
7448         const unsigned int *    dbm 
= daysbymonth
; 
7449         clock_sec_t             n
, x
, y
, z
; 
7451         // Calculate seconds, minutes and hours 
7453         n 
= secs 
% (24 * 3600); 
7454         dt
->second 
= n 
% 60; 
7456         dt
->minute 
= n 
% 60; 
7457         dt
->hour 
= (typeof(dt
->hour
))(n 
/ 60); 
7459         // Calculate day of week 
7461         n 
= secs 
/ (24 * 3600); 
7462 //      dt->dayWeek = (n + 4) % 7; 
7465         // Rebase from days since Unix epoch (1/1/1970) store in 'n', 
7466         // to days since 1/1/1968 to start on 4 year cycle, beginning 
7471         // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days. 
7472         // Valid before 2100, since 2100 is not a leap year. 
7474         x 
= n 
/ 1461;       // number of 4 year cycles 
7475         y 
= n 
% 1461;       // days into current 4 year cycle 
7478         // Add in years in the current 4 year cycle 
7481                 y 
-= 366;   // days after the leap year 
7482                 n 
= y 
% 365; // days into the current year 
7483                 z 
+= (1 + y 
/ 365); // years after the past 4-yr cycle 
7486                 dbm 
= lydaysbymonth
; 
7492         dt
->year 
= (typeof(dt
->year
))z
; 
7494         // Adjust remaining days value to start at 1 
7500         for (x 
= 1; (n 
> dbm
[x
]) && (x 
< 12); x
++) { 
7503         dt
->month 
= (typeof(dt
->month
))x
; 
7505         // Calculate day of month 
7507         dt
->day 
= (typeof(dt
->day
))(n 
- dbm
[x 
- 1]); 
7513 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct 
* dt
) 
7515         const unsigned int *    dbm 
= daysbymonth
; 
7518         if (dt
->year 
< 1970 || dt
->month 
> 12) { 
7522         // Seconds elapsed in the current day 
7524         secs 
= dt
->second 
+ 60 * dt
->minute 
+ 3600 * dt
->hour
; 
7526         // Number of days from 1/1/70 to beginning of current year 
7527         // Account for extra day every 4 years starting at 1973 
7529         y 
= dt
->year 
- 1970; 
7530         days 
= (y 
* 365) + ((y 
+ 1) / 4); 
7532         // Change table if current year is a leap year 
7534         if ((dt
->year 
% 4) == 0) { 
7535                 dbm 
= lydaysbymonth
; 
7538         // Add in days elapsed in the current year 
7540         days 
+= (dt
->day 
- 1) + dbm
[dt
->month 
- 1]; 
7542         // Add accumulated days to accumulated seconds 
7544         secs 
+= 24 * 3600 * days
; 
7550 IOPMrootDomain::getRUN_STATE(void) 
7552         return _aotNow 
? AOT_STATE 
: ON_STATE
; 
7556 IOPMrootDomain::isAOTMode() 
7562 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime
) 
7564         clock_sec_t     nowsecs
, wakesecs
; 
7565         clock_usec_t    nowmicrosecs
, wakemicrosecs
; 
7566         uint64_t        nowAbs
, wakeAbs
; 
7568         clock_gettimeofday_and_absolute_time(&nowsecs
, &nowmicrosecs
, &nowAbs
); 
7569         wakeAbs 
= continuoustime_to_absolutetime(wakeContinuousTime
); 
7570         if (wakeAbs 
< nowAbs
) { 
7571                 printf(LOG_PREFIX 
"wakeAbs %qd < nowAbs %qd\n", wakeAbs
, nowAbs
); 
7575         absolutetime_to_microtime(wakeAbs
, &wakesecs
, &wakemicrosecs
); 
7577         wakesecs 
+= nowsecs
; 
7578         wakemicrosecs 
+= nowmicrosecs
; 
7579         if (wakemicrosecs 
>= USEC_PER_SEC
) { 
7581                 wakemicrosecs 
-= USEC_PER_SEC
; 
7583         if (wakemicrosecs 
>= (USEC_PER_SEC 
/ 10)) { 
7587         IOPMConvertSecondsToCalendar(wakesecs
, &_aotWakeTimeCalendar
); 
7589         if (_aotWakeTimeContinuous 
!= wakeContinuousTime
) { 
7590                 _aotWakeTimeContinuous 
= wakeContinuousTime
; 
7591                 IOLog(LOG_PREFIX 
"setWakeTime: " YMDTF 
"\n", YMDT(&_aotWakeTimeCalendar
)); 
7593         _aotWakeTimeCalendar
.selector 
= kPMCalendarTypeMaintenance
; 
7594         _aotWakeTimeUTC               
= wakesecs
; 
7596         return kIOReturnSuccess
; 
7599 // assumes WAKEEVENT_LOCK 
7601 IOPMrootDomain::aotShouldExit(bool checkTimeSet
, bool software
) 
7604         const char * reason 
= ""; 
7608                 _aotMetrics
->softwareRequestCount
++; 
7609                 reason 
= "software request"; 
7610         } else if (kIOPMWakeEventAOTExitFlags 
& _aotPendingFlags
) { 
7612                 reason 
= gWakeReasonString
; 
7613         } else if (checkTimeSet 
&& (kPMCalendarTypeInvalid 
== _aotWakeTimeCalendar
.selector
)) { 
7615                 _aotMetrics
->noTimeSetCount
++; 
7616                 reason 
= "flipbook expired"; 
7617         } else if ((kIOPMAOTModeRespectTimers 
& _aotMode
) && _calendarWakeAlarmUTC
) { 
7620                 clock_get_calendar_microtime(&sec
, &usec
); 
7621                 if (_calendarWakeAlarmUTC 
<= sec
) { 
7623                         _aotMetrics
->rtcAlarmsCount
++; 
7624                         reason 
= "user alarm"; 
7627         exitNow 
= (_aotNow 
&& _aotExit
); 
7630                 IOLog(LOG_PREFIX 
"AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n", 
7632                     _aotMetrics
->sleepCount
, 
7633                     _aotMetrics
->possibleCount
, 
7634                     _aotMetrics
->confirmedPossibleCount
, 
7635                     _aotMetrics
->rejectedPossibleCount
, 
7636                     _aotMetrics
->expiredPossibleCount
, 
7637                     _aotMetrics
->noTimeSetCount
, 
7638                     _aotMetrics
->rtcAlarmsCount
); 
7644 IOPMrootDomain::aotExit(bool cps
) 
7646         uint32_t savedMessageMask
; 
7649         _aotTasksSuspended  
= false; 
7650         _aotReadyToFullWake 
= false; 
7651         if (_aotTimerScheduled
) { 
7652                 _aotTimerES
->cancelTimeout(); 
7653                 _aotTimerScheduled 
= false; 
7655         updateTasksSuspend(); 
7657         _aotMetrics
->totalTime 
+= mach_absolute_time() - _aotLastWakeTime
; 
7658         _aotLastWakeTime 
= 0; 
7659         if (_aotMetrics
->sleepCount 
&& (_aotMetrics
->sleepCount 
<= kIOPMAOTMetricsKernelWakeCountMax
)) { 
7661                 strlcpy(&_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount 
- 1][0], 
7663                     sizeof(_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
])); 
7667         _aotWakeTimeCalendar
.selector 
= kPMCalendarTypeInvalid
; 
7669         // Preserve the message mask since a system wake transition 
7670         // may have already started and initialized the mask. 
7671         savedMessageMask 
= _systemMessageClientMask
; 
7672         _systemMessageClientMask 
= kSystemMessageClientLegacyApp
; 
7673         tellClients(kIOMessageSystemWillPowerOn
); 
7674         _systemMessageClientMask 
= savedMessageMask 
| kSystemMessageClientLegacyApp
; 
7677                 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit
); 
7682 IOPMrootDomain::aotEvaluate(IOTimerEventSource 
* timer
) 
7686         IOLog("aotEvaluate(%d) 0x%x\n", (timer 
!= NULL
), _aotPendingFlags
); 
7689         exitNow 
= aotShouldExit(false, false); 
7690         if (timer 
!= NULL
) { 
7691                 _aotTimerScheduled 
= false; 
7698                 if (_aotLingerTime
) { 
7700                         IOLog("aot linger before sleep\n"); 
7701                         clock_absolutetime_interval_to_deadline(_aotLingerTime
, &deadline
); 
7702                         clock_delay_until(deadline
); 
7705                 privateSleepSystem(kIOPMSleepReasonSoftware
); 
7709 //****************************************************************************** 
7712 // Conditions that affect our wake/sleep decision has changed. 
7713 // If conditions dictate that the system must remain awake, clamp power 
7714 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP 
7715 // is TRUE, then remove the power clamp and allow the power state to drop 
7717 //****************************************************************************** 
7720 IOPMrootDomain::adjustPowerState( bool sleepASAP 
) 
7722         DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n", 
7723             getPowerStateString((uint32_t) getPowerState()), sleepASAP
, idleSleepEnabled
); 
7730                 if (AOT_STATE 
!= getPowerState()) { 
7734                 exitNow 
= aotShouldExit(true, false); 
7736                     && !_aotTimerScheduled
 
7737                     && (kIOPMWakeEventAOTPossibleExit 
== (kIOPMWakeEventAOTPossibleFlags 
& _aotPendingFlags
))) { 
7738                         _aotTimerScheduled 
= true; 
7739                         if (_aotLingerTime
) { 
7740                                 _aotTimerES
->setTimeout(_aotLingerTime
); 
7742                                 _aotTimerES
->setTimeout(800, kMillisecondScale
); 
7749                         _aotReadyToFullWake 
= true; 
7750                         if (!_aotTimerScheduled
) { 
7751                                 privateSleepSystem(kIOPMSleepReasonSoftware
); 
7757         if ((!idleSleepEnabled
) || !checkSystemSleepEnabled()) { 
7758                 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState
); 
7759         } else if (sleepASAP
) { 
7760                 changePowerStateWithTagToPriv(SLEEP_STATE
, kCPSReasonAdjustPowerState
); 
7765 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn
) 
7768                 if (!checkSystemCanSustainFullWake()) { 
7769                         DLOG("System cannot sustain full wake\n"); 
7773                 // Force wrangler to max power state. If system is in dark wake 
7774                 // this alone won't raise the wrangler's power state. 
7776                         wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMax
); 
7779                 // System in dark wake, always requesting full wake should 
7780                 // not have any bad side-effects, even if the request fails. 
7782                 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) { 
7783                         setProperty(kIOPMRootDomainWakeTypeKey
, kIOPMRootDomainWakeTypeNotification
); 
7784                         requestFullWake( kFullWakeReasonDisplayOn 
); 
7787                 // Relenquish desire to power up display. 
7788                 // Must first transition to state 1 since wrangler doesn't 
7789                 // power off the displays at state 0. At state 0 the root 
7790                 // domain is removed from the wrangler's power client list. 
7792                         wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMin 
+ 1); 
7793                         wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMin
); 
7798 //****************************************************************************** 
7799 // dispatchPowerEvent 
7801 // IOPMPowerStateQueue callback function. Running on PM work loop thread. 
7802 //****************************************************************************** 
7805 IOPMrootDomain::dispatchPowerEvent( 
7806         uint32_t event
, void * arg0
, uint64_t arg1 
) 
7811         case kPowerEventFeatureChanged
: 
7812                 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7813                 messageClients(kIOPMMessageFeatureChange
, this); 
7816         case kPowerEventReceivedPowerNotification
: 
7817                 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7818                 handlePowerNotification((UInt32
)(uintptr_t) arg0 
); 
7821         case kPowerEventSystemBootCompleted
: 
7822                 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7823                 if (systemBooting
) { 
7824                         systemBooting 
= false; 
7826                         // read noidle setting from Device Tree 
7827                         OSSharedPtr
<IORegistryEntry
> defaults 
= IORegistryEntry::fromPath("IODeviceTree:/defaults"); 
7828                         if (defaults 
!= NULL
) { 
7829                                 OSSharedPtr
<OSObject
> noIdleProp 
= defaults
->copyProperty("no-idle"); 
7830                                 OSData 
*data 
= OSDynamicCast(OSData
, noIdleProp
.get()); 
7831                                 if ((data 
!= NULL
) && (data
->getLength() == 4)) { 
7832                                         gNoIdleFlag 
= *(uint32_t*)data
->getBytesNoCopy(); 
7833                                         DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag
); 
7836                         if (lowBatteryCondition 
|| thermalEmergencyState
) { 
7837                                 if (lowBatteryCondition
) { 
7838                                         privateSleepSystem(kIOPMSleepReasonLowPower
); 
7840                                         privateSleepSystem(kIOPMSleepReasonThermalEmergency
); 
7842                                 // The rest is unnecessary since the system is expected 
7843                                 // to sleep immediately. The following wake will update 
7848                         sleepWakeDebugMemAlloc(); 
7849                         saveFailureData2File(); 
7851                         // If lid is closed, re-send lid closed notification 
7852                         // now that booting is complete. 
7853                         if (clamshellClosed
) { 
7854                                 handlePowerNotification(kLocalEvalClamshellCommand
); 
7856                         evaluatePolicy( kStimulusAllowSystemSleepChanged 
); 
7860         case kPowerEventSystemShutdown
: 
7861                 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7862                 if (kOSBooleanTrue 
== (OSBoolean 
*) arg0
) { 
7863                         /* We set systemShutdown = true during shutdown 
7864                          *  to prevent sleep at unexpected times while loginwindow is trying 
7865                          *  to shutdown apps and while the OS is trying to transition to 
7866                          *  complete power of. 
7868                          *  Set to true during shutdown, as soon as loginwindow shows 
7869                          *  the "shutdown countdown dialog", through individual app 
7870                          *  termination, and through black screen kernel shutdown. 
7872                         systemShutdown 
= true; 
7875                          *  A shutdown was initiated, but then the shutdown 
7876                          *  was cancelled, clearing systemShutdown to false here. 
7878                         systemShutdown 
= false; 
7882         case kPowerEventUserDisabledSleep
: 
7883                 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7884                 userDisabledAllSleep 
= (kOSBooleanTrue 
== (OSBoolean 
*) arg0
); 
7887         case kPowerEventRegisterSystemCapabilityClient
: 
7888                 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7890                 // reset() handles the arg0 == nullptr case for us 
7891                 systemCapabilityNotifier
.reset((IONotifier 
*) arg0
, OSRetain
); 
7892                 /* intentional fall-through */ 
7893                 [[clang::fallthrough]]; 
7895         case kPowerEventRegisterKernelCapabilityClient
: 
7896                 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7897                 if (!_joinedCapabilityClients
) { 
7898                         _joinedCapabilityClients 
= OSSet::withCapacity(8); 
7901                         OSSharedPtr
<IONotifier
> notify((IONotifier 
*) arg0
, OSNoRetain
); 
7902                         if (_joinedCapabilityClients
) { 
7903                                 _joinedCapabilityClients
->setObject(notify
.get()); 
7904                                 synchronizePowerTree( kIOPMSyncNoChildNotify 
); 
7909         case kPowerEventPolicyStimulus
: 
7910                 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7912                         int stimulus 
= (int)(uintptr_t) arg0
; 
7913                         evaluatePolicy(stimulus
, (uint32_t) arg1
); 
7917         case kPowerEventAssertionCreate
: 
7918                 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7920                         pmAssertions
->handleCreateAssertion((OSData 
*)arg0
); 
7925         case kPowerEventAssertionRelease
: 
7926                 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7928                         pmAssertions
->handleReleaseAssertion(arg1
); 
7932         case kPowerEventAssertionSetLevel
: 
7933                 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7935                         pmAssertions
->handleSetAssertionLevel(arg1
, (IOPMDriverAssertionLevel
)(uintptr_t)arg0
); 
7939         case kPowerEventQueueSleepWakeUUID
: 
7940                 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7941                 handleQueueSleepWakeUUID((OSObject 
*)arg0
); 
7943         case kPowerEventPublishSleepWakeUUID
: 
7944                 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7945                 handlePublishSleepWakeUUID((bool)arg0
); 
7948         case kPowerEventSetDisplayPowerOn
: 
7949                 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7951                         displayPowerOnRequested 
= true; 
7953                         displayPowerOnRequested 
= false; 
7955                 handleSetDisplayPowerOn(displayPowerOnRequested
); 
7958         case kPowerEventPublishWakeType
: 
7959                 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7961                 // Don't replace wake type property if already set 
7962                 if ((arg0 
== gIOPMWakeTypeUserKey
) || 
7963                     !propertyExists(kIOPMRootDomainWakeTypeKey
)) { 
7964                         const char * wakeType 
= NULL
; 
7966                         if (arg0 
== gIOPMWakeTypeUserKey
) { 
7967                                 requestUserActive(this, "WakeTypeUser"); 
7968                                 wakeType 
= kIOPMRootDomainWakeTypeUser
; 
7969                         } else if (arg0 
== gIOPMSettingDebugWakeRelativeKey
) { 
7970                                 requestUserActive(this, "WakeTypeAlarm"); 
7971                                 wakeType 
= kIOPMRootDomainWakeTypeAlarm
; 
7972                         } else if (arg0 
== gIOPMSettingSleepServiceWakeCalendarKey
) { 
7973                                 darkWakeSleepService 
= true; 
7974                                 wakeType 
= kIOPMRootDomainWakeTypeSleepService
; 
7975                         } else if (arg0 
== gIOPMSettingMaintenanceWakeCalendarKey
) { 
7976                                 wakeType 
= kIOPMRootDomainWakeTypeMaintenance
; 
7980                                 setProperty(kIOPMRootDomainWakeTypeKey
, wakeType
); 
7985         case kPowerEventAOTEvaluate
: 
7986                 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
); 
7987                 if (_aotReadyToFullWake
) { 
7994 //****************************************************************************** 
7995 // systemPowerEventOccurred 
7997 // The power controller is notifying us of a hardware-related power management 
7998 // event that we must handle. 
8000 // systemPowerEventOccurred covers the same functionality that 
8001 // receivePowerNotification does; it simply provides a richer API for conveying 
8002 // more information. 
8003 //****************************************************************************** 
8006 IOPMrootDomain::systemPowerEventOccurred( 
8007         const OSSymbol 
*event
, 
8010         IOReturn        attempt 
= kIOReturnSuccess
; 
8011         OSSharedPtr
<OSNumber
>        newNumber
; 
8014                 return kIOReturnBadArgument
; 
8017         newNumber 
= OSNumber::withNumber(intValue
, 8 * sizeof(intValue
)); 
8019                 return kIOReturnInternalError
; 
8022         attempt 
= systemPowerEventOccurred(event
, static_cast<OSObject 
*>(newNumber
.get())); 
8028 IOPMrootDomain::setThermalState(OSObject 
*value
) 
8032         if (gIOPMWorkLoop
->inGate() == false) { 
8033                 gIOPMWorkLoop
->runAction( 
8034                         OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::setThermalState
), 
8040         if (value 
&& (num 
= OSDynamicCast(OSNumber
, value
))) { 
8041                 thermalWarningState 
= ((num
->unsigned32BitValue() == kIOPMThermalLevelWarning
) || 
8042                     (num
->unsigned32BitValue() == kIOPMThermalLevelTrap
)) ? 1 : 0; 
8047 IOPMrootDomain::systemPowerEventOccurred( 
8048         const OSSymbol 
*event
, 
8051         OSSharedPtr
<OSDictionary
> thermalsDict
; 
8052         bool shouldUpdate 
= true; 
8054         if (!event 
|| !value
) { 
8055                 return kIOReturnBadArgument
; 
8059         // We reuse featuresDict Lock because it already exists and guards 
8060         // the very infrequently used publish/remove feature mechanism; so there's zero rsk 
8061         // of stepping on that lock. 
8062         if (featuresDictLock
) { 
8063                 IOLockLock(featuresDictLock
); 
8066         OSSharedPtr
<OSObject
> origThermalsProp 
= copyProperty(kIOPMRootDomainPowerStatusKey
); 
8067         OSDictionary 
* origThermalsDict 
= OSDynamicCast(OSDictionary
, origThermalsProp
.get()); 
8069         if (origThermalsDict
) { 
8070                 thermalsDict 
= OSDictionary::withDictionary(origThermalsDict
); 
8072                 thermalsDict 
= OSDictionary::withCapacity(1); 
8075         if (!thermalsDict
) { 
8076                 shouldUpdate 
= false; 
8080         thermalsDict
->setObject(event
, value
); 
8082         setProperty(kIOPMRootDomainPowerStatusKey
, thermalsDict
.get()); 
8086         if (featuresDictLock
) { 
8087                 IOLockUnlock(featuresDictLock
); 
8092                     event
->isEqualTo(kIOPMThermalLevelWarningKey
)) { 
8093                         setThermalState(value
); 
8095                 messageClients(kIOPMMessageSystemPowerEventOccurred
, (void *)NULL
); 
8098         return kIOReturnSuccess
; 
8101 //****************************************************************************** 
8102 // receivePowerNotification 
8104 // The power controller is notifying us of a hardware-related power management 
8105 // event that we must handle. This may be a result of an 'environment' interrupt 
8106 // from the power mgt micro. 
8107 //****************************************************************************** 
8110 IOPMrootDomain::receivePowerNotification( UInt32 msg 
) 
8112         if (msg 
& kIOPMPowerButton
) { 
8113                 uint32_t currentPhase 
= pmTracer
->getTracePhase(); 
8114                 if (currentPhase 
!= kIOPMTracePointSystemUp 
&& currentPhase 
> kIOPMTracePointSystemSleep
) { 
8115                         DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase
); 
8116                         swd_flags 
|= SWD_PWR_BTN_STACKSHOT
; 
8117                         thread_call_enter(powerButtonDown
); 
8119                         DEBUG_LOG("power button pressed when system is up\n"); 
8121         } else if (msg 
& kIOPMPowerButtonUp
) { 
8122                 if (swd_flags 
& SWD_PWR_BTN_STACKSHOT
) { 
8123                         swd_flags 
&= ~SWD_PWR_BTN_STACKSHOT
; 
8124                         thread_call_enter(powerButtonUp
); 
8127                 pmPowerStateQueue
->submitPowerEvent( 
8128                         kPowerEventReceivedPowerNotification
, (void *)(uintptr_t) msg 
); 
8130         return kIOReturnSuccess
; 
8134 IOPMrootDomain::handlePowerNotification( UInt32 msg 
) 
8136         bool        eval_clamshell 
= false; 
8137         bool        eval_clamshell_alarm 
= false; 
8142          * Local (IOPMrootDomain only) eval clamshell command 
8144         if (msg 
& kLocalEvalClamshellCommand
) { 
8145                 if ((gClamshellFlags 
& kClamshell_WAR_47715679
) && isRTCAlarmWake
) { 
8146                         eval_clamshell_alarm 
= true; 
8148                         // reset isRTCAlarmWake. This evaluation should happen only once 
8149                         // on RTC/Alarm wake. Any clamshell events after wake should follow 
8150                         // the regular evaluation 
8151                         isRTCAlarmWake 
= false; 
8153                         eval_clamshell 
= true; 
8160         if (msg 
& kIOPMOverTemp
) { 
8161                 DLOG("Thermal overtemp message received!\n"); 
8162                 thermalEmergencyState 
= true; 
8163                 privateSleepSystem(kIOPMSleepReasonThermalEmergency
); 
8167          * Forward DW thermal notification to client, if system is not going to sleep 
8169         if ((msg 
& kIOPMDWOverTemp
) && (_systemTransitionType 
!= kSystemTransitionSleep
)) { 
8170                 DLOG("DarkWake thermal limits message received!\n"); 
8171                 messageClients(kIOPMMessageDarkWakeThermalEmergency
); 
8177         if (msg 
& kIOPMSleepNow
) { 
8178                 privateSleepSystem(kIOPMSleepReasonSoftware
); 
8184         if (msg 
& kIOPMPowerEmergency
) { 
8185                 DLOG("Received kIOPMPowerEmergency"); 
8186                 lowBatteryCondition 
= true; 
8187                 privateSleepSystem(kIOPMSleepReasonLowPower
); 
8193         if (msg 
& kIOPMClamshellOpened
) { 
8194                 DLOG("Clamshell opened\n"); 
8195                 // Received clamshel open message from clamshell controlling driver 
8196                 // Update our internal state and tell general interest clients 
8197                 clamshellClosed 
= false; 
8198                 clamshellExists 
= true; 
8200                 // Don't issue a hid tickle when lid is open and polled on wake 
8201                 if (msg 
& kIOPMSetValue
) { 
8202                         setProperty(kIOPMRootDomainWakeTypeKey
, "Lid Open"); 
8207                 informCPUStateChange(kInformLid
, 0); 
8209                 // Tell general interest clients 
8210                 sendClientClamshellNotification(); 
8212                 bool aborting 
=  ((lastSleepReason 
== kIOPMSleepReasonClamshell
) 
8213                     || (lastSleepReason 
== kIOPMSleepReasonIdle
) 
8214                     || (lastSleepReason 
== kIOPMSleepReasonMaintenance
)); 
8216                         userActivityCount
++; 
8218                 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount
, lastSleepReason
); 
8223          * Send the clamshell interest notification since the lid is closing. 
8225         if (msg 
& kIOPMClamshellClosed
) { 
8226                 if ((clamshellIgnoreClose 
|| (gClamshellFlags 
& kClamshell_WAR_38378787
)) && 
8227                     clamshellClosed 
&& clamshellExists
) { 
8228                         DLOG("Ignoring redundant Clamshell close event\n"); 
8230                         DLOG("Clamshell closed\n"); 
8231                         // Received clamshel open message from clamshell controlling driver 
8232                         // Update our internal state and tell general interest clients 
8233                         clamshellClosed 
= true; 
8234                         clamshellExists 
= true; 
8236                         // Ignore all following clamshell close events until the clamshell 
8237                         // is opened or the system sleeps. When a clamshell close triggers 
8238                         // a system wake, the lid driver may send us two clamshell close 
8239                         // events, one for the clamshell close event itself, and a second 
8240                         // close event when the driver polls the lid state on wake. 
8241                         clamshellIgnoreClose 
= true; 
8244                         informCPUStateChange(kInformLid
, 1); 
8246                         // Tell general interest clients 
8247                         sendClientClamshellNotification(); 
8249                         // And set eval_clamshell = so we can attempt 
8250                         eval_clamshell 
= true; 
8255          * Set Desktop mode (sent from graphics) 
8257          *  -> reevaluate lid state 
8259         if (msg 
& kIOPMSetDesktopMode
) { 
8260                 desktopMode 
= (0 != (msg 
& kIOPMSetValue
)); 
8261                 msg 
&= ~(kIOPMSetDesktopMode 
| kIOPMSetValue
); 
8262                 DLOG("Desktop mode %d\n", desktopMode
); 
8264                 sendClientClamshellNotification(); 
8266                 // Re-evaluate the lid state 
8267                 eval_clamshell 
= true; 
8271          * AC Adaptor connected 
8273          *  -> reevaluate lid state 
8275         if (msg 
& kIOPMSetACAdaptorConnected
) { 
8276                 acAdaptorConnected 
= (0 != (msg 
& kIOPMSetValue
)); 
8277                 msg 
&= ~(kIOPMSetACAdaptorConnected 
| kIOPMSetValue
); 
8280                 informCPUStateChange(kInformAC
, !acAdaptorConnected
); 
8282                 // Tell BSD if AC is connected 
8283                 //      0 == external power source; 1 == on battery 
8284                 post_sys_powersource(acAdaptorConnected 
? 0:1); 
8286                 sendClientClamshellNotification(); 
8288                 // Re-evaluate the lid state 
8289                 eval_clamshell 
= true; 
8291                 // Lack of AC may have latched a display wrangler tickle. 
8292                 // This mirrors the hardware's USB wake event latch, where a latched 
8293                 // USB wake event followed by an AC attach will trigger a full wake. 
8294                 latchDisplayWranglerTickle( false ); 
8297                 // AC presence will reset the standy timer delay adjustment. 
8298                 _standbyTimerResetSeconds 
= 0; 
8300                 if (!userIsActive
) { 
8301                         // Reset userActivityTime when power supply is changed(rdr 13789330) 
8302                         clock_get_uptime(&userActivityTime
); 
8307          * Enable Clamshell (external display disappear) 
8309          *  -> reevaluate lid state 
8311         if (msg 
& kIOPMEnableClamshell
) { 
8312                 DLOG("Clamshell enabled\n"); 
8314                 // Re-evaluate the lid state 
8315                 // System should sleep on external display disappearance 
8316                 // in lid closed operation. 
8317                 if (true == clamshellDisabled
) { 
8318                         eval_clamshell 
= true; 
8320 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 
8321                         // Also clear kClamshellSleepDisableInternal when graphics enables 
8322                         // the clamshell during a full wake. When graphics is behaving as 
8323                         // expected, this will allow clamshell close to be honored earlier 
8324                         // rather than waiting for the delayed evaluation. 
8325                         if ((clamshellSleepDisableMask 
& kClamshellSleepDisableInternal
) && 
8326                             (CAP_PENDING(kIOPMSystemCapabilityGraphics
) || 
8327                             CAP_CURRENT(kIOPMSystemCapabilityGraphics
))) { 
8328                                 setClamShellSleepDisable(false, kClamshellSleepDisableInternal
); 
8330                                 // Cancel the TC to avoid an extra kLocalEvalClamshellCommand 
8331                                 // when timer expires which is harmless but useless. 
8332                                 thread_call_cancel(fullWakeThreadCall
); 
8337                 clamshellDisabled 
= false; 
8338                 sendClientClamshellNotification(); 
8342          * Disable Clamshell (external display appeared) 
8343          * We don't bother re-evaluating clamshell state. If the system is awake, 
8344          * the lid is probably open. 
8346         if (msg 
& kIOPMDisableClamshell
) { 
8347                 DLOG("Clamshell disabled\n"); 
8348                 clamshellDisabled 
= true; 
8349                 sendClientClamshellNotification(); 
8353          * Evaluate clamshell and SLEEP if appropriate 
8355         if (eval_clamshell_alarm 
&& clamshellClosed
) { 
8356                 if (shouldSleepOnRTCAlarmWake()) { 
8357                         privateSleepSystem(kIOPMSleepReasonClamshell
); 
8359         } else if (eval_clamshell 
&& clamshellClosed
) { 
8360                 if (shouldSleepOnClamshellClosed()) { 
8361                         privateSleepSystem(kIOPMSleepReasonClamshell
); 
8363                         evaluatePolicy( kStimulusDarkWakeEvaluate 
); 
8367         if (msg 
& kIOPMProModeEngaged
) { 
8369                 DLOG("ProModeEngaged\n"); 
8370                 messageClient(kIOPMMessageProModeStateChange
, systemCapabilityNotifier
.get(), &newState
, sizeof(newState
)); 
8373         if (msg 
& kIOPMProModeDisengaged
) { 
8375                 DLOG("ProModeDisengaged\n"); 
8376                 messageClient(kIOPMMessageProModeStateChange
, systemCapabilityNotifier
.get(), &newState
, sizeof(newState
)); 
8380 //****************************************************************************** 
8383 // Evaluate root-domain policy in response to external changes. 
8384 //****************************************************************************** 
8387 IOPMrootDomain::evaluatePolicy( int stimulus
, uint32_t arg 
) 
8391                         int idleSleepEnabled    
: 1; 
8392                         int idleSleepDisabled   
: 1; 
8393                         int displaySleep        
: 1; 
8394                         int sleepDelayChanged   
: 1; 
8395                         int evaluateDarkWake    
: 1; 
8396                         int adjustPowerState    
: 1; 
8397                         int userBecameInactive  
: 1; 
8398                         int displaySleepEntry   
: 1; 
8408         case kStimulusDisplayWranglerSleep
: 
8409                 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
); 
8410                 if (!wranglerPowerOff
) { 
8411                         // wrangler is in sleep state or lower 
8412                         flags
.bit
.displaySleep 
= true; 
8414                 if (!wranglerAsleep
) { 
8415                         // transition from wrangler wake to wrangler sleep 
8416                         flags
.bit
.displaySleepEntry 
= true; 
8417                         wranglerAsleep 
= true; 
8421         case kStimulusDisplayWranglerWake
: 
8422                 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
); 
8423                 displayIdleForDemandSleep 
= false; 
8424                 wranglerPowerOff 
= false; 
8425                 wranglerAsleep 
= false; 
8428         case kStimulusEnterUserActiveState
: 
8429                 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
); 
8430                 if (_preventUserActive
) { 
8431                         DLOG("user active dropped\n"); 
8434                 if (!userIsActive
) { 
8435                         userIsActive 
= true; 
8436                         userWasActive 
= true; 
8437                         clock_get_uptime(&gUserActiveAbsTime
); 
8439                         // Stay awake after dropping demand for display power on 
8440                         if (kFullWakeReasonDisplayOn 
== fullWakeReason
) { 
8441                                 fullWakeReason 
= fFullWakeReasonDisplayOnAndLocalUser
; 
8442                                 DLOG("User activity while in notification wake\n"); 
8443                                 changePowerStateWithOverrideTo( getRUN_STATE(), 0); 
8446                         kdebugTrace(kPMLogUserActiveState
, 0, 1, 0); 
8447                         setProperty(gIOPMUserIsActiveKey
.get(), kOSBooleanTrue
); 
8448                         messageClients(kIOPMMessageUserIsActiveChanged
); 
8450                 flags
.bit
.idleSleepDisabled 
= true; 
8453         case kStimulusLeaveUserActiveState
: 
8454                 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
); 
8456                         clock_get_uptime(&gUserInactiveAbsTime
); 
8457                         userIsActive 
= false; 
8458                         clock_get_uptime(&userBecameInactiveTime
); 
8459                         flags
.bit
.userBecameInactive 
= true; 
8461                         kdebugTrace(kPMLogUserActiveState
, 0, 0, 0); 
8462                         setProperty(gIOPMUserIsActiveKey
.get(), kOSBooleanFalse
); 
8463                         messageClients(kIOPMMessageUserIsActiveChanged
); 
8467         case kStimulusAggressivenessChanged
: 
8469                 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
); 
8470                 unsigned long   aggressiveValue
; 
8471                 uint32_t        minutesToIdleSleep  
= 0; 
8472                 uint32_t        minutesToDisplayDim 
= 0; 
8473                 uint32_t        minutesDelta        
= 0; 
8475                 // Fetch latest display and system sleep slider values. 
8476                 aggressiveValue 
= 0; 
8477                 getAggressiveness(kPMMinutesToSleep
, &aggressiveValue
); 
8478                 minutesToIdleSleep 
= (uint32_t) aggressiveValue
; 
8480                 aggressiveValue 
= 0; 
8481                 getAggressiveness(kPMMinutesToDim
, &aggressiveValue
); 
8482                 minutesToDisplayDim 
= (uint32_t) aggressiveValue
; 
8483                 DLOG("aggressiveness changed: system %u->%u, display %u\n", 
8484                     sleepSlider
, minutesToIdleSleep
, minutesToDisplayDim
); 
8486                 DLOG("idle time -> %d secs (ena %d)\n", 
8487                     idleSeconds
, (minutesToIdleSleep 
!= 0)); 
8489                 // How long to wait before sleeping the system once 
8490                 // the displays turns off is indicated by 'extraSleepDelay'. 
8492                 if (minutesToIdleSleep 
> minutesToDisplayDim
) { 
8493                         minutesDelta 
= minutesToIdleSleep 
- minutesToDisplayDim
; 
8494                 } else if (minutesToIdleSleep 
== minutesToDisplayDim
) { 
8498                 if ((!idleSleepEnabled
) && (minutesToIdleSleep 
!= 0)) { 
8499                         idleSleepEnabled 
= flags
.bit
.idleSleepEnabled 
= true; 
8502                 if ((idleSleepEnabled
) && (minutesToIdleSleep 
== 0)) { 
8503                         flags
.bit
.idleSleepDisabled 
= true; 
8504                         idleSleepEnabled 
= false; 
8506 #if !defined(XNU_TARGET_OS_OSX) 
8507                 if (0x7fffffff == minutesToIdleSleep
) { 
8508                         minutesToIdleSleep 
= idleSeconds
; 
8510 #endif /* !defined(XNU_TARGET_OS_OSX) */ 
8512                 if (((minutesDelta 
!= extraSleepDelay
) || 
8513                     (userActivityTime 
!= userActivityTime_prev
)) && 
8514                     !flags
.bit
.idleSleepEnabled 
&& !flags
.bit
.idleSleepDisabled
) { 
8515                         flags
.bit
.sleepDelayChanged 
= true; 
8518                 if (systemDarkWake 
&& !darkWakeToSleepASAP 
&& 
8519                     (flags
.bit
.idleSleepEnabled 
|| flags
.bit
.idleSleepDisabled
)) { 
8520                         // Reconsider decision to remain in dark wake 
8521                         flags
.bit
.evaluateDarkWake 
= true; 
8524                 sleepSlider 
= minutesToIdleSleep
; 
8525                 extraSleepDelay 
= minutesDelta
; 
8526                 userActivityTime_prev 
= userActivityTime
; 
8529         case kStimulusDemandSystemSleep
: 
8530                 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
); 
8531                 displayIdleForDemandSleep 
= true; 
8532                 if (wrangler 
&& wranglerIdleSettings
) { 
8533                         // Request wrangler idle only when demand sleep is triggered 
8535                         if (CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) { 
8536                                 wrangler
->setProperties(wranglerIdleSettings
.get()); 
8537                                 DLOG("Requested wrangler idle\n"); 
8540                 // arg = sleepReason 
8541                 changePowerStateWithOverrideTo( SLEEP_STATE
, arg 
); 
8544         case kStimulusAllowSystemSleepChanged
: 
8545                 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
); 
8546                 flags
.bit
.adjustPowerState 
= true; 
8549         case kStimulusDarkWakeActivityTickle
: 
8550                 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
); 
8551                 // arg == true implies real and not self generated wrangler tickle. 
8552                 // Update wake type on PM work loop instead of the tickle thread to 
8553                 // eliminate the possibility of an early tickle clobbering the wake 
8554                 // type set by the platform driver. 
8556                         setProperty(kIOPMRootDomainWakeTypeKey
, kIOPMRootDomainWakeTypeHIDActivity
); 
8559                 if (!darkWakeExit
) { 
8560                         if (latchDisplayWranglerTickle(true)) { 
8561                                 DLOG("latched tickle\n"); 
8565                         darkWakeExit 
= true; 
8566                         DLOG("Requesting full wake due to dark wake activity tickle\n"); 
8567                         requestFullWake( kFullWakeReasonLocalUser 
); 
8571         case kStimulusDarkWakeEntry
: 
8572         case kStimulusDarkWakeReentry
: 
8573                 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
); 
8574                 // Any system transitions since the last dark wake transition 
8575                 // will invalid the stimulus. 
8577                 if (arg 
== _systemStateGeneration
) { 
8578                         DLOG("dark wake entry\n"); 
8579                         systemDarkWake 
= true; 
8581                         // Keep wranglerPowerOff an invariant when wrangler is absent 
8583                                 wranglerPowerOff 
= true; 
8586                         if (kStimulusDarkWakeEntry 
== stimulus
) { 
8587                                 clock_get_uptime(&userBecameInactiveTime
); 
8588                                 flags
.bit
.evaluateDarkWake 
= true; 
8589                                 if (activitySinceSleep()) { 
8590                                         DLOG("User activity recorded while going to darkwake\n"); 
8595                         // Always accelerate disk spindown while in dark wake, 
8596                         // even if system does not support/allow sleep. 
8598                         cancelIdleSleepTimer(); 
8599                         setQuickSpinDownTimeout(); 
8603         case kStimulusDarkWakeEvaluate
: 
8604                 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
); 
8605                 if (systemDarkWake
) { 
8606                         flags
.bit
.evaluateDarkWake 
= true; 
8610         case kStimulusNoIdleSleepPreventers
: 
8611                 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
); 
8612                 flags
.bit
.adjustPowerState 
= true; 
8614         } /* switch(stimulus) */ 
8616         if (flags
.bit
.evaluateDarkWake 
&& (kFullWakeReasonNone 
== fullWakeReason
)) { 
8617                 DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n", 
8618                     darkWakeToSleepASAP
, clamshellClosed
, clamshellDisabled
, clamshellSleepDisableMask
, desktopMode
, acAdaptorConnected
); 
8619                 if (darkWakeToSleepASAP 
|| 
8620                     (clamshellClosed 
&& !(desktopMode 
&& acAdaptorConnected
))) { 
8621                         uint32_t newSleepReason
; 
8623                         if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) { 
8624                                 // System was previously in full wake. Sleep reason from 
8625                                 // full to dark already recorded in fullToDarkReason. 
8627                                 if (lowBatteryCondition
) { 
8628                                         newSleepReason 
= kIOPMSleepReasonLowPower
; 
8629                                 } else if (thermalEmergencyState
) { 
8630                                         newSleepReason 
= kIOPMSleepReasonThermalEmergency
; 
8632                                         newSleepReason 
= fullToDarkReason
; 
8635                                 // In dark wake from system sleep. 
8637                                 if (darkWakeSleepService
) { 
8638                                         newSleepReason 
= kIOPMSleepReasonSleepServiceExit
; 
8640                                         newSleepReason 
= kIOPMSleepReasonMaintenance
; 
8644                         if (checkSystemCanSleep(newSleepReason
)) { 
8645                                 privateSleepSystem(newSleepReason
); 
8647                 } else { // non-maintenance (network) dark wake 
8648                         if (checkSystemCanSleep(kIOPMSleepReasonIdle
)) { 
8649                                 // Release power clamp, and wait for children idle. 
8650                                 adjustPowerState(true); 
8652                                 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep
); 
8657         if (systemDarkWake
) { 
8658                 // The rest are irrelevant while system is in dark wake. 
8662         if ((flags
.bit
.displaySleepEntry
) && 
8663             (kFullWakeReasonDisplayOn 
== fullWakeReason
)) { 
8664                 // kIOPMSleepReasonNotificationWakeExit 
8665                 DLOG("Display sleep while in notification wake\n"); 
8666                 changePowerStateWithOverrideTo(SLEEP_STATE
, kIOPMSleepReasonNotificationWakeExit
); 
8669         if (flags
.bit
.userBecameInactive 
|| flags
.bit
.sleepDelayChanged
) { 
8670                 bool cancelQuickSpindown 
= false; 
8672                 if (flags
.bit
.sleepDelayChanged
) { 
8673                         // Cancel existing idle sleep timer and quick disk spindown. 
8674                         // New settings will be applied by the idleSleepEnabled flag 
8675                         // handler below if idle sleep is enabled. 
8677                         DLOG("extra sleep timer changed\n"); 
8678                         cancelIdleSleepTimer(); 
8679                         cancelQuickSpindown 
= true; 
8681                         DLOG("user inactive\n"); 
8684                 if (!userIsActive 
&& idleSleepEnabled
) { 
8685                         startIdleSleepTimer(getTimeToIdleSleep()); 
8688                 if (cancelQuickSpindown
) { 
8689                         restoreUserSpinDownTimeout(); 
8693         if (flags
.bit
.idleSleepEnabled
) { 
8694                 DLOG("idle sleep timer enabled\n"); 
8696 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 
8697                         startIdleSleepTimer(getTimeToIdleSleep()); 
8699                         changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled
); 
8700                         startIdleSleepTimer( idleSeconds 
); 
8703                         // Start idle timer if prefs now allow system sleep 
8704                         // and user is already inactive. Disk spindown is 
8705                         // accelerated upon timer expiration. 
8707                         if (!userIsActive
) { 
8708                                 startIdleSleepTimer(getTimeToIdleSleep()); 
8713         if (flags
.bit
.idleSleepDisabled
) { 
8714                 DLOG("idle sleep timer disabled\n"); 
8715                 cancelIdleSleepTimer(); 
8716                 restoreUserSpinDownTimeout(); 
8720         if (flags
.bit
.adjustPowerState
) { 
8721                 bool sleepASAP 
= false; 
8723                 if (!systemBooting 
&& (0 == idleSleepPreventersCount())) { 
8725                                 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy
); 
8726                                 if (idleSleepEnabled
) { 
8727 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 
8728                                         if (!extraSleepDelay 
&& !idleSleepTimerPending
) { 
8732                                         // stay awake for at least idleSeconds 
8733                                         startIdleSleepTimer(idleSeconds
); 
8736                         } else if (!extraSleepDelay 
&& !idleSleepTimerPending 
&& !systemDarkWake
) { 
8741                 adjustPowerState(sleepASAP
); 
8745 //****************************************************************************** 
8748 IOPMrootDomain::idleSleepPreventersCount() 
8751                 unsigned int count __block
; 
8753                 preventIdleSleepList
->iterateObjects(^bool (OSObject 
* obj
) 
8755                         count 
+= (NULL 
== obj
->metaCast("AppleARMBacklight")); 
8761         return preventIdleSleepList
->getCount(); 
8765 //****************************************************************************** 
8768 // Request transition from dark wake to full wake 
8769 //****************************************************************************** 
8772 IOPMrootDomain::requestFullWake( FullWakeReason reason 
) 
8774         uint32_t        options 
= 0; 
8775         IOService 
*     pciRoot 
= NULL
; 
8776         bool            promotion 
= false; 
8778         // System must be in dark wake and a valid reason for entering full wake 
8779         if ((kFullWakeReasonNone 
== reason
) || 
8780             (kFullWakeReasonNone 
!= fullWakeReason
) || 
8781             (CAP_CURRENT(kIOPMSystemCapabilityGraphics
))) { 
8785         // Will clear reason upon exit from full wake 
8786         fullWakeReason 
= reason
; 
8788         _desiredCapability 
|= (kIOPMSystemCapabilityGraphics 
| 
8789             kIOPMSystemCapabilityAudio
); 
8791         if ((kSystemTransitionWake 
== _systemTransitionType
) && 
8792             !(_pendingCapability 
& kIOPMSystemCapabilityGraphics
) && 
8793             !darkWakePowerClamped
) { 
8794                 // Promote to full wake while waking up to dark wake due to tickle. 
8795                 // PM will hold off notifying the graphics subsystem about system wake 
8796                 // as late as possible, so if a HID tickle does arrive, graphics can 
8797                 // power up from this same wake transition. Otherwise, the latency to 
8798                 // power up graphics on the following transition can be huge on certain 
8799                 // systems. However, once any power clamping has taken effect, it is 
8800                 // too late to promote the current dark wake transition to a full wake. 
8801                 _pendingCapability 
|= (kIOPMSystemCapabilityGraphics 
| 
8802                     kIOPMSystemCapabilityAudio
); 
8804                 // Tell the PCI parent of audio and graphics drivers to stop 
8805                 // delaying the child notifications. Same for root domain. 
8806                 pciRoot 
= pciHostBridgeDriver
.get(); 
8807                 willEnterFullWake(); 
8811         // Unsafe to cancel once graphics was powered. 
8812         // If system woke from dark wake, the return to sleep can 
8813         // be cancelled. "awake -> dark -> sleep" transition 
8814         // can be cancelled also, during the "dark -> sleep" phase 
8815         // *prior* to driver power down. 
8816         if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics
) || 
8817             _pendingCapability 
== 0) { 
8818                 options 
|= kIOPMSyncCancelPowerDown
; 
8821         synchronizePowerTree(options
, pciRoot
); 
8823         if (kFullWakeReasonLocalUser 
== fullWakeReason
) { 
8824                 // IOGraphics doesn't light the display even though graphics is 
8825                 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104) 
8826                 // So, do an explicit activity tickle 
8828                         wrangler
->activityTickle(0, 0); 
8832         // Log a timestamp for the initial full wake request. 
8833         // System may not always honor this full wake request. 
8834         if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) { 
8838                 clock_get_uptime(&now
); 
8839                 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
); 
8840                 absolutetime_to_nanoseconds(now
, &nsec
); 
8841                 MSG("full wake %s (reason %u) %u ms\n", 
8842                     promotion 
? "promotion" : "request", 
8843                     fullWakeReason
, ((int)((nsec
) / NSEC_PER_MSEC
))); 
8847 //****************************************************************************** 
8848 // willEnterFullWake 
8850 // System will enter full wake from sleep, from dark wake, or from dark 
8851 // wake promotion. This function aggregate things that are in common to 
8852 // all three full wake transitions. 
8854 // Assumptions: fullWakeReason was updated 
8855 //****************************************************************************** 
8858 IOPMrootDomain::willEnterFullWake( void ) 
8860         hibernateRetry 
= false; 
8861         sleepToStandby 
= false; 
8862         standbyNixed   
= false; 
8863         resetTimers    
= false; 
8864         sleepTimerMaintenance 
= false; 
8866         assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics
)); 
8868         _systemMessageClientMask 
= kSystemMessageClientPowerd 
| 
8869             kSystemMessageClientLegacyApp
; 
8871         if ((_highestCapability 
& kIOPMSystemCapabilityGraphics
) == 0) { 
8872                 // First time to attain full wake capability since the last wake 
8873                 _systemMessageClientMask 
|= kSystemMessageClientKernel
; 
8875                 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics 
8876                 setProperty(gIOPMUserTriggeredFullWakeKey
.get(), 
8877                     (kFullWakeReasonLocalUser 
== fullWakeReason
) ? 
8878                     kOSBooleanTrue 
: kOSBooleanFalse
); 
8881         IOHibernateSetWakeCapabilities(_pendingCapability
); 
8884         IOService::setAdvisoryTickleEnable( true ); 
8885         tellClients(kIOMessageSystemWillPowerOn
); 
8886         preventTransitionToUserActive(false); 
8889 //****************************************************************************** 
8890 // fullWakeDelayedWork 
8892 // System has already entered full wake. Invoked by a delayed thread call. 
8893 //****************************************************************************** 
8896 IOPMrootDomain::fullWakeDelayedWork( void ) 
8898 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 
8899         if (!gIOPMWorkLoop
->inGate()) { 
8900                 gIOPMWorkLoop
->runAction( 
8901                         OSMemberFunctionCast(IOWorkLoop::Action
, this, 
8902                         &IOPMrootDomain::fullWakeDelayedWork
), this); 
8906         DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n", 
8907             _currentCapability
, _pendingCapability
, _highestCapability
, 
8908             clamshellDisabled
, clamshellSleepDisableMask
); 
8910         if (clamshellExists 
&& 
8911             CAP_CURRENT(kIOPMSystemCapabilityGraphics
) && 
8912             !CAP_CHANGE(kIOPMSystemCapabilityGraphics
)) { 
8913                 if (clamshellSleepDisableMask 
& kClamshellSleepDisableInternal
) { 
8914                         setClamShellSleepDisable(false, kClamshellSleepDisableInternal
); 
8916                         // Not the initial full wake after waking from sleep. 
8917                         // Evaluate the clamshell for rdar://problem/9157444. 
8918                         receivePowerNotification(kLocalEvalClamshellCommand
); 
8924 //****************************************************************************** 
8925 // evaluateAssertions 
8927 //****************************************************************************** 
8929 // Bitmask of all kernel assertions that prevent system idle sleep. 
8930 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient. 
8931 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \ 
8932         (kIOPMDriverAssertionReservedBit7 | \ 
8933          kIOPMDriverAssertionPreventSystemIdleSleepBit) 
8936 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions
, IOPMDriverAssertionType oldAssertions
) 
8938         IOPMDriverAssertionType changedBits 
= newAssertions 
^ oldAssertions
; 
8940         messageClients(kIOPMMessageDriverAssertionsChanged
); 
8942         if (changedBits 
& kIOPMDriverAssertionPreventDisplaySleepBit
) { 
8944                         bool value 
= (newAssertions 
& kIOPMDriverAssertionPreventDisplaySleepBit
) ? true : false; 
8946                         DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value
); 
8947                         wrangler
->setIgnoreIdleTimer( value 
); 
8951         if (changedBits 
& kIOPMDriverAssertionCPUBit
) { 
8953                         IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit 
& newAssertions
))); 
8955                 evaluatePolicy(_aotNow 
? kStimulusNoIdleSleepPreventers 
: kStimulusDarkWakeEvaluate
); 
8956                 if (!assertOnWakeSecs 
&& gIOLastWakeAbsTime
) { 
8958                         clock_usec_t    microsecs
; 
8959                         clock_get_uptime(&now
); 
8960                         SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
); 
8961                         absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
); 
8962                         if (assertOnWakeReport
) { 
8963                                 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
); 
8964                                 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
); 
8969         if (changedBits 
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) { 
8970                 if ((newAssertions 
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) != 0) { 
8971                         if ((oldAssertions 
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) == 0) { 
8972                                 DLOG("PreventIdleSleep driver assertion raised\n"); 
8973                                 bool ok 
= updatePreventIdleSleepList(this, true); 
8974                                 if (ok 
&& (changedBits 
& kIOPMDriverAssertionPreventSystemIdleSleepBit
)) { 
8975                                         // Cancel idle sleep if there is one in progress 
8976                                         cancelIdlePowerDown(this); 
8980                         DLOG("PreventIdleSleep driver assertion dropped\n"); 
8981                         updatePreventIdleSleepList(this, false); 
8989 //****************************************************************************** 
8992 //****************************************************************************** 
8995 IOPMrootDomain::pmStatsRecordEvent( 
8997         AbsoluteTime        timestamp
) 
8999         bool        starting 
= eventIndex 
& kIOPMStatsEventStartFlag 
? true:false; 
9000         bool        stopping 
= eventIndex 
& kIOPMStatsEventStopFlag 
? true:false; 
9003         OSSharedPtr
<OSData
> publishPMStats
; 
9005         eventIndex 
&= ~(kIOPMStatsEventStartFlag 
| kIOPMStatsEventStopFlag
); 
9007         absolutetime_to_nanoseconds(timestamp
, &nsec
); 
9009         switch (eventIndex
) { 
9010         case kIOPMStatsHibernateImageWrite
: 
9012                         gPMStats
.hibWrite
.start 
= nsec
; 
9013                 } else if (stopping
) { 
9014                         gPMStats
.hibWrite
.stop 
= nsec
; 
9018                         delta 
= gPMStats
.hibWrite
.stop 
- gPMStats
.hibWrite
.start
; 
9019                         IOLog("PMStats: Hibernate write took %qd ms\n", delta 
/ NSEC_PER_MSEC
); 
9022         case kIOPMStatsHibernateImageRead
: 
9024                         gPMStats
.hibRead
.start 
= nsec
; 
9025                 } else if (stopping
) { 
9026                         gPMStats
.hibRead
.stop 
= nsec
; 
9030                         delta 
= gPMStats
.hibRead
.stop 
- gPMStats
.hibRead
.start
; 
9031                         IOLog("PMStats: Hibernate read took %qd ms\n", delta 
/ NSEC_PER_MSEC
); 
9033                         publishPMStats 
= OSData::withBytes(&gPMStats
, sizeof(gPMStats
)); 
9034                         setProperty(kIOPMSleepStatisticsKey
, publishPMStats
.get()); 
9035                         bzero(&gPMStats
, sizeof(gPMStats
)); 
9042  * Appends a record of the application response to 
9043  * IOPMrootDomain::pmStatsAppResponses 
9046 IOPMrootDomain::pmStatsRecordApplicationResponse( 
9047         const OSSymbol      
*response
, 
9053         IOPMPowerStateIndex powerState
, 
9056         OSSharedPtr
<OSDictionary
>    responseDescription
; 
9057         OSSharedPtr
<OSNumber
>        delayNum
; 
9058         OSSharedPtr
<OSNumber
>        powerCaps
; 
9059         OSSharedPtr
<OSNumber
>        pidNum
; 
9060         OSSharedPtr
<OSNumber
>        msgNum
; 
9061         OSSharedPtr
<const OSSymbol
>  appname
; 
9062         OSSharedPtr
<const OSSymbol
>  sleep
; 
9063         OSSharedPtr
<const OSSymbol
>  wake
; 
9064         IOPMServiceInterestNotifier 
*notify 
= NULL
; 
9066         if (object 
&& (notify 
= OSDynamicCast(IOPMServiceInterestNotifier
, object
))) { 
9067                 if (response
->isEqualTo(gIOPMStatsResponseTimedOut
.get())) { 
9068                         notify
->ackTimeoutCnt
++; 
9070                         notify
->ackTimeoutCnt 
= 0; 
9074         if (response
->isEqualTo(gIOPMStatsResponsePrompt
.get()) || 
9075             (_systemTransitionType 
== kSystemTransitionNone
) || (_systemTransitionType 
== kSystemTransitionNewCapClient
)) { 
9080         if (response
->isEqualTo(gIOPMStatsDriverPSChangeSlow
.get())) { 
9081                 kdebugTrace(kPMLogDrvPSChangeDelay
, id
, messageType
, delay_ms
); 
9082         } else if (notify
) { 
9083                 // User space app or kernel capability client 
9085                         kdebugTrace(kPMLogAppResponseDelay
, id
, notify
->msgType
, delay_ms
); 
9087                         kdebugTrace(kPMLogDrvResponseDelay
, notify
->uuid0
, messageType
, delay_ms
); 
9089                 notify
->msgType 
= 0; 
9092         responseDescription 
= OSDictionary::withCapacity(5); 
9093         if (responseDescription
) { 
9095                         responseDescription
->setObject(_statsResponseTypeKey
.get(), response
); 
9098                 msgNum 
= OSNumber::withNumber(messageType
, 32); 
9100                         responseDescription
->setObject(_statsMessageTypeKey
.get(), msgNum
.get()); 
9103                 if (!name 
&& notify 
&& notify
->identifier
) { 
9104                         name 
= notify
->identifier
->getCStringNoCopy(); 
9107                 if (name 
&& (strlen(name
) > 0)) { 
9108                         appname 
= OSSymbol::withCString(name
); 
9110                                 responseDescription
->setObject(_statsNameKey
.get(), appname
.get()); 
9114                 if (!id 
&& notify
) { 
9118                         pidNum 
= OSNumber::withNumber(id
, 64); 
9120                                 responseDescription
->setObject(_statsPIDKey
.get(), pidNum
.get()); 
9124                 delayNum 
= OSNumber::withNumber(delay_ms
, 32); 
9126                         responseDescription
->setObject(_statsTimeMSKey
.get(), delayNum
.get()); 
9129                 if (response
->isEqualTo(gIOPMStatsDriverPSChangeSlow
.get())) { 
9130                         powerCaps 
= OSNumber::withNumber(powerState
, 32); 
9132 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG) 
9133                         static const char * driverCallTypes
[] = { 
9134                                 [kDriverCallInformPreChange
]  = "powerStateWillChangeTo", 
9135                                 [kDriverCallInformPostChange
] = "powerStateDidChangeTo", 
9136                                 [kDriverCallSetPowerState
]    = "setPowerState" 
9139                         if (messageType 
< (sizeof(driverCallTypes
) / sizeof(driverCallTypes
[0]))) { 
9140                                 DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n", 
9141                                     name
, id
, driverCallTypes
[messageType
], (uint32_t) powerState
, 
9142                                     async 
? "async " : "", delay_ms
); 
9146                         powerCaps 
= OSNumber::withNumber(_pendingCapability
, 32); 
9149                         responseDescription
->setObject(_statsPowerCapsKey
.get(), powerCaps
.get()); 
9152                 sleep 
= OSSymbol::withCString("Sleep"); 
9153                 wake 
= OSSymbol::withCString("Wake"); 
9154                 if (_systemTransitionType 
== kSystemTransitionSleep
) { 
9155                         responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, sleep
.get()); 
9156                 } else if (_systemTransitionType 
== kSystemTransitionWake
) { 
9157                         responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, wake
.get()); 
9158                 } else if (_systemTransitionType 
== kSystemTransitionCapability
) { 
9159                         if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) { 
9160                                 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, sleep
.get()); 
9161                         } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) { 
9162                                 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, wake
.get()); 
9166                 IOLockLock(pmStatsLock
); 
9167                 if (pmStatsAppResponses 
&& pmStatsAppResponses
->getCount() < 50) { 
9168                         pmStatsAppResponses
->setObject(responseDescription
.get()); 
9170                 IOLockUnlock(pmStatsLock
); 
9177 // MARK: PMTraceWorker 
9179 //****************************************************************************** 
9180 // TracePoint support 
9182 //****************************************************************************** 
9184 #define kIOPMRegisterNVRAMTracePointHandlerKey  \ 
9185         "IOPMRegisterNVRAMTracePointHandler" 
9188 IOPMrootDomain::callPlatformFunction( 
9189         const OSSymbol 
* functionName
, 
9190         bool waitForFunction
, 
9191         void * param1
, void * param2
, 
9192         void * param3
, void * param4 
) 
9194         if (pmTracer 
&& functionName 
&& 
9195             functionName
->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey
) && 
9196             !pmTracer
->tracePointHandler 
&& !pmTracer
->tracePointTarget
) { 
9197                 uint32_t    tracePointPhases
, tracePointPCI
; 
9198                 uint64_t    statusCode
; 
9200                 pmTracer
->tracePointHandler 
= (IOPMTracePointHandler
) param1
; 
9201                 pmTracer
->tracePointTarget  
= (void *) param2
; 
9202                 tracePointPCI               
= (uint32_t)(uintptr_t) param3
; 
9203                 tracePointPhases            
= (uint32_t)(uintptr_t) param4
; 
9204                 if ((tracePointPhases 
& 0xff) == kIOPMTracePointSystemSleep
) { 
9205                         OSSharedPtr
<IORegistryEntry
> node 
= IORegistryEntry::fromPath( "/chosen", gIODTPlane 
); 
9207                                 OSSharedPtr
<OSObject
> bootRomFailureProp
; 
9208                                 bootRomFailureProp 
= node
->copyProperty(kIOEFIBootRomFailureKey
); 
9209                                 OSData 
*data 
= OSDynamicCast(OSData
, bootRomFailureProp
.get()); 
9210                                 uint32_t bootFailureCode
; 
9211                                 if (data 
&& data
->getLength() == sizeof(bootFailureCode
)) { 
9212                                         // Failure code from EFI/BootRom is a four byte structure 
9213                                         memcpy(&bootFailureCode
, data
->getBytesNoCopy(), sizeof(bootFailureCode
)); 
9214                                         tracePointPCI 
= OSSwapBigToHostInt32(bootFailureCode
); 
9218                 statusCode 
= (((uint64_t)tracePointPCI
) << 32) | tracePointPhases
; 
9219                 if ((tracePointPhases 
& 0xff) != kIOPMTracePointSystemUp
) { 
9220                         MSG("Sleep failure code 0x%08x 0x%08x\n", 
9221                             tracePointPCI
, tracePointPhases
); 
9223                 setProperty(kIOPMSleepWakeFailureCodeKey
, statusCode
, 64); 
9224                 pmTracer
->tracePointHandler( pmTracer
->tracePointTarget
, 0, 0 ); 
9226                 return kIOReturnSuccess
; 
9229         else if (functionName 
&& 
9230             functionName
->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey
)) { 
9231                 if (gSleepPolicyHandler
) { 
9232                         return kIOReturnExclusiveAccess
; 
9235                         return kIOReturnBadArgument
; 
9237                 gSleepPolicyHandler 
= (IOPMSystemSleepPolicyHandler
) param1
; 
9238                 gSleepPolicyTarget  
= (void *) param2
; 
9239                 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue
); 
9240                 return kIOReturnSuccess
; 
9244         return super::callPlatformFunction( 
9245                 functionName
, waitForFunction
, param1
, param2
, param3
, param4
); 
9249 IOPMrootDomain::kdebugTrace(uint32_t event
, uint64_t id
, 
9250     uintptr_t param1
, uintptr_t param2
, uintptr_t param3
) 
9252         uint32_t code   
= IODBG_POWER(event
); 
9253         uint64_t regId  
= id
; 
9255                 regId  
= getRegistryEntryID(); 
9257         KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
, code
, (uintptr_t) regId
, param1
, param2
, param3
, 0); 
9261 IOPMrootDomain::tracePoint( uint8_t point 
) 
9263         if (systemBooting
) { 
9267         if (kIOPMTracePointWakeCapabilityClients 
== point
) { 
9268                 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable
); 
9271         kdebugTrace(kPMLogSleepWakeTracePoint
, 0, point
, 0); 
9272         pmTracer
->tracePoint(point
); 
9276 kext_log_putc(char c
) 
9278         if (gKextNameEnd 
|| gKextNamePos 
>= (sizeof(gKextNameBuf
) - 1)) { 
9281         if (c 
== '(' || c 
== '[' || c 
== ' ') { 
9283                 gKextNameEnd 
= true; 
9286         gKextNameBuf
[gKextNamePos
++] = c
; 
9290 kext_log(const char *fmt
, ...) 
9294         va_start(listp
, fmt
); 
9295         _doprnt(fmt
, &listp
, &kext_log_putc
, 16); 
9301 static OSPtr
<const OSSymbol
> 
9302 copyKextIdentifierWithAddress(vm_address_t address
) 
9304         OSSharedPtr
<const OSSymbol
> identifer
; 
9306         IOLockLock(gHaltLogLock
); 
9308         gKextNameEnd 
= false; 
9310         gKextNameBuf
[0] = 0; 
9312         OSKext::printKextsInBacktrace(&address
, 1, kext_log
, OSKext::kPrintKextsLock 
| OSKext::kPrintKextsTerse
); 
9313         gKextNameBuf
[sizeof(gKextNameBuf
) - 1] = 0; 
9314         identifer 
= OSSymbol::withCString((gKextNameBuf
[0] != 0) ? gKextNameBuf 
: kOSKextKernelIdentifier
); 
9316         IOLockUnlock(gHaltLogLock
); 
9321 // Caller serialized using PM workloop 
9323 IOPMrootDomain::getNotificationClientName(OSObject 
*object
) 
9325         IOPMServiceInterestNotifier 
*notifier 
= (typeof(notifier
))object
; 
9326         const char *clientName 
= "UNKNOWN"; 
9328         if (!notifier
->clientName
) { 
9329                 // Check for user client 
9330                 if (systemCapabilityNotifier 
&& (((IOPMServiceInterestNotifier 
*) systemCapabilityNotifier
.get())->handler 
== notifier
->handler
)) { 
9331                         OSNumber 
*clientID 
= NULL
; 
9332                         messageClient(kIOMessageCopyClientID
, object
, &clientID
); 
9334                                 OSSharedPtr
<OSString
> string(IOCopyLogNameForPID(clientID
->unsigned32BitValue()), OSNoRetain
); 
9336                                         notifier
->clientName 
= OSSymbol::withString(string
.get()); 
9338                                 clientID
->release(); 
9340                 } else if (notifier
->identifier
) { 
9341                         notifier
->clientName
.reset(notifier
->identifier
.get(), OSRetain
); 
9345         if (notifier
->clientName
) { 
9346                 clientName 
= notifier
->clientName
->getCStringNoCopy(); 
9353 IOPMrootDomain::traceNotification(OSObject 
*object
, bool start
, uint64_t timestamp
, uint32_t msgIndex
) 
9355         IOPMServiceInterestNotifier 
*notifier
; 
9357         if (systemBooting
) { 
9360         notifier 
= OSDynamicCast(IOPMServiceInterestNotifier
, object
); 
9366                 pmTracer
->traceDetail(notifier
->uuid0 
>> 32); 
9367                 kdebugTrace(kPMLogSleepWakeMessage
, pmTracer
->getTracePhase(), 
9368                     (uintptr_t) notifier
->msgType
, (uintptr_t) notifier
->uuid0
, (uintptr_t) notifier
->uuid1
); 
9370                 // Update notifier state used for response/ack logging 
9371                 notifier
->msgIndex 
= msgIndex
; 
9372                 notifier
->msgAbsTime 
= timestamp
; 
9374                 if (msgIndex 
!= UINT_MAX
) { 
9375                         DLOG("%s[%u] to %s\n", getIOMessageString(notifier
->msgType
), msgIndex
, getNotificationClientName(notifier
)); 
9377                         DLOG("%s to %s\n", getIOMessageString(notifier
->msgType
), getNotificationClientName(notifier
)); 
9380                 assert(notifierObject 
== NULL
); 
9381                 notifierThread 
= current_thread(); 
9382                 notifierObject
.reset(notifier
, OSRetain
); 
9387                 SUB_ABSOLUTETIME(×tamp
, ¬ifier
->msgAbsTime
); 
9388                 absolutetime_to_nanoseconds(timestamp
, &nsec
); 
9389                 delayMS 
= (uint32_t)(nsec 
/ 1000000ULL); 
9390                 if (delayMS 
> notifier
->maxMsgDelayMS
) { 
9391                         notifier
->maxMsgDelayMS 
= delayMS
; 
9394                 assert(notifierObject 
== notifier
); 
9395                 notifierObject
.reset(); 
9396                 notifierThread 
= NULL
; 
9401 IOPMrootDomain::traceNotificationAck(OSObject 
*object
, uint32_t delay_ms
) 
9403         if (systemBooting
) { 
9406         IOPMServiceInterestNotifier 
*notifier 
= OSDynamicCast(IOPMServiceInterestNotifier
, object
); 
9411         kdebugTrace(kPMLogDrvResponseDelay
, notifier
->uuid0
, 
9412             (uintptr_t) notifier
->uuid1
, (uintptr_t) 0, (uintptr_t) delay_ms
); 
9414         DLOG("%s[%u] ack from %s took %d ms\n", 
9415             getIOMessageString(notifier
->msgType
), notifier
->msgIndex
, getNotificationClientName(notifier
), delay_ms
); 
9416         if (delay_ms 
> notifier
->maxAckDelayMS
) { 
9417                 notifier
->maxAckDelayMS 
= delay_ms
; 
9422 IOPMrootDomain::traceNotificationResponse(OSObject 
*object
, uint32_t delay_ms
, uint32_t ack_time_us
) 
9424         if (systemBooting
) { 
9427         IOPMServiceInterestNotifier 
*notifier 
= OSDynamicCast(IOPMServiceInterestNotifier
, object
); 
9432         kdebugTrace(kPMLogDrvResponseDelay
, notifier
->uuid0
, 
9433             (uintptr_t) notifier
->uuid1
, (uintptr_t)(ack_time_us 
/ 1000), (uintptr_t) delay_ms
); 
9435         if (ack_time_us 
== 0) { 
9436                 // Client work is done and ack will not be forthcoming 
9437                 DLOG("%s[%u] response from %s took %d ms\n", 
9438                     getIOMessageString(notifier
->msgType
), notifier
->msgIndex
, getNotificationClientName(notifier
), delay_ms
); 
9440                 // Client needs more time and it must ack within ack_time_us 
9441                 DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n", 
9442                     getIOMessageString(notifier
->msgType
), notifier
->msgIndex
, getNotificationClientName(notifier
), delay_ms
, ack_time_us
); 
9447 IOPMrootDomain::traceFilteredNotification(OSObject 
*object
) 
9449         if ((kIOLogDebugPower 
& gIOKitDebug
) == 0) { 
9452         if (systemBooting
) { 
9455         IOPMServiceInterestNotifier 
*notifier 
= OSDynamicCast(IOPMServiceInterestNotifier
, object
); 
9460         DLOG("%s to %s dropped\n", getIOMessageString(notifier
->msgType
), getNotificationClientName(notifier
)); 
9464 IOPMrootDomain::traceDetail(uint32_t msgType
, uint32_t msgIndex
, uint32_t delay
) 
9466         if (!systemBooting
) { 
9467                 uint32_t detail 
= ((msgType 
& 0xffff) << 16) | (delay 
& 0xffff); 
9468                 pmTracer
->traceDetail( detail 
); 
9469                 kdebugTrace(kPMLogSleepWakeTracePoint
, pmTracer
->getTracePhase(), msgType
, delay
); 
9470                 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer
->getTracePhase(), msgType
, delay
); 
9475 IOPMrootDomain::configureReportGated(uint64_t channel_id
, uint64_t action
, void *result
) 
9478         void        **report 
= NULL
; 
9481         uint32_t    *clientCnt
; 
9486         if (channel_id 
== kAssertDelayChID
) { 
9487                 report 
= &assertOnWakeReport
; 
9488                 bktCnt 
= kAssertDelayBcktCnt
; 
9489                 bktSize 
= kAssertDelayBcktSize
; 
9490                 clientCnt 
= &assertOnWakeClientCnt
; 
9491         } else if (channel_id 
== kSleepDelaysChID
) { 
9492                 report 
= &sleepDelaysReport
; 
9493                 bktCnt 
= kSleepDelaysBcktCnt
; 
9494                 bktSize 
= kSleepDelaysBcktSize
; 
9495                 clientCnt 
= &sleepDelaysClientCnt
; 
9502         case kIOReportEnable
: 
9509                 reportSize 
= HISTREPORT_BUFSIZE(bktCnt
); 
9510                 *report 
= IOMalloc(reportSize
); 
9511                 if (*report 
== NULL
) { 
9514                 bzero(*report
, reportSize
); 
9515                 HISTREPORT_INIT((uint16_t)bktCnt
, bktSize
, *report
, reportSize
, 
9516                     getRegistryEntryID(), channel_id
, kIOReportCategoryPower
); 
9518                 if (channel_id 
== kAssertDelayChID
) { 
9519                         assertOnWakeSecs 
= 0; 
9524         case kIOReportDisable
: 
9525                 if (*clientCnt 
== 0) { 
9528                 if (*clientCnt 
== 1) { 
9529                         IOFree(*report
, HISTREPORT_BUFSIZE(bktCnt
)); 
9534                 if (channel_id 
== kAssertDelayChID
) { 
9535                         assertOnWakeSecs 
= -1; // Invalid value to prevent updates 
9539         case kIOReportGetDimensions
: 
9541                         HISTREPORT_UPDATERES(*report
, kIOReportGetDimensions
, result
); 
9550 IOPMrootDomain::configureReport(IOReportChannelList    
*channelList
, 
9551     IOReportConfigureAction action
, 
9556         uint64_t configAction 
= (uint64_t)action
; 
9558         for (cnt 
= 0; cnt 
< channelList
->nchannels
; cnt
++) { 
9559                 if ((channelList
->channels
[cnt
].channel_id 
== kSleepCntChID
) || 
9560                     (channelList
->channels
[cnt
].channel_id 
== kDarkWkCntChID
) || 
9561                     (channelList
->channels
[cnt
].channel_id 
== kUserWkCntChID
)) { 
9562                         if (action 
!= kIOReportGetDimensions
) { 
9565                         SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
); 
9566                 } else if ((channelList
->channels
[cnt
].channel_id 
== kAssertDelayChID
) || 
9567                     (channelList
->channels
[cnt
].channel_id 
== kSleepDelaysChID
)) { 
9568                         gIOPMWorkLoop
->runAction( 
9569                                 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::configureReportGated
), 
9570                                 (OSObject 
*)this, (void *)channelList
->channels
[cnt
].channel_id
, 
9571                                 (void *)configAction
, (void *)result
); 
9575         return super::configureReport(channelList
, action
, result
, destination
); 
9579 IOPMrootDomain::updateReportGated(uint64_t ch_id
, void *result
, IOBufferMemoryDescriptor 
*dest
) 
9588         if (ch_id 
== kAssertDelayChID
) { 
9589                 report 
= &assertOnWakeReport
; 
9590         } else if (ch_id 
== kSleepDelaysChID
) { 
9591                 report 
= &sleepDelaysReport
; 
9594                 return kIOReturnBadArgument
; 
9597         if (*report 
== NULL
) { 
9598                 return kIOReturnNotOpen
; 
9601         HISTREPORT_UPDATEPREP(*report
, data2cpy
, size2cpy
); 
9602         if (size2cpy 
> (dest
->getCapacity() - dest
->getLength())) { 
9603                 return kIOReturnOverrun
; 
9606         HISTREPORT_UPDATERES(*report
, kIOReportCopyChannelData
, result
); 
9607         dest
->appendBytes(data2cpy
, size2cpy
); 
9609         return kIOReturnSuccess
; 
9613 IOPMrootDomain::updateReport(IOReportChannelList      
*channelList
, 
9614     IOReportUpdateAction      action
, 
9620         uint8_t buf
[SIMPLEREPORT_BUFSIZE
]; 
9621         IOBufferMemoryDescriptor 
*dest 
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject 
*)destination
); 
9625         if (action 
!= kIOReportCopyChannelData
) { 
9629         for (cnt 
= 0; cnt 
< channelList
->nchannels
; cnt
++) { 
9630                 ch_id 
= channelList
->channels
[cnt
].channel_id
; 
9632                 if ((ch_id 
== kAssertDelayChID
) || (ch_id 
== kSleepDelaysChID
)) { 
9633                         gIOPMWorkLoop
->runAction( 
9634                                 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::updateReportGated
), 
9635                                 (OSObject 
*)this, (void *)ch_id
, 
9636                                 (void *)result
, (void *)dest
); 
9638                 } else if ((ch_id 
== kSleepCntChID
) || 
9639                     (ch_id 
== kDarkWkCntChID
) || (ch_id 
== kUserWkCntChID
)) { 
9640                         SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), ch_id
, kIOReportCategoryPower
); 
9645                 if (ch_id 
== kSleepCntChID
) { 
9646                         SIMPLEREPORT_SETVALUE(buf
, sleepCnt
); 
9647                 } else if (ch_id 
== kDarkWkCntChID
) { 
9648                         SIMPLEREPORT_SETVALUE(buf
, darkWakeCnt
); 
9649                 } else if (ch_id 
== kUserWkCntChID
) { 
9650                         SIMPLEREPORT_SETVALUE(buf
, displayWakeCnt
); 
9653                 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
); 
9654                 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
); 
9655                 dest
->appendBytes(data2cpy
, size2cpy
); 
9659         return super::updateReport(channelList
, action
, result
, destination
); 
9663 //****************************************************************************** 
9664 // PMTraceWorker Class 
9666 //****************************************************************************** 
9669 #define super OSObject 
9670 OSDefineMetaClassAndStructors(PMTraceWorker
, OSObject
) 
9672 #define kPMBestGuessPCIDevicesCount     25 
9673 #define kPMMaxRTCBitfieldSize           32 
9675 OSPtr
<PMTraceWorker
> 
9676 PMTraceWorker::tracer(IOPMrootDomain 
* owner
) 
9678         OSSharedPtr
<PMTraceWorker
> me 
= OSMakeShared
<PMTraceWorker
>(); 
9679         if (!me 
|| !me
->init()) { 
9683         DLOG("PMTraceWorker %p\n", OBFUSCATE(me
.get())); 
9685         // Note that we cannot instantiate the PCI device -> bit mappings here, since 
9686         // the IODeviceTree has not yet been created by IOPlatformExpert. We create 
9687         // this dictionary lazily. 
9689         me
->pciDeviceBitMappings 
= NULL
; 
9690         me
->pmTraceWorkerLock 
= IOLockAlloc(); 
9691         me
->tracePhase 
= kIOPMTracePointSystemUp
; 
9692         me
->traceData32 
= 0; 
9693         me
->loginWindowData 
= 0; 
9694         me
->coreDisplayData 
= 0; 
9695         me
->coreGraphicsData 
= 0; 
9700 PMTraceWorker::RTC_TRACE(void) 
9702         if (tracePointHandler 
&& tracePointTarget
) { 
9705                 IOLockLock(pmTraceWorkerLock
); 
9706                 wordA 
= (loginWindowData 
<< 24) | (coreDisplayData 
<< 16) | 
9707                     (coreGraphicsData 
<< 8) | tracePhase
; 
9708                 IOLockUnlock(pmTraceWorkerLock
); 
9710                 tracePointHandler( tracePointTarget
, traceData32
, wordA 
); 
9711                 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32
, wordA
); 
9713 #if DEVELOPMENT || DEBUG 
9714         if ((swd_panic_phase 
!= 0) && (swd_panic_phase 
== tracePhase
)) { 
9715                 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase
); 
9716                 IOLock 
*l 
= IOLockAlloc(); 
9724 PMTraceWorker::recordTopLevelPCIDevice(IOService 
* pciDevice
) 
9726         OSSharedPtr
<const OSSymbol
>    deviceName
; 
9729         IOLockLock(pmTraceWorkerLock
); 
9731         if (!pciDeviceBitMappings
) { 
9732                 pciDeviceBitMappings 
= OSArray::withCapacity(kPMBestGuessPCIDevicesCount
); 
9733                 if (!pciDeviceBitMappings
) { 
9738         // Check for bitmask overflow. 
9739         if (pciDeviceBitMappings
->getCount() >= kPMMaxRTCBitfieldSize
) { 
9743         if ((deviceName 
= pciDevice
->copyName()) && 
9744             (pciDeviceBitMappings
->getNextIndexOfObject(deviceName
.get(), 0) == (unsigned int)-1) && 
9745             pciDeviceBitMappings
->setObject(deviceName
.get())) { 
9746                 index 
= pciDeviceBitMappings
->getCount() - 1; 
9747                 _LOG("PMTrace PCI array: set object %s => %d\n", 
9748                     deviceName
->getCStringNoCopy(), index
); 
9751         if (!addedToRegistry 
&& (index 
>= 0)) { 
9752                 addedToRegistry 
= owner
->setProperty("PCITopLevel", this); 
9756         IOLockUnlock(pmTraceWorkerLock
); 
9761 PMTraceWorker::serialize(OSSerialize 
*s
) const 
9764         if (pciDeviceBitMappings
) { 
9765                 IOLockLock(pmTraceWorkerLock
); 
9766                 ok 
= pciDeviceBitMappings
->serialize(s
); 
9767                 IOLockUnlock(pmTraceWorkerLock
); 
9773 PMTraceWorker::tracePoint(uint8_t phase
) 
9775         // clear trace detail when phase begins 
9776         if (tracePhase 
!= phase
) { 
9782         DLOG("trace point 0x%02x\n", tracePhase
); 
9787 PMTraceWorker::traceDetail(uint32_t detail
) 
9789         if (detail 
== traceData32
) { 
9792         traceData32 
= detail
; 
9797 PMTraceWorker::traceComponentWakeProgress(uint32_t component
, uint32_t data
) 
9799         switch (component
) { 
9800         case kIOPMLoginWindowProgress
: 
9801                 loginWindowData 
= data 
& kIOPMLoginWindowProgressMask
; 
9803         case kIOPMCoreDisplayProgress
: 
9804                 coreDisplayData 
= data 
& kIOPMCoreDisplayProgressMask
; 
9806         case kIOPMCoreGraphicsProgress
: 
9807                 coreGraphicsData 
= data 
& kIOPMCoreGraphicsProgressMask
; 
9813         DLOG("component trace point 0x%02x data 0x%08x\n", component
, data
); 
9818 PMTraceWorker::tracePCIPowerChange( 
9819         change_t type
, IOService 
*service
, uint32_t changeFlags
, uint32_t bitNum
) 
9822         uint32_t    expectedFlag
; 
9824         // Ignore PCI changes outside of system sleep/wake. 
9825         if ((kIOPMTracePointSleepPowerPlaneDrivers 
!= tracePhase
) && 
9826             (kIOPMTracePointWakePowerPlaneDrivers 
!= tracePhase
)) { 
9830         // Only record the WillChange transition when going to sleep, 
9831         // and the DidChange on the way up. 
9832         changeFlags 
&= (kIOPMDomainWillChange 
| kIOPMDomainDidChange
); 
9833         expectedFlag 
= (kIOPMTracePointSleepPowerPlaneDrivers 
== tracePhase
) ? 
9834             kIOPMDomainWillChange 
: kIOPMDomainDidChange
; 
9835         if (changeFlags 
!= expectedFlag
) { 
9839         // Mark this device off in our bitfield 
9840         if (bitNum 
< kPMMaxRTCBitfieldSize
) { 
9841                 bitMask 
= (1 << bitNum
); 
9843                 if (kPowerChangeStart 
== type
) { 
9844                         traceData32 
|= bitMask
; 
9845                         _LOG("PMTrace: Device %s started  - bit %2d mask 0x%08x => 0x%08x\n", 
9846                             service
->getName(), bitNum
, bitMask
, traceData32
); 
9847                         owner
->kdebugTrace(kPMLogPCIDevChangeStart
, service
->getRegistryEntryID(), traceData32
, 0); 
9849                         traceData32 
&= ~bitMask
; 
9850                         _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n", 
9851                             service
->getName(), bitNum
, bitMask
, traceData32
); 
9852                         owner
->kdebugTrace(kPMLogPCIDevChangeDone
, service
->getRegistryEntryID(), traceData32
, 0); 
9855                 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase
, traceData32
); 
9861 PMTraceWorker::getPMStatusCode() 
9863         return ((uint64_t)traceData32 
<< 32) | ((uint64_t)tracePhase
); 
9867 PMTraceWorker::getTracePhase() 
9873 PMTraceWorker::getTraceData() 
9879 // MARK: PMHaltWorker 
9881 //****************************************************************************** 
9882 // PMHaltWorker Class 
9884 //****************************************************************************** 
9887 PMHaltWorker::worker( void ) 
9893                 me 
= OSTypeAlloc( PMHaltWorker 
); 
9894                 if (!me 
|| !me
->init()) { 
9898                 me
->lock 
= IOLockAlloc(); 
9903                 DLOG("PMHaltWorker %p\n", OBFUSCATE(me
)); 
9904                 me
->retain(); // thread holds extra retain 
9905                 if (KERN_SUCCESS 
!= kernel_thread_start(&PMHaltWorker::main
, (void *) me
, &thread
)) { 
9909                 thread_deallocate(thread
); 
9920 PMHaltWorker::free( void ) 
9922         DLOG("PMHaltWorker free %p\n", OBFUSCATE(this)); 
9927         return OSObject::free(); 
9931 PMHaltWorker::main( void * arg
, wait_result_t waitResult 
) 
9933         PMHaltWorker 
* me 
= (PMHaltWorker 
*) arg
; 
9935         IOLockLock( gPMHaltLock 
); 
9937         me
->depth 
= gPMHaltDepth
; 
9938         IOLockUnlock( gPMHaltLock 
); 
9940         while (me
->depth 
>= 0) { 
9941                 PMHaltWorker::work( me 
); 
9943                 IOLockLock( gPMHaltLock 
); 
9944                 if (++gPMHaltIdleCount 
>= gPMHaltBusyCount
) { 
9945                         // This is the last thread to finish work on this level, 
9946                         // inform everyone to start working on next lower level. 
9948                         me
->depth 
= gPMHaltDepth
; 
9949                         gPMHaltIdleCount 
= 0; 
9950                         thread_wakeup((event_t
) &gPMHaltIdleCount
); 
9952                         // One or more threads are still working on this level, 
9953                         // this thread must wait. 
9954                         me
->depth 
= gPMHaltDepth 
- 1; 
9956                                 IOLockSleep(gPMHaltLock
, &gPMHaltIdleCount
, THREAD_UNINT
); 
9957                         } while (me
->depth 
!= gPMHaltDepth
); 
9959                 IOLockUnlock( gPMHaltLock 
); 
9962         // No more work to do, terminate thread 
9963         DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me
), me
->visits
); 
9964         thread_wakeup( &gPMHaltDepth 
); 
9969 PMHaltWorker::work( PMHaltWorker 
* me 
) 
9971         OSSharedPtr
<IOService
>     service
; 
9973         AbsoluteTime    startTime
, elapsedTime
; 
9980                 // Claim an unit of work from the shared pool 
9981                 IOLockLock( gPMHaltLock 
); 
9982                 inner 
= (OSSet 
*)gPMHaltArray
->getObject(me
->depth
); 
9984                         service
.reset(OSDynamicCast(IOService
, inner
->getAnyObject()), OSRetain
); 
9986                                 inner
->removeObject(service
.get()); 
9989                 IOLockUnlock( gPMHaltLock 
); 
9991                         break; // no more work at this depth 
9993                 clock_get_uptime(&startTime
); 
9995                 if (!service
->isInactive() && 
9996                     service
->setProperty(gPMHaltClientAcknowledgeKey
.get(), me
)) { 
9997                         IOLockLock(me
->lock
); 
9998                         me
->startTime 
= startTime
; 
9999                         me
->service   
= service
.get(); 
10000                         me
->timeout   
= false; 
10001                         IOLockUnlock(me
->lock
); 
10003                         service
->systemWillShutdown( gPMHaltMessageType
); 
10005                         // Wait for driver acknowledgement 
10006                         IOLockLock(me
->lock
); 
10007                         while (service
->propertyExists(gPMHaltClientAcknowledgeKey
.get())) { 
10008                                 IOLockSleep(me
->lock
, me
, THREAD_UNINT
); 
10010                         me
->service 
= NULL
; 
10011                         timeout 
= me
->timeout
; 
10012                         IOLockUnlock(me
->lock
); 
10015                 deltaTime 
= computeDeltaTimeMS(&startTime
, &elapsedTime
); 
10016                 if ((deltaTime 
> kPMHaltTimeoutMS
) || timeout
) { 
10017                         LOG("%s driver %s (0x%llx) took %u ms\n", 
10018                             (gPMHaltMessageType 
== kIOMessageSystemWillPowerOff
) ? 
10019                             "PowerOff" : "Restart", 
10020                             service
->getName(), service
->getRegistryEntryID(), 
10021                             (uint32_t) deltaTime 
); 
10022                         halt_log_enter("PowerOff/Restart handler completed", 
10023                             OSMemberFunctionCast(const void *, service
.get(), &IOService::systemWillShutdown
), 
10032 PMHaltWorker::checkTimeout( PMHaltWorker 
* me
, AbsoluteTime 
* now 
) 
10035         AbsoluteTime    startTime
; 
10036         AbsoluteTime    endTime
; 
10040         IOLockLock(me
->lock
); 
10041         if (me
->service 
&& !me
->timeout
) { 
10042                 startTime 
= me
->startTime
; 
10044                 if (CMP_ABSOLUTETIME(&endTime
, &startTime
) > 0) { 
10045                         SUB_ABSOLUTETIME(&endTime
, &startTime
); 
10046                         absolutetime_to_nanoseconds(endTime
, &nano
); 
10048                 if (nano 
> 3000000000ULL) { 
10049                         me
->timeout 
= true; 
10051                         halt_log_enter("PowerOff/Restart still waiting on handler", 
10052                             OSMemberFunctionCast(const void *, me
->service
, &IOService::systemWillShutdown
), 
10054                         MSG("%s still waiting on %s\n", 
10055                             (gPMHaltMessageType 
== kIOMessageSystemWillPowerOff
) ?  "PowerOff" : "Restart", 
10056                             me
->service
->getName()); 
10059         IOLockUnlock(me
->lock
); 
10062 //****************************************************************************** 
10063 // acknowledgeSystemWillShutdown 
10065 // Acknowledgement from drivers that they have prepared for shutdown/restart. 
10066 //****************************************************************************** 
10069 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService 
* from 
) 
10071         PMHaltWorker            
* worker
; 
10072         OSSharedPtr
<OSObject
>     prop
; 
10078         //DLOG("%s acknowledged\n", from->getName()); 
10079         prop 
= from
->copyProperty( gPMHaltClientAcknowledgeKey
.get()); 
10081                 worker 
= (PMHaltWorker 
*) prop
.get(); 
10082                 IOLockLock(worker
->lock
); 
10083                 from
->removeProperty( gPMHaltClientAcknowledgeKey
.get()); 
10084                 thread_wakeup((event_t
) worker
); 
10085                 IOLockUnlock(worker
->lock
); 
10087                 DLOG("%s acknowledged without worker property\n", 
10093 //****************************************************************************** 
10094 // notifySystemShutdown 
10096 // Notify all objects in PM tree that system will shutdown or restart 
10097 //****************************************************************************** 
10100 notifySystemShutdown( IOService 
* root
, uint32_t messageType 
) 
10102 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get()) 
10103         OSSharedPtr
<IORegistryIterator
>  iter
; 
10104         IORegistryEntry 
*                entry
; 
10107         OSSharedPtr
<OSSet
>               newInner
; 
10108         PMHaltWorker 
*                   workers
[kPMHaltMaxWorkers
]; 
10109         AbsoluteTime                     deadline
; 
10110         unsigned int                     totalNodes 
= 0; 
10111         unsigned int                     depth
; 
10112         unsigned int                     rootDepth
; 
10113         unsigned int                     numWorkers
; 
10114         unsigned int                     count
; 
10119         DLOG("%s msgType = 0x%x\n", __FUNCTION__
, messageType
); 
10121         baseFunc 
= OSMemberFunctionCast(void *, root
, &IOService::systemWillShutdown
); 
10123         // Iterate the entire PM tree starting from root 
10125         rootDepth 
= root
->getDepth( gIOPowerPlane 
); 
10130         // debug - for repeated test runs 
10131         while (PMHaltWorker::metaClass
->getInstanceCount()) { 
10135         if (!gPMHaltArray
) { 
10136                 gPMHaltArray 
= OSArray::withCapacity(40); 
10137                 if (!gPMHaltArray
) { 
10141                 gPMHaltArray
->flushCollection(); 
10144         if (!gPMHaltLock
) { 
10145                 gPMHaltLock 
= IOLockAlloc(); 
10146                 if (!gPMHaltLock
) { 
10151         if (!gPMHaltClientAcknowledgeKey
) { 
10152                 gPMHaltClientAcknowledgeKey 
= 
10153                     OSSymbol::withCStringNoCopy("PMShutdown"); 
10154                 if (!gPMHaltClientAcknowledgeKey
) { 
10159         gPMHaltMessageType 
= messageType
; 
10161         // Depth-first walk of PM plane 
10163         iter 
= IORegistryIterator::iterateOver( 
10164                 root
, gIOPowerPlane
, kIORegistryIterateRecursively
); 
10167                 while ((entry 
= iter
->getNextObject())) { 
10168                         node 
= OSDynamicCast(IOService
, entry
); 
10174                             OSMemberFunctionCast(void *, node
, &IOService::systemWillShutdown
)) { 
10178                         depth 
= node
->getDepth( gIOPowerPlane 
); 
10179                         if (depth 
<= rootDepth
) { 
10185                         // adjust to zero based depth 
10186                         depth 
-= (rootDepth 
+ 1); 
10188                         // gPMHaltArray is an array of containers, each container 
10189                         // refers to nodes with the same depth. 
10191                         count 
= gPMHaltArray
->getCount(); 
10192                         while (depth 
>= count
) { 
10193                                 // expand array and insert placeholders 
10194                                 gPMHaltArray
->setObject(PLACEHOLDER
); 
10197                         count 
= gPMHaltArray
->getCount(); 
10198                         if (depth 
< count
) { 
10199                                 inner 
= (OSSet 
*)gPMHaltArray
->getObject(depth
); 
10200                                 if (inner 
== PLACEHOLDER
) { 
10201                                         newInner 
= OSSet::withCapacity(40); 
10203                                                 gPMHaltArray
->replaceObject(depth
, newInner
.get()); 
10204                                                 inner 
= newInner
.get(); 
10208                                 // PM nodes that appear more than once in the tree will have 
10209                                 // the same depth, OSSet will refuse to add the node twice. 
10211                                         ok 
= inner
->setObject(node
); 
10215                                 DLOG("Skipped PM node %s\n", node
->getName()); 
10221         for (int i 
= 0; (inner 
= (OSSet 
*)gPMHaltArray
->getObject(i
)); i
++) { 
10223                 if (inner 
!= PLACEHOLDER
) { 
10224                         count 
= inner
->getCount(); 
10226                 DLOG("Nodes at depth %u = %u\n", i
, count
); 
10229         // strip placeholders (not all depths are populated) 
10231         for (int i 
= 0; (inner 
= (OSSet 
*)gPMHaltArray
->getObject(i
));) { 
10232                 if (inner 
== PLACEHOLDER
) { 
10233                         gPMHaltArray
->removeObject(i
); 
10236                 count 
= inner
->getCount(); 
10237                 if (count 
> numWorkers
) { 
10238                         numWorkers 
= count
; 
10240                 totalNodes 
+= count
; 
10244         if (gPMHaltArray
->getCount() == 0 || !numWorkers
) { 
10248         gPMHaltBusyCount 
= 0; 
10249         gPMHaltIdleCount 
= 0; 
10250         gPMHaltDepth 
= gPMHaltArray
->getCount() - 1; 
10252         // Create multiple workers (and threads) 
10254         if (numWorkers 
> kPMHaltMaxWorkers
) { 
10255                 numWorkers 
= kPMHaltMaxWorkers
; 
10258         DLOG("PM nodes %u, maxDepth %u, workers %u\n", 
10259             totalNodes
, gPMHaltArray
->getCount(), numWorkers
); 
10261         for (unsigned int i 
= 0; i 
< numWorkers
; i
++) { 
10262                 workers
[i
] = PMHaltWorker::worker(); 
10265         // Wait for workers to exhaust all available work 
10267         IOLockLock(gPMHaltLock
); 
10268         while (gPMHaltDepth 
>= 0) { 
10269                 clock_interval_to_deadline(1000, kMillisecondScale
, &deadline
); 
10271                 waitResult 
= IOLockSleepDeadline( 
10272                         gPMHaltLock
, &gPMHaltDepth
, deadline
, THREAD_UNINT
); 
10273                 if (THREAD_TIMED_OUT 
== waitResult
) { 
10275                         clock_get_uptime(&now
); 
10277                         IOLockUnlock(gPMHaltLock
); 
10278                         for (unsigned int i 
= 0; i 
< numWorkers
; i
++) { 
10280                                         PMHaltWorker::checkTimeout(workers
[i
], &now
); 
10283                         IOLockLock(gPMHaltLock
); 
10286         IOLockUnlock(gPMHaltLock
); 
10288         // Release all workers 
10290         for (unsigned int i 
= 0; i 
< numWorkers
; i
++) { 
10292                         workers
[i
]->release(); 
10294                 // worker also retained by it's own thread 
10298         DLOG("%s done\n", __FUNCTION__
); 
10303 // MARK: Kernel Assertion 
10305 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
10307 IOPMDriverAssertionID
 
10308 IOPMrootDomain::createPMAssertion( 
10309         IOPMDriverAssertionType whichAssertionBits
, 
10310         IOPMDriverAssertionLevel assertionLevel
, 
10311         IOService 
*ownerService
, 
10312         const char *ownerDescription
) 
10315         IOPMDriverAssertionID     newAssertion
; 
10317         if (!pmAssertions
) { 
10321         ret 
= pmAssertions
->createAssertion(whichAssertionBits
, assertionLevel
, ownerService
, ownerDescription
, &newAssertion
); 
10323         if (kIOReturnSuccess 
== ret
) { 
10324                 return newAssertion
; 
10331 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion
) 
10333         if (!pmAssertions
) { 
10334                 return kIOReturnInternalError
; 
10337         return pmAssertions
->releaseAssertion(releaseAssertion
); 
10342 IOPMrootDomain::setPMAssertionLevel( 
10343         IOPMDriverAssertionID assertionID
, 
10344         IOPMDriverAssertionLevel assertionLevel
) 
10346         return pmAssertions
->setAssertionLevel(assertionID
, assertionLevel
); 
10349 IOPMDriverAssertionLevel
 
10350 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion
) 
10352         IOPMDriverAssertionType       sysLevels
; 
10354         if (!pmAssertions 
|| whichAssertion 
== 0) { 
10355                 return kIOPMDriverAssertionLevelOff
; 
10358         sysLevels 
= pmAssertions
->getActivatedAssertions(); 
10360         // Check that every bit set in argument 'whichAssertion' is asserted 
10361         // in the aggregate bits. 
10362         if ((sysLevels 
& whichAssertion
) == whichAssertion
) { 
10363                 return kIOPMDriverAssertionLevelOn
; 
10365                 return kIOPMDriverAssertionLevelOff
; 
10370 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels
) 
10372         if (!pmAssertions
) { 
10373                 return kIOReturnNotFound
; 
10376         return pmAssertions
->setUserAssertionLevels(inLevels
); 
10380 IOPMrootDomain::serializeProperties( OSSerialize 
* s 
) const 
10382         if (pmAssertions
) { 
10383                 pmAssertions
->publishProperties(); 
10385         return IOService::serializeProperties(s
); 
10388 OSSharedPtr
<OSObject
> 
10389 IOPMrootDomain::copyProperty( const char * aKey
) const 
10391         OSSharedPtr
<OSObject
> obj
; 
10392         obj 
= IOService::copyProperty(aKey
); 
10398         if (!strncmp(aKey
, kIOPMSleepWakeWdogRebootKey
, 
10399             sizeof(kIOPMSleepWakeWdogRebootKey
))) { 
10400                 if (swd_flags 
& SWD_BOOT_BY_SW_WDOG
) { 
10401                         return OSSharedPtr
<OSBoolean
>(kOSBooleanTrue
, OSNoRetain
); 
10403                         return OSSharedPtr
<OSBoolean
>(kOSBooleanFalse
, OSNoRetain
); 
10407         if (!strncmp(aKey
, kIOPMSleepWakeWdogLogsValidKey
, 
10408             sizeof(kIOPMSleepWakeWdogLogsValidKey
))) { 
10409                 if (swd_flags 
& SWD_VALID_LOGS
) { 
10410                         return OSSharedPtr
<OSBoolean
>(kOSBooleanTrue
, OSNoRetain
); 
10412                         return OSSharedPtr
<OSBoolean
>(kOSBooleanFalse
, OSNoRetain
); 
10417          * XXX: We should get rid of "DesktopMode" property  when 'kAppleClamshellCausesSleepKey' 
10418          * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be 
10419          * issued by DisplayWrangler on darkwake. 
10421         if (!strcmp(aKey
, "DesktopMode")) { 
10423                         return OSSharedPtr
<OSBoolean
>(kOSBooleanTrue
, OSNoRetain
); 
10425                         return OSSharedPtr
<OSBoolean
>(kOSBooleanFalse
, OSNoRetain
); 
10428         if (!strcmp(aKey
, "DisplayIdleForDemandSleep")) { 
10429                 if (displayIdleForDemandSleep
) { 
10430                         return OSSharedPtr
<OSBoolean
>(kOSBooleanTrue
, OSNoRetain
); 
10432                         return OSSharedPtr
<OSBoolean
>(kOSBooleanFalse
, OSNoRetain
); 
10436         if (!strcmp(aKey
, kIOPMDriverWakeEventsKey
)) { 
10437                 OSSharedPtr
<OSArray
> array
; 
10439                 if (_systemWakeEventsArray 
&& _systemWakeEventsArray
->getCount()) { 
10440                         OSSharedPtr
<OSCollection
> collection 
= _systemWakeEventsArray
->copyCollection(); 
10442                                 array 
= OSDynamicPtrCast
<OSArray
>(collection
); 
10445                 WAKEEVENT_UNLOCK(); 
10446                 return os::move(array
); 
10449         if (!strcmp(aKey
, kIOPMSleepStatisticsAppsKey
)) { 
10450                 OSSharedPtr
<OSArray
> array
; 
10451                 IOLockLock(pmStatsLock
); 
10452                 if (pmStatsAppResponses 
&& pmStatsAppResponses
->getCount()) { 
10453                         OSSharedPtr
<OSCollection
> collection 
= pmStatsAppResponses
->copyCollection(); 
10455                                 array 
= OSDynamicPtrCast
<OSArray
>(collection
); 
10458                 IOLockUnlock(pmStatsLock
); 
10459                 return os::move(array
); 
10462         if (!strcmp(aKey
, kIOPMIdleSleepPreventersKey
)) { 
10463                 OSArray 
*idleSleepList 
= NULL
; 
10464                 gRootDomain
->copySleepPreventersList(&idleSleepList
, NULL
); 
10465                 return OSSharedPtr
<OSArray
>(idleSleepList
, OSNoRetain
); 
10468         if (!strcmp(aKey
, kIOPMSystemSleepPreventersKey
)) { 
10469                 OSArray 
*systemSleepList 
= NULL
; 
10470                 gRootDomain
->copySleepPreventersList(NULL
, &systemSleepList
); 
10471                 return OSSharedPtr
<OSArray
>(systemSleepList
, OSNoRetain
); 
10474         if (!strcmp(aKey
, kIOPMIdleSleepPreventersWithIDKey
)) { 
10475                 OSArray 
*idleSleepList 
= NULL
; 
10476                 gRootDomain
->copySleepPreventersListWithID(&idleSleepList
, NULL
); 
10477                 return OSSharedPtr
<OSArray
>(idleSleepList
, OSNoRetain
); 
10480         if (!strcmp(aKey
, kIOPMSystemSleepPreventersWithIDKey
)) { 
10481                 OSArray 
*systemSleepList 
= NULL
; 
10482                 gRootDomain
->copySleepPreventersListWithID(NULL
, &systemSleepList
); 
10483                 return OSSharedPtr
<OSArray
>(systemSleepList
, OSNoRetain
); 
10489 // MARK: Wake Event Reporting 
10492 IOPMrootDomain::copyWakeReasonString( char * outBuf
, size_t bufSize 
) 
10495         strlcpy(outBuf
, gWakeReasonString
, bufSize
); 
10496         WAKEEVENT_UNLOCK(); 
10500 IOPMrootDomain::copyShutdownReasonString( char * outBuf
, size_t bufSize 
) 
10503         strlcpy(outBuf
, gShutdownReasonString
, bufSize
); 
10504         WAKEEVENT_UNLOCK(); 
10507 //****************************************************************************** 
10508 // acceptSystemWakeEvents 
10510 // Private control for the acceptance of driver wake event claims. 
10511 //****************************************************************************** 
10514 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control 
) 
10516         bool logWakeReason 
= false; 
10520         case kAcceptSystemWakeEvents_Enable
: 
10521                 assert(_acceptSystemWakeEvents 
== false); 
10522                 if (!_systemWakeEventsArray
) { 
10523                         _systemWakeEventsArray 
= OSArray::withCapacity(4); 
10525                 _acceptSystemWakeEvents 
= (_systemWakeEventsArray 
!= NULL
); 
10526                 if (!(_aotNow 
&& (kIOPMWakeEventAOTExitFlags 
& _aotPendingFlags
))) { 
10527                         gWakeReasonString
[0] = '\0'; 
10528                         if (_systemWakeEventsArray
) { 
10529                                 _systemWakeEventsArray
->flushCollection(); 
10533                 // Remove stale WakeType property before system sleep 
10534                 removeProperty(kIOPMRootDomainWakeTypeKey
); 
10535                 removeProperty(kIOPMRootDomainWakeReasonKey
); 
10538         case kAcceptSystemWakeEvents_Disable
: 
10539                 _acceptSystemWakeEvents 
= false; 
10540 #if defined(XNU_TARGET_OS_OSX) 
10541                 logWakeReason 
= (gWakeReasonString
[0] != '\0'); 
10542 #else /* !defined(XNU_TARGET_OS_OSX) */ 
10543                 logWakeReason 
= gWakeReasonSysctlRegistered
; 
10545                 static int panic_allowed 
= -1; 
10547                 if ((panic_allowed 
== -1) && 
10548                     (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed
, sizeof(panic_allowed
)) == false)) { 
10552                 if (panic_allowed
) { 
10554                         // Panic if wake reason is null or empty 
10555                         for (i 
= 0; (i 
< strlen(gWakeReasonString
)); i
++) { 
10556                                 if ((gWakeReasonString
[i
] != ' ') && (gWakeReasonString
[i
] != '\t')) { 
10560                         if (i 
>= strlen(gWakeReasonString
)) { 
10561                                 panic("Wake reason is empty\n"); 
10564 #endif /* DEVELOPMENT */ 
10565 #endif /* !defined(XNU_TARGET_OS_OSX) */ 
10567                 // publish kIOPMRootDomainWakeReasonKey if not already set 
10568                 if (!propertyExists(kIOPMRootDomainWakeReasonKey
)) { 
10569                         setProperty(kIOPMRootDomainWakeReasonKey
, gWakeReasonString
); 
10573         case kAcceptSystemWakeEvents_Reenable
: 
10574                 assert(_acceptSystemWakeEvents 
== false); 
10575                 _acceptSystemWakeEvents 
= (_systemWakeEventsArray 
!= NULL
); 
10576                 removeProperty(kIOPMRootDomainWakeReasonKey
); 
10579         WAKEEVENT_UNLOCK(); 
10581         if (logWakeReason
) { 
10582                 MSG("system wake events: %s\n", gWakeReasonString
); 
10586 //****************************************************************************** 
10587 // claimSystemWakeEvent 
10589 // For a driver to claim a device is the source/conduit of a system wake event. 
10590 //****************************************************************************** 
10593 IOPMrootDomain::claimSystemWakeEvent( 
10594         IOService 
*     device
, 
10595         IOOptionBits    flags
, 
10596         const char *    reason
, 
10597         OSObject 
*      details 
) 
10599         OSSharedPtr
<const OSSymbol
>     deviceName
; 
10600         OSSharedPtr
<OSNumber
>           deviceRegId
; 
10601         OSSharedPtr
<OSNumber
>           claimTime
; 
10602         OSSharedPtr
<OSData
>             flagsData
; 
10603         OSSharedPtr
<OSString
>           reasonString
; 
10604         OSSharedPtr
<OSDictionary
>       dict
; 
10605         uint64_t                        timestamp
; 
10606         bool                            addWakeReason
; 
10608         if (!device 
|| !reason
) { 
10612         pmEventTimeStamp(×tamp
); 
10614         IOOptionBits        aotFlags 
= 0; 
10615         bool                needAOTEvaluate 
= FALSE
; 
10617         if (kIOPMAOTModeAddEventFlags 
& _aotMode
) { 
10618                 if (!strcmp("hold", reason
) 
10619                     || !strcmp("help", reason
) 
10620                     || !strcmp("menu", reason
) 
10621                     || !strcmp("stockholm", reason
) 
10622                     || !strcmp("ringer", reason
) 
10623                     || !strcmp("ringerab", reason
) 
10624                     || !strcmp("smc0", reason
) 
10625                     || !strcmp("AOP.RTPWakeupAP", reason
) 
10626                     || !strcmp("BT.OutboxNotEmpty", reason
) 
10627                     || !strcmp("WL.OutboxNotEmpty", reason
)) { 
10628                         flags 
|= kIOPMWakeEventAOTExit
; 
10632 #if DEVELOPMENT || DEBUG 
10633         if (_aotLingerTime 
&& !strcmp("rtc", reason
)) { 
10634                 flags 
|= kIOPMWakeEventAOTPossibleExit
; 
10636 #endif /* DEVELOPMENT || DEBUG */ 
10638 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 
10639         // Publishing the WakeType is serialized by the PM work loop 
10640         if (!strcmp("rtc", reason
) && (_nextScheduledAlarmType 
!= NULL
)) { 
10641                 pmPowerStateQueue
->submitPowerEvent(kPowerEventPublishWakeType
, 
10642                     (void *) _nextScheduledAlarmType
.get()); 
10645         // Workaround for the missing wake HID event 
10646         if (gDarkWakeFlags 
& kDarkWakeFlagUserWakeWorkaround
) { 
10647                 if (!strcmp("trackpadkeyboard", reason
)) { 
10648                         pmPowerStateQueue
->submitPowerEvent(kPowerEventPublishWakeType
, 
10649                             (void *) gIOPMWakeTypeUserKey
.get()); 
10654         deviceName   
= device
->copyName(gIOServicePlane
); 
10655         deviceRegId  
= OSNumber::withNumber(device
->getRegistryEntryID(), 64); 
10656         claimTime    
= OSNumber::withNumber(timestamp
, 64); 
10657         flagsData    
= OSData::withBytes(&flags
, sizeof(flags
)); 
10658         reasonString 
= OSString::withCString(reason
); 
10659         dict 
= OSDictionary::withCapacity(5 + (details 
? 1 : 0)); 
10660         if (!dict 
|| !deviceName 
|| !deviceRegId 
|| !claimTime 
|| !flagsData 
|| !reasonString
) { 
10664         dict
->setObject(gIONameKey
, deviceName
.get()); 
10665         dict
->setObject(gIORegistryEntryIDKey
, deviceRegId
.get()); 
10666         dict
->setObject(kIOPMWakeEventTimeKey
, claimTime
.get()); 
10667         dict
->setObject(kIOPMWakeEventFlagsKey
, flagsData
.get()); 
10668         dict
->setObject(kIOPMWakeEventReasonKey
, reasonString
.get()); 
10670                 dict
->setObject(kIOPMWakeEventDetailsKey
, details
); 
10674         addWakeReason 
= _acceptSystemWakeEvents
; 
10676                 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason
, deviceName
->getCStringNoCopy(), (int)flags
, _aotPendingFlags
, _aotReadyToFullWake
); 
10678         aotFlags        
= (kIOPMWakeEventAOTFlags 
& flags
); 
10679         aotFlags        
= (aotFlags 
& ~_aotPendingFlags
); 
10680         needAOTEvaluate 
= false; 
10681         if (_aotNow 
&& aotFlags
) { 
10682                 if (kIOPMWakeEventAOTPossibleExit 
& flags
) { 
10683                         _aotMetrics
->possibleCount
++; 
10685                 if (kIOPMWakeEventAOTConfirmedPossibleExit 
& flags
) { 
10686                         _aotMetrics
->confirmedPossibleCount
++; 
10688                 if (kIOPMWakeEventAOTRejectedPossibleExit 
& flags
) { 
10689                         _aotMetrics
->rejectedPossibleCount
++; 
10691                 if (kIOPMWakeEventAOTExpiredPossibleExit 
& flags
) { 
10692                         _aotMetrics
->expiredPossibleCount
++; 
10695                 _aotPendingFlags 
|= aotFlags
; 
10696                 addWakeReason     
= _aotNow 
&& _systemWakeEventsArray 
&& ((kIOPMWakeEventAOTExitFlags 
& aotFlags
)); 
10697                 needAOTEvaluate   
= _aotReadyToFullWake
; 
10699         DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n", 
10700             reason
, (int)flags
, deviceName
->getCStringNoCopy(), device
->getRegistryEntryID(), 
10701             _aotNow
, pmTracer
->getTracePhase(), addWakeReason
); 
10703         if (!gWakeReasonSysctlRegistered
) { 
10704                 // Lazy registration until the platform driver stops registering 
10706                 gWakeReasonSysctlRegistered 
= true; 
10708         if (addWakeReason
) { 
10709                 _systemWakeEventsArray
->setObject(dict
.get()); 
10710                 if (gWakeReasonString
[0] != '\0') { 
10711                         strlcat(gWakeReasonString
, " ", sizeof(gWakeReasonString
)); 
10713                 strlcat(gWakeReasonString
, reason
, sizeof(gWakeReasonString
)); 
10716         WAKEEVENT_UNLOCK(); 
10717         if (needAOTEvaluate
) { 
10718                 // Call aotEvaluate() on PM work loop since it may call 
10719                 // aotExit() which accesses PM state. 
10720                 pmPowerStateQueue
->submitPowerEvent(kPowerEventAOTEvaluate
); 
10727 //****************************************************************************** 
10728 // claimSystemBootEvent 
10730 // For a driver to claim a device is the source/conduit of a system boot event. 
10731 //****************************************************************************** 
10734 IOPMrootDomain::claimSystemBootEvent( 
10735         IOService 
*              device
, 
10736         IOOptionBits             flags
, 
10737         const char *             reason
, 
10738         __unused OSObject 
*      details 
) 
10740         if (!device 
|| !reason
) { 
10744         DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason
, device
->getName(), (uint32_t) flags
); 
10746         if (!gBootReasonSysctlRegistered
) { 
10747                 // Lazy sysctl registration after setting gBootReasonString 
10748                 strlcat(gBootReasonString
, reason
, sizeof(gBootReasonString
)); 
10749                 os_atomic_store(&gBootReasonSysctlRegistered
, true, release
); 
10751         WAKEEVENT_UNLOCK(); 
10754 //****************************************************************************** 
10755 // claimSystemShutdownEvent 
10757 // For drivers to claim a system shutdown event on the ensuing boot. 
10758 //****************************************************************************** 
10761 IOPMrootDomain::claimSystemShutdownEvent( 
10762         IOService 
*              device
, 
10763         IOOptionBits             flags
, 
10764         const char *             reason
, 
10765         __unused OSObject 
*      details 
) 
10767         if (!device 
|| !reason
) { 
10771         DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason
, device
->getName(), (uint32_t) flags
); 
10773         if (gShutdownReasonString
[0] != '\0') { 
10774                 strlcat(gShutdownReasonString
, " ", sizeof(gShutdownReasonString
)); 
10776         strlcat(gShutdownReasonString
, reason
, sizeof(gShutdownReasonString
)); 
10778         gShutdownReasonSysctlRegistered 
= true; 
10779         WAKEEVENT_UNLOCK(); 
10782 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
10785 // MARK: PMSettingHandle 
10787 OSDefineMetaClassAndStructors( PMSettingHandle
, OSObject 
) 
10790 PMSettingHandle::free( void ) 
10793                 pmso
->clientHandleFreed(); 
10802 // MARK: PMSettingObject 
10805 #define super OSObject 
10806 OSDefineMetaClassAndFinalStructors( PMSettingObject
, OSObject 
) 
10809  * Static constructor/initializer for PMSettingObject 
10811 PMSettingObject 
*PMSettingObject::pmSettingObject( 
10812         IOPMrootDomain                      
* parent_arg
, 
10813         IOPMSettingControllerCallback       handler_arg
, 
10814         OSObject                            
* target_arg
, 
10815         uintptr_t                           refcon_arg
, 
10816         uint32_t                            supportedPowerSources
, 
10817         const OSSymbol 
*                    settings
[], 
10818         OSObject                            
* *handle_obj
) 
10820         uint32_t                            settingCount 
= 0; 
10821         PMSettingObject                     
*pmso 
= NULL
; 
10822         PMSettingHandle                     
*pmsh 
= NULL
; 
10824         if (!parent_arg 
|| !handler_arg 
|| !settings 
|| !handle_obj
) { 
10828         // count OSSymbol entries in NULL terminated settings array 
10829         while (settings
[settingCount
]) { 
10832         if (0 == settingCount
) { 
10836         pmso 
= new PMSettingObject
; 
10837         if (!pmso 
|| !pmso
->init()) { 
10841         pmsh 
= new PMSettingHandle
; 
10842         if (!pmsh 
|| !pmsh
->init()) { 
10846         queue_init(&pmso
->calloutQueue
); 
10847         pmso
->parent       
= parent_arg
; 
10848         pmso
->func         
= handler_arg
; 
10849         pmso
->target       
= target_arg
; 
10850         pmso
->refcon       
= refcon_arg
; 
10851         pmso
->settingCount 
= settingCount
; 
10853         pmso
->retain(); // handle holds a retain on pmso 
10857         pmso
->publishedFeatureID 
= (uint32_t *)IOMalloc(sizeof(uint32_t) * settingCount
); 
10858         if (pmso
->publishedFeatureID
) { 
10859                 for (unsigned int i 
= 0; i 
< settingCount
; i
++) { 
10860                         // Since there is now at least one listener to this setting, publish 
10861                         // PM root domain support for it. 
10862                         parent_arg
->publishPMSetting( settings
[i
], 
10863                             supportedPowerSources
, &pmso
->publishedFeatureID
[i
] ); 
10867         *handle_obj 
= pmsh
; 
10881 PMSettingObject::free( void ) 
10883         if (publishedFeatureID
) { 
10884                 for (uint32_t i 
= 0; i 
< settingCount
; i
++) { 
10885                         if (publishedFeatureID
[i
]) { 
10886                                 parent
->removePublishedFeature( publishedFeatureID
[i
] ); 
10890                 IOFree(publishedFeatureID
, sizeof(uint32_t) * settingCount
); 
10897 PMSettingObject::dispatchPMSetting( const OSSymbol 
* type
, OSObject 
* object 
) 
10899         return (*func
)(target
, type
, object
, refcon
); 
10903 PMSettingObject::clientHandleFreed( void ) 
10905         parent
->deregisterPMSettingObject(this); 
10909 // MARK: PMAssertionsTracker 
10911 //********************************************************************************* 
10912 //********************************************************************************* 
10913 //********************************************************************************* 
10914 // class PMAssertionsTracker Implementation 
10916 #define kAssertUniqueIDStart    500 
10918 PMAssertionsTracker 
* 
10919 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain 
*rootDomain 
) 
10921         PMAssertionsTracker    
*me
; 
10923         me 
= new PMAssertionsTracker
; 
10924         if (!me 
|| !me
->init()) { 
10931         me
->owner 
= rootDomain
; 
10932         me
->issuingUniqueID 
= kAssertUniqueIDStart
; 
10933         me
->assertionsArray 
= OSArray::withCapacity(5); 
10934         me
->assertionsKernel 
= 0; 
10935         me
->assertionsUser 
= 0; 
10936         me
->assertionsCombined 
= 0; 
10937         me
->assertionsArrayLock 
= IOLockAlloc(); 
10938         me
->tabulateProducerCount 
= me
->tabulateConsumerCount 
= 0; 
10940         assert(me
->assertionsArray
); 
10941         assert(me
->assertionsArrayLock
); 
10947  * - Update assertionsKernel to reflect the state of all 
10948  * assertions in the kernel. 
10949  * - Update assertionsCombined to reflect both kernel & user space. 
10952 PMAssertionsTracker::tabulate(void) 
10956         PMAssertStruct      
*_a 
= NULL
; 
10959         IOPMDriverAssertionType oldKernel 
= assertionsKernel
; 
10960         IOPMDriverAssertionType oldCombined 
= assertionsCombined
; 
10964         assertionsKernel 
= 0; 
10965         assertionsCombined 
= 0; 
10967         if (!assertionsArray
) { 
10971         if ((count 
= assertionsArray
->getCount())) { 
10972                 for (i 
= 0; i 
< count
; i
++) { 
10973                         _d 
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
)); 
10975                                 _a 
= (PMAssertStruct 
*)_d
->getBytesNoCopy(); 
10976                                 if (_a 
&& (kIOPMDriverAssertionLevelOn 
== _a
->level
)) { 
10977                                         assertionsKernel 
|= _a
->assertionBits
; 
10983         tabulateProducerCount
++; 
10984         assertionsCombined 
= assertionsKernel 
| assertionsUser
; 
10986         if ((assertionsKernel 
!= oldKernel
) || 
10987             (assertionsCombined 
!= oldCombined
)) { 
10988                 owner
->evaluateAssertions(assertionsCombined
, oldCombined
); 
10993 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct 
*assertStruct 
) 
10998         if (((assertStruct
->assertionBits 
& kIOPMDriverAssertionCPUBit
) == 0) || 
10999             (assertStruct
->assertCPUStartTime 
== 0)) { 
11003         now 
= mach_absolute_time(); 
11004         SUB_ABSOLUTETIME(&now
, &assertStruct
->assertCPUStartTime
); 
11005         absolutetime_to_nanoseconds(now
, &nsec
); 
11006         assertStruct
->assertCPUDuration 
+= nsec
; 
11007         assertStruct
->assertCPUStartTime 
= 0; 
11009         if (assertStruct
->assertCPUDuration 
> maxAssertCPUDuration
) { 
11010                 maxAssertCPUDuration 
= assertStruct
->assertCPUDuration
; 
11011                 maxAssertCPUEntryId 
= assertStruct
->registryEntryID
; 
11016 PMAssertionsTracker::reportCPUBitAccounting( void ) 
11018         PMAssertStruct 
*_a
; 
11026         // Account for drivers that are still holding the CPU assertion 
11027         if (assertionsKernel 
& kIOPMDriverAssertionCPUBit
) { 
11028                 now 
= mach_absolute_time(); 
11029                 if ((count 
= assertionsArray
->getCount())) { 
11030                         for (i 
= 0; i 
< count
; i
++) { 
11031                                 _d 
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
)); 
11033                                         _a 
= (PMAssertStruct 
*)_d
->getBytesNoCopy(); 
11034                                         if ((_a
->assertionBits 
& kIOPMDriverAssertionCPUBit
) && 
11035                                             (_a
->level 
== kIOPMDriverAssertionLevelOn
) && 
11036                                             (_a
->assertCPUStartTime 
!= 0)) { 
11037                                                 // Don't modify PMAssertStruct, leave that 
11038                                                 // for updateCPUBitAccounting() 
11039                                                 SUB_ABSOLUTETIME(&now
, &_a
->assertCPUStartTime
); 
11040                                                 absolutetime_to_nanoseconds(now
, &nsec
); 
11041                                                 nsec 
+= _a
->assertCPUDuration
; 
11042                                                 if (nsec 
> maxAssertCPUDuration
) { 
11043                                                         maxAssertCPUDuration 
= nsec
; 
11044                                                         maxAssertCPUEntryId 
= _a
->registryEntryID
; 
11052         if (maxAssertCPUDuration
) { 
11053                 DLOG("cpu assertion held for %llu ms by 0x%llx\n", 
11054                     (maxAssertCPUDuration 
/ NSEC_PER_MSEC
), maxAssertCPUEntryId
); 
11057         maxAssertCPUDuration 
= 0; 
11058         maxAssertCPUEntryId 
= 0; 
11062 PMAssertionsTracker::publishProperties( void ) 
11064         OSSharedPtr
<OSArray
>             assertionsSummary
; 
11066         if (tabulateConsumerCount 
!= tabulateProducerCount
) { 
11067                 IOLockLock(assertionsArrayLock
); 
11069                 tabulateConsumerCount 
= tabulateProducerCount
; 
11071                 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed" 
11073                 assertionsSummary 
= copyAssertionsArray(); 
11074                 if (assertionsSummary
) { 
11075                         owner
->setProperty(kIOPMAssertionsDriverDetailedKey
, assertionsSummary
.get()); 
11077                         owner
->removeProperty(kIOPMAssertionsDriverDetailedKey
); 
11080                 /* Publish the IOPMrootDomain property "DriverPMAssertions" 
11082                 owner
->setProperty(kIOPMAssertionsDriverKey
, assertionsKernel
, 64); 
11084                 IOLockUnlock(assertionsArrayLock
); 
11088 PMAssertionsTracker::PMAssertStruct 
* 
11089 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id
, int *index
) 
11091         PMAssertStruct      
*_a 
= NULL
; 
11097         if (assertionsArray
 
11098             && (count 
= assertionsArray
->getCount())) { 
11099                 for (i 
= 0; i 
< count
; i
++) { 
11100                         _d 
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
)); 
11102                                 _a 
= (PMAssertStruct 
*)_d
->getBytesNoCopy(); 
11103                                 if (_a 
&& (_id 
== _a
->id
)) { 
11121 /* PMAssertionsTracker::handleCreateAssertion 
11122  * Perform assertion work on the PM workloop. Do not call directly. 
11125 PMAssertionsTracker::handleCreateAssertion(OSData 
*newAssertion
) 
11127         PMAssertStruct 
*assertStruct
; 
11131         if (newAssertion
) { 
11132                 IOLockLock(assertionsArrayLock
); 
11133                 assertStruct 
= (PMAssertStruct 
*) newAssertion
->getBytesNoCopy(); 
11134                 if ((assertStruct
->assertionBits 
& kIOPMDriverAssertionCPUBit
) && 
11135                     (assertStruct
->level 
== kIOPMDriverAssertionLevelOn
)) { 
11136                         assertStruct
->assertCPUStartTime 
= mach_absolute_time(); 
11138                 assertionsArray
->setObject(newAssertion
); 
11139                 IOLockUnlock(assertionsArrayLock
); 
11140                 newAssertion
->release(); 
11144         return kIOReturnSuccess
; 
11147 /* PMAssertionsTracker::createAssertion 
11148  * createAssertion allocates memory for a new PM assertion, and affects system behavior, if 
11152 PMAssertionsTracker::createAssertion( 
11153         IOPMDriverAssertionType which
, 
11154         IOPMDriverAssertionLevel level
, 
11155         IOService 
*serviceID
, 
11156         const char *whoItIs
, 
11157         IOPMDriverAssertionID 
*outID
) 
11159         OSSharedPtr
<OSData
>         dataStore
; 
11160         PMAssertStruct  track
; 
11162         // Warning: trillions and trillions of created assertions may overflow the unique ID. 
11163         track
.id 
= OSIncrementAtomic64((SInt64
*) &issuingUniqueID
); 
11164         track
.level 
= level
; 
11165         track
.assertionBits 
= which
; 
11167         // NB: ownerString is explicitly managed by PMAssertStruct 
11168         // it will be released in `handleReleaseAssertion' below 
11169         track
.ownerString 
= whoItIs 
? OSSymbol::withCString(whoItIs
).detach():nullptr; 
11170         track
.ownerService 
= serviceID
; 
11171         track
.registryEntryID 
= serviceID 
? serviceID
->getRegistryEntryID():0; 
11172         track
.modifiedTime 
= 0; 
11173         pmEventTimeStamp(&track
.createdTime
); 
11174         track
.assertCPUStartTime 
= 0; 
11175         track
.assertCPUDuration 
= 0; 
11177         dataStore 
= OSData::withBytes(&track
, sizeof(PMAssertStruct
)); 
11179                 if (track
.ownerString
) { 
11180                         track
.ownerString
->release(); 
11181                         track
.ownerString 
= NULL
; 
11183                 return kIOReturnNoMemory
; 
11188         if (owner 
&& owner
->pmPowerStateQueue
) { 
11189                 // queue action is responsible for releasing dataStore 
11190                 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionCreate
, (void *)dataStore
.detach()); 
11193         return kIOReturnSuccess
; 
11196 /* PMAssertionsTracker::handleReleaseAssertion 
11197  * Runs in PM workloop. Do not call directly. 
11200 PMAssertionsTracker::handleReleaseAssertion( 
11201         IOPMDriverAssertionID _id
) 
11206         PMAssertStruct  
*assertStruct 
= detailsForID(_id
, &index
); 
11208         if (!assertStruct
) { 
11209                 return kIOReturnNotFound
; 
11212         IOLockLock(assertionsArrayLock
); 
11214         if ((assertStruct
->assertionBits 
& kIOPMDriverAssertionCPUBit
) && 
11215             (assertStruct
->level 
== kIOPMDriverAssertionLevelOn
)) { 
11216                 updateCPUBitAccounting(assertStruct
); 
11219         if (assertStruct
->ownerString
) { 
11220                 assertStruct
->ownerString
->release(); 
11221                 assertStruct
->ownerString 
= NULL
; 
11224         assertionsArray
->removeObject(index
); 
11225         IOLockUnlock(assertionsArrayLock
); 
11228         return kIOReturnSuccess
; 
11231 /* PMAssertionsTracker::releaseAssertion 
11232  * Releases an assertion and affects system behavior if appropiate. 
11233  * Actual work happens on PM workloop. 
11236 PMAssertionsTracker::releaseAssertion( 
11237         IOPMDriverAssertionID _id
) 
11239         if (owner 
&& owner
->pmPowerStateQueue
) { 
11240                 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionRelease
, NULL
, _id
); 
11242         return kIOReturnSuccess
; 
11245 /* PMAssertionsTracker::handleSetAssertionLevel 
11246  * Runs in PM workloop. Do not call directly. 
11249 PMAssertionsTracker::handleSetAssertionLevel( 
11250         IOPMDriverAssertionID    _id
, 
11251         IOPMDriverAssertionLevel _level
) 
11253         PMAssertStruct      
*assertStruct 
= detailsForID(_id
, NULL
); 
11257         if (!assertStruct
) { 
11258                 return kIOReturnNotFound
; 
11261         IOLockLock(assertionsArrayLock
); 
11262         pmEventTimeStamp(&assertStruct
->modifiedTime
); 
11263         if ((assertStruct
->assertionBits 
& kIOPMDriverAssertionCPUBit
) && 
11264             (assertStruct
->level 
!= _level
)) { 
11265                 if (_level 
== kIOPMDriverAssertionLevelOn
) { 
11266                         assertStruct
->assertCPUStartTime 
= mach_absolute_time(); 
11268                         updateCPUBitAccounting(assertStruct
); 
11271         assertStruct
->level 
= _level
; 
11272         IOLockUnlock(assertionsArrayLock
); 
11275         return kIOReturnSuccess
; 
11278 /* PMAssertionsTracker::setAssertionLevel 
11281 PMAssertionsTracker::setAssertionLevel( 
11282         IOPMDriverAssertionID    _id
, 
11283         IOPMDriverAssertionLevel _level
) 
11285         if (owner 
&& owner
->pmPowerStateQueue
) { 
11286                 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionSetLevel
, 
11287                     (void *)(uintptr_t)_level
, _id
); 
11290         return kIOReturnSuccess
; 
11294 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0
) 
11296         IOPMDriverAssertionType new_user_levels 
= *(IOPMDriverAssertionType 
*) arg0
; 
11300         if (new_user_levels 
!= assertionsUser
) { 
11301                 DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser
, new_user_levels
); 
11302                 assertionsUser 
= new_user_levels
; 
11306         return kIOReturnSuccess
; 
11310 PMAssertionsTracker::setUserAssertionLevels( 
11311         IOPMDriverAssertionType new_user_levels
) 
11313         if (gIOPMWorkLoop
) { 
11314                 gIOPMWorkLoop
->runAction( 
11315                         OSMemberFunctionCast( 
11316                                 IOWorkLoop::Action
, 
11318                                 &PMAssertionsTracker::handleSetUserAssertionLevels
), 
11320                         (void *) &new_user_levels
, NULL
, NULL
, NULL
); 
11323         return kIOReturnSuccess
; 
11327 OSSharedPtr
<OSArray
> 
11328 PMAssertionsTracker::copyAssertionsArray(void) 
11332         OSSharedPtr
<OSArray
>     outArray 
= NULL
; 
11334         if (!assertionsArray 
|| (0 == (count 
= assertionsArray
->getCount()))) { 
11337         outArray 
= OSArray::withCapacity(count
); 
11342         for (i 
= 0; i 
< count
; i
++) { 
11343                 PMAssertStruct  
*_a 
= NULL
; 
11345                 OSSharedPtr
<OSDictionary
>    details
; 
11347                 _d 
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
)); 
11348                 if (_d 
&& (_a 
= (PMAssertStruct 
*)_d
->getBytesNoCopy())) { 
11349                         OSSharedPtr
<OSNumber
>        _n
; 
11351                         details 
= OSDictionary::withCapacity(7); 
11356                         outArray
->setObject(details
.get()); 
11358                         _n 
= OSNumber::withNumber(_a
->id
, 64); 
11360                                 details
->setObject(kIOPMDriverAssertionIDKey
, _n
.get()); 
11362                         _n 
= OSNumber::withNumber(_a
->createdTime
, 64); 
11364                                 details
->setObject(kIOPMDriverAssertionCreatedTimeKey
, _n
.get()); 
11366                         _n 
= OSNumber::withNumber(_a
->modifiedTime
, 64); 
11368                                 details
->setObject(kIOPMDriverAssertionModifiedTimeKey
, _n
.get()); 
11370                         _n 
= OSNumber::withNumber((uintptr_t)_a
->registryEntryID
, 64); 
11372                                 details
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, _n
.get()); 
11374                         _n 
= OSNumber::withNumber(_a
->level
, 64); 
11376                                 details
->setObject(kIOPMDriverAssertionLevelKey
, _n
.get()); 
11378                         _n 
= OSNumber::withNumber(_a
->assertionBits
, 64); 
11380                                 details
->setObject(kIOPMDriverAssertionAssertedKey
, _n
.get()); 
11383                         if (_a
->ownerString
) { 
11384                                 details
->setObject(kIOPMDriverAssertionOwnerStringKey
, _a
->ownerString
); 
11390         return os::move(outArray
); 
11393 IOPMDriverAssertionType
 
11394 PMAssertionsTracker::getActivatedAssertions(void) 
11396         return assertionsCombined
; 
11399 IOPMDriverAssertionLevel
 
11400 PMAssertionsTracker::getAssertionLevel( 
11401         IOPMDriverAssertionType type
) 
11403         // FIXME: unused and also wrong 
11404         if (type 
&& ((type 
& assertionsKernel
) == assertionsKernel
)) { 
11405                 return kIOPMDriverAssertionLevelOn
; 
11407                 return kIOPMDriverAssertionLevelOff
; 
11411 //********************************************************************************* 
11412 //********************************************************************************* 
11413 //********************************************************************************* 
11417 pmEventTimeStamp(uint64_t *recordTS
) 
11420         clock_usec_t    tusec
; 
11426         // We assume tsec fits into 32 bits; 32 bits holds enough 
11427         // seconds for 136 years since the epoch in 1970. 
11428         clock_get_calendar_microtime(&tsec
, &tusec
); 
11431         // Pack the sec & microsec calendar time into a uint64_t, for fun. 
11433         *recordTS 
|= (uint32_t)tusec
; 
11434         *recordTS 
|= ((uint64_t)tsec 
<< 32); 
11440 // MARK: IORootParent 
11442 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
11444 OSDefineMetaClassAndFinalStructors(IORootParent
, IOService
) 
11446 // The reason that root domain needs a root parent is to facilitate demand 
11447 // sleep, since a power change from the root parent cannot be vetoed. 
11449 // The above statement is no longer true since root domain now performs 
11450 // demand sleep using overrides. But root parent remains to avoid changing 
11451 // the power tree stacking. Root parent is parked at the max power state. 
11454 static IOPMPowerState patriarchPowerStates
[2] = 
11456         {1, 0, ON_POWER
, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
11457         {1, 0, ON_POWER
, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
11461 IORootParent::initialize( void ) 
11464         gIOPMPSExternalConnectedKey 
= OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey
); 
11465         gIOPMPSExternalChargeCapableKey 
= OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey
); 
11466         gIOPMPSBatteryInstalledKey 
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey
); 
11467         gIOPMPSIsChargingKey 
= OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey
); 
11468         gIOPMPSAtWarnLevelKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey
); 
11469         gIOPMPSAtCriticalLevelKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey
); 
11470         gIOPMPSCurrentCapacityKey 
= OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey
); 
11471         gIOPMPSMaxCapacityKey 
= OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey
); 
11472         gIOPMPSDesignCapacityKey 
= OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey
); 
11473         gIOPMPSTimeRemainingKey 
= OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey
); 
11474         gIOPMPSAmperageKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey
); 
11475         gIOPMPSVoltageKey 
= OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey
); 
11476         gIOPMPSCycleCountKey 
= OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey
); 
11477         gIOPMPSMaxErrKey 
= OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey
); 
11478         gIOPMPSAdapterInfoKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey
); 
11479         gIOPMPSLocationKey 
= OSSymbol::withCStringNoCopy(kIOPMPSLocationKey
); 
11480         gIOPMPSErrorConditionKey 
= OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey
); 
11481         gIOPMPSManufacturerKey 
= OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey
); 
11482         gIOPMPSManufactureDateKey 
= OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey
); 
11483         gIOPMPSModelKey 
= OSSymbol::withCStringNoCopy(kIOPMPSModelKey
); 
11484         gIOPMPSSerialKey 
= OSSymbol::withCStringNoCopy(kIOPMPSSerialKey
); 
11485         gIOPMPSLegacyBatteryInfoKey 
= OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey
); 
11486         gIOPMPSBatteryHealthKey 
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey
); 
11487         gIOPMPSHealthConfidenceKey 
= OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey
); 
11488         gIOPMPSCapacityEstimatedKey 
= OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey
); 
11489         gIOPMPSBatteryChargeStatusKey 
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey
); 
11490         gIOPMPSBatteryTemperatureKey 
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey
); 
11491         gIOPMPSAdapterDetailsKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey
); 
11492         gIOPMPSChargerConfigurationKey 
= OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey
); 
11493         gIOPMPSAdapterDetailsIDKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey
); 
11494         gIOPMPSAdapterDetailsWattsKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey
); 
11495         gIOPMPSAdapterDetailsRevisionKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey
); 
11496         gIOPMPSAdapterDetailsSerialNumberKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey
); 
11497         gIOPMPSAdapterDetailsFamilyKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey
); 
11498         gIOPMPSAdapterDetailsAmperageKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey
); 
11499         gIOPMPSAdapterDetailsDescriptionKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey
); 
11500         gIOPMPSAdapterDetailsPMUConfigurationKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey
); 
11501         gIOPMPSAdapterDetailsSourceIDKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey
); 
11502         gIOPMPSAdapterDetailsErrorFlagsKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey
); 
11503         gIOPMPSAdapterDetailsSharedSourceKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey
); 
11504         gIOPMPSAdapterDetailsCloakedKey 
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey
); 
11505         gIOPMPSInvalidWakeSecondsKey 
= OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey
); 
11506         gIOPMPSPostChargeWaitSecondsKey 
= OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey
); 
11507         gIOPMPSPostDishargeWaitSecondsKey 
= OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey
); 
11511 IORootParent::start( IOService 
* nub 
) 
11513         IOService::start(nub
); 
11514         attachToParent( getRegistryRoot(), gIOPowerPlane 
); 
11516         registerPowerDriver(this, patriarchPowerStates
, 2); 
11522 IORootParent::shutDownSystem( void ) 
11527 IORootParent::restartSystem( void ) 
11532 IORootParent::sleepSystem( void ) 
11537 IORootParent::dozeSystem( void ) 
11542 IORootParent::sleepToDoze( void ) 
11547 IORootParent::wakeSystem( void ) 
11551 OSSharedPtr
<OSObject
> 
11552 IORootParent::copyProperty( const char * aKey
) const 
11554         return IOService::copyProperty(aKey
); 
11558 IOPMrootDomain::getWatchdogTimeout() 
11560         if (gSwdSleepWakeTimeout
) { 
11561                 gSwdSleepTimeout 
= gSwdWakeTimeout 
= gSwdSleepWakeTimeout
; 
11563         if ((pmTracer
->getTracePhase() < kIOPMTracePointSystemSleep
) || 
11564             (pmTracer
->getTracePhase() == kIOPMTracePointDarkWakeEntry
)) { 
11565                 return gSwdSleepTimeout 
? gSwdSleepTimeout 
: WATCHDOG_SLEEP_TIMEOUT
; 
11567                 return gSwdWakeTimeout 
? gSwdWakeTimeout 
: WATCHDOG_WAKE_TIMEOUT
; 
11572 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION) 
11574 IOPMrootDomain::restartWithStackshot() 
11576         takeStackshot(true); 
11578         return kIOReturnSuccess
; 
11582 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger
) 
11584         takeStackshot(wdogTrigger
); 
11588 IOPMrootDomain::tracePhase2String(uint32_t tracePhase
, const char **phaseString
, const char **description
) 
11590         switch (tracePhase
) { 
11591         case kIOPMTracePointSleepStarted
: 
11592                 *phaseString 
= "kIOPMTracePointSleepStarted"; 
11593                 *description 
= "starting sleep"; 
11596         case kIOPMTracePointSleepApplications
: 
11597                 *phaseString 
= "kIOPMTracePointSleepApplications"; 
11598                 *description 
= "notifying applications"; 
11601         case kIOPMTracePointSleepPriorityClients
: 
11602                 *phaseString 
= "kIOPMTracePointSleepPriorityClients"; 
11603                 *description 
= "notifying clients about upcoming system capability changes"; 
11606         case kIOPMTracePointSleepWillChangeInterests
: 
11607                 *phaseString 
= "kIOPMTracePointSleepWillChangeInterests"; 
11608                 *description 
= "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes"; 
11611         case kIOPMTracePointSleepPowerPlaneDrivers
: 
11612                 *phaseString 
= "kIOPMTracePointSleepPowerPlaneDrivers"; 
11613                 *description 
= "calling power state change callbacks"; 
11616         case kIOPMTracePointSleepDidChangeInterests
: 
11617                 *phaseString 
= "kIOPMTracePointSleepDidChangeInterests"; 
11618                 *description 
= "calling rootDomain's clients about rootDomain's state changes"; 
11621         case kIOPMTracePointSleepCapabilityClients
: 
11622                 *phaseString 
= "kIOPMTracePointSleepCapabilityClients"; 
11623                 *description 
= "notifying clients about current system capabilities"; 
11626         case kIOPMTracePointSleepPlatformActions
: 
11627                 *phaseString 
= "kIOPMTracePointSleepPlatformActions"; 
11628                 *description 
= "calling Quiesce/Sleep action callbacks"; 
11631         case kIOPMTracePointSleepCPUs
: 
11633                 *phaseString 
= "kIOPMTracePointSleepCPUs"; 
11634 #if defined(__i386__) || defined(__x86_64__) 
11636                  * We cannot use the getCPUNumber() method to get the cpu number, since 
11637                  * that cpu number is unrelated to the cpu number we need (we need the cpu 
11638                  * number as enumerated by the scheduler, NOT the CPU number enumerated 
11639                  * by ACPIPlatform as the CPUs are enumerated in MADT order). 
11640                  * Instead, pass the Mach processor pointer associated with the current 
11641                  * shutdown target so its associated cpu_id can be used in 
11642                  * processor_to_datastring. 
11644                 if (currentShutdownTarget 
!= NULL 
&& 
11645                     currentShutdownTarget
->getMachProcessor() != NULL
) { 
11646                         const char *sbuf 
= processor_to_datastring("halting all non-boot CPUs", 
11647                             currentShutdownTarget
->getMachProcessor()); 
11648                         *description 
= sbuf
; 
11650                         *description 
= "halting all non-boot CPUs"; 
11653                 *description 
= "halting all non-boot CPUs"; 
11657         case kIOPMTracePointSleepPlatformDriver
: 
11658                 *phaseString 
= "kIOPMTracePointSleepPlatformDriver"; 
11659                 *description 
= "executing platform specific code"; 
11662         case kIOPMTracePointHibernate
: 
11663                 *phaseString 
= "kIOPMTracePointHibernate"; 
11664                 *description 
= "writing the hibernation image"; 
11667         case kIOPMTracePointSystemSleep
: 
11668                 *phaseString 
= "kIOPMTracePointSystemSleep"; 
11669                 *description 
= "in EFI/Bootrom after last point of entry to sleep"; 
11672         case kIOPMTracePointWakePlatformDriver
: 
11673                 *phaseString 
= "kIOPMTracePointWakePlatformDriver"; 
11674                 *description 
= "executing platform specific code"; 
11678         case kIOPMTracePointWakePlatformActions
: 
11679                 *phaseString 
= "kIOPMTracePointWakePlatformActions"; 
11680                 *description 
= "calling Wake action callbacks"; 
11683         case kIOPMTracePointWakeCPUs
: 
11684                 *phaseString 
= "kIOPMTracePointWakeCPUs"; 
11685                 *description 
= "starting non-boot CPUs"; 
11688         case kIOPMTracePointWakeWillPowerOnClients
: 
11689                 *phaseString 
= "kIOPMTracePointWakeWillPowerOnClients"; 
11690                 *description 
= "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients"; 
11693         case kIOPMTracePointWakeWillChangeInterests
: 
11694                 *phaseString 
= "kIOPMTracePointWakeWillChangeInterests"; 
11695                 *description 
= "calling rootDomain's clients about upcoming rootDomain's state changes"; 
11698         case kIOPMTracePointWakeDidChangeInterests
: 
11699                 *phaseString 
= "kIOPMTracePointWakeDidChangeInterests"; 
11700                 *description 
= "calling rootDomain's clients about completed rootDomain's state changes"; 
11703         case kIOPMTracePointWakePowerPlaneDrivers
: 
11704                 *phaseString 
= "kIOPMTracePointWakePowerPlaneDrivers"; 
11705                 *description 
= "calling power state change callbacks"; 
11708         case kIOPMTracePointWakeCapabilityClients
: 
11709                 *phaseString 
= "kIOPMTracePointWakeCapabilityClients"; 
11710                 *description 
= "informing clients about current system capabilities"; 
11713         case kIOPMTracePointWakeApplications
: 
11714                 *phaseString 
= "kIOPMTracePointWakeApplications"; 
11715                 *description 
= "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients"; 
11718         case kIOPMTracePointDarkWakeEntry
: 
11719                 *phaseString 
= "kIOPMTracePointDarkWakeEntry"; 
11720                 *description 
= "entering darkwake on way to sleep"; 
11723         case kIOPMTracePointDarkWakeExit
: 
11724                 *phaseString 
= "kIOPMTracePointDarkWakeExit"; 
11725                 *description 
= "entering fullwake from darkwake"; 
11729                 *phaseString 
= NULL
; 
11730                 *description 
= NULL
; 
11735 IOPMrootDomain::saveFailureData2File() 
11737         unsigned int len 
= 0; 
11738         char  failureStr
[512]; 
11741         OSNumber 
*statusCode
; 
11742         uint64_t pmStatusCode 
= 0; 
11743         uint32_t phaseData 
= 0; 
11744         uint32_t phaseDetail 
= 0; 
11745         bool efiFailure 
= false; 
11747         OSSharedPtr
<OSObject
> statusCodeProp 
= copyProperty(kIOPMSleepWakeFailureCodeKey
); 
11748         statusCode 
= OSDynamicCast(OSNumber
, statusCodeProp
.get()); 
11750                 pmStatusCode 
= statusCode
->unsigned64BitValue(); 
11751                 phaseData 
= pmStatusCode 
& 0xFFFFFFFF; 
11752                 phaseDetail 
= (pmStatusCode 
>> 32) & 0xFFFFFFFF; 
11753                 if ((phaseData 
& 0xFF) == kIOPMTracePointSystemSleep
) { 
11754                         LOG("Sleep Wake failure in EFI\n"); 
11757                         snprintf(failureStr
, sizeof(failureStr
), "Sleep Wake failure in EFI\n\nFailure code:: 0x%08x 0x%08x\n\nPlease IGNORE the below stackshot\n", phaseDetail
, phaseData
); 
11758                         len 
= (typeof(len
))strnlen(failureStr
, sizeof(failureStr
)); 
11763                 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic
, NULL
, &len
)) { 
11764                         swd_flags 
|= SWD_BOOT_BY_SW_WDOG
; 
11765                         PERemoveNVRAMProperty(kIOSleepWakeFailurePanic
); 
11766                         // dump panic will handle saving nvram data 
11770                 /* Keeping this around for capturing data during power 
11773                 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString
, NULL
, &len
)) { 
11774                         DLOG("No sleep wake failure string\n"); 
11778                         DLOG("Ignoring zero byte SleepWake failure string\n"); 
11782                 // if PMStatus code is zero, delete stackshot and return 
11784                         if (((pmStatusCode 
& 0xFFFFFFFF) & 0xFF) == 0) { 
11785                                 // there was no sleep wake failure 
11786                                 // this can happen if delete stackshot was called 
11787                                 // before take stackshot completed. Let us delete any 
11788                                 // sleep wake failure data in nvram 
11789                                 DLOG("Deleting stackshot on successful wake\n"); 
11795                 if (len 
> sizeof(failureStr
)) { 
11796                         len 
= sizeof(failureStr
); 
11799                 PEReadNVRAMProperty(kIOSleepWakeFailureString
, failureStr
, &len
); 
11801         if (failureStr
[0] != 0) { 
11802                 error 
= sleepWakeDebugSaveFile(kSleepWakeFailureStringFile
, failureStr
, len
); 
11804                         DLOG("Failed to save SleepWake failure string to file. error:%d\n", error
); 
11806                         DLOG("Saved SleepWake failure string to file.\n"); 
11810         if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) { 
11815                 unsigned int len 
= 0; 
11817                 char nvram_var_name_buffer
[20]; 
11818                 unsigned int concat_len 
= 0; 
11819                 swd_hdr      
*hdr 
= NULL
; 
11822                 hdr 
= (swd_hdr 
*)swd_buffer
; 
11823                 outbuf 
= (char *)hdr 
+ hdr
->spindump_offset
; 
11824                 OSBoundedArrayRef
<char> boundedOutBuf(outbuf
, hdr
->alloc_size 
- hdr
->spindump_offset
); 
11826                 for (int i 
= 0; i 
< 8; i
++) { 
11827                         snprintf(nvram_var_name_buffer
, sizeof(nvram_var_name_buffer
), "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, i 
+ 1); 
11828                         if (!PEReadNVRAMProperty(nvram_var_name_buffer
, NULL
, &len
)) { 
11829                                 LOG("No SleepWake blob to read beyond chunk %d\n", i
); 
11832                         if (PEReadNVRAMProperty(nvram_var_name_buffer
, boundedOutBuf
.slice(concat_len
, len
).data(), &len
) == FALSE
) { 
11833                                 PERemoveNVRAMProperty(nvram_var_name_buffer
); 
11834                                 LOG("Could not read the property :-(\n"); 
11837                         PERemoveNVRAMProperty(nvram_var_name_buffer
); 
11840                 LOG("Concatenated length for the SWD blob %d\n", concat_len
); 
11843                         error 
= sleepWakeDebugSaveFile(kSleepWakeStacksFilename
, outbuf
, concat_len
); 
11845                                 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error
); 
11847                                 LOG("Saved SleepWake zipped data to file.\n"); 
11850                         // There is a sleep wake failure string but no stackshot 
11851                         // Write a placeholder stacks file so that swd runs 
11852                         snprintf(outbuf
, 20, "%s", "No stackshot data\n"); 
11853                         error 
= sleepWakeDebugSaveFile(kSleepWakeStacksFilename
, outbuf
, 20); 
11855                                 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error
); 
11857                                 LOG("Saved SleepWake zipped data to file.\n"); 
11861                 LOG("No buffer allocated to save failure stackshot\n"); 
11865         gRootDomain
->swd_lock 
= 0; 
11867         PERemoveNVRAMProperty(kIOSleepWakeFailureString
); 
11873 IOPMrootDomain::getFailureData(thread_t 
*thread
, char *failureStr
, size_t strLen
) 
11875         OSSharedPtr
<IORegistryIterator
>    iter
; 
11876         OSSharedPtr
<const OSSymbol
>        kextName 
= NULL
; 
11877         IORegistryEntry 
*       entry
; 
11879         bool                    nodeFound 
= false; 
11881         const void *            callMethod 
= NULL
; 
11882         const char *            objectName 
= NULL
; 
11883         uint32_t                timeout 
= getWatchdogTimeout(); 
11884         const char *            phaseString 
= NULL
; 
11885         const char *            phaseDescription 
= NULL
; 
11887         IOPMServiceInterestNotifier 
*notifier 
= OSDynamicCast(IOPMServiceInterestNotifier
, notifierObject
.get()); 
11888         uint32_t tracePhase 
= pmTracer
->getTracePhase(); 
11891         if ((tracePhase 
< kIOPMTracePointSystemSleep
) || (tracePhase 
== kIOPMTracePointDarkWakeEntry
)) { 
11892                 snprintf(failureStr
, strLen
, "Sleep transition timed out after %d seconds", timeout
); 
11894                 snprintf(failureStr
, strLen
, "Wake transition timed out after %d seconds", timeout
); 
11896         tracePhase2String(tracePhase
, &phaseString
, &phaseDescription
); 
11898         if (notifierThread
) { 
11899                 if (notifier 
&& (notifier
->identifier
)) { 
11900                         objectName 
= notifier
->identifier
->getCStringNoCopy(); 
11902                 *thread 
= notifierThread
; 
11904                 iter 
= IORegistryIterator::iterateOver( 
11905                         getPMRootDomain(), gIOPowerPlane
, kIORegistryIterateRecursively
); 
11908                         while ((entry 
= iter
->getNextObject())) { 
11909                                 node 
= OSDynamicCast(IOService
, entry
); 
11913                                 if (OSDynamicCast(IOPowerConnection
, node
)) { 
11917                                 if (node
->getBlockingDriverCall(thread
, &callMethod
)) { 
11924                         kextName 
= copyKextIdentifierWithAddress((vm_address_t
) callMethod
); 
11926                                 objectName 
= kextName
->getCStringNoCopy(); 
11930         if (phaseDescription
) { 
11931                 strlcat(failureStr
, " while ", strLen
); 
11932                 strlcat(failureStr
, phaseDescription
, strLen
); 
11933                 strlcat(failureStr
, ".", strLen
); 
11936                 strlcat(failureStr
, " Suspected bundle: ", strLen
); 
11937                 strlcat(failureStr
, objectName
, strLen
); 
11938                 strlcat(failureStr
, ".", strLen
); 
11941                 char threadName
[40]; 
11942                 snprintf(threadName
, sizeof(threadName
), " Thread 0x%llx.", thread_tid(*thread
)); 
11943                 strlcat(failureStr
, threadName
, strLen
); 
11946         DLOG("%s\n", failureStr
); 
11949 struct swd_stackshot_compressed_data 
{ 
11950         z_output_func   zoutput
; 
11952         uint64_t                totalbytes
; 
11953         uint64_t                lastpercent
; 
11955         unsigned                outremain
; 
11960 struct swd_stackshot_compressed_data swd_zip_var 
= { }; 
11963 swd_zs_alloc(void *__unused ref
, u_int items
, u_int size
) 
11966         LOG("Alloc in zipping %d items of size %d\n", items
, size
); 
11968         result 
= (void *)(swd_zs_zmem 
+ swd_zs_zoffset
); 
11969         swd_zs_zoffset 
+= ~31L & (31 + (items 
* size
)); // 32b align for vector crc 
11970         LOG("Offset %zu\n", swd_zs_zoffset
); 
11975 swd_zinput(z_streamp strm
, Bytef 
*buf
, unsigned size
) 
11979         len 
= strm
->avail_in
; 
11988         if (strm
->next_in 
!= (Bytef 
*) strm
) { 
11989                 memcpy(buf
, strm
->next_in
, len
); 
11994         strm
->adler 
= z_crc32(strm
->adler
, buf
, len
); 
11996         strm
->avail_in 
-= len
; 
11997         strm
->next_in  
+= len
; 
11998         strm
->total_in 
+= len
; 
12004 swd_zoutput(z_streamp strm
, Bytef 
*buf
, unsigned len
) 
12006         unsigned int i 
= 0; 
12007         // if outlen > max size don't add to the buffer 
12008         assert(buf 
!= NULL
); 
12010                 if (swd_zip_var
.outlen 
+ len 
> SWD_COMPRESSED_BUFSIZE
) { 
12011                         LOG("No space to GZIP... not writing to NVRAM\n"); 
12015         for (i 
= 0; i 
< len
; i
++) { 
12016                 *(swd_zip_var
.outbuf 
+ swd_zip_var
.outlen 
+ i
) = *(buf 
+ i
); 
12018         swd_zip_var
.outlen 
+= len
; 
12023 swd_zs_free(void * __unused ref
, void * __unused ptr
) 
12028 swd_compress(char *inPtr
, char *outPtr
, size_t numBytes
) 
12033         if (((unsigned int) numBytes
) != numBytes
) { 
12037         if (!swd_zs
.zalloc
) { 
12038                 swd_zs
.zalloc 
= swd_zs_alloc
; 
12039                 swd_zs
.zfree 
= swd_zs_free
; 
12040                 if (deflateInit2(&swd_zs
, Z_BEST_SPEED
, Z_DEFLATED
, wbits 
+ 16, memlevel
, Z_DEFAULT_STRATEGY
)) { 
12041                         // allocation failed 
12042                         bzero(&swd_zs
, sizeof(swd_zs
)); 
12043                         // swd_zs_zoffset = 0; 
12045                         LOG("PMRD inited the zlib allocation routines\n"); 
12049         swd_zip_var
.zipped 
= 0; 
12050         swd_zip_var
.totalbytes 
= 0; // should this be the max that we have? 
12051         swd_zip_var
.lastpercent 
= 0; 
12052         swd_zip_var
.error 
= kIOReturnSuccess
; 
12053         swd_zip_var
.outremain 
= 0; 
12054         swd_zip_var
.outlen 
= 0; 
12055         swd_zip_var
.writes 
= 0; 
12056         swd_zip_var
.outbuf 
= (Bytef 
*)outPtr
; 
12058         swd_zip_var
.totalbytes 
= numBytes
; 
12060         swd_zs
.avail_in 
= 0; 
12061         swd_zs
.next_in 
= NULL
; 
12062         swd_zs
.avail_out 
= 0; 
12063         swd_zs
.next_out 
= NULL
; 
12065         deflateResetWithIO(&swd_zs
, swd_zinput
, swd_zoutput
); 
12071         while (swd_zip_var
.error 
>= 0) { 
12072                 if (!zs
->avail_in
) { 
12073                         zs
->next_in 
= (unsigned char *)inPtr 
? (Bytef 
*)inPtr 
: (Bytef 
*)zs
; /* zero marker? */ 
12074                         zs
->avail_in 
= (unsigned int) numBytes
; 
12076                 if (!zs
->avail_out
) { 
12077                         zs
->next_out 
= (Bytef 
*)zs
; 
12078                         zs
->avail_out 
= UINT32_MAX
; 
12080                 zr 
= deflate(zs
, Z_NO_FLUSH
); 
12081                 if (Z_STREAM_END 
== zr
) { 
12085                         LOG("ZERR %d\n", zr
); 
12086                         swd_zip_var
.error 
= zr
; 
12088                         if (zs
->total_in 
== numBytes
) { 
12094         //now flush the stream 
12095         while (swd_zip_var
.error 
>= 0) { 
12096                 if (!zs
->avail_out
) { 
12097                         zs
->next_out 
= (Bytef 
*)zs
; 
12098                         zs
->avail_out 
= UINT32_MAX
; 
12100                 zr 
= deflate(zs
, Z_FINISH
); 
12101                 if (Z_STREAM_END 
== zr
) { 
12105                         LOG("ZERR %d\n", zr
); 
12106                         swd_zip_var
.error 
= zr
; 
12108                         if (zs
->total_in 
== numBytes
) { 
12109                                 LOG("Total output size %d\n", swd_zip_var
.outlen
); 
12115         return swd_zip_var
.outlen
; 
12119 IOPMrootDomain::deleteStackshot() 
12121         if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) { 
12122                 // takeStackshot hasn't completed 
12125         LOG("Deleting any sleepwake failure data in nvram\n"); 
12127         PERemoveNVRAMProperty(kIOSleepWakeFailureString
); 
12128         char nvram_var_name_buf
[20]; 
12129         for (int i 
= 0; i 
< 8; i
++) { 
12130                 snprintf(nvram_var_name_buf
, sizeof(nvram_var_name_buf
), "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, i 
+ 1); 
12131                 if (PERemoveNVRAMProperty(nvram_var_name_buf
) == false) { 
12132                         LOG("Removing %s returned false\n", nvram_var_name_buf
); 
12135         // force NVRAM sync 
12136         if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey
, kIONVRAMSyncNowPropertyKey
, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey
)) == false) { 
12137                 DLOG("Failed to force nvram sync\n"); 
12139         gRootDomain
->swd_lock 
= 0; 
12143 IOPMrootDomain::takeStackshot(bool wdogTrigger
) 
12145         swd_hdr 
*                hdr 
= NULL
; 
12149         kern_return_t            kr 
= KERN_SUCCESS
; 
12154         uint32_t                 bytesRemaining
; 
12155         unsigned                 bytesWritten 
= 0; 
12157         char                     failureStr
[512]; 
12158         thread_t                 thread 
= NULL
; 
12159         const char *             swfPanic 
= "swfPanic"; 
12164 #if defined(__i386__) || defined(__x86_64__) 
12165         const bool               concise 
= false; 
12167         const bool               concise 
= true; 
12170         if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) { 
12175         if ((kIOSleepWakeWdogOff 
& gIOKitDebug
) || systemBooting 
|| systemShutdown 
|| gWillShutdown
) { 
12180                 getFailureData(&thread
, failureStr
, sizeof(failureStr
)); 
12182                 if (concise 
|| (PEGetCoprocessorVersion() >= kCoprocessorVersion2
)) { 
12183                         goto skip_stackshot
; 
12188                 clock_get_uptime(&now
); 
12189                 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
); 
12190                 absolutetime_to_nanoseconds(now
, &nsec
); 
12191                 snprintf(failureStr
, sizeof(failureStr
), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec
) / NSEC_PER_MSEC
))); 
12194         if (swd_buffer 
== NULL
) { 
12195                 sleepWakeDebugMemAlloc(); 
12196                 if (swd_buffer 
== NULL
) { 
12200         hdr 
= (swd_hdr 
*)swd_buffer
; 
12201         bufSize 
= hdr
->alloc_size
; 
12203         dstAddr 
= (char*)hdr 
+ hdr
->spindump_offset
; 
12204         flags 
= STACKSHOT_KCDATA_FORMAT 
| STACKSHOT_NO_IO_STATS 
| STACKSHOT_SAVE_KEXT_LOADINFO 
| STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY 
| STACKSHOT_THREAD_WAITINFO
; 
12205         /* If not wdogTrigger only take kernel tasks stackshot 
12213         /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS 
12214          * If we run out of space, take stackshot with only kernel task 
12216         while (success 
== 0 && cnt 
< max_cnt
) { 
12217                 bytesRemaining 
= bufSize 
- hdr
->spindump_offset
; 
12219                 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining
); 
12221                 size 
= bytesRemaining
; 
12222                 kr 
= stack_snapshot_from_kernel(pid
, dstAddr
, size
, flags
, 0, 0, &bytesWritten
); 
12223                 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n", 
12224                     kr
, pid
, size
, flags
, bytesWritten
); 
12225                 if (kr 
== KERN_INSUFFICIENT_BUFFER_SIZE
) { 
12229                                 LOG("Insufficient buffer size for only kernel task\n"); 
12233                 if (kr 
== KERN_SUCCESS
) { 
12234                         if (bytesWritten 
== 0) { 
12235                                 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr
, size
, flags
); 
12238                         bytesRemaining 
-= bytesWritten
; 
12239                         hdr
->spindump_size 
= (bufSize 
- bytesRemaining 
- hdr
->spindump_offset
); 
12241                         memset(hdr
->reason
, 0x20, sizeof(hdr
->reason
)); 
12243                         // Compress stackshot and save to NVRAM 
12245                                 char *outbuf 
= (char *)swd_compressed_buffer
; 
12247                                 int num_chunks 
= 0; 
12248                                 int max_chunks 
= 0; 
12250                                 char nvram_var_name_buffer
[20]; 
12252                                 outlen 
= swd_compress((char*)hdr 
+ hdr
->spindump_offset
, outbuf
, bytesWritten
); 
12255                                         max_chunks 
= outlen 
/ (2096 - 200); 
12256                                         leftover 
= outlen 
% (2096 - 200); 
12258                                         if (max_chunks 
< 8) { 
12259                                                 for (num_chunks 
= 0; num_chunks 
< max_chunks
; num_chunks
++) { 
12260                                                         snprintf(nvram_var_name_buffer
, sizeof(nvram_var_name_buffer
), "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, num_chunks 
+ 1); 
12261                                                         if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer
, (outbuf 
+ (num_chunks 
* (2096 - 200))), (2096 - 200)) == FALSE
) { 
12262                                                                 LOG("Failed to update NVRAM %d\n", num_chunks
); 
12267                                                         snprintf(nvram_var_name_buffer
, sizeof(nvram_var_name_buffer
), "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, num_chunks 
+ 1); 
12268                                                         if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer
, (outbuf 
+ (num_chunks 
* (2096 - 200))), leftover
) == FALSE
) { 
12269                                                                 LOG("Failed to update NVRAM with leftovers\n"); 
12273                                                 LOG("Successfully saved stackshot to NVRAM\n"); 
12275                                                 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen
); 
12279                                                         LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen
); 
12288         if (failureStr
[0]) { 
12289                 // append sleep-wake failure code 
12290                 char traceCode
[80]; 
12291                 snprintf(traceCode
, sizeof(traceCode
), "\nFailure code:: 0x%08x %08x\n", 
12292                     pmTracer
->getTraceData(), pmTracer
->getTracePhase()); 
12293                 strlcat(failureStr
, traceCode
, sizeof(failureStr
)); 
12294                 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString
, failureStr
, (unsigned int) strnlen(failureStr
, sizeof(failureStr
))) == false) { 
12295                         DLOG("Failed to write SleepWake failure string\n"); 
12299         // force NVRAM sync 
12300         if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey
, kIONVRAMSyncNowPropertyKey
, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey
)) == false) { 
12301                 DLOG("Failed to force nvram sync\n"); 
12306                 if (PEGetCoprocessorVersion() < kCoprocessorVersion2
) { 
12307                         if (swd_flags 
& SWD_BOOT_BY_SW_WDOG
) { 
12308                                 // If current boot is due to this watch dog trigger restart in previous boot, 
12309                                 // then don't trigger again until at least 1 successful sleep & wake. 
12310                                 if (!(sleepCnt 
&& (displayWakeCnt 
|| darkWakeCnt
))) { 
12311                                         LOG("Shutting down due to repeated Sleep/Wake failures\n"); 
12312                                         if (!tasksSuspended
) { 
12313                                                 tasksSuspended 
= TRUE
; 
12314                                                 updateTasksSuspend(); 
12316                                         PEHaltRestart(kPEHaltCPU
); 
12320                         if (gSwdPanic 
== 0) { 
12321                                 LOG("Calling panic prevented by swd_panic boot-args. Calling restart"); 
12322                                 if (!tasksSuspended
) { 
12323                                         tasksSuspended 
= TRUE
; 
12324                                         updateTasksSuspend(); 
12326                                 PEHaltRestart(kPERestartCPU
); 
12329                 if (!concise 
&& (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic
, swfPanic
, (unsigned int) strlen(swfPanic
)) == false)) { 
12330                         DLOG("Failed to write SleepWake failure panic key\n"); 
12332 #if defined(__x86_64__) 
12334                         panic_with_thread_context(0, NULL
, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT
, thread
, "%s", failureStr
); 
12336 #endif /* defined(__x86_64__) */ 
12338                         panic_with_options(0, NULL
, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT
, "%s", failureStr
); 
12341                 gRootDomain
->swd_lock 
= 0; 
12347 IOPMrootDomain::sleepWakeDebugMemAlloc() 
12349         vm_size_t    size 
= SWD_STACKSHOT_SIZE 
+ SWD_COMPRESSED_BUFSIZE 
+ SWD_ZLIB_BUFSIZE
; 
12351         swd_hdr      
*hdr 
= NULL
; 
12352         void         *bufPtr 
= NULL
; 
12354         OSSharedPtr
<IOBufferMemoryDescriptor
>  memDesc
; 
12357         if (kIOSleepWakeWdogOff 
& gIOKitDebug
) { 
12361         if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) { 
12365         memDesc 
= IOBufferMemoryDescriptor::inTaskWithOptions( 
12366                 kernel_task
, kIODirectionIn 
| kIOMemoryMapperNone
, 
12368         if (memDesc 
== NULL
) { 
12369                 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n"); 
12373         bufPtr 
= memDesc
->getBytesNoCopy(); 
12375         // Carve out memory for zlib routines 
12376         swd_zs_zmem 
= (vm_offset_t
)bufPtr
; 
12377         bufPtr 
= (char *)bufPtr 
+ SWD_ZLIB_BUFSIZE
; 
12379         // Carve out memory for compressed stackshots 
12380         swd_compressed_buffer 
= bufPtr
; 
12381         bufPtr 
= (char *)bufPtr 
+ SWD_COMPRESSED_BUFSIZE
; 
12383         // Remaining is used for holding stackshot 
12384         hdr 
= (swd_hdr 
*)bufPtr
; 
12385         memset(hdr
, 0, sizeof(swd_hdr
)); 
12387         hdr
->signature 
= SWD_HDR_SIGNATURE
; 
12388         hdr
->alloc_size 
= SWD_STACKSHOT_SIZE
; 
12390         hdr
->spindump_offset 
= sizeof(swd_hdr
); 
12391         swd_buffer 
= (void *)hdr
; 
12392         swd_memDesc 
= os::move(memDesc
); 
12393         DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr
->alloc_size
, hdr
->spindump_offset
); 
12396         gRootDomain
->swd_lock 
= 0; 
12400 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc() 
12403         vm_size_t    size 
= SWD_SPINDUMP_SIZE
; 
12405         swd_hdr      
*hdr 
= NULL
; 
12407         OSSharedPtr
<IOBufferMemoryDescriptor
>  memDesc
; 
12409         if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) { 
12413         memDesc 
= IOBufferMemoryDescriptor::inTaskWithOptions( 
12414                 kernel_task
, kIODirectionIn 
| kIOMemoryMapperNone
, 
12415                 SWD_SPINDUMP_SIZE
); 
12417         if (memDesc 
== NULL
) { 
12418                 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n"); 
12423         hdr 
= (swd_hdr 
*)memDesc
->getBytesNoCopy(); 
12424         memset(hdr
, 0, sizeof(swd_hdr
)); 
12426         hdr
->signature 
= SWD_HDR_SIGNATURE
; 
12427         hdr
->alloc_size 
= size
; 
12429         hdr
->spindump_offset 
= sizeof(swd_hdr
); 
12430         swd_spindump_buffer 
= (void *)hdr
; 
12431         swd_spindump_memDesc 
= os::move(memDesc
); 
12434         gRootDomain
->swd_lock 
= 0; 
12435 #endif /* UNUSED */ 
12439 IOPMrootDomain::sleepWakeDebugEnableWdog() 
12444 IOPMrootDomain::sleepWakeDebugIsWdogEnabled() 
12446         return !systemBooting 
&& !systemShutdown 
&& !gWillShutdown
; 
12450 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile() 
12452         swd_hdr 
*hdr 
= NULL
; 
12453         errno_t error 
= EIO
; 
12455         if (swd_spindump_buffer 
&& gSpinDumpBufferFull
) { 
12456                 hdr 
= (swd_hdr 
*)swd_spindump_buffer
; 
12458                 error 
= sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump", 
12459                     (char*)hdr 
+ hdr
->spindump_offset
, hdr
->spindump_size
); 
12465                 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump", 
12466                     (char*)hdr 
+ offsetof(swd_hdr
, UUID
), 
12467                     sizeof(swd_hdr
) - offsetof(swd_hdr
, UUID
)); 
12469                 gSpinDumpBufferFull 
= false; 
12474 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name
, char *buf
, int len
) 
12476         struct vnode         
*vp 
= NULL
; 
12477         vfs_context_t        ctx 
= vfs_context_create(vfs_context_current()); 
12478         kauth_cred_t         cred 
= vfs_context_ucred(ctx
); 
12479         struct vnode_attr    va
; 
12480         errno_t      error 
= EIO
; 
12482         if (vnode_open(name
, (O_CREAT 
| FWRITE 
| O_NOFOLLOW
), 
12483             S_IRUSR 
| S_IRGRP 
| S_IROTH
, VNODE_LOOKUP_NOFOLLOW
, &vp
, ctx
) != 0) { 
12484                 LOG("Failed to open the file %s\n", name
); 
12485                 swd_flags 
|= SWD_FILEOP_ERROR
; 
12489         VATTR_WANTED(&va
, va_nlink
); 
12490         /* Don't dump to non-regular files or files with links. */ 
12491         if (vp
->v_type 
!= VREG 
|| 
12492             vnode_getattr(vp
, &va
, ctx
) || va
.va_nlink 
!= 1) { 
12493                 LOG("Bailing as this is not a regular file\n"); 
12494                 swd_flags 
|= SWD_FILEOP_ERROR
; 
12498         VATTR_SET(&va
, va_data_size
, 0); 
12499         vnode_setattr(vp
, &va
, ctx
); 
12503                 error 
= vn_rdwr(UIO_WRITE
, vp
, buf
, len
, 0, 
12504                     UIO_SYSSPACE
, IO_NODELOCKED 
| IO_UNIT
, cred
, (int *) NULL
, vfs_context_proc(ctx
)); 
12506                         LOG("Failed to save sleep wake log. err 0x%x\n", error
); 
12507                         swd_flags 
|= SWD_FILEOP_ERROR
; 
12509                         DLOG("Saved %d bytes to file %s\n", len
, name
); 
12515                 vnode_close(vp
, FWRITE
, ctx
); 
12518                 vfs_context_rele(ctx
); 
12524 #else /* defined(__i386__) || defined(__x86_64__) */ 
12527 IOPMrootDomain::sleepWakeDebugTrig(bool restart
) 
12530                 if (gSwdPanic 
== 0) { 
12533                 panic("Sleep/Wake hang detected"); 
12539 IOPMrootDomain::takeStackshot(bool restart
) 
12541 #pragma unused(restart) 
12545 IOPMrootDomain::deleteStackshot() 
12550 IOPMrootDomain::sleepWakeDebugMemAlloc() 
12555 IOPMrootDomain::saveFailureData2File() 
12560 IOPMrootDomain::sleepWakeDebugEnableWdog() 
12565 IOPMrootDomain::sleepWakeDebugIsWdogEnabled() 
12571 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile() 
12576 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name
, char *buf
, int len
) 
12581 #endif /* defined(__i386__) || defined(__x86_64__) */