2 * Copyright (c) 1998-2019 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@
28 #include <libkern/c++/OSKext.h>
29 #include <libkern/c++/OSMetaClass.h>
30 #include <libkern/OSAtomic.h>
31 #include <libkern/OSDebug.h>
32 #include <IOKit/IOWorkLoop.h>
33 #include <IOKit/IOCommandGate.h>
34 #include <IOKit/IOTimerEventSource.h>
35 #include <IOKit/IOPlatformExpert.h>
36 #include <IOKit/IOCPU.h>
37 #include <IOKit/IOKitDebug.h>
38 #include <IOKit/IOTimeStamp.h>
39 #include <IOKit/pwr_mgt/IOPMlog.h>
40 #include <IOKit/pwr_mgt/RootDomain.h>
41 #include <IOKit/pwr_mgt/IOPMPrivate.h>
42 #include <IOKit/IODeviceTreeSupport.h>
43 #include <IOKit/IOMessage.h>
44 #include <IOKit/IOReturn.h>
45 #include <IOKit/IONVRAM.h>
46 #include "RootDomainUserClient.h"
47 #include "IOKit/pwr_mgt/IOPowerConnection.h"
48 #include "IOPMPowerStateQueue.h"
49 #include <IOKit/IOCatalogue.h>
50 #include <IOKit/IOReportMacros.h>
51 #include <IOKit/IOLib.h>
52 #include <IOKit/IOKitKeys.h>
53 #include "IOKitKernelInternal.h"
55 #include <IOKit/IOHibernatePrivate.h>
57 #include <console/video_console.h>
58 #include <sys/syslog.h>
59 #include <sys/sysctl.h>
60 #include <sys/vnode.h>
61 #include <sys/vnode_internal.h>
62 #include <sys/fcntl.h>
64 #include <pexpert/protos.h>
65 #include <AssertMacros.h>
68 #include "IOServicePrivate.h" // _IOServiceInterestNotifier
69 #include "IOServicePMPrivate.h"
71 #include <libkern/zlib.h>
74 #include <mach/shared_region.h>
75 #include <kern/clock.h>
78 #if defined(__i386__) || defined(__x86_64__)
80 #include "IOPMrootDomainInternal.h"
81 const char *processor_to_datastring(const char *prefix
, processor_t target_processor
);
85 #define kIOPMrootDomainClass "IOPMrootDomain"
86 #define LOG_PREFIX "PMRD: "
90 do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
93 do { kprintf(LOG_PREFIX x); } while (false)
95 #if DEVELOPMENT || DEBUG
96 #define DEBUG_LOG(x...) do { \
97 if (kIOLogPMRootDomain & gIOKitDebug) \
98 kprintf(LOG_PREFIX x); \
99 os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \
102 #define DEBUG_LOG(x...)
105 #define DLOG(x...) do { \
106 if (kIOLogPMRootDomain & gIOKitDebug) \
107 kprintf(LOG_PREFIX x); \
109 os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
112 #define DMSG(x...) do { \
113 if (kIOLogPMRootDomain & gIOKitDebug) { \
114 kprintf(LOG_PREFIX x); \
121 #define CHECK_THREAD_CONTEXT
122 #ifdef CHECK_THREAD_CONTEXT
123 static IOWorkLoop
* gIOPMWorkLoop
= NULL
;
124 #define ASSERT_GATED() \
126 if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
127 panic("RootDomain: not inside PM gate"); \
131 #define ASSERT_GATED()
132 #endif /* CHECK_THREAD_CONTEXT */
134 #define CAP_LOSS(c) \
135 (((_pendingCapability & (c)) == 0) && \
136 ((_currentCapability & (c)) != 0))
138 #define CAP_GAIN(c) \
139 (((_currentCapability & (c)) == 0) && \
140 ((_pendingCapability & (c)) != 0))
142 #define CAP_CHANGE(c) \
143 (((_currentCapability ^ _pendingCapability) & (c)) != 0)
145 #define CAP_CURRENT(c) \
146 ((_currentCapability & (c)) != 0)
148 #define CAP_HIGHEST(c) \
149 ((_highestCapability & (c)) != 0)
151 #if defined(__i386__) || defined(__x86_64__)
152 #define DARK_TO_FULL_EVALUATE_CLAMSHELL 1
155 // Event types for IOPMPowerStateQueue::submitPowerEvent()
157 kPowerEventFeatureChanged
= 1, // 1
158 kPowerEventReceivedPowerNotification
, // 2
159 kPowerEventSystemBootCompleted
, // 3
160 kPowerEventSystemShutdown
, // 4
161 kPowerEventUserDisabledSleep
, // 5
162 kPowerEventRegisterSystemCapabilityClient
, // 6
163 kPowerEventRegisterKernelCapabilityClient
, // 7
164 kPowerEventPolicyStimulus
, // 8
165 kPowerEventAssertionCreate
, // 9
166 kPowerEventAssertionRelease
, // 10
167 kPowerEventAssertionSetLevel
, // 11
168 kPowerEventQueueSleepWakeUUID
, // 12
169 kPowerEventPublishSleepWakeUUID
, // 13
170 kPowerEventSetDisplayPowerOn
// 14
173 // For evaluatePolicy()
174 // List of stimuli that affects the root domain policy.
176 kStimulusDisplayWranglerSleep
, // 0
177 kStimulusDisplayWranglerWake
, // 1
178 kStimulusAggressivenessChanged
, // 2
179 kStimulusDemandSystemSleep
, // 3
180 kStimulusAllowSystemSleepChanged
, // 4
181 kStimulusDarkWakeActivityTickle
, // 5
182 kStimulusDarkWakeEntry
, // 6
183 kStimulusDarkWakeReentry
, // 7
184 kStimulusDarkWakeEvaluate
, // 8
185 kStimulusNoIdleSleepPreventers
, // 9
186 kStimulusEnterUserActiveState
, // 10
187 kStimulusLeaveUserActiveState
// 11
191 IOReturn
OSKextSystemSleepOrWake( UInt32
);
193 extern "C" ppnum_t
pmap_find_phys(pmap_t pmap
, addr64_t va
);
194 extern "C" addr64_t
kvtophys(vm_offset_t va
);
195 extern "C" boolean_t
kdp_has_polled_corefile();
197 static void idleSleepTimerExpired( thread_call_param_t
, thread_call_param_t
);
198 static void notifySystemShutdown( IOService
* root
, uint32_t messageType
);
199 static void handleAggressivesFunction( thread_call_param_t
, thread_call_param_t
);
200 static void pmEventTimeStamp(uint64_t *recordTS
);
201 static void powerButtonUpCallout( thread_call_param_t
, thread_call_param_t
);
202 static void powerButtonDownCallout( thread_call_param_t
, thread_call_param_t
);
204 static int IOPMConvertSecondsToCalendar(long secs
, IOPMCalendarStruct
* dt
);
205 static long IOPMConvertCalendarToSeconds(const IOPMCalendarStruct
* dt
);
206 #define YMDTF "%04d/%02d/%d %02d:%02d:%02d"
207 #define YMDT(cal) ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second
209 // "IOPMSetSleepSupported" callPlatformFunction name
210 static const OSSymbol
*sleepSupportedPEFunction
= NULL
;
211 static const OSSymbol
*sleepMessagePEFunction
= NULL
;
213 static const OSSymbol
* gIOPMPSExternalConnectedKey
;
214 static const OSSymbol
* gIOPMPSExternalChargeCapableKey
;
215 static const OSSymbol
* gIOPMPSBatteryInstalledKey
;
216 static const OSSymbol
* gIOPMPSIsChargingKey
;
217 static const OSSymbol
* gIOPMPSAtWarnLevelKey
;
218 static const OSSymbol
* gIOPMPSAtCriticalLevelKey
;
219 static const OSSymbol
* gIOPMPSCurrentCapacityKey
;
220 static const OSSymbol
* gIOPMPSMaxCapacityKey
;
221 static const OSSymbol
* gIOPMPSDesignCapacityKey
;
222 static const OSSymbol
* gIOPMPSTimeRemainingKey
;
223 static const OSSymbol
* gIOPMPSAmperageKey
;
224 static const OSSymbol
* gIOPMPSVoltageKey
;
225 static const OSSymbol
* gIOPMPSCycleCountKey
;
226 static const OSSymbol
* gIOPMPSMaxErrKey
;
227 static const OSSymbol
* gIOPMPSAdapterInfoKey
;
228 static const OSSymbol
* gIOPMPSLocationKey
;
229 static const OSSymbol
* gIOPMPSErrorConditionKey
;
230 static const OSSymbol
* gIOPMPSManufacturerKey
;
231 static const OSSymbol
* gIOPMPSManufactureDateKey
;
232 static const OSSymbol
* gIOPMPSModelKey
;
233 static const OSSymbol
* gIOPMPSSerialKey
;
234 static const OSSymbol
* gIOPMPSLegacyBatteryInfoKey
;
235 static const OSSymbol
* gIOPMPSBatteryHealthKey
;
236 static const OSSymbol
* gIOPMPSHealthConfidenceKey
;
237 static const OSSymbol
* gIOPMPSCapacityEstimatedKey
;
238 static const OSSymbol
* gIOPMPSBatteryChargeStatusKey
;
239 static const OSSymbol
* gIOPMPSBatteryTemperatureKey
;
240 static const OSSymbol
* gIOPMPSAdapterDetailsKey
;
241 static const OSSymbol
* gIOPMPSChargerConfigurationKey
;
242 static const OSSymbol
* gIOPMPSAdapterDetailsIDKey
;
243 static const OSSymbol
* gIOPMPSAdapterDetailsWattsKey
;
244 static const OSSymbol
* gIOPMPSAdapterDetailsRevisionKey
;
245 static const OSSymbol
* gIOPMPSAdapterDetailsSerialNumberKey
;
246 static const OSSymbol
* gIOPMPSAdapterDetailsFamilyKey
;
247 static const OSSymbol
* gIOPMPSAdapterDetailsAmperageKey
;
248 static const OSSymbol
* gIOPMPSAdapterDetailsDescriptionKey
;
249 static const OSSymbol
* gIOPMPSAdapterDetailsPMUConfigurationKey
;
250 static const OSSymbol
* gIOPMPSAdapterDetailsSourceIDKey
;
251 static const OSSymbol
* gIOPMPSAdapterDetailsErrorFlagsKey
;
252 static const OSSymbol
* gIOPMPSAdapterDetailsSharedSourceKey
;
253 static const OSSymbol
* gIOPMPSAdapterDetailsCloakedKey
;
254 static const OSSymbol
* gIOPMPSInvalidWakeSecondsKey
;
255 static const OSSymbol
* gIOPMPSPostChargeWaitSecondsKey
;
256 static const OSSymbol
* gIOPMPSPostDishargeWaitSecondsKey
;
258 #define kIOSleepSupportedKey "IOSleepSupported"
259 #define kIOPMSystemCapabilitiesKey "System Capabilities"
261 #define kIORequestWranglerIdleKey "IORequestIdle"
262 #define kDefaultWranglerIdlePeriod 1000 // in milliseconds
264 #define kIOSleepWakeFailureString "SleepWakeFailureString"
265 #define kIOEFIBootRomFailureKey "wake-failure"
266 #define kIOSleepWakeFailurePanic "SleepWakeFailurePanic"
268 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
269 | kIOPMSupportedOnBatt \
270 | kIOPMSupportedOnUPS)
272 #define kLocalEvalClamshellCommand (1 << 15)
273 #define kIdleSleepRetryInterval (3 * 60)
276 kWranglerPowerStateMin
= 0,
277 kWranglerPowerStateSleep
= 2,
278 kWranglerPowerStateDim
= 3,
279 kWranglerPowerStateMax
= 4
292 getPowerStateString( uint32_t state
)
294 #define POWER_STATE(x) {(uint32_t) x, #x}
296 static const IONamedValue powerStates
[] = {
297 POWER_STATE( OFF_STATE
),
298 POWER_STATE( RESTART_STATE
),
299 POWER_STATE( SLEEP_STATE
),
300 POWER_STATE( AOT_STATE
),
301 POWER_STATE( ON_STATE
),
304 return IOFindNameForValue(state
, powerStates
);
307 #define ON_POWER kIOPMPowerOn
308 #define RESTART_POWER kIOPMRestart
309 #define SLEEP_POWER kIOPMAuxPowerOn
311 static IOPMPowerState
312 ourPowerStates
[NUM_POWER_STATES
] =
315 .capabilityFlags
= 0,
316 .outputPowerCharacter
= 0,
317 .inputPowerRequirement
= 0 },
319 .capabilityFlags
= kIOPMRestartCapability
,
320 .outputPowerCharacter
= kIOPMRestart
,
321 .inputPowerRequirement
= RESTART_POWER
},
323 .capabilityFlags
= kIOPMSleepCapability
,
324 .outputPowerCharacter
= kIOPMSleep
,
325 .inputPowerRequirement
= SLEEP_POWER
},
327 .capabilityFlags
= kIOPMAOTCapability
,
328 .outputPowerCharacter
= kIOPMAOTPower
,
329 .inputPowerRequirement
= ON_POWER
},
331 .capabilityFlags
= kIOPMPowerOn
,
332 .outputPowerCharacter
= kIOPMPowerOn
,
333 .inputPowerRequirement
= ON_POWER
},
336 #define kIOPMRootDomainWakeTypeSleepService "SleepService"
337 #define kIOPMRootDomainWakeTypeMaintenance "Maintenance"
338 #define kIOPMRootDomainWakeTypeSleepTimer "SleepTimer"
339 #define kIOPMrootDomainWakeTypeLowBattery "LowBattery"
340 #define kIOPMRootDomainWakeTypeUser "User"
341 #define kIOPMRootDomainWakeTypeAlarm "Alarm"
342 #define kIOPMRootDomainWakeTypeNetwork "Network"
343 #define kIOPMRootDomainWakeTypeHIDActivity "HID Activity"
344 #define kIOPMRootDomainWakeTypeNotification "Notification"
345 #define kIOPMRootDomainWakeTypeHibernateError "HibernateError"
347 // Special interest that entitles the interested client from receiving
348 // all system messages. Only used by powerd.
350 #define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest"
352 // Entitlement required for root domain clients
353 #define kRootDomainEntitlementSetProperty "com.apple.private.iokit.rootdomain-set-property"
355 #define WAKEEVENT_LOCK() IOLockLock(wakeEventLock)
356 #define WAKEEVENT_UNLOCK() IOLockUnlock(wakeEventLock)
361 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock)
362 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock)
364 #define kAggressivesMinValue 1
367 getAggressivenessTypeString( uint32_t type
)
369 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
371 static const IONamedValue aggressivenessTypes
[] = {
372 AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness
),
373 AGGRESSIVENESS_TYPE( kPMMinutesToDim
),
374 AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown
),
375 AGGRESSIVENESS_TYPE( kPMMinutesToSleep
),
376 AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings
),
377 AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed
),
378 AGGRESSIVENESS_TYPE( kPMPowerSource
),
379 AGGRESSIVENESS_TYPE( kPMMotionSensor
),
380 AGGRESSIVENESS_TYPE( kPMLastAggressivenessType
),
383 return IOFindNameForValue(type
, aggressivenessTypes
);
387 kAggressivesStateBusy
= 0x01,
388 kAggressivesStateQuickSpindown
= 0x02
391 struct AggressivesRecord
{
397 struct AggressivesRequest
{
403 AggressivesRecord record
;
408 kAggressivesRequestTypeService
= 1,
409 kAggressivesRequestTypeRecord
413 kAggressivesOptionSynchronous
= 0x00000001,
414 kAggressivesOptionQuickSpindownEnable
= 0x00000100,
415 kAggressivesOptionQuickSpindownDisable
= 0x00000200,
416 kAggressivesOptionQuickSpindownMask
= 0x00000300
420 kAggressivesRecordFlagModified
= 0x00000001,
421 kAggressivesRecordFlagMinValue
= 0x00000002
424 // System Sleep Preventers
427 kPMUserDisabledAllSleep
= 1,
428 kPMSystemRestartBootingInProgress
,
429 kPMConfigPreventSystemSleep
,
430 kPMChildPreventSystemSleep
,
436 getSystemSleepPreventerString( uint32_t preventer
)
438 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x}
439 static const IONamedValue systemSleepPreventers
[] = {
440 SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep
),
441 SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress
),
442 SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep
),
443 SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep
),
444 SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion
),
445 SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported
),
448 return IOFindNameForValue(preventer
, systemSleepPreventers
);
453 kDarkWakeFlagHIDTickleEarly
= 0x01,// hid tickle before gfx suppression
454 kDarkWakeFlagHIDTickleLate
= 0x02,// hid tickle after gfx suppression
455 kDarkWakeFlagHIDTickleNone
= 0x03,// hid tickle is not posted
456 kDarkWakeFlagHIDTickleMask
= 0x03,
457 kDarkWakeFlagAlarmIsDark
= 0x0100,
458 kDarkWakeFlagGraphicsPowerState1
= 0x0200,
459 kDarkWakeFlagAudioNotSuppressed
= 0x0400
462 static IOPMrootDomain
* gRootDomain
;
463 static IONotifier
* gSysPowerDownNotifier
= NULL
;
464 static UInt32 gSleepOrShutdownPending
= 0;
465 static UInt32 gWillShutdown
= 0;
466 static UInt32 gPagingOff
= 0;
467 static UInt32 gSleepWakeUUIDIsSet
= false;
468 static uint32_t gAggressivesState
= 0;
469 static uint32_t gHaltTimeMaxLog
;
470 static uint32_t gHaltTimeMaxPanic
;
471 IOLock
* gHaltLogLock
;
472 static char * gHaltLog
;
473 enum { kHaltLogSize
= 2048 };
474 static size_t gHaltLogPos
;
475 static uint64_t gHaltStartTime
;
478 uuid_string_t bootsessionuuid_string
;
480 static uint32_t gDarkWakeFlags
= kDarkWakeFlagHIDTickleNone
;
481 static uint32_t gNoIdleFlag
= 0;
482 static uint32_t gSwdPanic
= 1;
483 static uint32_t gSwdSleepTimeout
= 0;
484 static uint32_t gSwdWakeTimeout
= 0;
485 static uint32_t gSwdSleepWakeTimeout
= 0;
486 static PMStatsStruct gPMStats
;
487 #if DEVELOPMENT || DEBUG
488 static uint32_t swd_panic_phase
;
493 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler
= NULL
;
494 static IOPMSystemSleepPolicyVariables
* gSleepPolicyVars
= NULL
;
495 static void * gSleepPolicyTarget
;
498 struct timeval gIOLastSleepTime
;
499 struct timeval gIOLastWakeTime
;
501 struct timeval gIOLastUserSleepTime
;
503 static char gWakeReasonString
[128];
504 static bool gWakeReasonSysctlRegistered
= false;
505 static AbsoluteTime gIOLastWakeAbsTime
;
506 static AbsoluteTime gIOLastSleepAbsTime
;
507 static AbsoluteTime gUserActiveAbsTime
;
508 static AbsoluteTime gUserInactiveAbsTime
;
510 #if defined(__i386__) || defined(__x86_64__)
511 static bool gSpinDumpBufferFull
= false;
515 vm_offset_t swd_zs_zmem
;
516 //size_t swd_zs_zsize;
517 size_t swd_zs_zoffset
;
518 #if defined(__i386__) || defined(__x86_64__)
519 IOCPU
*currentShutdownTarget
= NULL
;
522 static unsigned int gPMHaltBusyCount
;
523 static unsigned int gPMHaltIdleCount
;
524 static int gPMHaltDepth
;
525 static uint32_t gPMHaltMessageType
;
526 static IOLock
* gPMHaltLock
= NULL
;
527 static OSArray
* gPMHaltArray
= NULL
;
528 static const OSSymbol
* gPMHaltClientAcknowledgeKey
= NULL
;
529 static bool gPMQuiesced
;
531 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
532 #define kCPUUnknownIndex 9999999
539 const OSSymbol
*gIOPMStatsResponseTimedOut
;
540 const OSSymbol
*gIOPMStatsResponseCancel
;
541 const OSSymbol
*gIOPMStatsResponseSlow
;
542 const OSSymbol
*gIOPMStatsResponsePrompt
;
543 const OSSymbol
*gIOPMStatsDriverPSChangeSlow
;
545 #define kBadPMFeatureID 0
549 * Opaque handle passed to clients of registerPMSettingController()
551 class PMSettingHandle
: public OSObject
553 OSDeclareFinalStructors( PMSettingHandle
);
554 friend class PMSettingObject
;
557 PMSettingObject
*pmso
;
558 void free(void) APPLE_KEXT_OVERRIDE
;
563 * Internal object to track each PM setting controller
565 class PMSettingObject
: public OSObject
567 OSDeclareFinalStructors( PMSettingObject
);
568 friend class IOPMrootDomain
;
571 queue_head_t calloutQueue
;
573 IOPMrootDomain
*parent
;
574 PMSettingHandle
*pmsh
;
575 IOPMSettingControllerCallback func
;
578 uint32_t *publishedFeatureID
;
579 uint32_t settingCount
;
582 void free(void) APPLE_KEXT_OVERRIDE
;
585 static PMSettingObject
*pmSettingObject(
586 IOPMrootDomain
*parent_arg
,
587 IOPMSettingControllerCallback handler_arg
,
588 OSObject
*target_arg
,
589 uintptr_t refcon_arg
,
590 uint32_t supportedPowerSources
,
591 const OSSymbol
*settings
[],
592 OSObject
**handle_obj
);
594 void dispatchPMSetting(const OSSymbol
*type
, OSObject
*object
);
595 void clientHandleFreed(void);
598 struct PMSettingCallEntry
{
603 #define PMSETTING_LOCK() IOLockLock(settingsCtrlLock)
604 #define PMSETTING_UNLOCK() IOLockUnlock(settingsCtrlLock)
605 #define PMSETTING_WAIT(p) IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
606 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
610 * Internal helper object for logging trace points to RTC
611 * IOPMrootDomain and only IOPMrootDomain should instantiate
612 * exactly one of these.
615 typedef void (*IOPMTracePointHandler
)(
616 void * target
, uint32_t code
, uint32_t data
);
618 class PMTraceWorker
: public OSObject
620 OSDeclareDefaultStructors(PMTraceWorker
);
622 typedef enum { kPowerChangeStart
, kPowerChangeCompleted
} change_t
;
624 static PMTraceWorker
*tracer( IOPMrootDomain
* );
625 void tracePCIPowerChange(change_t
, IOService
*, uint32_t, uint32_t);
626 void tracePoint(uint8_t phase
);
627 void traceDetail(uint32_t detail
);
628 void traceComponentWakeProgress(uint32_t component
, uint32_t data
);
629 int recordTopLevelPCIDevice(IOService
*);
630 void RTC_TRACE(void);
631 virtual bool serialize(OSSerialize
*s
) const APPLE_KEXT_OVERRIDE
;
633 IOPMTracePointHandler tracePointHandler
;
634 void * tracePointTarget
;
635 uint64_t getPMStatusCode();
636 uint8_t getTracePhase();
637 uint32_t getTraceData();
639 IOPMrootDomain
*owner
;
640 IOLock
*pmTraceWorkerLock
;
641 OSArray
*pciDeviceBitMappings
;
643 uint8_t addedToRegistry
;
645 uint32_t traceData32
;
646 uint8_t loginWindowData
;
647 uint8_t coreDisplayData
;
648 uint8_t coreGraphicsData
;
652 * PMAssertionsTracker
653 * Tracks kernel and user space PM assertions
655 class PMAssertionsTracker
: public OSObject
657 OSDeclareFinalStructors(PMAssertionsTracker
);
659 static PMAssertionsTracker
*pmAssertionsTracker( IOPMrootDomain
* );
661 IOReturn
createAssertion(IOPMDriverAssertionType
, IOPMDriverAssertionLevel
, IOService
*, const char *, IOPMDriverAssertionID
*);
662 IOReturn
releaseAssertion(IOPMDriverAssertionID
);
663 IOReturn
setAssertionLevel(IOPMDriverAssertionID
, IOPMDriverAssertionLevel
);
664 IOReturn
setUserAssertionLevels(IOPMDriverAssertionType
);
666 OSArray
*copyAssertionsArray(void);
667 IOPMDriverAssertionType
getActivatedAssertions(void);
668 IOPMDriverAssertionLevel
getAssertionLevel(IOPMDriverAssertionType
);
670 IOReturn
handleCreateAssertion(OSData
*);
671 IOReturn
handleReleaseAssertion(IOPMDriverAssertionID
);
672 IOReturn
handleSetAssertionLevel(IOPMDriverAssertionID
, IOPMDriverAssertionLevel
);
673 IOReturn
handleSetUserAssertionLevels(void * arg0
);
674 void publishProperties(void);
678 IOPMDriverAssertionID id
;
679 IOPMDriverAssertionType assertionBits
;
680 uint64_t createdTime
;
681 uint64_t modifiedTime
;
682 const OSSymbol
*ownerString
;
683 IOService
*ownerService
;
684 uint64_t registryEntryID
;
685 IOPMDriverAssertionLevel level
;
688 uint32_t tabulateProducerCount
;
689 uint32_t tabulateConsumerCount
;
691 PMAssertStruct
*detailsForID(IOPMDriverAssertionID
, int *);
694 IOPMrootDomain
*owner
;
695 OSArray
*assertionsArray
;
696 IOLock
*assertionsArrayLock
;
697 IOPMDriverAssertionID issuingUniqueID
__attribute__((aligned(8)));/* aligned for atomic access */
698 IOPMDriverAssertionType assertionsKernel
;
699 IOPMDriverAssertionType assertionsUser
;
700 IOPMDriverAssertionType assertionsCombined
;
703 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker
, OSObject
);
707 * Internal helper object for Shutdown/Restart notifications.
709 #define kPMHaltMaxWorkers 8
710 #define kPMHaltTimeoutMS 100
712 class PMHaltWorker
: public OSObject
714 OSDeclareFinalStructors( PMHaltWorker
);
717 IOService
* service
;// service being worked on
718 AbsoluteTime startTime
; // time when work started
719 int depth
; // work on nubs at this PM-tree depth
720 int visits
; // number of nodes visited (debug)
722 bool timeout
;// service took too long
724 static PMHaltWorker
* worker( void );
725 static void main( void * arg
, wait_result_t waitResult
);
726 static void work( PMHaltWorker
* me
);
727 static void checkTimeout( PMHaltWorker
* me
, AbsoluteTime
* now
);
728 virtual void free( void ) APPLE_KEXT_OVERRIDE
;
731 OSDefineMetaClassAndFinalStructors( PMHaltWorker
, OSObject
)
734 #define super IOService
735 OSDefineMetaClassAndFinalStructors(IOPMrootDomain
, IOService
)
738 IOPMRootDomainGetWillShutdown(void)
740 return gWillShutdown
!= 0;
744 IOPMRootDomainWillShutdown(void)
746 if (OSCompareAndSwap(0, 1, &gWillShutdown
)) {
747 IOService::willShutdown();
748 for (int i
= 0; i
< 100; i
++) {
749 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending
)) {
757 extern "C" IONotifier
*
758 registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
760 return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref
);
763 extern "C" IONotifier
*
764 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
766 return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref
);
770 acknowledgeSleepWakeNotification(void * PMrefcon
)
772 return gRootDomain
->allowPowerChange((unsigned long)PMrefcon
);
776 vetoSleepWakeNotification(void * PMrefcon
)
778 return gRootDomain
->cancelPowerChange((unsigned long)PMrefcon
);
782 rootDomainRestart( void )
784 return gRootDomain
->restartSystem();
788 rootDomainShutdown( void )
790 return gRootDomain
->shutdownSystem();
794 halt_log_putc(char c
)
796 if (gHaltLogPos
>= (kHaltLogSize
- 2)) {
799 gHaltLog
[gHaltLogPos
++] = c
;
803 _doprnt_log(const char *fmt
,
809 halt_log(const char *fmt
, ...)
813 va_start(listp
, fmt
);
814 _doprnt_log(fmt
, &listp
, &halt_log_putc
, 16);
821 halt_log_enter(const char * what
, const void * pc
, uint64_t time
)
823 uint64_t nano
, millis
;
828 absolutetime_to_nanoseconds(time
, &nano
);
829 millis
= nano
/ NSEC_PER_MSEC
;
834 IOLockLock(gHaltLogLock
);
836 halt_log("%s: %qd ms @ 0x%lx, ", what
, millis
, VM_KERNEL_UNSLIDE(pc
));
837 OSKext::printKextsInBacktrace((vm_offset_t
*) &pc
, 1, &halt_log
,
838 OSKext::kPrintKextsLock
| OSKext::kPrintKextsUnslide
| OSKext::kPrintKextsTerse
);
840 halt_log("%s: %qd ms\n", what
, millis
);
843 gHaltLog
[gHaltLogPos
] = 0;
844 IOLockUnlock(gHaltLogLock
);
847 extern uint32_t gFSState
;
850 IOSystemShutdownNotification(int stage
)
854 if (kIOSystemShutdownNotificationStageRootUnmount
== stage
) {
856 uint64_t nano
, millis
;
857 startTime
= mach_absolute_time();
858 IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC
);
859 absolutetime_to_nanoseconds(mach_absolute_time() - startTime
, &nano
);
860 millis
= nano
/ NSEC_PER_MSEC
;
861 if (gHaltTimeMaxLog
&& (millis
>= gHaltTimeMaxLog
)) {
862 printf("waitQuiet() for unmount %qd ms\n", millis
);
868 assert(kIOSystemShutdownNotificationStageProcessExit
== stage
);
870 IOLockLock(gHaltLogLock
);
872 gHaltLog
= IONew(char, kHaltLogSize
);
873 gHaltStartTime
= mach_absolute_time();
878 IOLockUnlock(gHaltLogLock
);
880 startTime
= mach_absolute_time();
881 IOPMRootDomainWillShutdown();
882 halt_log_enter("IOPMRootDomainWillShutdown", NULL
, mach_absolute_time() - startTime
);
884 startTime
= mach_absolute_time();
885 IOHibernateSystemPostWake(true);
886 halt_log_enter("IOHibernateSystemPostWake", NULL
, mach_absolute_time() - startTime
);
888 if (OSCompareAndSwap(0, 1, &gPagingOff
)) {
889 gRootDomain
->handlePlatformHaltRestart(kPEPagingOff
);
894 extern "C" int sync_internal(void);
897 * A device is always in the highest power state which satisfies its driver,
898 * its policy-maker, and any power children it has, but within the constraint
899 * of the power state provided by its parent. The driver expresses its desire by
900 * calling changePowerStateTo(), the policy-maker expresses its desire by calling
901 * changePowerStateToPriv(), and the children express their desires by calling
902 * requestPowerDomainState().
904 * The Root Power Domain owns the policy for idle and demand sleep for the system.
905 * It is a power-managed IOService just like the others in the system.
906 * It implements several power states which map to what we see as Sleep and On.
908 * The sleep policy is as follows:
909 * 1. Sleep is prevented if the case is open so that nobody will think the machine
910 * is off and plug/unplug cards.
911 * 2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
912 * 3. System cannot Sleep if some object in the tree is in a power state marked
913 * kIOPMPreventSystemSleep.
915 * These three conditions are enforced using the "driver clamp" by calling
916 * changePowerStateTo(). For example, if the case is opened,
917 * changePowerStateTo(ON_STATE) is called to hold the system on regardless
918 * of the desires of the children of the root or the state of the other clamp.
920 * Demand Sleep is initiated by pressing the front panel power button, closing
921 * the clamshell, or selecting the menu item. In this case the root's parent
922 * actually initiates the power state change so that the root domain has no
923 * choice and does not give applications the opportunity to veto the change.
925 * Idle Sleep occurs if no objects in the tree are in a state marked
926 * kIOPMPreventIdleSleep. When this is true, the root's children are not holding
927 * the root on, so it sets the "policy-maker clamp" by calling
928 * changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
929 * This timer is set for the difference between the sleep timeout slider and the
930 * display dim timeout slider. When the timer expires, it releases its clamp and
931 * now nothing is holding it awake, so it falls asleep.
933 * Demand sleep is prevented when the system is booting. When preferences are
934 * transmitted by the loginwindow at the end of boot, a flag is cleared,
935 * and this allows subsequent Demand Sleep.
938 //******************************************************************************
941 IOPMrootDomain::construct( void )
943 IOPMrootDomain
*root
;
945 root
= new IOPMrootDomain
;
953 //******************************************************************************
954 // updateConsoleUsersCallout
956 //******************************************************************************
959 updateConsoleUsersCallout(thread_call_param_t p0
, thread_call_param_t p1
)
961 IOPMrootDomain
* rootDomain
= (IOPMrootDomain
*) p0
;
962 rootDomain
->updateConsoleUsers();
966 IOPMrootDomain::updateConsoleUsers(void)
968 IOService::updateConsoleUsers(NULL
, kIOMessageSystemHasPoweredOn
);
969 if (tasksSuspended
) {
970 tasksSuspended
= FALSE
;
971 updateTasksSuspend();
976 IOPMrootDomain::updateTasksSuspend(void)
980 newSuspend
= (tasksSuspended
|| _aotTasksSuspended
);
981 if (newSuspend
== tasksSuspendState
) {
984 tasksSuspendState
= newSuspend
;
985 tasks_system_suspend(newSuspend
);
988 //******************************************************************************
991 disk_sync_callout( thread_call_param_t p0
, thread_call_param_t p1
)
993 IOService
* rootDomain
= (IOService
*) p0
;
994 uint32_t notifyRef
= (uint32_t)(uintptr_t) p1
;
995 uint32_t powerState
= rootDomain
->getPowerState();
997 DLOG("disk_sync_callout ps=%u\n", powerState
);
999 if (ON_STATE
== powerState
) {
1003 // Block sleep until trim issued on previous wake path is completed.
1004 IOHibernateSystemPostWake(true);
1009 IOHibernateSystemPostWake(false);
1012 gRootDomain
->sleepWakeDebugSaveSpinDumpFile();
1017 rootDomain
->allowPowerChange(notifyRef
);
1018 DLOG("disk_sync_callout finish\n");
1021 //******************************************************************************
1023 computeDeltaTimeMS( const AbsoluteTime
* startTime
, AbsoluteTime
* elapsedTime
)
1025 AbsoluteTime endTime
;
1028 clock_get_uptime(&endTime
);
1029 if (CMP_ABSOLUTETIME(&endTime
, startTime
) <= 0) {
1032 SUB_ABSOLUTETIME(&endTime
, startTime
);
1033 absolutetime_to_nanoseconds(endTime
, &nano
);
1034 *elapsedTime
= endTime
;
1037 return (UInt32
)(nano
/ NSEC_PER_MSEC
);
1040 //******************************************************************************
1043 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1045 struct timeval
*swt
= (struct timeval
*)arg1
;
1046 struct proc
*p
= req
->p
;
1048 if (p
== kernproc
) {
1049 return sysctl_io_opaque(req
, swt
, sizeof(*swt
), NULL
);
1050 } else if (proc_is64bit(p
)) {
1051 struct user64_timeval t
= {};
1052 t
.tv_sec
= swt
->tv_sec
;
1053 t
.tv_usec
= swt
->tv_usec
;
1054 return sysctl_io_opaque(req
, &t
, sizeof(t
), NULL
);
1056 struct user32_timeval t
= {};
1057 t
.tv_sec
= swt
->tv_sec
;
1058 t
.tv_usec
= swt
->tv_usec
;
1059 return sysctl_io_opaque(req
, &t
, sizeof(t
), NULL
);
1063 static SYSCTL_PROC(_kern
, OID_AUTO
, sleeptime
,
1064 CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1065 &gIOLastUserSleepTime
, 0, sysctl_sleepwaketime
, "S,timeval", "");
1067 static SYSCTL_PROC(_kern
, OID_AUTO
, waketime
,
1068 CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1069 &gIOLastWakeTime
, 0, sysctl_sleepwaketime
, "S,timeval", "");
1071 SYSCTL_QUAD(_kern
, OID_AUTO
, wake_abs_time
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &gIOLastWakeAbsTime
, "");
1072 SYSCTL_QUAD(_kern
, OID_AUTO
, sleep_abs_time
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &gIOLastSleepAbsTime
, "");
1073 SYSCTL_QUAD(_kern
, OID_AUTO
, useractive_abs_time
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &gUserActiveAbsTime
, "");
1074 SYSCTL_QUAD(_kern
, OID_AUTO
, userinactive_abs_time
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &gUserInactiveAbsTime
, "");
1078 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1080 int new_value
, changed
;
1081 int error
= sysctl_io_number(req
, gWillShutdown
, sizeof(int), &new_value
, &changed
);
1083 if (!gWillShutdown
&& (new_value
== 1)) {
1084 IOPMRootDomainWillShutdown();
1092 static SYSCTL_PROC(_kern
, OID_AUTO
, willshutdown
,
1093 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1094 NULL
, 0, sysctl_willshutdown
, "I", "");
1096 extern struct sysctl_oid sysctl__kern_iokittest
;
1097 extern struct sysctl_oid sysctl__debug_iokit
;
1099 #if !CONFIG_EMBEDDED
1102 sysctl_progressmeterenable
1103 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1106 int new_value
, changed
;
1108 error
= sysctl_io_number(req
, vc_progressmeter_enable
, sizeof(int), &new_value
, &changed
);
1111 vc_enable_progressmeter(new_value
);
1118 sysctl_progressmeter
1119 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1122 int new_value
, changed
;
1124 error
= sysctl_io_number(req
, vc_progressmeter_value
, sizeof(int), &new_value
, &changed
);
1127 vc_set_progressmeter(new_value
);
1133 static SYSCTL_PROC(_kern
, OID_AUTO
, progressmeterenable
,
1134 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1135 NULL
, 0, sysctl_progressmeterenable
, "I", "");
1137 static SYSCTL_PROC(_kern
, OID_AUTO
, progressmeter
,
1138 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1139 NULL
, 0, sysctl_progressmeter
, "I", "");
1141 #endif /* !CONFIG_EMBEDDED */
1146 sysctl_consoleoptions
1147 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1152 error
= sysctl_io_number(req
, vc_user_options
.options
, sizeof(uint32_t), &new_value
, &changed
);
1155 vc_user_options
.options
= new_value
;
1161 static SYSCTL_PROC(_kern
, OID_AUTO
, consoleoptions
,
1162 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1163 NULL
, 0, sysctl_consoleoptions
, "I", "");
1167 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1169 return sysctl_io_opaque(req
, &vc_user_options
, sizeof(vc_user_options
), NULL
);
1172 static SYSCTL_PROC(_kern
, OID_AUTO
, progressoptions
,
1173 CTLTYPE_STRUCT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
| CTLFLAG_ANYBODY
,
1174 NULL
, 0, sysctl_progressoptions
, "S,vc_progress_user_options", "");
1178 sysctl_wakereason SYSCTL_HANDLER_ARGS
1180 char wr
[sizeof(gWakeReasonString
)];
1184 gRootDomain
->copyWakeReasonString(wr
, sizeof(wr
));
1187 return sysctl_io_string(req
, wr
, 0, 0, NULL
);
1190 SYSCTL_PROC(_kern
, OID_AUTO
, wakereason
,
1191 CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1192 NULL
, 0, sysctl_wakereason
, "A", "wakereason");
1195 sysctl_targettype SYSCTL_HANDLER_ARGS
1203 root
= IOService::getServiceRoot();
1204 if (root
&& (obj
= root
->copyProperty(gIODTTargetTypeKey
))) {
1205 if ((data
= OSDynamicCast(OSData
, obj
))) {
1206 strlcpy(tt
, (const char *) data
->getBytesNoCopy(), sizeof(tt
));
1210 return sysctl_io_string(req
, tt
, 0, 0, NULL
);
1213 SYSCTL_PROC(_hw
, OID_AUTO
, targettype
,
1214 CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1215 NULL
, 0, sysctl_targettype
, "A", "targettype");
1217 static SYSCTL_INT(_debug
, OID_AUTO
, darkwake
, CTLFLAG_RW
, &gDarkWakeFlags
, 0, "");
1218 static SYSCTL_INT(_debug
, OID_AUTO
, noidle
, CTLFLAG_RW
, &gNoIdleFlag
, 0, "");
1219 static SYSCTL_INT(_debug
, OID_AUTO
, swd_sleep_timeout
, CTLFLAG_RW
, &gSwdSleepTimeout
, 0, "");
1220 static SYSCTL_INT(_debug
, OID_AUTO
, swd_wake_timeout
, CTLFLAG_RW
, &gSwdWakeTimeout
, 0, "");
1221 static SYSCTL_INT(_debug
, OID_AUTO
, swd_timeout
, CTLFLAG_RW
, &gSwdSleepWakeTimeout
, 0, "");
1222 static SYSCTL_INT(_debug
, OID_AUTO
, swd_panic
, CTLFLAG_RW
, &gSwdPanic
, 0, "");
1223 #if DEVELOPMENT || DEBUG
1224 static SYSCTL_INT(_debug
, OID_AUTO
, swd_panic_phase
, CTLFLAG_RW
, &swd_panic_phase
, 0, "");
1227 //******************************************************************************
1231 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1233 if (NULL
== gRootDomain
) {
1236 if (NULL
== gRootDomain
->_aotMetrics
) {
1239 return sysctl_io_opaque(req
, gRootDomain
->_aotMetrics
, sizeof(IOPMAOTMetrics
), NULL
);
1242 static SYSCTL_PROC(_kern
, OID_AUTO
, aotmetrics
,
1243 CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
| CTLFLAG_ANYBODY
,
1244 NULL
, 0, sysctl_aotmetrics
, "S,IOPMAOTMetrics", "");
1248 update_aotmode(uint32_t mode
)
1252 if (!gIOPMWorkLoop
) {
1255 result
= gIOPMWorkLoop
->runActionBlock(^IOReturn (void) {
1256 unsigned int oldCount
;
1258 if (mode
&& !gRootDomain
->_aotMetrics
) {
1259 gRootDomain
->_aotMetrics
= IONewZero(IOPMAOTMetrics
, 1);
1260 if (!gRootDomain
->_aotMetrics
) {
1265 oldCount
= gRootDomain
->idleSleepPreventersCount();
1266 gRootDomain
->_aotMode
= mode
;
1267 gRootDomain
->updatePreventIdleSleepListInternal(NULL
, false, oldCount
);
1275 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1280 if (NULL
== gRootDomain
) {
1283 error
= sysctl_io_number(req
, gRootDomain
->_aotMode
, sizeof(uint32_t), &new_value
, &changed
);
1284 if (changed
&& gIOPMWorkLoop
) {
1285 error
= update_aotmode(new_value
);
1291 static SYSCTL_PROC(_kern
, OID_AUTO
, aotmodebits
,
1292 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1293 NULL
, 0, sysctl_aotmodebits
, "I", "");
1297 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1302 if (NULL
== gRootDomain
) {
1305 error
= sysctl_io_number(req
, gRootDomain
->_aotMode
, sizeof(uint32_t), &new_value
, &changed
);
1306 if (changed
&& gIOPMWorkLoop
) {
1308 new_value
= kIOPMAOTModeDefault
; // & ~kIOPMAOTModeRespectTimers;
1310 error
= update_aotmode(new_value
);
1316 static SYSCTL_PROC(_kern
, OID_AUTO
, aotmode
,
1317 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
| CTLFLAG_ANYBODY
,
1318 NULL
, 0, sysctl_aotmode
, "I", "");
1320 //******************************************************************************
1322 static const OSSymbol
* gIOPMSettingAutoWakeCalendarKey
;
1323 static const OSSymbol
* gIOPMSettingAutoWakeSecondsKey
;
1324 static const OSSymbol
* gIOPMSettingAutoPowerCalendarKey
;
1325 static const OSSymbol
* gIOPMSettingAutoPowerSecondsKey
;
1326 static const OSSymbol
* gIOPMSettingDebugWakeRelativeKey
;
1327 static const OSSymbol
* gIOPMSettingDebugPowerRelativeKey
;
1328 static const OSSymbol
* gIOPMSettingMaintenanceWakeCalendarKey
;
1329 static const OSSymbol
* gIOPMSettingSleepServiceWakeCalendarKey
;
1330 static const OSSymbol
* gIOPMSettingSilentRunningKey
;
1331 static const OSSymbol
* gIOPMUserTriggeredFullWakeKey
;
1332 static const OSSymbol
* gIOPMUserIsActiveKey
;
1334 //******************************************************************************
1337 //******************************************************************************
1339 #define kRootDomainSettingsCount 19
1340 #define kRootDomainNoPublishSettingsCount 3
1343 IOPMrootDomain::start( IOService
* nub
)
1345 OSIterator
*psIterator
;
1346 OSDictionary
*tmpDict
;
1347 IORootParent
* patriarch
;
1352 gIOPMSettingAutoWakeCalendarKey
= OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey
);
1353 gIOPMSettingAutoWakeSecondsKey
= OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey
);
1354 gIOPMSettingAutoPowerCalendarKey
= OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey
);
1355 gIOPMSettingAutoPowerSecondsKey
= OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey
);
1356 gIOPMSettingDebugWakeRelativeKey
= OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey
);
1357 gIOPMSettingDebugPowerRelativeKey
= OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey
);
1358 gIOPMSettingMaintenanceWakeCalendarKey
= OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey
);
1359 gIOPMSettingSleepServiceWakeCalendarKey
= OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey
);
1360 gIOPMSettingSilentRunningKey
= OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey
);
1361 gIOPMUserTriggeredFullWakeKey
= OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey
);
1362 gIOPMUserIsActiveKey
= OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey
);
1364 gIOPMStatsResponseTimedOut
= OSSymbol::withCString(kIOPMStatsResponseTimedOut
);
1365 gIOPMStatsResponseCancel
= OSSymbol::withCString(kIOPMStatsResponseCancel
);
1366 gIOPMStatsResponseSlow
= OSSymbol::withCString(kIOPMStatsResponseSlow
);
1367 gIOPMStatsResponsePrompt
= OSSymbol::withCString(kIOPMStatsResponsePrompt
);
1368 gIOPMStatsDriverPSChangeSlow
= OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow
);
1370 sleepSupportedPEFunction
= OSSymbol::withCString("IOPMSetSleepSupported");
1371 sleepMessagePEFunction
= OSSymbol::withCString("IOPMSystemSleepMessage");
1373 const OSSymbol
*settingsArr
[kRootDomainSettingsCount
] =
1375 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey
),
1376 gIOPMSettingAutoWakeSecondsKey
,
1377 gIOPMSettingAutoPowerSecondsKey
,
1378 gIOPMSettingAutoWakeCalendarKey
,
1379 gIOPMSettingAutoPowerCalendarKey
,
1380 gIOPMSettingDebugWakeRelativeKey
,
1381 gIOPMSettingDebugPowerRelativeKey
,
1382 OSSymbol::withCString(kIOPMSettingWakeOnRingKey
),
1383 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
),
1384 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey
),
1385 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey
),
1386 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey
),
1387 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey
),
1388 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey
),
1389 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey
),
1390 OSSymbol::withCString(kIOPMStateConsoleShutdown
),
1391 OSSymbol::withCString(kIOPMSettingProModeControl
),
1392 OSSymbol::withCString(kIOPMSettingProModeDefer
),
1393 gIOPMSettingSilentRunningKey
,
1396 const OSSymbol
*noPublishSettingsArr
[kRootDomainNoPublishSettingsCount
] =
1398 OSSymbol::withCString(kIOPMSettingProModeControl
),
1399 OSSymbol::withCString(kIOPMSettingProModeDefer
),
1400 gIOPMSettingSilentRunningKey
,
1403 PE_parse_boot_argn("darkwake", &gDarkWakeFlags
, sizeof(gDarkWakeFlags
));
1404 PE_parse_boot_argn("noidle", &gNoIdleFlag
, sizeof(gNoIdleFlag
));
1405 PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout
, sizeof(gSwdSleepTimeout
));
1406 PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout
, sizeof(gSwdWakeTimeout
));
1407 PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout
, sizeof(gSwdSleepWakeTimeout
));
1408 PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic
, sizeof(gHaltTimeMaxPanic
));
1409 PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog
, sizeof(gHaltTimeMaxLog
));
1411 queue_init(&aggressivesQueue
);
1412 aggressivesThreadCall
= thread_call_allocate(handleAggressivesFunction
, this);
1413 aggressivesData
= OSData::withCapacity(
1414 sizeof(AggressivesRecord
) * (kPMLastAggressivenessType
+ 4));
1416 featuresDictLock
= IOLockAlloc();
1417 settingsCtrlLock
= IOLockAlloc();
1418 wakeEventLock
= IOLockAlloc();
1419 gHaltLogLock
= IOLockAlloc();
1420 setPMRootDomain(this);
1422 extraSleepTimer
= thread_call_allocate(
1423 idleSleepTimerExpired
,
1424 (thread_call_param_t
) this);
1426 powerButtonDown
= thread_call_allocate(
1427 powerButtonDownCallout
,
1428 (thread_call_param_t
) this);
1430 powerButtonUp
= thread_call_allocate(
1431 powerButtonUpCallout
,
1432 (thread_call_param_t
) this);
1434 diskSyncCalloutEntry
= thread_call_allocate(
1436 (thread_call_param_t
) this);
1437 updateConsoleUsersEntry
= thread_call_allocate(
1438 &updateConsoleUsersCallout
,
1439 (thread_call_param_t
) this);
1441 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
1442 fullWakeThreadCall
= thread_call_allocate(
1443 OSMemberFunctionCast(thread_call_func_t
, this,
1444 &IOPMrootDomain::fullWakeDelayedWork
),
1445 (thread_call_param_t
) this);
1448 setProperty(kIOSleepSupportedKey
, true);
1450 bzero(&gPMStats
, sizeof(gPMStats
));
1452 pmTracer
= PMTraceWorker::tracer(this);
1454 pmAssertions
= PMAssertionsTracker::pmAssertionsTracker(this);
1456 userDisabledAllSleep
= false;
1457 systemBooting
= true;
1458 idleSleepEnabled
= false;
1460 idleSleepTimerPending
= false;
1462 clamshellClosed
= false;
1463 clamshellExists
= false;
1464 clamshellDisabled
= true;
1465 acAdaptorConnected
= true;
1466 clamshellSleepDisabled
= false;
1467 gWakeReasonString
[0] = '\0';
1469 // Initialize to user active.
1470 // Will never transition to user inactive w/o wrangler.
1471 fullWakeReason
= kFullWakeReasonLocalUser
;
1472 userIsActive
= userWasActive
= true;
1473 clock_get_uptime(&gUserActiveAbsTime
);
1474 setProperty(gIOPMUserIsActiveKey
, kOSBooleanTrue
);
1476 // Set the default system capabilities at boot.
1477 _currentCapability
= kIOPMSystemCapabilityCPU
|
1478 kIOPMSystemCapabilityGraphics
|
1479 kIOPMSystemCapabilityAudio
|
1480 kIOPMSystemCapabilityNetwork
;
1482 _pendingCapability
= _currentCapability
;
1483 _desiredCapability
= _currentCapability
;
1484 _highestCapability
= _currentCapability
;
1485 setProperty(kIOPMSystemCapabilitiesKey
, _currentCapability
, 64);
1487 queuedSleepWakeUUIDString
= NULL
;
1488 initializeBootSessionUUID();
1489 pmStatsAppResponses
= OSArray::withCapacity(5);
1490 _statsNameKey
= OSSymbol::withCString(kIOPMStatsNameKey
);
1491 _statsPIDKey
= OSSymbol::withCString(kIOPMStatsPIDKey
);
1492 _statsTimeMSKey
= OSSymbol::withCString(kIOPMStatsTimeMSKey
);
1493 _statsResponseTypeKey
= OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey
);
1494 _statsMessageTypeKey
= OSSymbol::withCString(kIOPMStatsMessageTypeKey
);
1495 _statsPowerCapsKey
= OSSymbol::withCString(kIOPMStatsPowerCapabilityKey
);
1496 assertOnWakeSecs
= -1;// Invalid value to prevent updates
1498 pmStatsLock
= IOLockAlloc();
1499 idxPMCPUClamshell
= kCPUUnknownIndex
;
1500 idxPMCPULimitedPower
= kCPUUnknownIndex
;
1502 tmpDict
= OSDictionary::withCapacity(1);
1503 setProperty(kRootDomainSupportedFeatures
, tmpDict
);
1506 settingsCallbacks
= OSDictionary::withCapacity(1);
1508 // Create a list of the valid PM settings that we'll relay to
1509 // interested clients in setProperties() => setPMSetting()
1510 allowedPMSettings
= OSArray::withObjects(
1511 (const OSObject
**)settingsArr
,
1512 kRootDomainSettingsCount
,
1515 // List of PM settings that should not automatically publish itself
1516 // as a feature when registered by a listener.
1517 noPublishPMSettings
= OSArray::withObjects(
1518 (const OSObject
**)noPublishSettingsArr
,
1519 kRootDomainNoPublishSettingsCount
,
1522 fPMSettingsDict
= OSDictionary::withCapacity(5);
1523 preventIdleSleepList
= OSSet::withCapacity(8);
1524 preventSystemSleepList
= OSSet::withCapacity(2);
1526 PMinit(); // creates gIOPMWorkLoop
1527 gIOPMWorkLoop
= getIOPMWorkloop();
1529 // Create IOPMPowerStateQueue used to queue external power
1530 // events, and to handle those events on the PM work loop.
1531 pmPowerStateQueue
= IOPMPowerStateQueue::PMPowerStateQueue(
1532 this, OSMemberFunctionCast(IOEventSource::Action
, this,
1533 &IOPMrootDomain::dispatchPowerEvent
));
1534 gIOPMWorkLoop
->addEventSource(pmPowerStateQueue
);
1537 _aotTimerES
= IOTimerEventSource::timerEventSource(this,
1538 OSMemberFunctionCast(IOTimerEventSource::Action
,
1539 this, &IOPMrootDomain::aotEvaluate
));
1540 gIOPMWorkLoop
->addEventSource(_aotTimerES
);
1542 // create our power parent
1543 patriarch
= new IORootParent
;
1545 patriarch
->attach(this);
1546 patriarch
->start(this);
1547 patriarch
->addPowerChild(this);
1549 registerPowerDriver(this, ourPowerStates
, NUM_POWER_STATES
);
1550 changePowerStateToPriv(ON_STATE
);
1552 // install power change handler
1553 gSysPowerDownNotifier
= registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, NULL
);
1556 // Register for a notification when IODisplayWrangler is published
1557 if ((tmpDict
= serviceMatching("IODisplayWrangler"))) {
1558 _displayWranglerNotifier
= addMatchingNotification(
1559 gIOPublishNotification
, tmpDict
,
1560 (IOServiceMatchingNotificationHandler
) & displayWranglerMatchPublished
,
1566 #if defined(__i386__) || defined(__x86_64__)
1568 wranglerIdleSettings
= NULL
;
1569 OSNumber
* wranglerIdlePeriod
= NULL
;
1570 wranglerIdleSettings
= OSDictionary::withCapacity(1);
1571 wranglerIdlePeriod
= OSNumber::withNumber(kDefaultWranglerIdlePeriod
, 32);
1573 if (wranglerIdleSettings
&& wranglerIdlePeriod
) {
1574 wranglerIdleSettings
->setObject(kIORequestWranglerIdleKey
,
1575 wranglerIdlePeriod
);
1578 if (wranglerIdlePeriod
) {
1579 wranglerIdlePeriod
->release();
1583 const OSSymbol
*ucClassName
= OSSymbol::withCStringNoCopy("RootDomainUserClient");
1584 setProperty(gIOUserClientClassKey
, (OSObject
*) ucClassName
);
1585 ucClassName
->release();
1587 // IOBacklightDisplay can take a long time to load at boot, or it may
1588 // not load at all if you're booting with clamshell closed. We publish
1589 // 'DisplayDims' here redundantly to get it published early and at all.
1590 OSDictionary
* matching
;
1591 matching
= serviceMatching("IOPMPowerSource");
1592 psIterator
= getMatchingServices( matching
);
1594 matching
->release();
1596 if (psIterator
&& psIterator
->getNextObject()) {
1597 // There's at least one battery on the system, so we publish
1598 // 'DisplayDims' support for the LCD.
1599 publishFeature("DisplayDims");
1602 psIterator
->release();
1605 // read swd_panic boot-arg
1606 PE_parse_boot_argn("swd_panic", &gSwdPanic
, sizeof(gSwdPanic
));
1607 sysctl_register_oid(&sysctl__kern_sleeptime
);
1608 sysctl_register_oid(&sysctl__kern_waketime
);
1609 sysctl_register_oid(&sysctl__kern_willshutdown
);
1610 sysctl_register_oid(&sysctl__kern_iokittest
);
1611 sysctl_register_oid(&sysctl__debug_iokit
);
1612 sysctl_register_oid(&sysctl__hw_targettype
);
1614 #if !CONFIG_EMBEDDED
1615 sysctl_register_oid(&sysctl__kern_progressmeterenable
);
1616 sysctl_register_oid(&sysctl__kern_progressmeter
);
1617 sysctl_register_oid(&sysctl__kern_wakereason
);
1618 #endif /* !CONFIG_EMBEDDED */
1619 sysctl_register_oid(&sysctl__kern_consoleoptions
);
1620 sysctl_register_oid(&sysctl__kern_progressoptions
);
1622 sysctl_register_oid(&sysctl__kern_aotmode
);
1623 sysctl_register_oid(&sysctl__kern_aotmodebits
);
1624 sysctl_register_oid(&sysctl__kern_aotmetrics
);
1627 IOHibernateSystemInit(this);
1630 registerService(); // let clients find us
1635 //******************************************************************************
1638 // Receive a setProperty call
1639 // The "System Boot" property means the system is completely booted.
1640 //******************************************************************************
1643 IOPMrootDomain::setProperties( OSObject
* props_obj
)
1645 IOReturn return_value
= kIOReturnSuccess
;
1646 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, props_obj
);
1649 const OSSymbol
*key
;
1651 OSCollectionIterator
* iter
= NULL
;
1654 return kIOReturnBadArgument
;
1657 bool clientEntitled
= false;
1658 obj
= IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty
);
1659 clientEntitled
= (obj
== kOSBooleanTrue
);
1660 OSSafeReleaseNULL(obj
);
1662 if (!clientEntitled
) {
1663 const char * errorSuffix
= NULL
;
1665 // IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1666 // That API can set 6 possible keys that are checked below.
1667 if ((dict
->getCount() == 1) &&
1668 (dict
->getObject(gIOPMSettingAutoWakeSecondsKey
) ||
1669 dict
->getObject(gIOPMSettingAutoPowerSecondsKey
) ||
1670 dict
->getObject(gIOPMSettingAutoWakeCalendarKey
) ||
1671 dict
->getObject(gIOPMSettingAutoPowerCalendarKey
) ||
1672 dict
->getObject(gIOPMSettingDebugWakeRelativeKey
) ||
1673 dict
->getObject(gIOPMSettingDebugPowerRelativeKey
))) {
1674 return_value
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
1675 if (return_value
!= kIOReturnSuccess
) {
1676 errorSuffix
= "privileged";
1679 return_value
= kIOReturnNotPermitted
;
1680 errorSuffix
= "entitled";
1683 if (return_value
!= kIOReturnSuccess
) {
1684 OSString
* procName
= IOCopyLogNameForPID(proc_selfpid());
1685 DLOG("%s failed, process %s is not %s\n", __func__
,
1686 procName
? procName
->getCStringNoCopy() : "", errorSuffix
);
1687 OSSafeReleaseNULL(procName
);
1688 return return_value
;
1692 const OSSymbol
*publish_simulated_battery_string
= OSSymbol::withCString("SoftwareSimulatedBatteries");
1693 const OSSymbol
*boot_complete_string
= OSSymbol::withCString("System Boot Complete");
1694 const OSSymbol
*sys_shutdown_string
= OSSymbol::withCString("System Shutdown");
1695 const OSSymbol
*stall_halt_string
= OSSymbol::withCString("StallSystemAtHalt");
1696 const OSSymbol
*battery_warning_disabled_string
= OSSymbol::withCString("BatteryWarningsDisabled");
1697 const OSSymbol
*idle_seconds_string
= OSSymbol::withCString("System Idle Seconds");
1698 const OSSymbol
*sleepdisabled_string
= OSSymbol::withCString("SleepDisabled");
1699 const OSSymbol
*ondeck_sleepwake_uuid_string
= OSSymbol::withCString(kIOPMSleepWakeUUIDKey
);
1700 const OSSymbol
*loginwindow_progress_string
= OSSymbol::withCString(kIOPMLoginWindowProgressKey
);
1701 const OSSymbol
*coredisplay_progress_string
= OSSymbol::withCString(kIOPMCoreDisplayProgressKey
);
1702 const OSSymbol
*coregraphics_progress_string
= OSSymbol::withCString(kIOPMCoreGraphicsProgressKey
);
1704 const OSSymbol
*hibernatemode_string
= OSSymbol::withCString(kIOHibernateModeKey
);
1705 const OSSymbol
*hibernatefile_string
= OSSymbol::withCString(kIOHibernateFileKey
);
1706 const OSSymbol
*hibernatefilemin_string
= OSSymbol::withCString(kIOHibernateFileMinSizeKey
);
1707 const OSSymbol
*hibernatefilemax_string
= OSSymbol::withCString(kIOHibernateFileMaxSizeKey
);
1708 const OSSymbol
*hibernatefreeratio_string
= OSSymbol::withCString(kIOHibernateFreeRatioKey
);
1709 const OSSymbol
*hibernatefreetime_string
= OSSymbol::withCString(kIOHibernateFreeTimeKey
);
1712 iter
= OSCollectionIterator::withCollection(dict
);
1714 return_value
= kIOReturnNoMemory
;
1718 while ((key
= (const OSSymbol
*) iter
->getNextObject()) &&
1719 (obj
= dict
->getObject(key
))) {
1720 if (key
->isEqualTo(publish_simulated_battery_string
)) {
1721 if (OSDynamicCast(OSBoolean
, obj
)) {
1722 publishResource(key
, kOSBooleanTrue
);
1724 } else if (key
->isEqualTo(idle_seconds_string
)) {
1725 if ((n
= OSDynamicCast(OSNumber
, obj
))) {
1726 setProperty(key
, n
);
1727 idleSeconds
= n
->unsigned32BitValue();
1729 } else if (key
->isEqualTo(boot_complete_string
)) {
1730 pmPowerStateQueue
->submitPowerEvent(kPowerEventSystemBootCompleted
);
1731 } else if (key
->isEqualTo(sys_shutdown_string
)) {
1732 if ((b
= OSDynamicCast(OSBoolean
, obj
))) {
1733 pmPowerStateQueue
->submitPowerEvent(kPowerEventSystemShutdown
, (void *) b
);
1735 } else if (key
->isEqualTo(battery_warning_disabled_string
)) {
1736 setProperty(key
, obj
);
1739 else if (key
->isEqualTo(hibernatemode_string
) ||
1740 key
->isEqualTo(hibernatefilemin_string
) ||
1741 key
->isEqualTo(hibernatefilemax_string
) ||
1742 key
->isEqualTo(hibernatefreeratio_string
) ||
1743 key
->isEqualTo(hibernatefreetime_string
)) {
1744 if ((n
= OSDynamicCast(OSNumber
, obj
))) {
1745 setProperty(key
, n
);
1747 } else if (key
->isEqualTo(hibernatefile_string
)) {
1748 OSString
* str
= OSDynamicCast(OSString
, obj
);
1750 setProperty(key
, str
);
1754 else if (key
->isEqualTo(sleepdisabled_string
)) {
1755 if ((b
= OSDynamicCast(OSBoolean
, obj
))) {
1756 setProperty(key
, b
);
1757 pmPowerStateQueue
->submitPowerEvent(kPowerEventUserDisabledSleep
, (void *) b
);
1759 } else if (key
->isEqualTo(ondeck_sleepwake_uuid_string
)) {
1761 pmPowerStateQueue
->submitPowerEvent(kPowerEventQueueSleepWakeUUID
, (void *)obj
);
1762 } else if (key
->isEqualTo(loginwindow_progress_string
)) {
1763 if (pmTracer
&& (n
= OSDynamicCast(OSNumber
, obj
))) {
1764 uint32_t data
= n
->unsigned32BitValue();
1765 pmTracer
->traceComponentWakeProgress(kIOPMLoginWindowProgress
, data
);
1766 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMLoginWindowProgress
, data
);
1768 } else if (key
->isEqualTo(coredisplay_progress_string
)) {
1769 if (pmTracer
&& (n
= OSDynamicCast(OSNumber
, obj
))) {
1770 uint32_t data
= n
->unsigned32BitValue();
1771 pmTracer
->traceComponentWakeProgress(kIOPMCoreDisplayProgress
, data
);
1772 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMCoreDisplayProgress
, data
);
1774 } else if (key
->isEqualTo(coregraphics_progress_string
)) {
1775 if (pmTracer
&& (n
= OSDynamicCast(OSNumber
, obj
))) {
1776 uint32_t data
= n
->unsigned32BitValue();
1777 pmTracer
->traceComponentWakeProgress(kIOPMCoreGraphicsProgress
, data
);
1778 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMCoreGraphicsProgress
, data
);
1780 } else if (key
->isEqualTo(kIOPMDeepSleepEnabledKey
) ||
1781 key
->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey
) ||
1782 key
->isEqualTo(kIOPMAutoPowerOffEnabledKey
) ||
1783 key
->isEqualTo(stall_halt_string
)) {
1784 if ((b
= OSDynamicCast(OSBoolean
, obj
))) {
1785 setProperty(key
, b
);
1787 } else if (key
->isEqualTo(kIOPMDeepSleepDelayKey
) ||
1788 key
->isEqualTo(kIOPMDeepSleepTimerKey
) ||
1789 key
->isEqualTo(kIOPMAutoPowerOffDelayKey
) ||
1790 key
->isEqualTo(kIOPMAutoPowerOffTimerKey
)) {
1791 if ((n
= OSDynamicCast(OSNumber
, obj
))) {
1792 setProperty(key
, n
);
1794 } else if (key
->isEqualTo(kIOPMUserWakeAlarmScheduledKey
)) {
1795 if (kOSBooleanTrue
== obj
) {
1796 OSBitOrAtomic(kIOPMAlarmBitCalendarWake
, &_userScheduledAlarm
);
1798 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake
, &_userScheduledAlarm
);
1800 DLOG("_userScheduledAlarm = 0x%x\n", (uint32_t) _userScheduledAlarm
);
1802 // Relay our allowed PM settings onto our registered PM clients
1803 else if ((allowedPMSettings
->getNextIndexOfObject(key
, 0) != (unsigned int) -1)) {
1804 return_value
= setPMSetting(key
, obj
);
1805 if (kIOReturnSuccess
!= return_value
) {
1809 if (gIOPMSettingDebugWakeRelativeKey
== key
) {
1810 if ((n
= OSDynamicCast(OSNumber
, obj
)) &&
1811 (_debugWakeSeconds
= n
->unsigned32BitValue())) {
1812 OSBitOrAtomic(kIOPMAlarmBitDebugWake
, &_scheduledAlarms
);
1814 _debugWakeSeconds
= 0;
1815 OSBitAndAtomic(~kIOPMAlarmBitDebugWake
, &_scheduledAlarms
);
1817 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms
);
1818 } else if (gIOPMSettingAutoWakeCalendarKey
== key
) {
1820 if ((data
= OSDynamicCast(OSData
, obj
)) &&
1821 (data
->getLength() == sizeof(IOPMCalendarStruct
))) {
1822 const IOPMCalendarStruct
* cs
=
1823 (const IOPMCalendarStruct
*) data
->getBytesNoCopy();
1824 IOLog("gIOPMSettingAutoWakeCalendarKey " YMDTF
"\n", YMDT(cs
));
1826 _scheduledAlarmUTC
= IOPMConvertCalendarToSeconds(cs
);
1827 OSBitOrAtomic(kIOPMAlarmBitCalendarWake
, &_scheduledAlarms
);
1829 _scheduledAlarmUTC
= 0;
1830 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake
, &_scheduledAlarms
);
1832 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms
);
1836 DLOG("setProperties(%s) not handled\n", key
->getCStringNoCopy());
1841 if (publish_simulated_battery_string
) {
1842 publish_simulated_battery_string
->release();
1844 if (boot_complete_string
) {
1845 boot_complete_string
->release();
1847 if (sys_shutdown_string
) {
1848 sys_shutdown_string
->release();
1850 if (stall_halt_string
) {
1851 stall_halt_string
->release();
1853 if (battery_warning_disabled_string
) {
1854 battery_warning_disabled_string
->release();
1856 if (idle_seconds_string
) {
1857 idle_seconds_string
->release();
1859 if (sleepdisabled_string
) {
1860 sleepdisabled_string
->release();
1862 if (ondeck_sleepwake_uuid_string
) {
1863 ondeck_sleepwake_uuid_string
->release();
1865 if (loginwindow_progress_string
) {
1866 loginwindow_progress_string
->release();
1868 if (coredisplay_progress_string
) {
1869 coredisplay_progress_string
->release();
1871 if (coregraphics_progress_string
) {
1872 coregraphics_progress_string
->release();
1875 if (hibernatemode_string
) {
1876 hibernatemode_string
->release();
1878 if (hibernatefile_string
) {
1879 hibernatefile_string
->release();
1881 if (hibernatefreeratio_string
) {
1882 hibernatefreeratio_string
->release();
1884 if (hibernatefreetime_string
) {
1885 hibernatefreetime_string
->release();
1891 return return_value
;
1895 // MARK: Aggressiveness
1897 //******************************************************************************
1898 // setAggressiveness
1900 // Override IOService::setAggressiveness()
1901 //******************************************************************************
1904 IOPMrootDomain::setAggressiveness(
1906 unsigned long value
)
1908 return setAggressiveness( type
, value
, 0 );
1912 * Private setAggressiveness() with an internal options argument.
1915 IOPMrootDomain::setAggressiveness(
1917 unsigned long value
,
1918 IOOptionBits options
)
1920 AggressivesRequest
* entry
;
1921 AggressivesRequest
* request
;
1924 if (type
== kPMMinutesToDim
|| type
== kPMMinutesToSleep
) {
1925 DLOG("setAggressiveness(%x) %s = %u\n",
1926 (uint32_t) options
, getAggressivenessTypeString((uint32_t) type
), (uint32_t) value
);
1928 DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
1929 (uint32_t) options
, getAggressivenessTypeString((uint32_t) type
), (uint32_t) value
);
1932 request
= IONew(AggressivesRequest
, 1);
1934 return kIOReturnNoMemory
;
1937 memset(request
, 0, sizeof(*request
));
1938 request
->options
= options
;
1939 request
->dataType
= kAggressivesRequestTypeRecord
;
1940 request
->data
.record
.type
= (uint32_t) type
;
1941 request
->data
.record
.value
= (uint32_t) value
;
1945 // Update disk quick spindown flag used by getAggressiveness().
1946 // Never merge requests with quick spindown flags set.
1948 if (options
& kAggressivesOptionQuickSpindownEnable
) {
1949 gAggressivesState
|= kAggressivesStateQuickSpindown
;
1950 } else if (options
& kAggressivesOptionQuickSpindownDisable
) {
1951 gAggressivesState
&= ~kAggressivesStateQuickSpindown
;
1953 // Coalesce requests with identical aggressives types.
1954 // Deal with callers that calls us too "aggressively".
1956 queue_iterate(&aggressivesQueue
, entry
, AggressivesRequest
*, chain
)
1958 if ((entry
->dataType
== kAggressivesRequestTypeRecord
) &&
1959 (entry
->data
.record
.type
== type
) &&
1960 ((entry
->options
& kAggressivesOptionQuickSpindownMask
) == 0)) {
1961 entry
->data
.record
.value
= value
;
1969 queue_enter(&aggressivesQueue
, request
, AggressivesRequest
*, chain
);
1972 AGGRESSIVES_UNLOCK();
1975 IODelete(request
, AggressivesRequest
, 1);
1978 if (options
& kAggressivesOptionSynchronous
) {
1979 handleAggressivesRequests(); // not truly synchronous
1981 thread_call_enter(aggressivesThreadCall
);
1984 return kIOReturnSuccess
;
1987 //******************************************************************************
1988 // getAggressiveness
1990 // Override IOService::setAggressiveness()
1991 // Fetch the aggressiveness factor with the given type.
1992 //******************************************************************************
1995 IOPMrootDomain::getAggressiveness(
1997 unsigned long * outLevel
)
2003 return kIOReturnBadArgument
;
2008 // Disk quick spindown in effect, report value = 1
2010 if ((gAggressivesState
& kAggressivesStateQuickSpindown
) &&
2011 (type
== kPMMinutesToSpinDown
)) {
2012 value
= kAggressivesMinValue
;
2016 // Consult the pending request queue.
2019 AggressivesRequest
* entry
;
2021 queue_iterate(&aggressivesQueue
, entry
, AggressivesRequest
*, chain
)
2023 if ((entry
->dataType
== kAggressivesRequestTypeRecord
) &&
2024 (entry
->data
.record
.type
== type
) &&
2025 ((entry
->options
& kAggressivesOptionQuickSpindownMask
) == 0)) {
2026 value
= entry
->data
.record
.value
;
2033 // Consult the backend records.
2035 if (!source
&& aggressivesData
) {
2036 AggressivesRecord
* record
;
2039 count
= aggressivesData
->getLength() / sizeof(AggressivesRecord
);
2040 record
= (AggressivesRecord
*) aggressivesData
->getBytesNoCopy();
2042 for (i
= 0; i
< count
; i
++, record
++) {
2043 if (record
->type
== type
) {
2044 value
= record
->value
;
2051 AGGRESSIVES_UNLOCK();
2054 *outLevel
= (unsigned long) value
;
2055 return kIOReturnSuccess
;
2057 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type
);
2058 *outLevel
= 0; // default return = 0, driver may not check for error
2059 return kIOReturnInvalid
;
2063 //******************************************************************************
2064 // joinAggressiveness
2066 // Request from IOService to join future aggressiveness broadcasts.
2067 //******************************************************************************
2070 IOPMrootDomain::joinAggressiveness(
2071 IOService
* service
)
2073 AggressivesRequest
* request
;
2075 if (!service
|| (service
== this)) {
2076 return kIOReturnBadArgument
;
2079 DEBUG_LOG("joinAggressiveness %s %p\n", service
->getName(), OBFUSCATE(service
));
2081 request
= IONew(AggressivesRequest
, 1);
2083 return kIOReturnNoMemory
;
2086 service
->retain(); // released by synchronizeAggressives()
2088 memset(request
, 0, sizeof(*request
));
2089 request
->dataType
= kAggressivesRequestTypeService
;
2090 request
->data
.service
= service
;
2093 queue_enter(&aggressivesQueue
, request
, AggressivesRequest
*, chain
);
2094 AGGRESSIVES_UNLOCK();
2096 thread_call_enter(aggressivesThreadCall
);
2098 return kIOReturnSuccess
;
2101 //******************************************************************************
2102 // handleAggressivesRequests
2104 // Backend thread processes all incoming aggressiveness requests in the queue.
2105 //******************************************************************************
2108 handleAggressivesFunction(
2109 thread_call_param_t param1
,
2110 thread_call_param_t param2
)
2113 ((IOPMrootDomain
*) param1
)->handleAggressivesRequests();
2118 IOPMrootDomain::handleAggressivesRequests( void )
2120 AggressivesRecord
* start
;
2121 AggressivesRecord
* record
;
2122 AggressivesRequest
* request
;
2123 queue_head_t joinedQueue
;
2127 bool pingSelf
= false;
2131 if ((gAggressivesState
& kAggressivesStateBusy
) || !aggressivesData
||
2132 queue_empty(&aggressivesQueue
)) {
2136 gAggressivesState
|= kAggressivesStateBusy
;
2137 count
= aggressivesData
->getLength() / sizeof(AggressivesRecord
);
2138 start
= (AggressivesRecord
*) aggressivesData
->getBytesNoCopy();
2142 queue_init(&joinedQueue
);
2145 // Remove request from the incoming queue in FIFO order.
2146 queue_remove_first(&aggressivesQueue
, request
, AggressivesRequest
*, chain
);
2147 switch (request
->dataType
) {
2148 case kAggressivesRequestTypeRecord
:
2149 // Update existing record if found.
2151 for (i
= 0, record
= start
; i
< count
; i
++, record
++) {
2152 if (record
->type
== request
->data
.record
.type
) {
2155 if (request
->options
& kAggressivesOptionQuickSpindownEnable
) {
2156 if ((record
->flags
& kAggressivesRecordFlagMinValue
) == 0) {
2158 record
->flags
|= (kAggressivesRecordFlagMinValue
|
2159 kAggressivesRecordFlagModified
);
2160 DLOG("disk spindown accelerated, was %u min\n",
2163 } else if (request
->options
& kAggressivesOptionQuickSpindownDisable
) {
2164 if (record
->flags
& kAggressivesRecordFlagMinValue
) {
2166 record
->flags
|= kAggressivesRecordFlagModified
;
2167 record
->flags
&= ~kAggressivesRecordFlagMinValue
;
2168 DLOG("disk spindown restored to %u min\n",
2171 } else if (record
->value
!= request
->data
.record
.value
) {
2172 record
->value
= request
->data
.record
.value
;
2173 if ((record
->flags
& kAggressivesRecordFlagMinValue
) == 0) {
2175 record
->flags
|= kAggressivesRecordFlagModified
;
2182 // No matching record, append a new record.
2184 ((request
->options
& kAggressivesOptionQuickSpindownDisable
) == 0)) {
2185 AggressivesRecord newRecord
;
2187 newRecord
.flags
= kAggressivesRecordFlagModified
;
2188 newRecord
.type
= request
->data
.record
.type
;
2189 newRecord
.value
= request
->data
.record
.value
;
2190 if (request
->options
& kAggressivesOptionQuickSpindownEnable
) {
2191 newRecord
.flags
|= kAggressivesRecordFlagMinValue
;
2192 DLOG("disk spindown accelerated\n");
2195 aggressivesData
->appendBytes(&newRecord
, sizeof(newRecord
));
2197 // OSData may have switched to another (larger) buffer.
2198 count
= aggressivesData
->getLength() / sizeof(AggressivesRecord
);
2199 start
= (AggressivesRecord
*) aggressivesData
->getBytesNoCopy();
2203 // Finished processing the request, release it.
2204 IODelete(request
, AggressivesRequest
, 1);
2207 case kAggressivesRequestTypeService
:
2208 // synchronizeAggressives() will free request.
2209 queue_enter(&joinedQueue
, request
, AggressivesRequest
*, chain
);
2213 panic("bad aggressives request type %x\n", request
->dataType
);
2216 } while (!queue_empty(&aggressivesQueue
));
2218 // Release the lock to perform work, with busy flag set.
2219 if (!queue_empty(&joinedQueue
) || broadcast
) {
2220 AGGRESSIVES_UNLOCK();
2221 if (!queue_empty(&joinedQueue
)) {
2222 synchronizeAggressives(&joinedQueue
, start
, count
);
2225 broadcastAggressives(start
, count
);
2230 // Remove the modified flag from all records.
2231 for (i
= 0, record
= start
; i
< count
; i
++, record
++) {
2232 if ((record
->flags
& kAggressivesRecordFlagModified
) &&
2233 ((record
->type
== kPMMinutesToDim
) ||
2234 (record
->type
== kPMMinutesToSleep
))) {
2238 record
->flags
&= ~kAggressivesRecordFlagModified
;
2241 // Check the incoming queue again since new entries may have been
2242 // added while lock was released above.
2243 } while (!queue_empty(&aggressivesQueue
));
2245 gAggressivesState
&= ~kAggressivesStateBusy
;
2248 AGGRESSIVES_UNLOCK();
2250 // Root domain is interested in system and display sleep slider changes.
2251 // Submit a power event to handle those changes on the PM work loop.
2253 if (pingSelf
&& pmPowerStateQueue
) {
2254 pmPowerStateQueue
->submitPowerEvent(
2255 kPowerEventPolicyStimulus
,
2256 (void *) kStimulusAggressivenessChanged
);
2260 //******************************************************************************
2261 // synchronizeAggressives
2263 // Push all known aggressiveness records to one or more IOService.
2264 //******************************************************************************
2267 IOPMrootDomain::synchronizeAggressives(
2268 queue_head_t
* joinedQueue
,
2269 const AggressivesRecord
* array
,
2272 IOService
* service
;
2273 AggressivesRequest
* request
;
2274 const AggressivesRecord
* record
;
2275 IOPMDriverCallEntry callEntry
;
2279 while (!queue_empty(joinedQueue
)) {
2280 queue_remove_first(joinedQueue
, request
, AggressivesRequest
*, chain
);
2281 if (request
->dataType
== kAggressivesRequestTypeService
) {
2282 service
= request
->data
.service
;
2287 IODelete(request
, AggressivesRequest
, 1);
2291 if (service
->assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetAggressive
)) {
2292 for (i
= 0, record
= array
; i
< count
; i
++, record
++) {
2293 value
= record
->value
;
2294 if (record
->flags
& kAggressivesRecordFlagMinValue
) {
2295 value
= kAggressivesMinValue
;
2298 _LOG("synchronizeAggressives 0x%x = %u to %s\n",
2299 record
->type
, value
, service
->getName());
2300 service
->setAggressiveness(record
->type
, value
);
2302 service
->deassertPMDriverCall(&callEntry
);
2304 service
->release(); // retained by joinAggressiveness()
2309 //******************************************************************************
2310 // broadcastAggressives
2312 // Traverse PM tree and call setAggressiveness() for records that have changed.
2313 //******************************************************************************
2316 IOPMrootDomain::broadcastAggressives(
2317 const AggressivesRecord
* array
,
2320 IORegistryIterator
* iter
;
2321 IORegistryEntry
* entry
;
2322 IOPowerConnection
* connect
;
2323 IOService
* service
;
2324 const AggressivesRecord
* record
;
2325 IOPMDriverCallEntry callEntry
;
2329 iter
= IORegistryIterator::iterateOver(
2330 this, gIOPowerPlane
, kIORegistryIterateRecursively
);
2334 while ((entry
= iter
->getNextObject())) {
2335 connect
= OSDynamicCast(IOPowerConnection
, entry
);
2336 if (!connect
|| !connect
->getReadyFlag()) {
2340 if ((service
= OSDynamicCast(IOService
, connect
->copyChildEntry(gIOPowerPlane
)))) {
2341 if (service
->assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetAggressive
)) {
2342 for (i
= 0, record
= array
; i
< count
; i
++, record
++) {
2343 if (record
->flags
& kAggressivesRecordFlagModified
) {
2344 value
= record
->value
;
2345 if (record
->flags
& kAggressivesRecordFlagMinValue
) {
2346 value
= kAggressivesMinValue
;
2348 _LOG("broadcastAggressives %x = %u to %s\n",
2349 record
->type
, value
, service
->getName());
2350 service
->setAggressiveness(record
->type
, value
);
2353 service
->deassertPMDriverCall(&callEntry
);
2358 }while (!entry
&& !iter
->isValid());
2363 //*****************************************
2364 // stackshot on power button press
2365 // ***************************************
2367 powerButtonDownCallout(thread_call_param_t us
, thread_call_param_t
)
2369 /* Power button pressed during wake
2372 DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2373 ((IOPMrootDomain
*)us
)->takeStackshot(false);
2377 powerButtonUpCallout(thread_call_param_t us
, thread_call_param_t
)
2379 /* Power button released.
2380 * Delete any stackshot data
2382 DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2383 ((IOPMrootDomain
*)us
)->deleteStackshot();
2385 //*************************************************************************
2389 // MARK: System Sleep
2391 //******************************************************************************
2392 // startIdleSleepTimer
2394 //******************************************************************************
2397 IOPMrootDomain::startIdleSleepTimer( uint32_t inSeconds
)
2399 AbsoluteTime deadline
;
2403 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag
);
2407 clock_interval_to_deadline(inSeconds
, kSecondScale
, &deadline
);
2408 thread_call_enter_delayed(extraSleepTimer
, deadline
);
2409 idleSleepTimerPending
= true;
2411 thread_call_enter(extraSleepTimer
);
2413 DLOG("idle timer set for %u seconds\n", inSeconds
);
2416 //******************************************************************************
2417 // cancelIdleSleepTimer
2419 //******************************************************************************
2422 IOPMrootDomain::cancelIdleSleepTimer( void )
2425 if (idleSleepTimerPending
) {
2426 DLOG("idle timer cancelled\n");
2427 thread_call_cancel(extraSleepTimer
);
2428 idleSleepTimerPending
= false;
2430 if (!assertOnWakeSecs
&& gIOLastWakeAbsTime
) {
2432 clock_usec_t microsecs
;
2433 clock_get_uptime(&now
);
2434 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
2435 absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
);
2436 if (assertOnWakeReport
) {
2437 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
);
2438 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
);
2444 //******************************************************************************
2445 // idleSleepTimerExpired
2447 //******************************************************************************
2450 idleSleepTimerExpired(
2451 thread_call_param_t us
, thread_call_param_t
)
2453 ((IOPMrootDomain
*)us
)->handleSleepTimerExpiration();
2456 //******************************************************************************
2457 // handleSleepTimerExpiration
2459 // The time between the sleep idle timeout and the next longest one has elapsed.
2460 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2461 //******************************************************************************
2464 IOPMrootDomain::handleSleepTimerExpiration( void )
2466 if (!gIOPMWorkLoop
->inGate()) {
2467 gIOPMWorkLoop
->runAction(
2468 OSMemberFunctionCast(IOWorkLoop::Action
, this,
2469 &IOPMrootDomain::handleSleepTimerExpiration
),
2476 DLOG("sleep timer expired\n");
2479 idleSleepTimerPending
= false;
2481 clock_get_uptime(&time
);
2482 setQuickSpinDownTimeout();
2483 adjustPowerState(true);
2486 //******************************************************************************
2487 // getTimeToIdleSleep
2489 // Returns number of seconds left before going into idle sleep.
2490 // Caller has to make sure that idle sleep is allowed at the time of calling
2492 //******************************************************************************
2495 IOPMrootDomain::getTimeToIdleSleep( void )
2497 AbsoluteTime now
, lastActivityTime
;
2499 uint32_t minutesSinceUserInactive
= 0;
2500 uint32_t sleepDelay
= 0;
2502 if (!idleSleepEnabled
) {
2506 if (userActivityTime
) {
2507 lastActivityTime
= userActivityTime
;
2509 lastActivityTime
= userBecameInactiveTime
;
2512 clock_get_uptime(&now
);
2513 if (CMP_ABSOLUTETIME(&now
, &lastActivityTime
) > 0) {
2514 SUB_ABSOLUTETIME(&now
, &lastActivityTime
);
2515 absolutetime_to_nanoseconds(now
, &nanos
);
2516 minutesSinceUserInactive
= nanos
/ (60000000000ULL);
2518 if (minutesSinceUserInactive
>= sleepSlider
) {
2521 sleepDelay
= sleepSlider
- minutesSinceUserInactive
;
2524 sleepDelay
= sleepSlider
;
2527 DLOG("user inactive %u min, time to idle sleep %u min\n",
2528 minutesSinceUserInactive
, sleepDelay
);
2530 return sleepDelay
* 60;
2533 //******************************************************************************
2534 // setQuickSpinDownTimeout
2536 //******************************************************************************
2539 IOPMrootDomain::setQuickSpinDownTimeout( void )
2543 kPMMinutesToSpinDown
, 0, kAggressivesOptionQuickSpindownEnable
);
2546 //******************************************************************************
2547 // restoreUserSpinDownTimeout
2549 //******************************************************************************
2552 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2556 kPMMinutesToSpinDown
, 0, kAggressivesOptionQuickSpindownDisable
);
2559 //******************************************************************************
2562 //******************************************************************************
2566 IOPMrootDomain::sleepSystem( void )
2568 return sleepSystemOptions(NULL
);
2573 IOPMrootDomain::sleepSystemOptions( OSDictionary
*options
)
2575 OSObject
*obj
= NULL
;
2576 OSString
*reason
= NULL
;
2577 /* sleepSystem is a public function, and may be called by any kernel driver.
2578 * And that's bad - drivers should sleep the system by calling
2579 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2581 * Note that user space app calls to IOPMSleepSystem() will also travel
2582 * this code path and thus be correctly identified as software sleeps.
2585 if (options
&& options
->getObject("OSSwitch")) {
2586 // Log specific sleep cause for OS Switch hibernation
2587 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate
);
2590 if (options
&& (obj
= options
->getObject("Sleep Reason"))) {
2591 reason
= OSDynamicCast(OSString
, obj
);
2592 if (reason
&& reason
->isEqualTo(kIOPMDarkWakeThermalEmergencyKey
)) {
2593 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency
);
2597 return privateSleepSystem( kIOPMSleepReasonSoftware
);
2602 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason
)
2604 /* Called from both gated and non-gated context */
2606 if (!checkSystemSleepEnabled() || !pmPowerStateQueue
) {
2607 return kIOReturnNotPermitted
;
2610 pmPowerStateQueue
->submitPowerEvent(
2611 kPowerEventPolicyStimulus
,
2612 (void *) kStimulusDemandSystemSleep
,
2615 return kIOReturnSuccess
;
2618 //******************************************************************************
2621 // This overrides powerChangeDone in IOService.
2622 //******************************************************************************
2624 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState
)
2626 #if !__i386__ && !__x86_64__
2627 uint64_t timeSinceReset
= 0;
2630 unsigned long newState
;
2632 clock_usec_t microsecs
;
2633 clock_sec_t adjWakeTime
;
2634 IOPMCalendarStruct nowCalendar
;
2637 newState
= getPowerState();
2638 DLOG("PowerChangeDone: %s->%s\n",
2639 getPowerStateString((uint32_t) previousPowerState
), getPowerStateString((uint32_t) getPowerState()));
2641 if (previousPowerState
== newState
) {
2645 notifierThread
= current_thread();
2646 switch (getPowerState()) {
2648 if (kPMCalendarTypeInvalid
!= _aotWakeTimeCalendar
.selector
) {
2651 PEGetUTCTimeOfDay(&secs
, µsecs
);
2654 if ((kIOPMAOTModeRespectTimers
& _aotMode
) && (_scheduledAlarmUTC
< _aotWakeTimeUTC
)) {
2655 IOLog("use _scheduledAlarmUTC\n");
2656 adjWakeTime
= _scheduledAlarmUTC
;
2657 } else if (_aotExit
|| (kIOPMWakeEventAOTExitFlags
& _aotPendingFlags
)) {
2658 IOLog("accelerate _aotWakeTime for exit\n");
2660 } else if (kIOPMDriverAssertionLevelOn
== getPMAssertionLevel(kIOPMDriverAssertionCPUBit
)) {
2661 IOLog("accelerate _aotWakeTime for assertion\n");
2665 IOPMConvertSecondsToCalendar(adjWakeTime
, &_aotWakeTimeCalendar
);
2668 IOPMConvertSecondsToCalendar(secs
, &nowCalendar
);
2669 IOLog("aotSleep at " YMDTF
" sched: " YMDTF
"\n", YMDT(&nowCalendar
), YMDT(&_aotWakeTimeCalendar
));
2671 IOReturn __unused ret
= setMaintenanceWakeCalendar(&_aotWakeTimeCalendar
);
2672 assert(kIOReturnSuccess
== ret
);
2674 if (_aotLastWakeTime
) {
2675 _aotMetrics
->totalTime
+= mach_absolute_time() - _aotLastWakeTime
;
2676 if (_aotMetrics
->sleepCount
&& (_aotMetrics
->sleepCount
<= kIOPMAOTMetricsKernelWakeCountMax
)) {
2677 strlcpy(&_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
- 1][0],
2679 sizeof(_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
]));
2682 _aotPendingFlags
&= ~kIOPMWakeEventAOTPerCycleFlags
;
2683 acceptSystemWakeEvents(true);
2685 // re-enable this timer for next sleep
2686 cancelIdleSleepTimer();
2688 clock_get_calendar_absolute_and_microtime(&secs
, µsecs
, &now
);
2690 gIOLastSleepTime
.tv_sec
= secs
;
2691 gIOLastSleepTime
.tv_usec
= microsecs
;
2692 if (!_aotLastWakeTime
) {
2693 gIOLastUserSleepTime
= gIOLastSleepTime
;
2696 gIOLastWakeTime
.tv_sec
= 0;
2697 gIOLastWakeTime
.tv_usec
= 0;
2698 gIOLastSleepAbsTime
= now
;
2700 if (wake2DarkwakeDelay
&& sleepDelaysReport
) {
2701 clock_sec_t wake2DarkwakeSecs
, darkwake2SleepSecs
;
2702 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2704 SUB_ABSOLUTETIME(&now
, &ts_sleepStart
);
2705 absolutetime_to_microtime(now
, &darkwake2SleepSecs
, µsecs
);
2706 absolutetime_to_microtime(wake2DarkwakeDelay
, &wake2DarkwakeSecs
, µsecs
);
2707 HISTREPORT_TALLYVALUE(sleepDelaysReport
,
2708 (int64_t)(wake2DarkwakeSecs
+ darkwake2SleepSecs
));
2710 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs
, (unsigned long)darkwake2SleepSecs
);
2711 wake2DarkwakeDelay
= 0;
2714 LOG("System %sSleep\n", gIOHibernateState
? "Safe" : "");
2716 IOHibernateSystemHasSlept();
2718 evaluateSystemSleepPolicyFinal();
2720 LOG("System Sleep\n");
2722 if (thermalWarningState
) {
2723 const OSSymbol
*event
= OSSymbol::withCString(kIOPMThermalLevelWarningKey
);
2725 systemPowerEventOccurred(event
, kIOPMThermalLevelUnknown
);
2729 assertOnWakeSecs
= 0;
2730 lowBatteryCondition
= false;
2732 #if DEVELOPMENT || DEBUG
2733 extern int g_should_log_clock_adjustments
;
2734 if (g_should_log_clock_adjustments
) {
2735 clock_sec_t secs
= 0;
2736 clock_usec_t microsecs
= 0;
2737 uint64_t now_b
= mach_absolute_time();
2741 PEGetUTCTimeOfDay(&secs
, µsecs
);
2743 uint64_t now_a
= mach_absolute_time();
2744 os_log(OS_LOG_DEFAULT
, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
2745 __func__
, (unsigned long)secs
, microsecs
, now_b
, now_a
);
2749 getPlatform()->sleepKernel();
2751 // The CPU(s) are off at this point,
2752 // Code will resume execution here upon wake.
2754 clock_get_uptime(&gIOLastWakeAbsTime
);
2755 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime
);
2756 _highestCapability
= 0;
2759 IOHibernateSystemWake();
2762 // sleep transition complete
2763 gSleepOrShutdownPending
= 0;
2765 // trip the reset of the calendar clock
2766 clock_wakeup_calendar();
2767 clock_get_calendar_microtime(&secs
, µsecs
);
2768 gIOLastWakeTime
.tv_sec
= secs
;
2769 gIOLastWakeTime
.tv_usec
= microsecs
;
2772 if (_aotWakeTimeCalendar
.selector
!= kPMCalendarTypeInvalid
) {
2773 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeInvalid
;
2776 PEGetUTCTimeOfDay(&secs
, µsecs
);
2777 IOPMConvertSecondsToCalendar(secs
, &nowCalendar
);
2778 IOLog("aotWake at " YMDTF
" sched: " YMDTF
"\n", YMDT(&nowCalendar
), YMDT(&_aotWakeTimeCalendar
));
2779 _aotMetrics
->sleepCount
++;
2780 _aotLastWakeTime
= gIOLastWakeAbsTime
;
2781 if (_aotMetrics
->sleepCount
<= kIOPMAOTMetricsKernelWakeCountMax
) {
2782 _aotMetrics
->kernelSleepTime
[_aotMetrics
->sleepCount
- 1]
2783 = (((uint64_t) gIOLastSleepTime
.tv_sec
) << 10) + (gIOLastSleepTime
.tv_usec
/ 1000);
2784 _aotMetrics
->kernelWakeTime
[_aotMetrics
->sleepCount
- 1]
2785 = (((uint64_t) gIOLastWakeTime
.tv_sec
) << 10) + (gIOLastWakeTime
.tv_usec
/ 1000);
2789 if (_aotWakeTimeUTC
<= secs
) {
2790 _aotTestTime
= _aotTestTime
+ _aotTestInterval
;
2792 setWakeTime(_aotTestTime
);
2797 LOG("System %sWake\n", gIOHibernateState
? "SafeSleep " : "");
2800 lastSleepReason
= 0;
2802 _lastDebugWakeSeconds
= _debugWakeSeconds
;
2803 _debugWakeSeconds
= 0;
2804 _scheduledAlarms
= 0;
2806 #if defined(__i386__) || defined(__x86_64__)
2807 kdebugTrace(kPMLogSystemWake
, 0, 0, 0);
2808 wranglerTickled
= false;
2809 graphicsSuppressed
= false;
2810 darkWakePostTickle
= false;
2811 darkWakeHibernateError
= false;
2812 darkWakeToSleepASAP
= true;
2813 logGraphicsClamp
= true;
2814 sleepTimerMaintenance
= false;
2815 sleepToStandby
= false;
2816 wranglerTickleLatched
= false;
2817 userWasActive
= false;
2818 isRTCAlarmWake
= false;
2819 fullWakeReason
= kFullWakeReasonNone
;
2821 OSString
* wakeType
= OSDynamicCast(
2822 OSString
, getProperty(kIOPMRootDomainWakeTypeKey
));
2823 OSString
* wakeReason
= OSDynamicCast(
2824 OSString
, getProperty(kIOPMRootDomainWakeReasonKey
));
2826 if (wakeReason
&& (wakeReason
->getLength() >= 2) &&
2827 gWakeReasonString
[0] == '\0') {
2828 // Until the platform driver can claim its wake reasons
2829 strlcat(gWakeReasonString
, wakeReason
->getCStringNoCopy(),
2830 sizeof(gWakeReasonString
));
2833 if (wakeType
&& wakeType
->isEqualTo(kIOPMrootDomainWakeTypeLowBattery
)) {
2834 lowBatteryCondition
= true;
2835 darkWakeMaintenance
= true;
2836 } else if ((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) != 0) {
2838 OSNumber
* hibOptions
= OSDynamicCast(
2839 OSNumber
, getProperty(kIOHibernateOptionsKey
));
2840 if (hibernateAborted
|| ((hibOptions
&&
2841 !(hibOptions
->unsigned32BitValue() & kIOHibernateOptionDarkWake
)))) {
2842 // Hibernate aborted, or EFI brought up graphics
2843 wranglerTickled
= true;
2844 if (hibernateAborted
) {
2845 DLOG("Hibernation aborted\n");
2847 DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions
->unsigned32BitValue());
2852 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeUser
) ||
2853 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeAlarm
))) {
2854 // User wake or RTC alarm
2855 wranglerTickled
= true;
2856 if (wakeType
->isEqualTo(kIOPMRootDomainWakeTypeAlarm
)) {
2857 isRTCAlarmWake
= true;
2859 } else if (wakeType
&&
2860 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer
)) {
2861 // SMC standby timer trumps SleepX
2862 darkWakeMaintenance
= true;
2863 sleepTimerMaintenance
= true;
2864 } else if ((_lastDebugWakeSeconds
!= 0) &&
2865 ((gDarkWakeFlags
& kDarkWakeFlagAlarmIsDark
) == 0)) {
2866 // SleepX before maintenance
2867 wranglerTickled
= true;
2868 } else if (wakeType
&&
2869 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeMaintenance
)) {
2870 darkWakeMaintenance
= true;
2871 } else if (wakeType
&&
2872 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepService
)) {
2873 darkWakeMaintenance
= true;
2874 darkWakeSleepService
= true;
2876 if (kIOHibernateStateWakingFromHibernate
== gIOHibernateState
) {
2877 sleepToStandby
= true;
2880 } else if (wakeType
&&
2881 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeHibernateError
)) {
2882 darkWakeMaintenance
= true;
2883 darkWakeHibernateError
= true;
2885 // Unidentified wake source, resume to full wake if debug
2886 // alarm is pending.
2888 if (_lastDebugWakeSeconds
&&
2889 (!wakeReason
|| wakeReason
->isEqualTo(""))) {
2890 wranglerTickled
= true;
2895 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer
)) {
2896 darkWakeMaintenance
= true;
2897 sleepTimerMaintenance
= true;
2898 } else if (hibernateAborted
|| !wakeType
||
2899 !wakeType
->isEqualTo(kIOPMRootDomainWakeTypeMaintenance
) ||
2900 !wakeReason
|| !wakeReason
->isEqualTo("RTC")) {
2901 // Post a HID tickle immediately - except for RTC maintenance wake.
2902 wranglerTickled
= true;
2904 darkWakeMaintenance
= true;
2908 if (wranglerTickled
) {
2909 darkWakeToSleepASAP
= false;
2910 fullWakeReason
= kFullWakeReasonLocalUser
;
2912 } else if (displayPowerOnRequested
&& checkSystemCanSustainFullWake()) {
2913 handleDisplayPowerOn();
2914 } else if (!darkWakeMaintenance
) {
2915 // Early/late tickle for non-maintenance wake.
2916 if (((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) ==
2917 kDarkWakeFlagHIDTickleEarly
) ||
2918 ((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) ==
2919 kDarkWakeFlagHIDTickleLate
)) {
2920 darkWakePostTickle
= true;
2923 #else /* !__i386__ && !__x86_64__ */
2924 timeSinceReset
= ml_get_time_since_reset();
2926 kdebugTrace(kPMLogSystemWake
, 0, timeSinceReset
>> 32, timeSinceReset
);
2927 // stay awake for at least 30 seconds
2928 wranglerTickled
= true;
2929 fullWakeReason
= kFullWakeReasonLocalUser
;
2930 startIdleSleepTimer(30);
2934 thread_call_enter(updateConsoleUsersEntry
);
2936 changePowerStateToPriv(getRUN_STATE());
2939 #if !__i386__ && !__x86_64__
2943 DLOG("Force re-evaluating aggressiveness\n");
2944 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
2945 pmPowerStateQueue
->submitPowerEvent(
2946 kPowerEventPolicyStimulus
,
2947 (void *) kStimulusNoIdleSleepPreventers
);
2949 // After changing to ON_STATE, invalidate any previously queued
2950 // request to change to a state less than ON_STATE. This isn't
2951 // necessary for AOT_STATE or if the device has only one running
2952 // state since the changePowerStateToPriv() issued at the tail
2953 // end of SLEEP_STATE case should take care of that.
2954 if (getPowerState() == ON_STATE
) {
2955 changePowerStateToPriv(ON_STATE
);
2959 #endif /* !__i386__ && !__x86_64__ */
2961 notifierThread
= NULL
;
2964 //******************************************************************************
2965 // requestPowerDomainState
2967 // Extend implementation in IOService. Running on PM work loop thread.
2968 //******************************************************************************
2971 IOPMrootDomain::requestPowerDomainState(
2972 IOPMPowerFlags childDesire
,
2973 IOPowerConnection
* childConnection
,
2974 unsigned long specification
)
2976 // Idle and system sleep prevention flags affects driver desire.
2977 // Children desire are irrelevant so they are cleared.
2979 return super::requestPowerDomainState(0, childConnection
, specification
);
2983 //******************************************************************************
2984 // updatePreventIdleSleepList
2986 // Called by IOService on PM work loop.
2987 // Returns true if PM policy recognized the driver's desire to prevent idle
2988 // sleep and updated the list of idle sleep preventers. Returns false otherwise
2989 //******************************************************************************
2992 IOPMrootDomain::updatePreventIdleSleepList(
2993 IOService
* service
, bool addNotRemove
)
2995 unsigned int oldCount
;
2997 oldCount
= idleSleepPreventersCount();
2998 return updatePreventIdleSleepListInternal(service
, addNotRemove
, oldCount
);
3002 IOPMrootDomain::updatePreventIdleSleepListInternal(
3003 IOService
* service
, bool addNotRemove
, unsigned int oldCount
)
3005 unsigned int newCount
;
3009 #if defined(__i386__) || defined(__x86_64__)
3010 // Disregard disk I/O (besides the display wrangler) as a factor preventing
3011 // idle sleep, except in the case of legacy disk I/O
3012 if (service
&& (service
!= wrangler
) && (service
!= this)) {
3019 preventIdleSleepList
->setObject(service
);
3020 DLOG("prevent idle sleep list: %s+ (%u)\n",
3021 service
->getName(), preventIdleSleepList
->getCount());
3022 } else if (preventIdleSleepList
->member(service
)) {
3023 preventIdleSleepList
->removeObject(service
);
3024 DLOG("prevent idle sleep list: %s- (%u)\n",
3025 service
->getName(), preventIdleSleepList
->getCount());
3028 newCount
= idleSleepPreventersCount();
3030 if ((oldCount
== 0) && (newCount
!= 0)) {
3031 // Driver added to empty prevent list.
3032 // Update the driver desire to prevent idle sleep.
3033 // Driver desire does not prevent demand sleep.
3035 changePowerStateTo(getRUN_STATE());
3036 } else if ((oldCount
!= 0) && (newCount
== 0)) {
3037 // Last driver removed from prevent list.
3038 // Drop the driver clamp to allow idle sleep.
3040 changePowerStateTo(SLEEP_STATE
);
3041 evaluatePolicy( kStimulusNoIdleSleepPreventers
);
3043 messageClient(kIOPMMessageIdleSleepPreventers
, systemCapabilityNotifier
,
3044 &newCount
, sizeof(newCount
));
3046 #if defined(__i386__) || defined(__x86_64__)
3047 if (addNotRemove
&& (service
== wrangler
) && !checkSystemCanSustainFullWake()) {
3048 DLOG("Cannot cancel idle sleep\n");
3049 return false; // do not idle-cancel
3056 //******************************************************************************
3058 //******************************************************************************
3061 IOPMrootDomain::startSpinDump(uint32_t spindumpKind
)
3063 messageClients(kIOPMMessageLaunchBootSpinDump
, (void *)(uintptr_t)spindumpKind
);
3066 //******************************************************************************
3067 // preventSystemSleepListUpdate
3069 // Called by IOService on PM work loop.
3070 //******************************************************************************
3073 IOPMrootDomain::updatePreventSystemSleepList(
3074 IOService
* service
, bool addNotRemove
)
3076 unsigned int oldCount
, newCount
;
3079 if (this == service
) {
3083 oldCount
= preventSystemSleepList
->getCount();
3085 preventSystemSleepList
->setObject(service
);
3086 DLOG("prevent system sleep list: %s+ (%u)\n",
3087 service
->getName(), preventSystemSleepList
->getCount());
3088 if (!assertOnWakeSecs
&& gIOLastWakeAbsTime
) {
3090 clock_usec_t microsecs
;
3091 clock_get_uptime(&now
);
3092 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
3093 absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
);
3094 if (assertOnWakeReport
) {
3095 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
);
3096 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
);
3099 } else if (preventSystemSleepList
->member(service
)) {
3100 preventSystemSleepList
->removeObject(service
);
3101 DLOG("prevent system sleep list: %s- (%u)\n",
3102 service
->getName(), preventSystemSleepList
->getCount());
3104 if ((oldCount
!= 0) && (preventSystemSleepList
->getCount() == 0)) {
3105 // Lost all system sleep preventers.
3106 // Send stimulus if system sleep was blocked, and is in dark wake.
3107 evaluatePolicy( kStimulusDarkWakeEvaluate
);
3110 newCount
= preventSystemSleepList
->getCount();
3111 messageClient(kIOPMMessageSystemSleepPreventers
, systemCapabilityNotifier
,
3112 &newCount
, sizeof(newCount
));
3116 IOPMrootDomain::copySleepPreventersList(OSArray
**idleSleepList
, OSArray
**systemSleepList
)
3118 OSCollectionIterator
*iterator
= NULL
;
3119 OSObject
*object
= NULL
;
3120 OSArray
*array
= NULL
;
3122 if (!gIOPMWorkLoop
->inGate()) {
3123 gIOPMWorkLoop
->runAction(
3124 OSMemberFunctionCast(IOWorkLoop::Action
, this,
3125 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList
),
3126 this, (void *)idleSleepList
, (void *)systemSleepList
);
3130 if (idleSleepList
&& preventIdleSleepList
&& (preventIdleSleepList
->getCount() != 0)) {
3131 iterator
= OSCollectionIterator::withCollection(preventIdleSleepList
);
3132 array
= OSArray::withCapacity(5);
3134 while ((object
= iterator
->getNextObject())) {
3135 IOService
*service
= OSDynamicCast(IOService
, object
);
3137 array
->setObject(OSSymbol::withCString(service
->getName()));
3141 iterator
->release();
3142 *idleSleepList
= array
;
3145 if (systemSleepList
&& preventSystemSleepList
&& (preventSystemSleepList
->getCount() != 0)) {
3146 iterator
= OSCollectionIterator::withCollection(preventSystemSleepList
);
3147 array
= OSArray::withCapacity(5);
3149 while ((object
= iterator
->getNextObject())) {
3150 IOService
*service
= OSDynamicCast(IOService
, object
);
3152 array
->setObject(OSSymbol::withCString(service
->getName()));
3156 iterator
->release();
3157 *systemSleepList
= array
;
3162 IOPMrootDomain::copySleepPreventersListWithID(OSArray
**idleSleepList
, OSArray
**systemSleepList
)
3164 OSCollectionIterator
*iterator
= NULL
;
3165 OSObject
*object
= NULL
;
3166 OSArray
*array
= NULL
;
3168 if (!gIOPMWorkLoop
->inGate()) {
3169 gIOPMWorkLoop
->runAction(
3170 OSMemberFunctionCast(IOWorkLoop::Action
, this,
3171 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID
),
3172 this, (void *)idleSleepList
, (void *)systemSleepList
);
3176 if (idleSleepList
&& preventIdleSleepList
&& (preventIdleSleepList
->getCount() != 0)) {
3177 iterator
= OSCollectionIterator::withCollection(preventIdleSleepList
);
3178 array
= OSArray::withCapacity(5);
3180 while ((object
= iterator
->getNextObject())) {
3181 IOService
*service
= OSDynamicCast(IOService
, object
);
3183 OSDictionary
*dict
= OSDictionary::withCapacity(2);
3185 OSNumber
*id
= OSNumber::withNumber(service
->getRegistryEntryID(), 64);
3186 dict
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, id
);
3187 dict
->setObject(kIOPMDriverAssertionOwnerStringKey
, OSSymbol::withCString(service
->getName()));
3188 array
->setObject(dict
);
3195 iterator
->release();
3196 *idleSleepList
= array
;
3199 if (systemSleepList
&& preventSystemSleepList
&& (preventSystemSleepList
->getCount() != 0)) {
3200 iterator
= OSCollectionIterator::withCollection(preventSystemSleepList
);
3201 array
= OSArray::withCapacity(5);
3203 while ((object
= iterator
->getNextObject())) {
3204 IOService
*service
= OSDynamicCast(IOService
, object
);
3206 OSDictionary
*dict
= OSDictionary::withCapacity(2);
3208 OSNumber
*id
= OSNumber::withNumber(service
->getRegistryEntryID(), 64);
3209 dict
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, id
);
3210 dict
->setObject(kIOPMDriverAssertionOwnerStringKey
, OSSymbol::withCString(service
->getName()));
3211 array
->setObject(dict
);
3218 iterator
->release();
3219 *systemSleepList
= array
;
3223 //******************************************************************************
3226 // Override the superclass implementation to send a different message type.
3227 //******************************************************************************
3230 IOPMrootDomain::tellChangeDown( unsigned long stateNum
)
3232 DLOG("tellChangeDown %s->%s\n",
3233 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3235 if (SLEEP_STATE
== stateNum
) {
3236 // Legacy apps were already told in the full->dark transition
3237 if (!ignoreTellChangeDown
) {
3238 tracePoint( kIOPMTracePointSleepApplications
);
3240 tracePoint( kIOPMTracePointSleepPriorityClients
);
3244 if (!ignoreTellChangeDown
) {
3245 userActivityAtSleep
= userActivityCount
;
3246 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep
);
3248 if (SLEEP_STATE
== stateNum
) {
3249 hibernateAborted
= false;
3251 // Direct callout into OSKext so it can disable kext unloads
3252 // during sleep/wake to prevent deadlocks.
3253 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep
);
3255 IOService::updateConsoleUsers(NULL
, kIOMessageSystemWillSleep
);
3257 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3258 // But tellClientsWithResponse() must be called for both.
3259 ignoreTellChangeDown
= true;
3263 return super::tellClientsWithResponse( kIOMessageSystemWillSleep
);
3266 //******************************************************************************
3269 // Override the superclass implementation to send a different message type.
3270 // This must be idle sleep since we don't ask during any other power change.
3271 //******************************************************************************
3274 IOPMrootDomain::askChangeDown( unsigned long stateNum
)
3276 DLOG("askChangeDown %s->%s\n",
3277 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3279 // Don't log for dark wake entry
3280 if (kSystemTransitionSleep
== _systemTransitionType
) {
3281 tracePoint( kIOPMTracePointSleepApplications
);
3284 return super::tellClientsWithResponse( kIOMessageCanSystemSleep
);
3287 //******************************************************************************
3288 // askChangeDownDone
3290 // An opportunity for root domain to cancel the power transition,
3291 // possibily due to an assertion created by powerd in response to
3292 // kIOMessageCanSystemSleep.
3295 // full -> dark wake transition
3296 // 1. Notify apps and powerd with kIOMessageCanSystemSleep
3297 // 2. askChangeDownDone()
3298 // dark -> sleep transition
3299 // 1. Notify powerd with kIOMessageCanSystemSleep
3300 // 2. askChangeDownDone()
3303 // full -> dark wake transition
3304 // 1. Notify powerd with kIOMessageCanSystemSleep
3305 // 2. askChangeDownDone()
3306 // dark -> sleep transition
3307 // 1. Notify powerd with kIOMessageCanSystemSleep
3308 // 2. askChangeDownDone()
3309 //******************************************************************************
3312 IOPMrootDomain::askChangeDownDone(
3313 IOPMPowerChangeFlags
* inOutChangeFlags
, bool * cancel
)
3315 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3316 *inOutChangeFlags
, *cancel
,
3317 _systemTransitionType
,
3318 _currentCapability
, _pendingCapability
);
3320 if ((false == *cancel
) && (kSystemTransitionSleep
== _systemTransitionType
)) {
3321 // Dark->Sleep transition.
3322 // Check if there are any deny sleep assertions.
3323 // lastSleepReason already set by handleOurPowerChangeStart()
3325 if (!checkSystemCanSleep(lastSleepReason
)) {
3326 // Cancel dark wake to sleep transition.
3327 // Must re-scan assertions upon entering dark wake.
3330 DLOG("cancel dark->sleep\n");
3332 if (_aotMode
&& (kPMCalendarTypeInvalid
!= _aotWakeTimeCalendar
.selector
)) {
3333 uint64_t now
= mach_continuous_time();
3334 if (((now
+ _aotWakePreWindow
) >= _aotWakeTimeContinuous
)
3335 && (now
< (_aotWakeTimeContinuous
+ _aotWakePostWindow
))) {
3337 IOLog("AOT wake window cancel: %qd, %qd\n", now
, _aotWakeTimeContinuous
);
3343 //******************************************************************************
3344 // systemDidNotSleep
3346 // Work common to both canceled or aborted sleep.
3347 //******************************************************************************
3350 IOPMrootDomain::systemDidNotSleep( void )
3352 // reset console lock state
3353 thread_call_enter(updateConsoleUsersEntry
);
3356 if (idleSleepEnabled
) {
3357 // stay awake for at least idleSeconds
3358 startIdleSleepTimer(idleSeconds
);
3361 if (idleSleepEnabled
&& !userIsActive
) {
3362 // Manually start the idle sleep timer besides waiting for
3363 // the user to become inactive.
3364 startIdleSleepTimer( kIdleSleepRetryInterval
);
3368 preventTransitionToUserActive(false);
3369 IOService::setAdvisoryTickleEnable( true );
3371 // After idle revert and cancel, send a did-change message to powerd
3372 // to balance the previous will-change message. Kernel clients do not
3373 // need this since sleep cannot be canceled once they are notified.
3375 if (toldPowerdCapWillChange
&& systemCapabilityNotifier
&&
3376 (_pendingCapability
!= _currentCapability
) &&
3377 ((_systemMessageClientMask
& kSystemMessageClientPowerd
) != 0)) {
3378 // Differs from a real capability gain change where notifyRef != 0,
3379 // but it is zero here since no response is expected.
3381 IOPMSystemCapabilityChangeParameters params
;
3383 bzero(¶ms
, sizeof(params
));
3384 params
.fromCapabilities
= _pendingCapability
;
3385 params
.toCapabilities
= _currentCapability
;
3386 params
.changeFlags
= kIOPMSystemCapabilityDidChange
;
3388 DLOG("MESG cap %x->%x did change\n",
3389 params
.fromCapabilities
, params
.toCapabilities
);
3390 messageClient(kIOMessageSystemCapabilityChange
, systemCapabilityNotifier
,
3391 ¶ms
, sizeof(params
));
3395 //******************************************************************************
3398 // Notify registered applications and kernel clients that we are not dropping
3401 // We override the superclass implementation so we can send a different message
3402 // type to the client or application being notified.
3404 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3405 //******************************************************************************
3408 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum
)
3410 DLOG("tellNoChangeDown %s->%s\n",
3411 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3413 // Sleep canceled, clear the sleep trace point.
3414 tracePoint(kIOPMTracePointSystemUp
);
3416 systemDidNotSleep();
3417 return tellClients( kIOMessageSystemWillNotSleep
);
3420 //******************************************************************************
3423 // Notify registered applications and kernel clients that we are raising power.
3425 // We override the superclass implementation so we can send a different message
3426 // type to the client or application being notified.
3427 //******************************************************************************
3430 IOPMrootDomain::tellChangeUp( unsigned long stateNum
)
3432 DLOG("tellChangeUp %s->%s\n",
3433 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3435 ignoreTellChangeDown
= false;
3437 if (stateNum
== ON_STATE
) {
3438 // Direct callout into OSKext so it can disable kext unloads
3439 // during sleep/wake to prevent deadlocks.
3440 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn
);
3442 // Notify platform that sleep was cancelled or resumed.
3443 getPlatform()->callPlatformFunction(
3444 sleepMessagePEFunction
, false,
3445 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn
,
3448 if (getPowerState() == ON_STATE
) {
3449 // Sleep was cancelled by idle cancel or revert
3450 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
3451 // rdar://problem/50363791
3452 // If system is in dark wake and sleep is cancelled, do not
3453 // send SystemWillPowerOn/HasPoweredOn messages to kernel
3454 // priority clients. They haven't yet seen a SystemWillSleep
3455 // message before the cancellation. So make sure the kernel
3456 // client bit is cleared in _systemMessageClientMask before
3457 // invoking the tellClients() below. This bit may have been
3458 // set by handleOurPowerChangeStart() anticipating a successful
3459 // sleep and setting the filter mask ahead of time allows the
3460 // SystemWillSleep message to go through.
3461 _systemMessageClientMask
&= ~kSystemMessageClientKernel
;
3464 systemDidNotSleep();
3465 tellClients( kIOMessageSystemWillPowerOn
);
3468 tracePoint( kIOPMTracePointWakeApplications
);
3469 tellClients( kIOMessageSystemHasPoweredOn
);
3473 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3474 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3475 ((params)->fromCapabilities & (flag)) && \
3476 (((params)->toCapabilities & (flag)) == 0))
3478 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3479 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3480 ((params)->toCapabilities & (flag)) && \
3481 (((params)->fromCapabilities & (flag)) == 0))
3483 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3484 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3485 ((params)->fromCapabilities & (flag)) && \
3486 (((params)->toCapabilities & (flag)) == 0))
3488 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3489 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3490 ((params)->toCapabilities & (flag)) && \
3491 (((params)->fromCapabilities & (flag)) == 0))
3493 //******************************************************************************
3494 // sysPowerDownHandler
3496 // Perform a vfs sync before system sleep.
3497 //******************************************************************************
3500 IOPMrootDomain::sysPowerDownHandler(
3501 void * target
, void * refCon
,
3502 UInt32 messageType
, IOService
* service
,
3503 void * messageArgs
, vm_size_t argSize
)
3505 static UInt32 lastSystemMessageType
= 0;
3508 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType
));
3510 // rdar://problem/50363791
3511 // Sanity check to make sure the SystemWill/Has message types are
3512 // received in the expected order for all kernel priority clients.
3513 if (messageType
== kIOMessageSystemWillSleep
||
3514 messageType
== kIOMessageSystemWillPowerOn
||
3515 messageType
== kIOMessageSystemHasPoweredOn
) {
3516 switch (messageType
) {
3517 case kIOMessageSystemWillPowerOn
:
3518 assert(lastSystemMessageType
== kIOMessageSystemWillSleep
);
3520 case kIOMessageSystemHasPoweredOn
:
3521 assert(lastSystemMessageType
== kIOMessageSystemWillPowerOn
);
3525 lastSystemMessageType
= messageType
;
3529 return kIOReturnUnsupported
;
3532 if (messageType
== kIOMessageSystemCapabilityChange
) {
3533 IOPMSystemCapabilityChangeParameters
* params
=
3534 (IOPMSystemCapabilityChangeParameters
*) messageArgs
;
3536 // Interested applications have been notified of an impending power
3537 // change and have acked (when applicable).
3538 // This is our chance to save whatever state we can before powering
3540 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3543 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3544 params
->fromCapabilities
, params
->toCapabilities
,
3545 params
->changeFlags
);
3547 if (CAP_WILL_CHANGE_TO_OFF(params
, kIOPMSystemCapabilityCPU
)) {
3548 // We will ack within 20 seconds
3549 params
->maxWaitForReply
= 20 * 1000 * 1000;
3552 gRootDomain
->evaluateSystemSleepPolicyEarly();
3554 // add in time we could spend freeing pages
3555 if (gRootDomain
->hibernateMode
&& !gRootDomain
->hibernateDisabled
) {
3556 params
->maxWaitForReply
= kCapabilityClientMaxWait
;
3558 DLOG("sysPowerDownHandler max wait %d s\n",
3559 (int) (params
->maxWaitForReply
/ 1000 / 1000));
3562 // Notify platform that sleep has begun, after the early
3563 // sleep policy evaluation.
3564 getPlatform()->callPlatformFunction(
3565 sleepMessagePEFunction
, false,
3566 (void *)(uintptr_t) kIOMessageSystemWillSleep
,
3569 if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
)) {
3570 // Purposely delay the ack and hope that shutdown occurs quickly.
3571 // Another option is not to schedule the thread and wait for
3573 AbsoluteTime deadline
;
3574 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
3575 thread_call_enter1_delayed(
3576 gRootDomain
->diskSyncCalloutEntry
,
3577 (thread_call_param_t
)(uintptr_t) params
->notifyRef
,
3581 gRootDomain
->diskSyncCalloutEntry
,
3582 (thread_call_param_t
)(uintptr_t) params
->notifyRef
);
3586 else if (CAP_DID_CHANGE_TO_ON(params
, kIOPMSystemCapabilityCPU
)) {
3587 // We will ack within 110 seconds
3588 params
->maxWaitForReply
= 110 * 1000 * 1000;
3591 gRootDomain
->diskSyncCalloutEntry
,
3592 (thread_call_param_t
)(uintptr_t) params
->notifyRef
);
3595 ret
= kIOReturnSuccess
;
3601 //******************************************************************************
3602 // handleQueueSleepWakeUUID
3604 // Called from IOPMrootDomain when we're initiating a sleep,
3605 // or indirectly from PM configd when PM decides to clear the UUID.
3606 // PM clears the UUID several minutes after successful wake from sleep,
3607 // so that we might associate App spindumps with the immediately previous
3610 // @param obj has a retain on it. We're responsible for releasing that retain.
3611 //******************************************************************************
3614 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject
*obj
)
3616 OSString
*str
= NULL
;
3618 if (kOSBooleanFalse
== obj
) {
3619 handlePublishSleepWakeUUID(NULL
);
3620 } else if ((str
= OSDynamicCast(OSString
, obj
))) {
3621 // This branch caches the UUID for an upcoming sleep/wake
3622 if (queuedSleepWakeUUIDString
) {
3623 queuedSleepWakeUUIDString
->release();
3624 queuedSleepWakeUUIDString
= NULL
;
3626 queuedSleepWakeUUIDString
= str
;
3627 queuedSleepWakeUUIDString
->retain();
3629 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString
->getCStringNoCopy());
3637 //******************************************************************************
3638 // handlePublishSleepWakeUUID
3640 // Called from IOPMrootDomain when we're initiating a sleep,
3641 // or indirectly from PM configd when PM decides to clear the UUID.
3642 // PM clears the UUID several minutes after successful wake from sleep,
3643 // so that we might associate App spindumps with the immediately previous
3645 //******************************************************************************
3648 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish
)
3653 * Clear the current UUID
3655 if (gSleepWakeUUIDIsSet
) {
3656 DLOG("SleepWake UUID cleared\n");
3658 gSleepWakeUUIDIsSet
= false;
3660 removeProperty(kIOPMSleepWakeUUIDKey
);
3661 messageClients(kIOPMMessageSleepWakeUUIDChange
, kIOPMMessageSleepWakeUUIDCleared
);
3665 * Optionally, publish a new UUID
3667 if (queuedSleepWakeUUIDString
&& shouldPublish
) {
3668 OSString
*publishThisUUID
= NULL
;
3670 publishThisUUID
= queuedSleepWakeUUIDString
;
3671 publishThisUUID
->retain();
3673 if (publishThisUUID
) {
3674 setProperty(kIOPMSleepWakeUUIDKey
, publishThisUUID
);
3675 publishThisUUID
->release();
3678 gSleepWakeUUIDIsSet
= true;
3679 messageClients(kIOPMMessageSleepWakeUUIDChange
, kIOPMMessageSleepWakeUUIDSet
);
3681 queuedSleepWakeUUIDString
->release();
3682 queuedSleepWakeUUIDString
= NULL
;
3686 //******************************************************************************
3687 // IOPMGetSleepWakeUUIDKey
3689 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
3690 // To get the full key -- a C string -- the buffer must large enough for
3691 // the end-of-string character.
3692 // The key is expected to be an UUID string
3693 //******************************************************************************
3696 IOPMCopySleepWakeUUIDKey(char *buffer
, size_t buf_len
)
3698 if (!gSleepWakeUUIDIsSet
) {
3702 if (buffer
!= NULL
) {
3705 string
= (OSString
*)
3706 gRootDomain
->copyProperty(kIOPMSleepWakeUUIDKey
);
3708 if (string
== NULL
) {
3711 strlcpy(buffer
, string
->getCStringNoCopy(), buf_len
);
3720 //******************************************************************************
3721 // initializeBootSessionUUID
3723 // Initialize the boot session uuid at boot up and sets it into registry.
3724 //******************************************************************************
3727 IOPMrootDomain::initializeBootSessionUUID(void)
3730 uuid_string_t new_uuid_string
;
3732 uuid_generate(new_uuid
);
3733 uuid_unparse_upper(new_uuid
, new_uuid_string
);
3734 memcpy(bootsessionuuid_string
, new_uuid_string
, sizeof(uuid_string_t
));
3736 setProperty(kIOPMBootSessionUUIDKey
, new_uuid_string
);
3739 //******************************************************************************
3740 // changePowerStateTo & changePowerStateToPriv
3742 // Override of these methods for logging purposes.
3743 //******************************************************************************
3746 IOPMrootDomain::changePowerStateTo( unsigned long ordinal
)
3748 DLOG("changePowerStateTo(%u)\n", (uint32_t) ordinal
);
3750 if ((ordinal
!= ON_STATE
) && (ordinal
!= AOT_STATE
) && (ordinal
!= SLEEP_STATE
)) {
3751 return kIOReturnUnsupported
;
3754 return super::changePowerStateTo(ordinal
);
3758 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal
)
3760 DLOG("changePowerStateToPriv(%u)\n", (uint32_t) ordinal
);
3762 if ((ordinal
!= ON_STATE
) && (ordinal
!= AOT_STATE
) && (ordinal
!= SLEEP_STATE
)) {
3763 return kIOReturnUnsupported
;
3766 return super::changePowerStateToPriv(ordinal
);
3769 //******************************************************************************
3772 //******************************************************************************
3775 IOPMrootDomain::activitySinceSleep(void)
3777 return userActivityCount
!= userActivityAtSleep
;
3781 IOPMrootDomain::abortHibernation(void)
3783 bool ret
= activitySinceSleep();
3785 if (ret
&& !hibernateAborted
&& checkSystemCanSustainFullWake()) {
3786 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount
, userActivityAtSleep
);
3787 hibernateAborted
= true;
3793 hibernate_should_abort(void)
3796 return gRootDomain
->abortHibernation();
3802 //******************************************************************************
3803 // willNotifyPowerChildren
3805 // Called after all interested drivers have all acknowledged the power change,
3806 // but before any power children is informed. Dispatched though a thread call,
3807 // so it is safe to perform work that might block on a sleeping disk. PM state
3808 // machine (not thread) will block w/o timeout until this function returns.
3809 //******************************************************************************
3812 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState
)
3817 if (SLEEP_STATE
== newPowerState
) {
3818 notifierThread
= current_thread();
3819 if (!tasksSuspended
) {
3820 AbsoluteTime deadline
;
3821 tasksSuspended
= TRUE
;
3822 updateTasksSuspend();
3824 clock_interval_to_deadline(10, kSecondScale
, &deadline
);
3825 #if !CONFIG_EMBEDDED
3826 vm_pageout_wait(AbsoluteTime_to_scalar(&deadline
));
3827 #endif /* !CONFIG_EMBEDDED */
3830 _aotReadyToFullWake
= false;
3832 if (_aotLingerTime
) {
3834 IOLog("aot linger no return\n");
3835 clock_absolutetime_interval_to_deadline(_aotLingerTime
, &deadline
);
3836 clock_delay_until(deadline
);
3841 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeInvalid
;
3843 bzero(_aotMetrics
, sizeof(IOPMAOTMetrics
));
3845 } else if (!_aotNow
&& !_debugWakeSeconds
) {
3848 _aotPendingFlags
= 0;
3849 _aotTasksSuspended
= true;
3850 _aotLastWakeTime
= 0;
3851 bzero(_aotMetrics
, sizeof(IOPMAOTMetrics
));
3852 if (kIOPMAOTModeCycle
& _aotMode
) {
3853 clock_interval_to_absolutetime_interval(60, kSecondScale
, &_aotTestInterval
);
3854 _aotTestTime
= mach_continuous_time() + _aotTestInterval
;
3855 setWakeTime(_aotTestTime
);
3857 uint32_t lingerSecs
;
3858 if (!PE_parse_boot_argn("aotlinger", &lingerSecs
, sizeof(lingerSecs
))) {
3861 clock_interval_to_absolutetime_interval(lingerSecs
, kSecondScale
, &_aotLingerTime
);
3862 clock_interval_to_absolutetime_interval(2000, kMillisecondScale
, &_aotWakePreWindow
);
3863 clock_interval_to_absolutetime_interval(1100, kMillisecondScale
, &_aotWakePostWindow
);
3867 IOHibernateSystemSleep();
3868 IOHibernateIOKitSleep();
3870 if (gRootDomain
->activitySinceSleep()) {
3871 dict
= OSDictionary::withCapacity(1);
3872 secs
= OSNumber::withNumber(1, 32);
3875 dict
->setObject(gIOPMSettingDebugWakeRelativeKey
, secs
);
3876 gRootDomain
->setProperties(dict
);
3877 MSG("Reverting sleep with relative wake\n");
3887 notifierThread
= NULL
;
3891 //******************************************************************************
3892 // sleepOnClamshellClosed
3894 // contains the logic to determine if the system should sleep when the clamshell
3896 //******************************************************************************
3899 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
3901 if (!clamshellExists
) {
3905 DLOG("clamshell closed %d, disabled %d, desktopMode %d, ac %d sleepDisabled %d\n",
3906 clamshellClosed
, clamshellDisabled
, desktopMode
, acAdaptorConnected
, clamshellSleepDisabled
);
3908 return !clamshellDisabled
&& !(desktopMode
&& acAdaptorConnected
) && !clamshellSleepDisabled
;
3912 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
3914 // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
3915 // closed && battery
3916 if (!clamshellExists
) {
3920 DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d, desktopMode %d, ac %d sleepDisabled %d\n",
3921 clamshellClosed
, clamshellDisabled
, desktopMode
, acAdaptorConnected
, clamshellSleepDisabled
);
3923 return !acAdaptorConnected
&& !clamshellSleepDisabled
;
3927 IOPMrootDomain::sendClientClamshellNotification( void )
3929 /* Only broadcast clamshell alert if clamshell exists. */
3930 if (!clamshellExists
) {
3934 setProperty(kAppleClamshellStateKey
,
3935 clamshellClosed
? kOSBooleanTrue
: kOSBooleanFalse
);
3937 setProperty(kAppleClamshellCausesSleepKey
,
3938 shouldSleepOnClamshellClosed() ? kOSBooleanTrue
: kOSBooleanFalse
);
3940 /* Argument to message is a bitfiel of
3941 * ( kClamshellStateBit | kClamshellSleepBit )
3943 messageClients(kIOPMMessageClamshellStateChange
,
3944 (void *)(uintptr_t) ((clamshellClosed
? kClamshellStateBit
: 0)
3945 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit
: 0)));
3948 //******************************************************************************
3949 // getSleepSupported
3952 //******************************************************************************
3955 IOPMrootDomain::getSleepSupported( void )
3957 return platformSleepSupport
;
3960 //******************************************************************************
3961 // setSleepSupported
3964 //******************************************************************************
3967 IOPMrootDomain::setSleepSupported( IOOptionBits flags
)
3969 DLOG("setSleepSupported(%x)\n", (uint32_t) flags
);
3970 OSBitOrAtomic(flags
, &platformSleepSupport
);
3973 //******************************************************************************
3974 // setDisableClamShellSleep
3976 //******************************************************************************
3979 IOPMrootDomain::setDisableClamShellSleep( bool val
)
3981 if (gIOPMWorkLoop
->inGate() == false) {
3982 gIOPMWorkLoop
->runAction(
3983 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::setDisableClamShellSleep
),
3989 DLOG("setDisableClamShellSleep(%x)\n", (uint32_t) val
);
3990 if (clamshellSleepDisabled
!= val
) {
3991 clamshellSleepDisabled
= val
;
3992 // If clamshellSleepDisabled is reset to 0, reevaluate if
3993 // system need to go to sleep due to clamshell state
3994 if (!clamshellSleepDisabled
&& clamshellClosed
) {
3995 handlePowerNotification(kLocalEvalClamshellCommand
);
4001 //******************************************************************************
4005 //******************************************************************************
4008 IOPMrootDomain::wakeFromDoze( void )
4010 // Preserve symbol for familes (IOUSBFamily and IOGraphics)
4016 //******************************************************************************
4019 // Adds a new feature to the supported features dictionary
4020 //******************************************************************************
4023 IOPMrootDomain::publishFeature( const char * feature
)
4025 publishFeature(feature
, kRD_AllPowerSources
, NULL
);
4028 //******************************************************************************
4029 // publishFeature (with supported power source specified)
4031 // Adds a new feature to the supported features dictionary
4032 //******************************************************************************
4035 IOPMrootDomain::publishFeature(
4036 const char *feature
,
4037 uint32_t supportedWhere
,
4038 uint32_t *uniqueFeatureID
)
4040 static uint16_t next_feature_id
= 500;
4042 OSNumber
*new_feature_data
= NULL
;
4043 OSNumber
*existing_feature
= NULL
;
4044 OSArray
*existing_feature_arr
= NULL
;
4045 OSObject
*osObj
= NULL
;
4046 uint32_t feature_value
= 0;
4048 supportedWhere
&= kRD_AllPowerSources
; // mask off any craziness!
4050 if (!supportedWhere
) {
4051 // Feature isn't supported anywhere!
4055 if (next_feature_id
> 5000) {
4056 // Far, far too many features!
4060 if (featuresDictLock
) {
4061 IOLockLock(featuresDictLock
);
4064 OSDictionary
*features
=
4065 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
4067 // Create new features dict if necessary
4068 if (features
&& OSDynamicCast(OSDictionary
, features
)) {
4069 features
= OSDictionary::withDictionary(features
);
4071 features
= OSDictionary::withCapacity(1);
4074 // Create OSNumber to track new feature
4076 next_feature_id
+= 1;
4077 if (uniqueFeatureID
) {
4078 // We don't really mind if the calling kext didn't give us a place
4079 // to stash their unique id. Many kexts don't plan to unload, and thus
4080 // have no need to remove themselves later.
4081 *uniqueFeatureID
= next_feature_id
;
4084 feature_value
= (uint32_t)next_feature_id
;
4085 feature_value
<<= 16;
4086 feature_value
+= supportedWhere
;
4088 new_feature_data
= OSNumber::withNumber(
4089 (unsigned long long)feature_value
, 32);
4091 // Does features object already exist?
4092 if ((osObj
= features
->getObject(feature
))) {
4093 if ((existing_feature
= OSDynamicCast(OSNumber
, osObj
))) {
4094 // We need to create an OSArray to hold the now 2 elements.
4095 existing_feature_arr
= OSArray::withObjects(
4096 (const OSObject
**)&existing_feature
, 1, 2);
4097 } else if ((existing_feature_arr
= OSDynamicCast(OSArray
, osObj
))) {
4098 // Add object to existing array
4099 existing_feature_arr
= OSArray::withArray(
4100 existing_feature_arr
,
4101 existing_feature_arr
->getCount() + 1);
4104 if (existing_feature_arr
) {
4105 existing_feature_arr
->setObject(new_feature_data
);
4106 features
->setObject(feature
, existing_feature_arr
);
4107 existing_feature_arr
->release();
4108 existing_feature_arr
= NULL
;
4111 // The easy case: no previously existing features listed. We simply
4112 // set the OSNumber at key 'feature' and we're on our way.
4113 features
->setObject(feature
, new_feature_data
);
4116 new_feature_data
->release();
4118 setProperty(kRootDomainSupportedFeatures
, features
);
4120 features
->release();
4122 if (featuresDictLock
) {
4123 IOLockUnlock(featuresDictLock
);
4126 // Notify EnergySaver and all those in user space so they might
4127 // re-populate their feature specific UI
4128 if (pmPowerStateQueue
) {
4129 pmPowerStateQueue
->submitPowerEvent( kPowerEventFeatureChanged
);
4133 //******************************************************************************
4134 // removePublishedFeature
4136 // Removes previously published feature
4137 //******************************************************************************
4140 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID
)
4142 IOReturn ret
= kIOReturnError
;
4143 uint32_t feature_value
= 0;
4144 uint16_t feature_id
= 0;
4145 bool madeAChange
= false;
4147 OSSymbol
*dictKey
= NULL
;
4148 OSCollectionIterator
*dictIterator
= NULL
;
4149 OSArray
*arrayMember
= NULL
;
4150 OSNumber
*numberMember
= NULL
;
4151 OSObject
*osObj
= NULL
;
4152 OSNumber
*osNum
= NULL
;
4153 OSArray
*arrayMemberCopy
;
4155 if (kBadPMFeatureID
== removeFeatureID
) {
4156 return kIOReturnNotFound
;
4159 if (featuresDictLock
) {
4160 IOLockLock(featuresDictLock
);
4163 OSDictionary
*features
=
4164 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
4166 if (features
&& OSDynamicCast(OSDictionary
, features
)) {
4167 // Any modifications to the dictionary are made to the copy to prevent
4168 // races & crashes with userland clients. Dictionary updated
4169 // automically later.
4170 features
= OSDictionary::withDictionary(features
);
4173 ret
= kIOReturnNotFound
;
4177 // We iterate 'features' dictionary looking for an entry tagged
4178 // with 'removeFeatureID'. If found, we remove it from our tracking
4179 // structures and notify the OS via a general interest message.
4181 dictIterator
= OSCollectionIterator::withCollection(features
);
4182 if (!dictIterator
) {
4186 while ((dictKey
= OSDynamicCast(OSSymbol
, dictIterator
->getNextObject()))) {
4187 osObj
= features
->getObject(dictKey
);
4189 // Each Feature is either tracked by an OSNumber
4190 if (osObj
&& (numberMember
= OSDynamicCast(OSNumber
, osObj
))) {
4191 feature_value
= numberMember
->unsigned32BitValue();
4192 feature_id
= (uint16_t)(feature_value
>> 16);
4194 if (feature_id
== (uint16_t)removeFeatureID
) {
4196 features
->removeObject(dictKey
);
4201 // Or tracked by an OSArray of OSNumbers
4202 } else if (osObj
&& (arrayMember
= OSDynamicCast(OSArray
, osObj
))) {
4203 unsigned int arrayCount
= arrayMember
->getCount();
4205 for (unsigned int i
= 0; i
< arrayCount
; i
++) {
4206 osNum
= OSDynamicCast(OSNumber
, arrayMember
->getObject(i
));
4211 feature_value
= osNum
->unsigned32BitValue();
4212 feature_id
= (uint16_t)(feature_value
>> 16);
4214 if (feature_id
== (uint16_t)removeFeatureID
) {
4216 if (1 == arrayCount
) {
4217 // If the array only contains one element, remove
4219 features
->removeObject(dictKey
);
4221 // Otherwise remove the element from a copy of the array.
4222 arrayMemberCopy
= OSArray::withArray(arrayMember
);
4223 if (arrayMemberCopy
) {
4224 arrayMemberCopy
->removeObject(i
);
4225 features
->setObject(dictKey
, arrayMemberCopy
);
4226 arrayMemberCopy
->release();
4237 dictIterator
->release();
4240 ret
= kIOReturnSuccess
;
4242 setProperty(kRootDomainSupportedFeatures
, features
);
4244 // Notify EnergySaver and all those in user space so they might
4245 // re-populate their feature specific UI
4246 if (pmPowerStateQueue
) {
4247 pmPowerStateQueue
->submitPowerEvent( kPowerEventFeatureChanged
);
4250 ret
= kIOReturnNotFound
;
4255 features
->release();
4257 if (featuresDictLock
) {
4258 IOLockUnlock(featuresDictLock
);
4263 //******************************************************************************
4264 // publishPMSetting (private)
4266 // Should only be called by PMSettingObject to publish a PM Setting as a
4267 // supported feature.
4268 //******************************************************************************
4271 IOPMrootDomain::publishPMSetting(
4272 const OSSymbol
* feature
, uint32_t where
, uint32_t * featureID
)
4274 if (noPublishPMSettings
&&
4275 (noPublishPMSettings
->getNextIndexOfObject(feature
, 0) != (unsigned int)-1)) {
4276 // Setting found in noPublishPMSettings array
4277 *featureID
= kBadPMFeatureID
;
4282 feature
->getCStringNoCopy(), where
, featureID
);
4285 //******************************************************************************
4286 // setPMSetting (private)
4288 // Internal helper to relay PM settings changes from user space to individual
4289 // drivers. Should be called only by IOPMrootDomain::setProperties.
4290 //******************************************************************************
4293 IOPMrootDomain::setPMSetting(
4294 const OSSymbol
*type
,
4297 PMSettingCallEntry
*entries
= NULL
;
4298 OSArray
*chosen
= NULL
;
4299 const OSArray
*array
;
4300 PMSettingObject
*pmso
;
4301 thread_t thisThread
;
4302 int i
, j
, count
, capacity
;
4305 return kIOReturnBadArgument
;
4310 // Update settings dict so changes are visible from copyPMSetting().
4311 fPMSettingsDict
->setObject(type
, object
);
4313 // Prep all PMSetting objects with the given 'type' for callout.
4314 array
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(type
));
4315 if (!array
|| ((capacity
= array
->getCount()) == 0)) {
4319 // Array to retain PMSetting objects targeted for callout.
4320 chosen
= OSArray::withCapacity(capacity
);
4322 goto unlock_exit
; // error
4324 entries
= IONew(PMSettingCallEntry
, capacity
);
4326 goto unlock_exit
; // error
4328 memset(entries
, 0, sizeof(PMSettingCallEntry
) * capacity
);
4330 thisThread
= current_thread();
4332 for (i
= 0, j
= 0; i
< capacity
; i
++) {
4333 pmso
= (PMSettingObject
*) array
->getObject(i
);
4334 if (pmso
->disabled
) {
4337 entries
[j
].thread
= thisThread
;
4338 queue_enter(&pmso
->calloutQueue
, &entries
[j
], PMSettingCallEntry
*, link
);
4339 chosen
->setObject(pmso
);
4349 // Call each pmso in the chosen array.
4350 for (i
= 0; i
< count
; i
++) {
4351 pmso
= (PMSettingObject
*) chosen
->getObject(i
);
4352 pmso
->dispatchPMSetting(type
, object
);
4356 for (i
= 0; i
< count
; i
++) {
4357 pmso
= (PMSettingObject
*) chosen
->getObject(i
);
4358 queue_remove(&pmso
->calloutQueue
, &entries
[i
], PMSettingCallEntry
*, link
);
4359 if (pmso
->waitThread
) {
4360 PMSETTING_WAKEUP(pmso
);
4370 IODelete(entries
, PMSettingCallEntry
, capacity
);
4373 return kIOReturnSuccess
;
4376 //******************************************************************************
4377 // copyPMSetting (public)
4379 // Allows kexts to safely read setting values, without being subscribed to
4381 //******************************************************************************
4384 IOPMrootDomain::copyPMSetting(
4385 OSSymbol
*whichSetting
)
4387 OSObject
*obj
= NULL
;
4389 if (!whichSetting
) {
4394 obj
= fPMSettingsDict
->getObject(whichSetting
);
4403 //******************************************************************************
4404 // registerPMSettingController (public)
4406 // direct wrapper to registerPMSettingController with uint32_t power source arg
4407 //******************************************************************************
4410 IOPMrootDomain::registerPMSettingController(
4411 const OSSymbol
* settings
[],
4412 IOPMSettingControllerCallback func
,
4417 return registerPMSettingController(
4419 (kIOPMSupportedOnAC
| kIOPMSupportedOnBatt
| kIOPMSupportedOnUPS
),
4420 func
, target
, refcon
, handle
);
4423 //******************************************************************************
4424 // registerPMSettingController (public)
4426 // Kexts may register for notifications when a particular setting is changed.
4427 // A list of settings is available in IOPM.h.
4429 // * settings - An OSArray containing OSSymbols. Caller should populate this
4430 // array with a list of settings caller wants notifications from.
4431 // * func - A C function callback of the type IOPMSettingControllerCallback
4432 // * target - caller may provide an OSObject *, which PM will pass as an
4433 // target to calls to "func"
4434 // * refcon - caller may provide an void *, which PM will pass as an
4435 // argument to calls to "func"
4436 // * handle - This is a return argument. We will populate this pointer upon
4437 // call success. Hold onto this and pass this argument to
4438 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
4440 // kIOReturnSuccess on success
4441 //******************************************************************************
4444 IOPMrootDomain::registerPMSettingController(
4445 const OSSymbol
* settings
[],
4446 uint32_t supportedPowerSources
,
4447 IOPMSettingControllerCallback func
,
4452 PMSettingObject
*pmso
= NULL
;
4453 OSObject
*pmsh
= NULL
;
4454 OSArray
*list
= NULL
;
4457 if (NULL
== settings
||
4460 return kIOReturnBadArgument
;
4463 pmso
= PMSettingObject::pmSettingObject(
4464 (IOPMrootDomain
*) this, func
, target
,
4465 refcon
, supportedPowerSources
, settings
, &pmsh
);
4469 return kIOReturnInternalError
;
4473 for (i
= 0; settings
[i
]; i
++) {
4474 list
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(settings
[i
]));
4476 // New array of callbacks for this setting
4477 list
= OSArray::withCapacity(1);
4478 settingsCallbacks
->setObject(settings
[i
], list
);
4482 // Add caller to the callback list
4483 list
->setObject(pmso
);
4487 // Return handle to the caller, the setting object is private.
4490 return kIOReturnSuccess
;
4493 //******************************************************************************
4494 // deregisterPMSettingObject (private)
4496 // Only called from PMSettingObject.
4497 //******************************************************************************
4500 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject
* pmso
)
4502 thread_t thisThread
= current_thread();
4503 PMSettingCallEntry
*callEntry
;
4504 OSCollectionIterator
*iter
;
4512 pmso
->disabled
= true;
4514 // Wait for all callout threads to finish.
4517 queue_iterate(&pmso
->calloutQueue
, callEntry
, PMSettingCallEntry
*, link
)
4519 if (callEntry
->thread
!= thisThread
) {
4525 assert(NULL
== pmso
->waitThread
);
4526 pmso
->waitThread
= thisThread
;
4527 PMSETTING_WAIT(pmso
);
4528 pmso
->waitThread
= NULL
;
4532 // Search each PM settings array in the kernel.
4533 iter
= OSCollectionIterator::withCollection(settingsCallbacks
);
4535 while ((sym
= OSDynamicCast(OSSymbol
, iter
->getNextObject()))) {
4536 array
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(sym
));
4537 index
= array
->getNextIndexOfObject(pmso
, 0);
4539 array
->removeObject(index
);
4550 //******************************************************************************
4551 // informCPUStateChange
4553 // Call into PM CPU code so that CPU power savings may dynamically adjust for
4554 // running on battery, with the lid closed, etc.
4556 // informCPUStateChange is a no-op on non x86 systems
4557 // only x86 has explicit support in the IntelCPUPowerManagement kext
4558 //******************************************************************************
4561 IOPMrootDomain::informCPUStateChange(
4565 #if defined(__i386__) || defined(__x86_64__)
4567 pmioctlVariableInfo_t varInfoStruct
;
4569 const char *varNameStr
= NULL
;
4570 int32_t *varIndex
= NULL
;
4572 if (kInformAC
== type
) {
4573 varNameStr
= kIOPMRootDomainBatPowerCString
;
4574 varIndex
= &idxPMCPULimitedPower
;
4575 } else if (kInformLid
== type
) {
4576 varNameStr
= kIOPMRootDomainLidCloseCString
;
4577 varIndex
= &idxPMCPUClamshell
;
4582 // Set the new value!
4583 // pmCPUControl will assign us a new ID if one doesn't exist yet
4584 bzero(&varInfoStruct
, sizeof(pmioctlVariableInfo_t
));
4585 varInfoStruct
.varID
= *varIndex
;
4586 varInfoStruct
.varType
= vBool
;
4587 varInfoStruct
.varInitValue
= value
;
4588 varInfoStruct
.varCurValue
= value
;
4589 strlcpy((char *)varInfoStruct
.varName
,
4590 (const char *)varNameStr
,
4591 sizeof(varInfoStruct
.varName
));
4594 pmCPUret
= pmCPUControl( PMIOCSETVARINFO
, (void *)&varInfoStruct
);
4596 // pmCPU only assigns numerical id's when a new varName is specified
4598 && (*varIndex
== kCPUUnknownIndex
)) {
4599 // pmCPUControl has assigned us a new variable ID.
4600 // Let's re-read the structure we just SET to learn that ID.
4601 pmCPUret
= pmCPUControl( PMIOCGETVARNAMEINFO
, (void *)&varInfoStruct
);
4603 if (0 == pmCPUret
) {
4604 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
4605 *varIndex
= varInfoStruct
.varID
;
4611 #endif /* __i386__ || __x86_64__ */
4615 // MARK: Deep Sleep Policy
4619 //******************************************************************************
4620 // evaluateSystemSleepPolicy
4621 //******************************************************************************
4623 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
4627 kIOPMSleepFlagHibernate
= 0x00000001,
4628 kIOPMSleepFlagSleepTimerEnable
= 0x00000002
4631 struct IOPMSystemSleepPolicyEntry
{
4632 uint32_t factorMask
;
4633 uint32_t factorBits
;
4634 uint32_t sleepFlags
;
4635 uint32_t wakeEvents
;
4636 } __attribute__((packed
));
4638 struct IOPMSystemSleepPolicyTable
{
4641 uint16_t entryCount
;
4642 IOPMSystemSleepPolicyEntry entries
[];
4643 } __attribute__((packed
));
4646 kIOPMSleepAttributeHibernateSetup
= 0x00000001,
4647 kIOPMSleepAttributeHibernateSleep
= 0x00000002
4651 getSleepTypeAttributes( uint32_t sleepType
)
4653 static const uint32_t sleepTypeAttributes
[kIOPMSleepTypeLast
] =
4658 /* safesleep */ kIOPMSleepAttributeHibernateSetup
,
4659 /* hibernate */ kIOPMSleepAttributeHibernateSetup
| kIOPMSleepAttributeHibernateSleep
,
4660 /* standby */ kIOPMSleepAttributeHibernateSetup
| kIOPMSleepAttributeHibernateSleep
,
4661 /* poweroff */ kIOPMSleepAttributeHibernateSetup
| kIOPMSleepAttributeHibernateSleep
,
4665 if (sleepType
>= kIOPMSleepTypeLast
) {
4669 return sleepTypeAttributes
[sleepType
];
4673 IOPMrootDomain::evaluateSystemSleepPolicy(
4674 IOPMSystemSleepParameters
* params
, int sleepPhase
, uint32_t * hibMode
)
4676 const IOPMSystemSleepPolicyTable
* pt
;
4677 OSObject
* prop
= NULL
;
4678 OSData
* policyData
;
4679 uint64_t currentFactors
= 0;
4680 char currentFactorsBuf
[512];
4681 uint32_t standbyDelay
= 0;
4682 uint32_t powerOffDelay
= 0;
4683 uint32_t powerOffTimer
= 0;
4684 uint32_t standbyTimer
= 0;
4686 bool standbyEnabled
;
4687 bool powerOffEnabled
;
4690 // Get platform's sleep policy table
4691 if (!gSleepPolicyHandler
) {
4692 prop
= getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey
);
4698 // Fetch additional settings
4699 standbyEnabled
= (getSleepOption(kIOPMDeepSleepDelayKey
, &standbyDelay
)
4700 && (getProperty(kIOPMDeepSleepEnabledKey
) == kOSBooleanTrue
));
4701 powerOffEnabled
= (getSleepOption(kIOPMAutoPowerOffDelayKey
, &powerOffDelay
)
4702 && (getProperty(kIOPMAutoPowerOffEnabledKey
) == kOSBooleanTrue
));
4703 if (!getSleepOption(kIOPMAutoPowerOffTimerKey
, &powerOffTimer
)) {
4704 powerOffTimer
= powerOffDelay
;
4706 if (!getSleepOption(kIOPMDeepSleepTimerKey
, &standbyTimer
)) {
4707 standbyTimer
= standbyDelay
;
4710 DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
4711 sleepPhase
, standbyEnabled
, standbyDelay
, standbyTimer
,
4712 powerOffEnabled
, powerOffDelay
, powerOffTimer
, *hibMode
);
4714 currentFactorsBuf
[0] = 0;
4715 // pmset level overrides
4716 if ((*hibMode
& kIOHibernateModeOn
) == 0) {
4717 if (!gSleepPolicyHandler
) {
4718 standbyEnabled
= false;
4719 powerOffEnabled
= false;
4721 } else if (!(*hibMode
& kIOHibernateModeSleep
)) {
4722 // Force hibernate (i.e. mode 25)
4723 // If standby is enabled, force standy.
4724 // If poweroff is enabled, force poweroff.
4725 if (standbyEnabled
) {
4726 currentFactors
|= kIOPMSleepFactorStandbyForced
;
4727 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "StandbyForced");
4728 } else if (powerOffEnabled
) {
4729 currentFactors
|= kIOPMSleepFactorAutoPowerOffForced
;
4730 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "AutoPowerOffForced");
4732 currentFactors
|= kIOPMSleepFactorHibernateForced
;
4733 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "HibernateForced");
4737 // Current factors based on environment and assertions
4738 if (sleepTimerMaintenance
) {
4739 currentFactors
|= kIOPMSleepFactorSleepTimerWake
;
4740 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "SleepTimerWake");
4742 if (standbyEnabled
&& sleepToStandby
&& !gSleepPolicyHandler
) {
4743 currentFactors
|= kIOPMSleepFactorSleepTimerWake
;
4744 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "SleepTimerWake");
4746 if (!clamshellClosed
) {
4747 currentFactors
|= kIOPMSleepFactorLidOpen
;
4748 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "LidOpen");
4750 if (acAdaptorConnected
) {
4751 currentFactors
|= kIOPMSleepFactorACPower
;
4752 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ACPower");
4754 if (lowBatteryCondition
) {
4755 currentFactors
|= kIOPMSleepFactorBatteryLow
;
4756 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "BatteryLow");
4758 if (!standbyDelay
|| !standbyTimer
) {
4759 currentFactors
|= kIOPMSleepFactorStandbyNoDelay
;
4760 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "StandbyNoDelay");
4762 if (standbyNixed
|| !standbyEnabled
) {
4763 currentFactors
|= kIOPMSleepFactorStandbyDisabled
;
4764 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "StandbyDisabled");
4767 currentFactors
|= kIOPMSleepFactorLocalUserActivity
;
4768 currentFactors
&= ~kIOPMSleepFactorSleepTimerWake
;
4769 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "LocalUserActivity, !SleepTimerWake");
4771 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit
) !=
4772 kIOPMDriverAssertionLevelOff
) {
4773 currentFactors
|= kIOPMSleepFactorUSBExternalDevice
;
4774 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "USBExternalDevice");
4776 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit
) !=
4777 kIOPMDriverAssertionLevelOff
) {
4778 currentFactors
|= kIOPMSleepFactorBluetoothHIDDevice
;
4779 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "BluetoothHIDDevice");
4781 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit
) !=
4782 kIOPMDriverAssertionLevelOff
) {
4783 currentFactors
|= kIOPMSleepFactorExternalMediaMounted
;
4784 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ExternalMediaMounted");
4786 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5
) !=
4787 kIOPMDriverAssertionLevelOff
) {
4788 currentFactors
|= kIOPMSleepFactorThunderboltDevice
;
4789 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ThunderboltDevice");
4791 if (_scheduledAlarms
!= 0) {
4792 currentFactors
|= kIOPMSleepFactorRTCAlarmScheduled
;
4793 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "RTCAlaramScheduled");
4795 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit
) !=
4796 kIOPMDriverAssertionLevelOff
) {
4797 currentFactors
|= kIOPMSleepFactorMagicPacketWakeEnabled
;
4798 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "MagicPacketWakeEnabled");
4800 #define TCPKEEPALIVE 1
4802 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit
) !=
4803 kIOPMDriverAssertionLevelOff
) {
4804 currentFactors
|= kIOPMSleepFactorNetworkKeepAliveActive
;
4805 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "NetworkKeepAliveActive");
4808 if (!powerOffEnabled
) {
4809 currentFactors
|= kIOPMSleepFactorAutoPowerOffDisabled
;
4810 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "AutoPowerOffDisabled");
4813 currentFactors
|= kIOPMSleepFactorExternalDisplay
;
4814 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ExternalDisplay");
4816 if (userWasActive
) {
4817 currentFactors
|= kIOPMSleepFactorLocalUserActivity
;
4818 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "LocalUserActivity");
4820 if (darkWakeHibernateError
&& !CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
4821 currentFactors
|= kIOPMSleepFactorHibernateFailed
;
4822 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "HibernateFailed");
4824 if (thermalWarningState
) {
4825 currentFactors
|= kIOPMSleepFactorThermalWarning
;
4826 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ThermalWarning");
4829 DLOG("sleep factors 0x%llx %s\n", currentFactors
, currentFactorsBuf
);
4831 if (gSleepPolicyHandler
) {
4832 uint32_t savedHibernateMode
;
4835 if (!gSleepPolicyVars
) {
4836 gSleepPolicyVars
= IONew(IOPMSystemSleepPolicyVariables
, 1);
4837 if (!gSleepPolicyVars
) {
4840 bzero(gSleepPolicyVars
, sizeof(*gSleepPolicyVars
));
4842 gSleepPolicyVars
->signature
= kIOPMSystemSleepPolicySignature
;
4843 gSleepPolicyVars
->version
= kIOPMSystemSleepPolicyVersion
;
4844 gSleepPolicyVars
->currentCapability
= _currentCapability
;
4845 gSleepPolicyVars
->highestCapability
= _highestCapability
;
4846 gSleepPolicyVars
->sleepFactors
= currentFactors
;
4847 gSleepPolicyVars
->sleepReason
= lastSleepReason
;
4848 gSleepPolicyVars
->sleepPhase
= sleepPhase
;
4849 gSleepPolicyVars
->standbyDelay
= standbyDelay
;
4850 gSleepPolicyVars
->standbyTimer
= standbyTimer
;
4851 gSleepPolicyVars
->poweroffDelay
= powerOffDelay
;
4852 gSleepPolicyVars
->scheduledAlarms
= _scheduledAlarms
| _userScheduledAlarm
;
4853 gSleepPolicyVars
->poweroffTimer
= powerOffTimer
;
4855 if (kIOPMSleepPhase0
== sleepPhase
) {
4856 // preserve hibernateMode
4857 savedHibernateMode
= gSleepPolicyVars
->hibernateMode
;
4858 gSleepPolicyVars
->hibernateMode
= *hibMode
;
4859 } else if (kIOPMSleepPhase1
== sleepPhase
) {
4860 // use original hibernateMode for phase2
4861 gSleepPolicyVars
->hibernateMode
= *hibMode
;
4864 result
= gSleepPolicyHandler(gSleepPolicyTarget
, gSleepPolicyVars
, params
);
4866 if (kIOPMSleepPhase0
== sleepPhase
) {
4867 // restore hibernateMode
4868 gSleepPolicyVars
->hibernateMode
= savedHibernateMode
;
4871 if ((result
!= kIOReturnSuccess
) ||
4872 (kIOPMSleepTypeInvalid
== params
->sleepType
) ||
4873 (params
->sleepType
>= kIOPMSleepTypeLast
) ||
4874 (kIOPMSystemSleepParametersVersion
!= params
->version
)) {
4875 MSG("sleep policy handler error\n");
4879 if ((getSleepTypeAttributes(params
->sleepType
) &
4880 kIOPMSleepAttributeHibernateSetup
) &&
4881 ((*hibMode
& kIOHibernateModeOn
) == 0)) {
4882 *hibMode
|= (kIOHibernateModeOn
| kIOHibernateModeSleep
);
4885 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
4886 params
->version
, params
->sleepType
, params
->sleepFlags
,
4887 params
->ecWakeEvents
, params
->ecWakeTimer
, params
->ecPoweroffTimer
);
4892 // Policy table is meaningless without standby enabled
4893 if (!standbyEnabled
) {
4897 // Validate the sleep policy table
4898 policyData
= OSDynamicCast(OSData
, prop
);
4899 if (!policyData
|| (policyData
->getLength() <= sizeof(IOPMSystemSleepPolicyTable
))) {
4903 pt
= (const IOPMSystemSleepPolicyTable
*) policyData
->getBytesNoCopy();
4904 if ((pt
->signature
!= kIOPMSystemSleepPolicySignature
) ||
4905 (pt
->version
!= 1) || (0 == pt
->entryCount
)) {
4909 if (((policyData
->getLength() - sizeof(IOPMSystemSleepPolicyTable
)) !=
4910 (sizeof(IOPMSystemSleepPolicyEntry
) * pt
->entryCount
))) {
4914 for (uint32_t i
= 0; i
< pt
->entryCount
; i
++) {
4915 const IOPMSystemSleepPolicyEntry
* entry
= &pt
->entries
[i
];
4916 mismatch
= (((uint32_t)currentFactors
^ entry
->factorBits
) & entry
->factorMask
);
4918 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
4919 entry
->factorMask
, entry
->factorBits
,
4920 entry
->sleepFlags
, entry
->wakeEvents
, mismatch
);
4925 DLOG("^ found match\n");
4928 params
->version
= kIOPMSystemSleepParametersVersion
;
4929 params
->reserved1
= 1;
4930 if (entry
->sleepFlags
& kIOPMSleepFlagHibernate
) {
4931 params
->sleepType
= kIOPMSleepTypeStandby
;
4933 params
->sleepType
= kIOPMSleepTypeNormalSleep
;
4936 params
->ecWakeEvents
= entry
->wakeEvents
;
4937 if (entry
->sleepFlags
& kIOPMSleepFlagSleepTimerEnable
) {
4938 if (kIOPMSleepPhase2
== sleepPhase
) {
4939 clock_sec_t now_secs
= gIOLastSleepTime
.tv_sec
;
4941 if (!_standbyTimerResetSeconds
||
4942 (now_secs
<= _standbyTimerResetSeconds
)) {
4943 // Reset standby timer adjustment
4944 _standbyTimerResetSeconds
= now_secs
;
4945 DLOG("standby delay %u, reset %u\n",
4946 standbyDelay
, (uint32_t) _standbyTimerResetSeconds
);
4947 } else if (standbyDelay
) {
4948 // Shorten the standby delay timer
4949 clock_sec_t elapsed
= now_secs
- _standbyTimerResetSeconds
;
4950 if (standbyDelay
> elapsed
) {
4951 standbyDelay
-= elapsed
;
4953 standbyDelay
= 1; // must be > 0
4955 DLOG("standby delay %u, elapsed %u\n",
4956 standbyDelay
, (uint32_t) elapsed
);
4959 params
->ecWakeTimer
= standbyDelay
;
4960 } else if (kIOPMSleepPhase2
== sleepPhase
) {
4961 // A sleep that does not enable the sleep timer will reset
4962 // the standby delay adjustment.
4963 _standbyTimerResetSeconds
= 0;
4976 static IOPMSystemSleepParameters gEarlySystemSleepParams
;
4979 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
4981 // Evaluate early (priority interest phase), before drivers sleep.
4983 DLOG("%s\n", __FUNCTION__
);
4984 removeProperty(kIOPMSystemSleepParametersKey
);
4986 // Full wake resets the standby timer delay adjustment
4987 if (_highestCapability
& kIOPMSystemCapabilityGraphics
) {
4988 _standbyTimerResetSeconds
= 0;
4991 hibernateDisabled
= false;
4993 getSleepOption(kIOHibernateModeKey
, &hibernateMode
);
4995 // Save for late evaluation if sleep is aborted
4996 bzero(&gEarlySystemSleepParams
, sizeof(gEarlySystemSleepParams
));
4998 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams
, kIOPMSleepPhase1
,
5000 if (!hibernateRetry
&&
5001 ((getSleepTypeAttributes(gEarlySystemSleepParams
.sleepType
) &
5002 kIOPMSleepAttributeHibernateSetup
) == 0)) {
5003 // skip hibernate setup
5004 hibernateDisabled
= true;
5008 // Publish IOPMSystemSleepType
5009 uint32_t sleepType
= gEarlySystemSleepParams
.sleepType
;
5010 if (sleepType
== kIOPMSleepTypeInvalid
) {
5012 sleepType
= kIOPMSleepTypeNormalSleep
;
5013 if (hibernateMode
& kIOHibernateModeOn
) {
5014 sleepType
= (hibernateMode
& kIOHibernateModeSleep
) ?
5015 kIOPMSleepTypeSafeSleep
: kIOPMSleepTypeHibernate
;
5017 } else if ((sleepType
== kIOPMSleepTypeStandby
) &&
5018 (gEarlySystemSleepParams
.ecPoweroffTimer
)) {
5019 // report the lowest possible sleep state
5020 sleepType
= kIOPMSleepTypePowerOff
;
5023 setProperty(kIOPMSystemSleepTypeKey
, sleepType
, 32);
5027 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5029 IOPMSystemSleepParameters params
;
5030 OSData
* paramsData
;
5032 // Evaluate sleep policy after sleeping drivers but before platform sleep.
5034 DLOG("%s\n", __FUNCTION__
);
5036 bzero(¶ms
, sizeof(params
));
5038 if (evaluateSystemSleepPolicy(¶ms
, kIOPMSleepPhase2
, &hibernateMode
)) {
5039 if ((kIOPMSleepTypeStandby
== params
.sleepType
)
5040 && gIOHibernateStandbyDisabled
&& gSleepPolicyVars
5041 && (!((kIOPMSleepFactorStandbyForced
| kIOPMSleepFactorAutoPowerOffForced
| kIOPMSleepFactorHibernateForced
)
5042 & gSleepPolicyVars
->sleepFactors
))) {
5043 standbyNixed
= true;
5047 || ((hibernateDisabled
|| hibernateAborted
) &&
5048 (getSleepTypeAttributes(params
.sleepType
) &
5049 kIOPMSleepAttributeHibernateSetup
))) {
5050 // Final evaluation picked a state requiring hibernation,
5051 // but hibernate isn't going to proceed. Arm a short sleep using
5052 // the early non-hibernate sleep parameters.
5053 bcopy(&gEarlySystemSleepParams
, ¶ms
, sizeof(params
));
5054 params
.sleepType
= kIOPMSleepTypeAbortedSleep
;
5055 params
.ecWakeTimer
= 1;
5059 // Set hibernateRetry flag to force hibernate setup on the
5061 hibernateRetry
= true;
5063 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5064 params
.ecWakeTimer
, hibernateDisabled
, hibernateAborted
, standbyNixed
);
5066 hibernateRetry
= false;
5069 if (kIOPMSleepTypeAbortedSleep
!= params
.sleepType
) {
5070 resetTimers
= false;
5073 paramsData
= OSData::withBytes(¶ms
, sizeof(params
));
5075 setProperty(kIOPMSystemSleepParametersKey
, paramsData
);
5076 paramsData
->release();
5079 if (getSleepTypeAttributes(params
.sleepType
) &
5080 kIOPMSleepAttributeHibernateSleep
) {
5081 // Disable sleep to force hibernation
5082 gIOHibernateMode
&= ~kIOHibernateModeSleep
;
5088 IOPMrootDomain::getHibernateSettings(
5089 uint32_t * hibernateModePtr
,
5090 uint32_t * hibernateFreeRatio
,
5091 uint32_t * hibernateFreeTime
)
5093 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5094 // has updated the hibernateDisabled flag.
5096 bool ok
= getSleepOption(kIOHibernateModeKey
, hibernateModePtr
);
5097 getSleepOption(kIOHibernateFreeRatioKey
, hibernateFreeRatio
);
5098 getSleepOption(kIOHibernateFreeTimeKey
, hibernateFreeTime
);
5099 if (hibernateDisabled
) {
5100 *hibernateModePtr
= 0;
5101 } else if (gSleepPolicyHandler
) {
5102 *hibernateModePtr
= hibernateMode
;
5104 DLOG("hibernateMode 0x%x\n", *hibernateModePtr
);
5109 IOPMrootDomain::getSleepOption( const char * key
, uint32_t * option
)
5111 OSObject
* optionsProp
;
5112 OSDictionary
* optionsDict
;
5113 OSObject
* obj
= NULL
;
5117 optionsProp
= copyProperty(kRootDomainSleepOptionsKey
);
5118 optionsDict
= OSDynamicCast(OSDictionary
, optionsProp
);
5121 obj
= optionsDict
->getObject(key
);
5127 obj
= copyProperty(key
);
5130 if ((num
= OSDynamicCast(OSNumber
, obj
))) {
5131 *option
= num
->unsigned32BitValue();
5133 } else if (OSDynamicCast(OSBoolean
, obj
)) {
5134 *option
= (obj
== kOSBooleanTrue
) ? 1 : 0;
5143 optionsProp
->release();
5148 #endif /* HIBERNATION */
5151 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType
, uint32_t * standbyTimer
)
5154 IOPMSystemSleepParameters params
;
5155 uint32_t hibMode
= 0;
5158 if (gIOPMWorkLoop
->inGate() == false) {
5159 IOReturn ret
= gIOPMWorkLoop
->runAction(
5160 OSMemberFunctionCast(IOWorkLoop::Action
, this,
5161 &IOPMrootDomain::getSystemSleepType
),
5163 (void *) sleepType
, (void *) standbyTimer
);
5167 getSleepOption(kIOHibernateModeKey
, &hibMode
);
5168 bzero(¶ms
, sizeof(params
));
5170 ok
= evaluateSystemSleepPolicy(¶ms
, kIOPMSleepPhase0
, &hibMode
);
5172 *sleepType
= params
.sleepType
;
5173 if (!getSleepOption(kIOPMDeepSleepTimerKey
, standbyTimer
) &&
5174 !getSleepOption(kIOPMDeepSleepDelayKey
, standbyTimer
)) {
5175 DLOG("Standby delay is not set\n");
5178 return kIOReturnSuccess
;
5182 return kIOReturnUnsupported
;
5186 // MARK: Shutdown and Restart
5188 //******************************************************************************
5189 // handlePlatformHaltRestart
5191 //******************************************************************************
5193 // Phases while performing shutdown/restart
5196 kNotifyPriorityClients
= 0x10,
5197 kNotifyPowerPlaneDrivers
= 0x20,
5198 kNotifyHaltRestartAction
= 0x30,
5203 struct HaltRestartApplierContext
{
5204 IOPMrootDomain
* RootDomain
;
5205 unsigned long PowerState
;
5206 IOPMPowerFlags PowerFlags
;
5209 const char * LogString
;
5210 shutdownPhase_t phase
;
5212 IOServiceInterestHandler handler
;
5216 shutdownPhase2String(shutdownPhase_t phase
)
5220 return "Notifications completed";
5221 case kNotifyPriorityClients
:
5222 return "Notifying priority clients";
5223 case kNotifyPowerPlaneDrivers
:
5224 return "Notifying power plane drivers";
5225 case kNotifyHaltRestartAction
:
5226 return "Notifying HaltRestart action handlers";
5228 return "Quiescing PM";
5235 platformHaltRestartApplier( OSObject
* object
, void * context
)
5237 IOPowerStateChangeNotification notify
;
5238 HaltRestartApplierContext
* ctx
;
5239 AbsoluteTime startTime
, elapsedTime
;
5242 ctx
= (HaltRestartApplierContext
*) context
;
5244 _IOServiceInterestNotifier
* notifier
;
5245 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
5246 memset(¬ify
, 0, sizeof(notify
));
5247 notify
.powerRef
= (void *)(uintptr_t)ctx
->Counter
;
5248 notify
.returnValue
= 0;
5249 notify
.stateNumber
= ctx
->PowerState
;
5250 notify
.stateFlags
= ctx
->PowerFlags
;
5253 ctx
->handler
= notifier
->handler
;
5256 clock_get_uptime(&startTime
);
5257 ctx
->RootDomain
->messageClient( ctx
->MessageType
, object
, (void *)¬ify
);
5258 deltaTime
= computeDeltaTimeMS(&startTime
, &elapsedTime
);
5260 if ((deltaTime
> kPMHaltTimeoutMS
) && notifier
) {
5261 LOG("%s handler %p took %u ms\n",
5262 ctx
->LogString
, OBFUSCATE(notifier
->handler
), deltaTime
);
5263 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier
->handler
, elapsedTime
);
5266 ctx
->handler
= NULL
;
5271 quiescePowerTreeCallback( void * target
, void * param
)
5273 IOLockLock(gPMHaltLock
);
5275 thread_wakeup(param
);
5276 IOLockUnlock(gPMHaltLock
);
5280 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type
)
5282 AbsoluteTime startTime
, elapsedTime
;
5285 memset(&gHaltRestartCtx
, 0, sizeof(gHaltRestartCtx
));
5286 gHaltRestartCtx
.RootDomain
= this;
5288 clock_get_uptime(&startTime
);
5291 case kPEUPSDelayHaltCPU
:
5292 gHaltRestartCtx
.PowerState
= OFF_STATE
;
5293 gHaltRestartCtx
.MessageType
= kIOMessageSystemWillPowerOff
;
5294 gHaltRestartCtx
.LogString
= "PowerOff";
5298 gHaltRestartCtx
.PowerState
= RESTART_STATE
;
5299 gHaltRestartCtx
.MessageType
= kIOMessageSystemWillRestart
;
5300 gHaltRestartCtx
.LogString
= "Restart";
5304 gHaltRestartCtx
.PowerState
= ON_STATE
;
5305 gHaltRestartCtx
.MessageType
= kIOMessageSystemPagingOff
;
5306 gHaltRestartCtx
.LogString
= "PagingOff";
5307 IOService::updateConsoleUsers(NULL
, kIOMessageSystemPagingOff
);
5309 IOHibernateSystemRestart();
5317 gHaltRestartCtx
.phase
= kNotifyPriorityClients
;
5318 // Notify legacy clients
5319 applyToInterested(gIOPriorityPowerStateInterest
, platformHaltRestartApplier
, &gHaltRestartCtx
);
5321 // For normal shutdown, turn off File Server Mode.
5322 if (kPEHaltCPU
== pe_type
) {
5323 const OSSymbol
* setting
= OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
);
5324 OSNumber
* num
= OSNumber::withNumber((unsigned long long) 0, 32);
5325 if (setting
&& num
) {
5326 setPMSetting(setting
, num
);
5333 if (kPEPagingOff
!= pe_type
) {
5334 gHaltRestartCtx
.phase
= kNotifyPowerPlaneDrivers
;
5335 // Notify in power tree order
5336 notifySystemShutdown(this, gHaltRestartCtx
.MessageType
);
5339 gHaltRestartCtx
.phase
= kNotifyHaltRestartAction
;
5340 #if !CONFIG_EMBEDDED
5341 IOCPURunPlatformHaltRestartActions(pe_type
);
5343 if (kPEPagingOff
!= pe_type
) {
5344 IOCPURunPlatformHaltRestartActions(pe_type
);
5348 // Wait for PM to quiesce
5349 if ((kPEPagingOff
!= pe_type
) && gPMHaltLock
) {
5350 gHaltRestartCtx
.phase
= kQuiescePM
;
5351 AbsoluteTime quiesceTime
= mach_absolute_time();
5353 IOLockLock(gPMHaltLock
);
5354 gPMQuiesced
= false;
5355 if (quiescePowerTree(this, &quiescePowerTreeCallback
, &gPMQuiesced
) ==
5357 while (!gPMQuiesced
) {
5358 IOLockSleep(gPMHaltLock
, &gPMQuiesced
, THREAD_UNINT
);
5361 IOLockUnlock(gPMHaltLock
);
5362 deltaTime
= computeDeltaTimeMS(&quiesceTime
, &elapsedTime
);
5363 DLOG("PM quiesce took %u ms\n", deltaTime
);
5364 halt_log_enter("Quiesce", NULL
, elapsedTime
);
5366 gHaltRestartCtx
.phase
= kNotifyDone
;
5368 deltaTime
= computeDeltaTimeMS(&startTime
, &elapsedTime
);
5369 LOG("%s all drivers took %u ms\n", gHaltRestartCtx
.LogString
, deltaTime
);
5371 halt_log_enter(gHaltRestartCtx
.LogString
, NULL
, elapsedTime
);
5373 deltaTime
= computeDeltaTimeMS(&gHaltStartTime
, &elapsedTime
);
5374 LOG("%s total %u ms\n", gHaltRestartCtx
.LogString
, deltaTime
);
5376 if (gHaltLog
&& gHaltTimeMaxLog
&& (deltaTime
>= gHaltTimeMaxLog
)) {
5377 printf("%s total %d ms:%s\n", gHaltRestartCtx
.LogString
, deltaTime
, gHaltLog
);
5380 checkShutdownTimeout();
5384 IOPMrootDomain::checkShutdownTimeout()
5386 AbsoluteTime elapsedTime
;
5387 uint32_t deltaTime
= computeDeltaTimeMS(&gHaltStartTime
, &elapsedTime
);
5389 if (gHaltTimeMaxPanic
&& (deltaTime
>= gHaltTimeMaxPanic
)) {
5396 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs
)
5399 if ((gHaltRestartCtx
.phase
== kNotifyPriorityClients
) && gHaltRestartCtx
.handler
) {
5400 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx
.handler
, mach_absolute_time() - gHaltStartTime
);
5402 panic("%s timed out in phase '%s'. Total %d ms:%s",
5403 gHaltRestartCtx
.LogString
, shutdownPhase2String(gHaltRestartCtx
.phase
), timeoutInMs
, gHaltLog
);
5405 panic("%s timed out in phase \'%s\'. Total %d ms",
5406 gHaltRestartCtx
.LogString
, shutdownPhase2String(gHaltRestartCtx
.phase
), timeoutInMs
);
5410 //******************************************************************************
5413 //******************************************************************************
5416 IOPMrootDomain::shutdownSystem( void )
5418 return kIOReturnUnsupported
;
5421 //******************************************************************************
5424 //******************************************************************************
5427 IOPMrootDomain::restartSystem( void )
5429 return kIOReturnUnsupported
;
5433 // MARK: System Capability
5435 //******************************************************************************
5436 // tagPowerPlaneService
5438 // Running on PM work loop thread.
5439 //******************************************************************************
5442 IOPMrootDomain::tagPowerPlaneService(
5443 IOService
* service
,
5444 IOPMActions
* actions
)
5447 bool isDisplayWrangler
;
5449 memset(actions
, 0, sizeof(*actions
));
5450 actions
->target
= this;
5452 if (service
== this) {
5453 actions
->actionPowerChangeStart
=
5454 OSMemberFunctionCast(
5455 IOPMActionPowerChangeStart
, this,
5456 &IOPMrootDomain::handleOurPowerChangeStart
);
5458 actions
->actionPowerChangeDone
=
5459 OSMemberFunctionCast(
5460 IOPMActionPowerChangeDone
, this,
5461 &IOPMrootDomain::handleOurPowerChangeDone
);
5463 actions
->actionPowerChangeOverride
=
5464 OSMemberFunctionCast(
5465 IOPMActionPowerChangeOverride
, this,
5466 &IOPMrootDomain::overrideOurPowerChange
);
5471 isDisplayWrangler
= (NULL
!= service
->metaCast("IODisplayWrangler"));
5472 if (isDisplayWrangler
) {
5474 // found the display wrangler, check for any display assertions already created
5475 if (pmAssertions
->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit
) {
5476 DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
5477 wrangler
->setIgnoreIdleTimer( true );
5481 isDisplayWrangler
= false;
5484 #if defined(__i386__) || defined(__x86_64__)
5485 if (isDisplayWrangler
) {
5486 flags
|= kPMActionsFlagIsDisplayWrangler
;
5488 if (service
->getProperty("IOPMStrictTreeOrder")) {
5489 flags
|= kPMActionsFlagIsGraphicsDevice
;
5491 if (service
->getProperty("IOPMUnattendedWakePowerState")) {
5492 flags
|= kPMActionsFlagIsAudioDevice
;
5496 // Find the power connection object that is a child of the PCI host
5497 // bridge, and has a graphics/audio device attached below. Mark the
5498 // power branch for delayed child notifications.
5501 IORegistryEntry
* child
= service
;
5502 IORegistryEntry
* parent
= child
->getParentEntry(gIOPowerPlane
);
5504 while (child
!= this) {
5505 if (child
->getProperty("IOPCITunnelled") == kOSBooleanTrue
) {
5506 // Skip delaying notifications and clamping power on external graphics and audio devices.
5507 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service
->getRegistryEntryID(), flags
);
5511 if ((parent
== pciHostBridgeDriver
) ||
5513 if (OSDynamicCast(IOPowerConnection
, child
)) {
5514 IOPowerConnection
* conn
= (IOPowerConnection
*) child
;
5515 conn
->delayChildNotification
= true;
5516 DLOG("delayChildNotification for 0x%llx\n", conn
->getRegistryEntryID());
5521 parent
= child
->getParentEntry(gIOPowerPlane
);
5526 DLOG("%s tag flags %x\n", service
->getName(), flags
);
5527 actions
->parameter
|= flags
;
5528 actions
->actionPowerChangeOverride
=
5529 OSMemberFunctionCast(
5530 IOPMActionPowerChangeOverride
, this,
5531 &IOPMrootDomain::overridePowerChangeForUIService
);
5533 if (flags
& kPMActionsFlagIsDisplayWrangler
) {
5534 actions
->actionActivityTickle
=
5535 OSMemberFunctionCast(
5536 IOPMActionActivityTickle
, this,
5537 &IOPMrootDomain::handleActivityTickleForDisplayWrangler
);
5539 actions
->actionUpdatePowerClient
=
5540 OSMemberFunctionCast(
5541 IOPMActionUpdatePowerClient
, this,
5542 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler
);
5547 // Locate the first PCI host bridge for PMTrace.
5548 if (!pciHostBridgeDevice
&& service
->metaCast("IOPCIBridge")) {
5549 IOService
* provider
= service
->getProvider();
5550 if (OSDynamicCast(IOPlatformDevice
, provider
) &&
5551 provider
->inPlane(gIODTPlane
)) {
5552 pciHostBridgeDevice
= provider
;
5553 pciHostBridgeDriver
= service
;
5554 DLOG("PMTrace found PCI host bridge %s->%s\n",
5555 provider
->getName(), service
->getName());
5559 // Tag top-level PCI devices. The order of PMinit() call does not
5560 // change across boots and is used as the PCI bit number.
5561 if (pciHostBridgeDevice
&& service
->metaCast("IOPCIDevice")) {
5562 // Would prefer to check built-in property, but tagPowerPlaneService()
5563 // is called before pciDevice->registerService().
5564 IORegistryEntry
* parent
= service
->getParentEntry(gIODTPlane
);
5565 if ((parent
== pciHostBridgeDevice
) && service
->getProperty("acpi-device")) {
5566 int bit
= pmTracer
->recordTopLevelPCIDevice( service
);
5568 // Save the assigned bit for fast lookup.
5569 actions
->parameter
|= (bit
& kPMActionsPCIBitNumberMask
);
5571 actions
->actionPowerChangeStart
=
5572 OSMemberFunctionCast(
5573 IOPMActionPowerChangeStart
, this,
5574 &IOPMrootDomain::handlePowerChangeStartForPCIDevice
);
5576 actions
->actionPowerChangeDone
=
5577 OSMemberFunctionCast(
5578 IOPMActionPowerChangeDone
, this,
5579 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice
);
5585 //******************************************************************************
5586 // PM actions for root domain
5587 //******************************************************************************
5590 IOPMrootDomain::overrideOurPowerChange(
5591 IOService
* service
,
5592 IOPMActions
* actions
,
5593 IOPMPowerStateIndex
* inOutPowerState
,
5594 IOPMPowerChangeFlags
* inOutChangeFlags
,
5595 IOPMRequestTag requestTag
)
5597 uint32_t powerState
= (uint32_t) *inOutPowerState
;
5598 uint32_t changeFlags
= *inOutChangeFlags
;
5599 uint32_t currentPowerState
= (uint32_t) getPowerState();
5601 if ((AOT_STATE
== powerState
) && (ON_STATE
== currentPowerState
)) {
5602 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
5603 *inOutChangeFlags
|= kIOPMNotDone
;
5607 if (changeFlags
& kIOPMParentInitiated
) {
5608 // Root parent is permanently pegged at max power,
5609 // a parent initiated power change is unexpected.
5610 *inOutChangeFlags
|= kIOPMNotDone
;
5614 if (powerState
< currentPowerState
) {
5615 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
5616 // Root domain is dropping power state ON->SLEEP.
5617 // If system is in full wake, first enter dark wake by
5618 // converting the power drop to a capability change.
5619 // Once in dark wake, transition to sleep state ASAP.
5621 darkWakeToSleepASAP
= true;
5623 // Drop graphics and audio capability
5624 _desiredCapability
&= ~(
5625 kIOPMSystemCapabilityGraphics
|
5626 kIOPMSystemCapabilityAudio
);
5628 // Convert to capability change (ON->ON)
5629 *inOutPowerState
= getRUN_STATE();
5630 *inOutChangeFlags
|= kIOPMSynchronize
;
5632 // Revert device desire from SLEEP to ON
5633 changePowerStateToPriv(getRUN_STATE());
5635 // System is in dark wake, ok to drop power state.
5636 // Broadcast root powering down to entire tree.
5637 *inOutChangeFlags
|= kIOPMRootChangeDown
;
5639 } else if (powerState
> currentPowerState
) {
5640 if ((_currentCapability
& kIOPMSystemCapabilityCPU
) == 0) {
5641 // Broadcast power up when waking from sleep, but not for the
5642 // initial power change at boot by checking for cpu capability.
5643 *inOutChangeFlags
|= kIOPMRootChangeUp
;
5649 IOPMrootDomain::handleOurPowerChangeStart(
5650 IOService
* service
,
5651 IOPMActions
* actions
,
5652 IOPMPowerStateIndex powerState
,
5653 IOPMPowerChangeFlags
* inOutChangeFlags
,
5654 IOPMRequestTag requestTag
)
5656 uint32_t changeFlags
= *inOutChangeFlags
;
5657 uint32_t currentPowerState
= (uint32_t) getPowerState();
5658 uint32_t sleepReason
= requestTag
? requestTag
: kIOPMSleepReasonIdle
;
5659 bool publishSleepReason
= false;
5661 _systemTransitionType
= kSystemTransitionNone
;
5662 _systemMessageClientMask
= 0;
5663 capabilityLoss
= false;
5664 toldPowerdCapWillChange
= false;
5666 if (lowBatteryCondition
) {
5667 // Low battery notification may arrive after the initial sleep request
5668 // has been queued. Override the sleep reason so powerd and others can
5669 // treat this as an emergency sleep.
5670 sleepReason
= kIOPMSleepReasonLowPower
;
5673 // 1. Explicit capability change.
5675 if (changeFlags
& kIOPMSynchronize
) {
5676 if (powerState
== ON_STATE
) {
5677 if (changeFlags
& kIOPMSyncNoChildNotify
) {
5678 _systemTransitionType
= kSystemTransitionNewCapClient
;
5680 _systemTransitionType
= kSystemTransitionCapability
;
5684 // 2. Going to sleep (cancellation still possible).
5685 else if (powerState
< currentPowerState
) {
5686 _systemTransitionType
= kSystemTransitionSleep
;
5688 // 3. Woke from (idle or demand) sleep.
5689 else if (!systemBooting
&&
5690 (changeFlags
& kIOPMSelfInitiated
) &&
5691 (powerState
> currentPowerState
)) {
5692 _systemTransitionType
= kSystemTransitionWake
;
5693 _desiredCapability
= kIOPMSystemCapabilityCPU
|
5694 kIOPMSystemCapabilityNetwork
;
5696 // Early exit from dark wake to full (e.g. LID open)
5697 if (kFullWakeReasonNone
!= fullWakeReason
) {
5698 _desiredCapability
|= (
5699 kIOPMSystemCapabilityGraphics
|
5700 kIOPMSystemCapabilityAudio
);
5703 IOHibernateSetWakeCapabilities(_desiredCapability
);
5707 // Update pending wake capability at the beginning of every
5708 // state transition (including synchronize). This will become
5709 // the current capability at the end of the transition.
5711 if (kSystemTransitionSleep
== _systemTransitionType
) {
5712 _pendingCapability
= 0;
5713 capabilityLoss
= true;
5714 } else if (kSystemTransitionNewCapClient
!= _systemTransitionType
) {
5715 _pendingCapability
= _desiredCapability
|
5716 kIOPMSystemCapabilityCPU
|
5717 kIOPMSystemCapabilityNetwork
;
5719 if (_pendingCapability
& kIOPMSystemCapabilityGraphics
) {
5720 _pendingCapability
|= kIOPMSystemCapabilityAudio
;
5723 if ((kSystemTransitionCapability
== _systemTransitionType
) &&
5724 (_pendingCapability
== _currentCapability
)) {
5725 // Cancel the PM state change.
5726 _systemTransitionType
= kSystemTransitionNone
;
5727 *inOutChangeFlags
|= kIOPMNotDone
;
5729 if (__builtin_popcount(_pendingCapability
) <
5730 __builtin_popcount(_currentCapability
)) {
5731 capabilityLoss
= true;
5735 // 1. Capability change.
5737 if (kSystemTransitionCapability
== _systemTransitionType
) {
5738 // Dark to Full transition.
5739 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
5740 tracePoint( kIOPMTracePointDarkWakeExit
);
5742 willEnterFullWake();
5745 // Full to Dark transition.
5746 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) {
5747 // Clear previous stats
5748 IOLockLock(pmStatsLock
);
5749 if (pmStatsAppResponses
) {
5750 pmStatsAppResponses
->release();
5751 pmStatsAppResponses
= OSArray::withCapacity(5);
5753 IOLockUnlock(pmStatsLock
);
5756 tracePoint( kIOPMTracePointDarkWakeEntry
);
5757 *inOutChangeFlags
|= kIOPMSyncTellPowerDown
;
5758 _systemMessageClientMask
= kSystemMessageClientPowerd
|
5759 kSystemMessageClientLegacyApp
;
5763 // Prevent user active transitions before notifying clients
5764 // that system will sleep.
5765 preventTransitionToUserActive(true);
5767 IOService::setAdvisoryTickleEnable( false );
5769 // Publish the sleep reason for full to dark wake
5770 publishSleepReason
= true;
5771 lastSleepReason
= fullToDarkReason
= sleepReason
;
5773 // Publish a UUID for the Sleep --> Wake cycle
5774 handlePublishSleepWakeUUID(true);
5775 if (sleepDelaysReport
) {
5776 clock_get_uptime(&ts_sleepStart
);
5777 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart
);
5780 wranglerTickled
= false;
5784 else if (kSystemTransitionSleep
== _systemTransitionType
) {
5785 // Beginning of a system sleep transition.
5786 // Cancellation is still possible.
5787 tracePoint( kIOPMTracePointSleepStarted
);
5789 _systemMessageClientMask
= kSystemMessageClientAll
;
5790 if ((_currentCapability
& kIOPMSystemCapabilityGraphics
) == 0) {
5791 _systemMessageClientMask
&= ~kSystemMessageClientLegacyApp
;
5793 if ((_highestCapability
& kIOPMSystemCapabilityGraphics
) == 0) {
5794 // Kernel priority clients are only notified on the initial
5795 // transition to full wake, so don't notify them unless system
5796 // has gained graphics capability since the last system wake.
5797 _systemMessageClientMask
&= ~kSystemMessageClientKernel
;
5800 gIOHibernateState
= 0;
5803 // Record the reason for dark wake back to sleep
5804 // System may not have ever achieved full wake
5806 publishSleepReason
= true;
5807 lastSleepReason
= sleepReason
;
5808 if (sleepDelaysReport
) {
5809 clock_get_uptime(&ts_sleepStart
);
5810 DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart
);
5814 else if (kSystemTransitionWake
== _systemTransitionType
) {
5815 tracePoint( kIOPMTracePointWakeWillPowerOnClients
);
5816 // Clear stats about sleep
5818 if (AOT_STATE
== powerState
) {
5819 _pendingCapability
= 0;
5822 if (_pendingCapability
& kIOPMSystemCapabilityGraphics
) {
5823 willEnterFullWake();
5825 // Message powerd only
5826 _systemMessageClientMask
= kSystemMessageClientPowerd
;
5827 tellClients(kIOMessageSystemWillPowerOn
);
5831 // The only location where the sleep reason is published. At this point
5832 // sleep can still be cancelled, but sleep reason should be published
5833 // early for logging purposes.
5835 if (publishSleepReason
) {
5836 static const char * IOPMSleepReasons
[] =
5838 kIOPMClamshellSleepKey
,
5839 kIOPMPowerButtonSleepKey
,
5840 kIOPMSoftwareSleepKey
,
5841 kIOPMOSSwitchHibernationKey
,
5843 kIOPMLowPowerSleepKey
,
5844 kIOPMThermalEmergencySleepKey
,
5845 kIOPMMaintenanceSleepKey
,
5846 kIOPMSleepServiceExitKey
,
5847 kIOPMDarkWakeThermalEmergencyKey
5850 // Record sleep cause in IORegistry
5851 uint32_t reasonIndex
= sleepReason
- kIOPMSleepReasonClamshell
;
5852 if (reasonIndex
< sizeof(IOPMSleepReasons
) / sizeof(IOPMSleepReasons
[0])) {
5853 DLOG("sleep reason %s\n", IOPMSleepReasons
[reasonIndex
]);
5854 setProperty(kRootDomainSleepReasonKey
, IOPMSleepReasons
[reasonIndex
]);
5858 if ((kSystemTransitionNone
!= _systemTransitionType
) &&
5859 (kSystemTransitionNewCapClient
!= _systemTransitionType
)) {
5860 _systemStateGeneration
++;
5861 systemDarkWake
= false;
5863 DLOG("=== START (%s->%s, 0x%x) type %u, gen %u, msg %x, "
5865 getPowerStateString(currentPowerState
), getPowerStateString((uint32_t) powerState
), *inOutChangeFlags
,
5866 _systemTransitionType
, _systemStateGeneration
,
5867 _systemMessageClientMask
,
5868 _desiredCapability
, _currentCapability
, _pendingCapability
);
5871 if ((AOT_STATE
== powerState
) && (SLEEP_STATE
!= currentPowerState
)) {
5872 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState
));
5874 if (_aotNow
&& (ON_STATE
== powerState
)) {
5875 aotShouldExit(false, true);
5881 IOPMrootDomain::handleOurPowerChangeDone(
5882 IOService
* service
,
5883 IOPMActions
* actions
,
5884 IOPMPowerStateIndex powerState
,
5885 IOPMPowerChangeFlags changeFlags
,
5886 IOPMRequestTag requestTag __unused
)
5888 if (kSystemTransitionNewCapClient
== _systemTransitionType
) {
5889 _systemTransitionType
= kSystemTransitionNone
;
5893 if (_systemTransitionType
!= kSystemTransitionNone
) {
5894 uint32_t currentPowerState
= (uint32_t) getPowerState();
5896 if (changeFlags
& kIOPMNotDone
) {
5897 // Power down was cancelled or vetoed.
5898 _pendingCapability
= _currentCapability
;
5899 lastSleepReason
= 0;
5901 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
) &&
5902 CAP_CURRENT(kIOPMSystemCapabilityCPU
)) {
5903 #if !CONFIG_EMBEDDED
5904 pmPowerStateQueue
->submitPowerEvent(
5905 kPowerEventPolicyStimulus
,
5906 (void *) kStimulusDarkWakeReentry
,
5907 _systemStateGeneration
);
5909 // On embedded, there are no factors that can prolong a
5910 // "darkWake" when a power down is vetoed. We need to
5911 // promote to "fullWake" at least once so that factors
5912 // that prevent idle sleep can assert themselves if required
5913 pmPowerStateQueue
->submitPowerEvent(
5914 kPowerEventPolicyStimulus
,
5915 (void *) kStimulusDarkWakeActivityTickle
);
5919 // Revert device desire to max.
5920 changePowerStateToPriv(getRUN_STATE());
5922 // Send message on dark wake to full wake promotion.
5923 // tellChangeUp() handles the normal SLEEP->ON case.
5925 if (kSystemTransitionCapability
== _systemTransitionType
) {
5926 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
5927 lastSleepReason
= 0; // stop logging wrangler tickles
5928 tellClients(kIOMessageSystemHasPoweredOn
);
5930 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) {
5931 // Going dark, reset full wake state
5932 // userIsActive will be cleared by wrangler powering down
5933 fullWakeReason
= kFullWakeReasonNone
;
5935 if (ts_sleepStart
) {
5936 clock_get_uptime(&wake2DarkwakeDelay
);
5937 SUB_ABSOLUTETIME(&wake2DarkwakeDelay
, &ts_sleepStart
);
5938 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay
);
5944 // Reset state after exiting from dark wake.
5946 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
) ||
5947 CAP_LOSS(kIOPMSystemCapabilityCPU
)) {
5948 darkWakeMaintenance
= false;
5949 darkWakeToSleepASAP
= false;
5950 pciCantSleepValid
= false;
5951 darkWakeSleepService
= false;
5953 if (CAP_LOSS(kIOPMSystemCapabilityCPU
)) {
5954 // Remove the influence of display power assertion
5955 // before next system wake.
5957 wrangler
->changePowerStateForRootDomain(
5958 kWranglerPowerStateMin
);
5960 removeProperty(gIOPMUserTriggeredFullWakeKey
);
5964 // Entered dark mode.
5966 if (((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0) &&
5967 (_pendingCapability
& kIOPMSystemCapabilityCPU
)) {
5968 // Queue an evaluation of whether to remain in dark wake,
5969 // and for how long. This serves the purpose of draining
5970 // any assertions from the queue.
5972 pmPowerStateQueue
->submitPowerEvent(
5973 kPowerEventPolicyStimulus
,
5974 (void *) kStimulusDarkWakeEntry
,
5975 _systemStateGeneration
);
5979 DLOG("=== FINISH (%s->%s, 0x%x) type %u, gen %u, msg %x, "
5980 "dcp %x:%x:%x, dbgtimer %u\n",
5981 getPowerStateString(currentPowerState
), getPowerStateString((uint32_t) powerState
), changeFlags
,
5982 _systemTransitionType
, _systemStateGeneration
,
5983 _systemMessageClientMask
,
5984 _desiredCapability
, _currentCapability
, _pendingCapability
,
5985 _lastDebugWakeSeconds
);
5987 if (_pendingCapability
& kIOPMSystemCapabilityGraphics
) {
5989 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
5990 if (clamshellExists
&& fullWakeThreadCall
&&
5991 CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
5992 // Not the initial graphics full power, graphics won't
5993 // send a power notification to trigger a lid state
5996 AbsoluteTime deadline
;
5997 clock_interval_to_deadline(45, kSecondScale
, &deadline
);
5998 thread_call_enter_delayed(fullWakeThreadCall
, deadline
);
6001 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU
)) {
6005 // Update current system capability.
6006 if (_currentCapability
!= _pendingCapability
) {
6007 _currentCapability
= _pendingCapability
;
6010 // Update highest system capability.
6012 _highestCapability
|= _currentCapability
;
6014 if (darkWakePostTickle
&&
6015 (kSystemTransitionWake
== _systemTransitionType
) &&
6016 (gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) ==
6017 kDarkWakeFlagHIDTickleLate
) {
6018 darkWakePostTickle
= false;
6020 } else if (wranglerTickled
) {
6021 requestFullWake( kFullWakeReasonLocalUser
);
6024 // Reset tracepoint at completion of capability change,
6025 // completion of wake transition, and aborted sleep transition.
6027 if ((_systemTransitionType
== kSystemTransitionCapability
) ||
6028 (_systemTransitionType
== kSystemTransitionWake
) ||
6029 ((_systemTransitionType
== kSystemTransitionSleep
) &&
6030 (changeFlags
& kIOPMNotDone
))) {
6031 setProperty(kIOPMSystemCapabilitiesKey
, _currentCapability
, 64);
6032 tracePoint( kIOPMTracePointSystemUp
);
6035 _systemTransitionType
= kSystemTransitionNone
;
6036 _systemMessageClientMask
= 0;
6037 toldPowerdCapWillChange
= false;
6039 logGraphicsClamp
= false;
6041 if (lowBatteryCondition
) {
6042 privateSleepSystem(kIOPMSleepReasonLowPower
);
6043 } else if ((fullWakeReason
== kFullWakeReasonDisplayOn
) && (!displayPowerOnRequested
)) {
6044 // Request for full wake is removed while system is waking up to full wake
6045 DLOG("DisplayOn fullwake request is removed\n");
6046 handleDisplayPowerOn();
6049 if (isRTCAlarmWake
) {
6050 pmPowerStateQueue
->submitPowerEvent(
6051 kPowerEventReceivedPowerNotification
, (void *)(uintptr_t) kLocalEvalClamshellCommand
);
6056 //******************************************************************************
6057 // PM actions for graphics and audio.
6058 //******************************************************************************
6061 IOPMrootDomain::overridePowerChangeForUIService(
6062 IOService
* service
,
6063 IOPMActions
* actions
,
6064 IOPMPowerStateIndex
* inOutPowerState
,
6065 IOPMPowerChangeFlags
* inOutChangeFlags
)
6067 uint32_t powerState
= (uint32_t) *inOutPowerState
;
6068 uint32_t changeFlags
= (uint32_t) *inOutChangeFlags
;
6070 if (kSystemTransitionNone
== _systemTransitionType
) {
6071 // Not in midst of a system transition.
6072 // Do not modify power limit enable state.
6073 } else if ((actions
->parameter
& kPMActionsFlagLimitPower
) == 0) {
6074 // Activate power limiter.
6076 if ((actions
->parameter
& kPMActionsFlagIsDisplayWrangler
) &&
6077 ((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0) &&
6078 (changeFlags
& kIOPMSynchronize
)) {
6079 actions
->parameter
|= kPMActionsFlagLimitPower
;
6080 } else if ((actions
->parameter
& kPMActionsFlagIsAudioDevice
) &&
6081 ((gDarkWakeFlags
& kDarkWakeFlagAudioNotSuppressed
) == 0) &&
6082 ((_pendingCapability
& kIOPMSystemCapabilityAudio
) == 0) &&
6083 (changeFlags
& kIOPMSynchronize
)) {
6084 actions
->parameter
|= kPMActionsFlagLimitPower
;
6085 } else if ((actions
->parameter
& kPMActionsFlagIsGraphicsDevice
) &&
6086 (_systemTransitionType
== kSystemTransitionSleep
)) {
6087 // For graphics devices, arm the limiter when entering
6088 // system sleep. Not when dropping to dark wake.
6089 actions
->parameter
|= kPMActionsFlagLimitPower
;
6092 if (actions
->parameter
& kPMActionsFlagLimitPower
) {
6093 DLOG("+ plimit %s %p\n",
6094 service
->getName(), OBFUSCATE(service
));
6097 // Remove power limit.
6099 if ((actions
->parameter
& (
6100 kPMActionsFlagIsDisplayWrangler
|
6101 kPMActionsFlagIsGraphicsDevice
)) &&
6102 (_pendingCapability
& kIOPMSystemCapabilityGraphics
)) {
6103 actions
->parameter
&= ~kPMActionsFlagLimitPower
;
6104 } else if ((actions
->parameter
& kPMActionsFlagIsAudioDevice
) &&
6105 (_pendingCapability
& kIOPMSystemCapabilityAudio
)) {
6106 actions
->parameter
&= ~kPMActionsFlagLimitPower
;
6109 if ((actions
->parameter
& kPMActionsFlagLimitPower
) == 0) {
6110 DLOG("- plimit %s %p\n",
6111 service
->getName(), OBFUSCATE(service
));
6115 if (actions
->parameter
& kPMActionsFlagLimitPower
) {
6116 uint32_t maxPowerState
= (uint32_t)(-1);
6118 if (changeFlags
& (kIOPMDomainDidChange
| kIOPMDomainWillChange
)) {
6119 // Enforce limit for system power/cap transitions.
6122 if ((service
->getPowerState() > maxPowerState
) &&
6123 (actions
->parameter
& kPMActionsFlagIsDisplayWrangler
)) {
6126 // Remove lingering effects of any tickle before entering
6127 // dark wake. It will take a new tickle to return to full
6128 // wake, so the existing tickle state is useless.
6130 if (changeFlags
& kIOPMDomainDidChange
) {
6131 *inOutChangeFlags
|= kIOPMExpireIdleTimer
;
6133 } else if (actions
->parameter
& kPMActionsFlagIsGraphicsDevice
) {
6137 // Deny all self-initiated changes when power is limited.
6138 // Wrangler tickle should never defeat the limiter.
6140 maxPowerState
= service
->getPowerState();
6143 if (powerState
> maxPowerState
) {
6144 DLOG("> plimit %s %p (%u->%u, 0x%x)\n",
6145 service
->getName(), OBFUSCATE(service
), powerState
, maxPowerState
,
6147 *inOutPowerState
= maxPowerState
;
6149 if (darkWakePostTickle
&&
6150 (actions
->parameter
& kPMActionsFlagIsDisplayWrangler
) &&
6151 (changeFlags
& kIOPMDomainWillChange
) &&
6152 ((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) ==
6153 kDarkWakeFlagHIDTickleEarly
)) {
6154 darkWakePostTickle
= false;
6159 if (!graphicsSuppressed
&& (changeFlags
& kIOPMDomainDidChange
)) {
6160 if (logGraphicsClamp
) {
6164 clock_get_uptime(&now
);
6165 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
6166 absolutetime_to_nanoseconds(now
, &nsec
);
6167 if (kIOLogPMRootDomain
& gIOKitDebug
) {
6168 MSG("Graphics suppressed %u ms\n",
6169 ((int)((nsec
) / NSEC_PER_MSEC
)));
6172 graphicsSuppressed
= true;
6178 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
6179 IOService
* service
,
6180 IOPMActions
* actions
)
6183 // Warning: Not running in PM work loop context - don't modify state !!!
6184 // Trap tickle directed to IODisplayWrangler while running with graphics
6185 // capability suppressed.
6187 assert(service
== wrangler
);
6189 clock_get_uptime(&userActivityTime
);
6190 bool aborting
= ((lastSleepReason
== kIOPMSleepReasonIdle
)
6191 || (lastSleepReason
== kIOPMSleepReasonMaintenance
)
6192 || (lastSleepReason
== kIOPMSleepReasonSoftware
));
6194 userActivityCount
++;
6195 DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
6196 userActivityCount
, lastSleepReason
);
6199 if (!wranglerTickled
&&
6200 ((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0)) {
6201 DLOG("display wrangler tickled\n");
6202 if (kIOLogPMRootDomain
& gIOKitDebug
) {
6203 OSReportWithBacktrace("Dark wake display tickle");
6205 if (pmPowerStateQueue
) {
6206 pmPowerStateQueue
->submitPowerEvent(
6207 kPowerEventPolicyStimulus
,
6208 (void *) kStimulusDarkWakeActivityTickle
,
6209 true /* set wake type */ );
6216 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
6217 IOService
* service
,
6218 IOPMActions
* actions
,
6219 const OSSymbol
* powerClient
,
6220 IOPMPowerStateIndex oldPowerState
,
6221 IOPMPowerStateIndex newPowerState
)
6224 assert(service
== wrangler
);
6226 // This function implements half of the user active detection
6227 // by monitoring changes to the display wrangler's device desire.
6229 // User becomes active when either:
6230 // 1. Wrangler's DeviceDesire increases to max, but wrangler is already
6231 // in max power state. This desire change in absence of a power state
6232 // change is detected within. This handles the case when user becomes
6233 // active while the display is already lit by setDisplayPowerOn().
6235 // 2. Power state change to max, and DeviceDesire is also at max.
6236 // Handled by displayWranglerNotification().
6238 // User becomes inactive when DeviceDesire drops to sleep state or below.
6240 DLOG("wrangler %s (ps %u, %u->%u)\n",
6241 powerClient
->getCStringNoCopy(),
6242 (uint32_t) service
->getPowerState(),
6243 (uint32_t) oldPowerState
, (uint32_t) newPowerState
);
6245 if (powerClient
== gIOPMPowerClientDevice
) {
6246 if ((newPowerState
> oldPowerState
) &&
6247 (newPowerState
== kWranglerPowerStateMax
) &&
6248 (service
->getPowerState() == kWranglerPowerStateMax
)) {
6249 evaluatePolicy( kStimulusEnterUserActiveState
);
6250 } else if ((newPowerState
< oldPowerState
) &&
6251 (newPowerState
<= kWranglerPowerStateSleep
)) {
6252 evaluatePolicy( kStimulusLeaveUserActiveState
);
6256 if (newPowerState
<= kWranglerPowerStateSleep
) {
6257 evaluatePolicy( kStimulusDisplayWranglerSleep
);
6258 } else if (newPowerState
== kWranglerPowerStateMax
) {
6259 evaluatePolicy( kStimulusDisplayWranglerWake
);
6264 //******************************************************************************
6265 // User active state management
6266 //******************************************************************************
6269 IOPMrootDomain::preventTransitionToUserActive( bool prevent
)
6272 _preventUserActive
= prevent
;
6273 if (wrangler
&& !_preventUserActive
) {
6274 // Allowing transition to user active, but the wrangler may have
6275 // already powered ON in case of sleep cancel/revert. Poll the
6276 // same conditions checked for in displayWranglerNotification()
6277 // to bring the user active state up to date.
6279 if ((wrangler
->getPowerState() == kWranglerPowerStateMax
) &&
6280 (wrangler
->getPowerStateForClient(gIOPMPowerClientDevice
) ==
6281 kWranglerPowerStateMax
)) {
6282 evaluatePolicy( kStimulusEnterUserActiveState
);
6288 //******************************************************************************
6289 // Approve usage of delayed child notification by PM.
6290 //******************************************************************************
6293 IOPMrootDomain::shouldDelayChildNotification(
6294 IOService
* service
)
6296 if (((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) != 0) &&
6297 (kFullWakeReasonNone
== fullWakeReason
) &&
6298 (kSystemTransitionWake
== _systemTransitionType
)) {
6299 DLOG("%s: delay child notify\n", service
->getName());
6305 //******************************************************************************
6306 // PM actions for PCI device.
6307 //******************************************************************************
6310 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
6311 IOService
* service
,
6312 IOPMActions
* actions
,
6313 IOPMPowerStateIndex powerState
,
6314 IOPMPowerChangeFlags
* inOutChangeFlags
)
6316 pmTracer
->tracePCIPowerChange(
6317 PMTraceWorker::kPowerChangeStart
,
6318 service
, *inOutChangeFlags
,
6319 (actions
->parameter
& kPMActionsPCIBitNumberMask
));
6323 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
6324 IOService
* service
,
6325 IOPMActions
* actions
,
6326 IOPMPowerStateIndex powerState
,
6327 IOPMPowerChangeFlags changeFlags
)
6329 pmTracer
->tracePCIPowerChange(
6330 PMTraceWorker::kPowerChangeCompleted
,
6331 service
, changeFlags
,
6332 (actions
->parameter
& kPMActionsPCIBitNumberMask
));
6335 //******************************************************************************
6338 // Override IOService::registerInterest() to intercept special clients.
6339 //******************************************************************************
6341 class IOPMServiceInterestNotifier
: public _IOServiceInterestNotifier
6343 friend class IOPMrootDomain
;
6344 OSDeclareDefaultStructors(IOPMServiceInterestNotifier
);
6347 uint32_t ackTimeoutCnt
;
6348 uint32_t msgType
;// Message pending ack
6352 const OSSymbol
*identifier
;
6355 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier
, _IOServiceInterestNotifier
)
6357 IONotifier
* IOPMrootDomain::registerInterest(
6358 const OSSymbol
* typeOfInterest
,
6359 IOServiceInterestHandler handler
,
6360 void * target
, void * ref
)
6362 IOPMServiceInterestNotifier
*notifier
= NULL
;
6363 bool isSystemCapabilityClient
;
6364 bool isKernelCapabilityClient
;
6365 IOReturn rc
= kIOReturnError
;;
6367 isSystemCapabilityClient
=
6369 typeOfInterest
->isEqualTo(kIOPMSystemCapabilityInterest
);
6371 isKernelCapabilityClient
=
6373 typeOfInterest
->isEqualTo(gIOPriorityPowerStateInterest
);
6375 if (isSystemCapabilityClient
) {
6376 typeOfInterest
= gIOAppPowerStateInterest
;
6379 notifier
= new IOPMServiceInterestNotifier
;
6384 if (notifier
->init()) {
6385 rc
= super::registerInterestForNotifier(notifier
, typeOfInterest
, handler
, target
, ref
);
6387 if (rc
!= kIOReturnSuccess
) {
6388 notifier
->release();
6393 if (pmPowerStateQueue
) {
6394 notifier
->ackTimeoutCnt
= 0;
6395 if (isSystemCapabilityClient
) {
6397 if (pmPowerStateQueue
->submitPowerEvent(
6398 kPowerEventRegisterSystemCapabilityClient
, notifier
) == false) {
6399 notifier
->release();
6403 if (isKernelCapabilityClient
) {
6405 if (pmPowerStateQueue
->submitPowerEvent(
6406 kPowerEventRegisterKernelCapabilityClient
, notifier
) == false) {
6407 notifier
->release();
6412 OSData
*data
= NULL
;
6413 uint8_t *uuid
= NULL
;
6414 OSKext
*kext
= OSKext::lookupKextWithAddress((vm_address_t
)handler
);
6416 data
= kext
->copyUUID();
6418 if (data
&& (data
->getLength() == sizeof(uuid_t
))) {
6419 uuid
= (uint8_t *)(data
->getBytesNoCopy());
6421 notifier
->uuid0
= ((uint64_t)(uuid
[0]) << 56) | ((uint64_t)(uuid
[1]) << 48) | ((uint64_t)(uuid
[2]) << 40) |
6422 ((uint64_t)(uuid
[3]) << 32) | ((uint64_t)(uuid
[4]) << 24) | ((uint64_t)(uuid
[5]) << 16) |
6423 ((uint64_t)(uuid
[6]) << 8) | (uuid
[7]);
6424 notifier
->uuid1
= ((uint64_t)(uuid
[8]) << 56) | ((uint64_t)(uuid
[9]) << 48) | ((uint64_t)(uuid
[10]) << 40) |
6425 ((uint64_t)(uuid
[11]) << 32) | ((uint64_t)(uuid
[12]) << 24) | ((uint64_t)(uuid
[13]) << 16) |
6426 ((uint64_t)(uuid
[14]) << 8) | (uuid
[15]);
6428 notifier
->identifier
= kext
->getIdentifier();
6440 //******************************************************************************
6441 // systemMessageFilter
6443 //******************************************************************************
6446 IOPMrootDomain::systemMessageFilter(
6447 void * object
, void * arg1
, void * arg2
, void * arg3
)
6449 const IOPMInterestContext
* context
= (const IOPMInterestContext
*) arg1
;
6450 bool isCapMsg
= (context
->messageType
== kIOMessageSystemCapabilityChange
);
6451 bool isCapClient
= false;
6453 IOPMServiceInterestNotifier
*notifier
;
6455 notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, (OSObject
*)object
);
6458 if ((kSystemTransitionNewCapClient
== _systemTransitionType
) &&
6459 (!isCapMsg
|| !_joinedCapabilityClients
||
6460 !_joinedCapabilityClients
->containsObject((OSObject
*) object
))) {
6464 // Capability change message for app and kernel clients.
6467 if ((context
->notifyType
== kNotifyPriority
) ||
6468 (context
->notifyType
== kNotifyCapabilityChangePriority
)) {
6472 if ((context
->notifyType
== kNotifyCapabilityChangeApps
) &&
6473 (object
== (void *) systemCapabilityNotifier
)) {
6479 IOPMSystemCapabilityChangeParameters
* capArgs
=
6480 (IOPMSystemCapabilityChangeParameters
*) arg2
;
6482 if (kSystemTransitionNewCapClient
== _systemTransitionType
) {
6483 capArgs
->fromCapabilities
= 0;
6484 capArgs
->toCapabilities
= _currentCapability
;
6485 capArgs
->changeFlags
= 0;
6487 capArgs
->fromCapabilities
= _currentCapability
;
6488 capArgs
->toCapabilities
= _pendingCapability
;
6490 if (context
->isPreChange
) {
6491 capArgs
->changeFlags
= kIOPMSystemCapabilityWillChange
;
6493 capArgs
->changeFlags
= kIOPMSystemCapabilityDidChange
;
6496 if ((object
== (void *) systemCapabilityNotifier
) &&
6497 context
->isPreChange
) {
6498 toldPowerdCapWillChange
= true;
6502 // Capability change messages only go to the PM configd plugin.
6503 // Wait for response post-change if capabilitiy is increasing.
6504 // Wait for response pre-change if capability is decreasing.
6506 if ((context
->notifyType
== kNotifyCapabilityChangeApps
) && arg3
&&
6507 ((capabilityLoss
&& context
->isPreChange
) ||
6508 (!capabilityLoss
&& !context
->isPreChange
))) {
6509 // app has not replied yet, wait for it
6510 *((OSObject
**) arg3
) = kOSBooleanFalse
;
6517 // Capability client will always see kIOMessageCanSystemSleep,
6518 // even for demand sleep. It will also have a chance to veto
6519 // sleep one last time after all clients have responded to
6520 // kIOMessageSystemWillSleep
6522 if ((kIOMessageCanSystemSleep
== context
->messageType
) ||
6523 (kIOMessageSystemWillNotSleep
== context
->messageType
)) {
6524 if (object
== (OSObject
*) systemCapabilityNotifier
) {
6529 // Not idle sleep, don't ask apps.
6530 if (context
->changeFlags
& kIOPMSkipAskPowerDown
) {
6535 if (kIOPMMessageLastCallBeforeSleep
== context
->messageType
) {
6536 if ((object
== (OSObject
*) systemCapabilityNotifier
) &&
6537 CAP_HIGHEST(kIOPMSystemCapabilityGraphics
) &&
6538 (fullToDarkReason
== kIOPMSleepReasonIdle
)) {
6544 // Reject capability change messages for legacy clients.
6545 // Reject legacy system sleep messages for capability client.
6547 if (isCapMsg
|| (object
== (OSObject
*) systemCapabilityNotifier
)) {
6551 // Filter system sleep messages.
6553 if ((context
->notifyType
== kNotifyApps
) &&
6554 (_systemMessageClientMask
& kSystemMessageClientLegacyApp
)) {
6559 if (notifier
->ackTimeoutCnt
>= 3) {
6560 *((OSObject
**) arg3
) = kOSBooleanFalse
;
6562 *((OSObject
**) arg3
) = kOSBooleanTrue
;
6566 } else if ((context
->notifyType
== kNotifyPriority
) &&
6567 (_systemMessageClientMask
& kSystemMessageClientKernel
)) {
6572 if (allow
&& isCapMsg
&& _joinedCapabilityClients
) {
6573 _joinedCapabilityClients
->removeObject((OSObject
*) object
);
6574 if (_joinedCapabilityClients
->getCount() == 0) {
6575 DLOG("destroyed capability client set %p\n",
6576 OBFUSCATE(_joinedCapabilityClients
));
6577 _joinedCapabilityClients
->release();
6578 _joinedCapabilityClients
= NULL
;
6582 notifier
->msgType
= context
->messageType
;
6588 //******************************************************************************
6589 // setMaintenanceWakeCalendar
6591 //******************************************************************************
6594 IOPMrootDomain::setMaintenanceWakeCalendar(
6595 const IOPMCalendarStruct
* calendar
)
6601 return kIOReturnBadArgument
;
6604 data
= OSData::withBytes((void *) calendar
, sizeof(*calendar
));
6606 return kIOReturnNoMemory
;
6609 if (kPMCalendarTypeMaintenance
== calendar
->selector
) {
6610 ret
= setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey
, data
);
6611 if (kIOReturnSuccess
== ret
) {
6612 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake
, &_scheduledAlarms
);
6614 } else if (kPMCalendarTypeSleepService
== calendar
->selector
) {
6615 ret
= setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey
, data
);
6616 if (kIOReturnSuccess
== ret
) {
6617 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake
, &_scheduledAlarms
);
6620 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms
);
6627 // MARK: Display Wrangler
6629 //******************************************************************************
6630 // displayWranglerNotification
6632 // Handle the notification when the IODisplayWrangler changes power state.
6633 //******************************************************************************
6636 IOPMrootDomain::displayWranglerNotification(
6637 void * target
, void * refCon
,
6638 UInt32 messageType
, IOService
* service
,
6639 void * messageArgument
, vm_size_t argSize
)
6642 int displayPowerState
;
6643 IOPowerStateChangeNotification
* params
=
6644 (IOPowerStateChangeNotification
*) messageArgument
;
6646 if ((messageType
!= kIOMessageDeviceWillPowerOff
) &&
6647 (messageType
!= kIOMessageDeviceHasPoweredOn
)) {
6648 return kIOReturnUnsupported
;
6653 return kIOReturnUnsupported
;
6656 displayPowerState
= params
->stateNumber
;
6657 DLOG("wrangler %s ps %d\n",
6658 getIOMessageString(messageType
), displayPowerState
);
6660 switch (messageType
) {
6661 case kIOMessageDeviceWillPowerOff
:
6662 // Display wrangler has dropped power due to display idle
6663 // or force system sleep.
6665 // 4 Display ON kWranglerPowerStateMax
6666 // 3 Display Dim kWranglerPowerStateDim
6667 // 2 Display Sleep kWranglerPowerStateSleep
6668 // 1 Not visible to user
6669 // 0 Not visible to user kWranglerPowerStateMin
6671 if (displayPowerState
<= kWranglerPowerStateSleep
) {
6672 gRootDomain
->evaluatePolicy( kStimulusDisplayWranglerSleep
);
6676 case kIOMessageDeviceHasPoweredOn
:
6677 // Display wrangler has powered on due to user activity
6678 // or wake from sleep.
6680 if (kWranglerPowerStateMax
== displayPowerState
) {
6681 gRootDomain
->evaluatePolicy( kStimulusDisplayWranglerWake
);
6683 // See comment in handleUpdatePowerClientForDisplayWrangler
6684 if (service
->getPowerStateForClient(gIOPMPowerClientDevice
) ==
6685 kWranglerPowerStateMax
) {
6686 gRootDomain
->evaluatePolicy( kStimulusEnterUserActiveState
);
6692 return kIOReturnUnsupported
;
6695 //******************************************************************************
6696 // displayWranglerMatchPublished
6698 // Receives a notification when the IODisplayWrangler is published.
6699 // When it's published we install a power state change handler.
6700 //******************************************************************************
6703 IOPMrootDomain::displayWranglerMatchPublished(
6706 IOService
* newService
,
6707 IONotifier
* notifier __unused
)
6710 // install a handler
6711 if (!newService
->registerInterest( gIOGeneralInterest
,
6712 &displayWranglerNotification
, target
, NULL
)) {
6719 //******************************************************************************
6722 //******************************************************************************
6725 IOPMrootDomain::reportUserInput( void )
6729 OSDictionary
* matching
;
6732 matching
= serviceMatching("IODisplayWrangler");
6733 iter
= getMatchingServices(matching
);
6735 matching
->release();
6738 wrangler
= OSDynamicCast(IOService
, iter
->getNextObject());
6744 wrangler
->activityTickle(0, 0);
6749 //******************************************************************************
6750 // latchDisplayWranglerTickle
6751 //******************************************************************************
6754 IOPMrootDomain::latchDisplayWranglerTickle( bool latch
)
6758 if (!(_currentCapability
& kIOPMSystemCapabilityGraphics
) &&
6759 !(_pendingCapability
& kIOPMSystemCapabilityGraphics
) &&
6760 !checkSystemCanSustainFullWake()) {
6761 // Currently in dark wake, and not transitioning to full wake.
6762 // Full wake is unsustainable, so latch the tickle to prevent
6763 // the display from lighting up momentarily.
6764 wranglerTickleLatched
= true;
6766 wranglerTickleLatched
= false;
6768 } else if (wranglerTickleLatched
&& checkSystemCanSustainFullWake()) {
6769 wranglerTickleLatched
= false;
6771 pmPowerStateQueue
->submitPowerEvent(
6772 kPowerEventPolicyStimulus
,
6773 (void *) kStimulusDarkWakeActivityTickle
);
6776 return wranglerTickleLatched
;
6782 //******************************************************************************
6783 // setDisplayPowerOn
6785 // For root domain user client
6786 //******************************************************************************
6789 IOPMrootDomain::setDisplayPowerOn( uint32_t options
)
6791 pmPowerStateQueue
->submitPowerEvent( kPowerEventSetDisplayPowerOn
,
6792 (void *) NULL
, options
);
6798 //******************************************************************************
6801 // Notification on battery class IOPowerSource appearance
6802 //******************************************************************************
6805 IOPMrootDomain::batteryPublished(
6808 IOService
* resourceService
,
6809 IONotifier
* notifier __unused
)
6811 // rdar://2936060&4435589
6812 // All laptops have dimmable LCD displays
6813 // All laptops have batteries
6814 // So if this machine has a battery, publish the fact that the backlight
6815 // supports dimming.
6816 ((IOPMrootDomain
*)root_domain
)->publishFeature("DisplayDims");
6822 // MARK: System PM Policy
6824 //******************************************************************************
6825 // checkSystemSleepAllowed
6827 //******************************************************************************
6830 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options
,
6831 uint32_t sleepReason
)
6835 // Conditions that prevent idle and demand system sleep.
6838 if (userDisabledAllSleep
) {
6839 err
= kPMUserDisabledAllSleep
; // 1. user-space sleep kill switch
6843 if (systemBooting
|| systemShutdown
|| gWillShutdown
) {
6844 err
= kPMSystemRestartBootingInProgress
; // 2. restart or shutdown in progress
6852 // Conditions above pegs the system at full wake.
6853 // Conditions below prevent system sleep but does not prevent
6854 // dark wake, and must be called from gated context.
6857 err
= kPMConfigPreventSystemSleep
; // 3. config does not support sleep
6861 if (lowBatteryCondition
|| thermalWarningState
) {
6862 break; // always sleep on low battery or when in thermal warning state
6865 if (sleepReason
== kIOPMSleepReasonDarkWakeThermalEmergency
) {
6866 break; // always sleep on dark wake thermal emergencies
6869 if (preventSystemSleepList
->getCount() != 0) {
6870 err
= kPMChildPreventSystemSleep
; // 4. child prevent system sleep clamp
6874 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit
) ==
6875 kIOPMDriverAssertionLevelOn
) {
6876 err
= kPMCPUAssertion
; // 5. CPU assertion
6880 if (pciCantSleepValid
) {
6881 if (pciCantSleepFlag
) {
6882 err
= kPMPCIUnsupported
; // 6. PCI card does not support PM (cached)
6885 } else if (sleepSupportedPEFunction
&&
6886 CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
6888 OSBitAndAtomic(~kPCICantSleep
, &platformSleepSupport
);
6889 ret
= getPlatform()->callPlatformFunction(
6890 sleepSupportedPEFunction
, false,
6891 NULL
, NULL
, NULL
, NULL
);
6892 pciCantSleepValid
= true;
6893 pciCantSleepFlag
= false;
6894 if ((platformSleepSupport
& kPCICantSleep
) ||
6895 ((ret
!= kIOReturnSuccess
) && (ret
!= kIOReturnUnsupported
))) {
6896 err
= 6; // 6. PCI card does not support PM
6897 pciCantSleepFlag
= true;
6904 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err
));
6911 IOPMrootDomain::checkSystemSleepEnabled( void )
6913 return checkSystemSleepAllowed(0, 0);
6917 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason
)
6920 return checkSystemSleepAllowed(1, sleepReason
);
6923 //******************************************************************************
6924 // checkSystemCanSustainFullWake
6925 //******************************************************************************
6928 IOPMrootDomain::checkSystemCanSustainFullWake( void )
6931 if (lowBatteryCondition
|| thermalWarningState
) {
6932 // Low battery wake, or received a low battery notification
6933 // while system is awake. This condition will persist until
6934 // the following wake.
6938 if (clamshellExists
&& clamshellClosed
&& !clamshellSleepDisabled
) {
6939 // Graphics state is unknown and external display might not be probed.
6940 // Do not incorporate state that requires graphics to be in max power
6941 // such as desktopMode or clamshellDisabled.
6943 if (!acAdaptorConnected
) {
6944 DLOG("full wake check: no AC\n");
6952 //******************************************************************************
6954 //******************************************************************************
6959 IOPMrootDomain::mustHibernate( void )
6961 return lowBatteryCondition
|| thermalWarningState
;
6964 #endif /* HIBERNATION */
6966 //******************************************************************************
6968 //******************************************************************************
6970 // Tables for accumulated days in year by month, latter used for leap years
6972 static const int daysbymonth
[] =
6973 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
6975 static const int lydaysbymonth
[] =
6976 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
6979 IOPMConvertSecondsToCalendar(long secs
, IOPMCalendarStruct
* dt
)
6981 const int * dbm
= daysbymonth
;
6988 // Calculate seconds, minutes and hours
6990 n
= secs
% (24 * 3600);
6991 dt
->second
= n
% 60;
6993 dt
->minute
= n
% 60;
6996 // Calculate day of week
6998 n
= secs
/ (24 * 3600);
6999 // dt->dayWeek = (n + 4) % 7;
7002 // Rebase from days since Unix epoch (1/1/1970) store in 'n',
7003 // to days since 1/1/1968 to start on 4 year cycle, beginning
7008 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7009 // Valid before 2100, since 2100 is not a leap year.
7011 x
= n
/ 1461; // number of 4 year cycles
7012 y
= n
% 1461; // days into current 4 year cycle
7015 // Add in years in the current 4 year cycle
7018 y
-= 366; // days after the leap year
7019 n
= y
% 365; // days into the current year
7020 z
+= (1 + y
/ 365); // years after the past 4-yr cycle
7023 dbm
= lydaysbymonth
;
7031 // Adjust remaining days value to start at 1
7037 for (x
= 1; n
> dbm
[x
]; x
++) {
7042 // Calculate day of month
7044 dt
->day
= n
- dbm
[x
- 1];
7050 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct
* dt
)
7052 const int * dbm
= daysbymonth
;
7055 if (dt
->year
< 1970) {
7059 // Seconds elapsed in the current day
7061 secs
= dt
->second
+ 60 * dt
->minute
+ 3600 * dt
->hour
;
7063 // Number of days from 1/1/70 to beginning of current year
7064 // Account for extra day every 4 years starting at 1973
7066 y
= dt
->year
- 1970;
7067 days
= (y
* 365) + ((y
+ 1) / 4);
7069 // Change table if current year is a leap year
7071 if ((dt
->year
% 4) == 0) {
7072 dbm
= lydaysbymonth
;
7075 // Add in days elapsed in the current year
7077 days
+= (dt
->day
- 1) + dbm
[dt
->month
- 1];
7079 // Add accumulated days to accumulated seconds
7081 secs
+= 24 * 3600 * days
;
7087 IOPMrootDomain::getRUN_STATE(void)
7089 return _aotNow
? AOT_STATE
: ON_STATE
;
7093 IOPMrootDomain::isAOTMode()
7099 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime
)
7101 clock_sec_t nowsecs
, wakesecs
;
7102 clock_usec_t nowmicrosecs
, wakemicrosecs
;
7103 uint64_t nowAbs
, wakeAbs
;
7105 clock_gettimeofday_and_absolute_time(&nowsecs
, &nowmicrosecs
, &nowAbs
);
7106 wakeAbs
= continuoustime_to_absolutetime(wakeContinuousTime
);
7107 if (wakeAbs
< nowAbs
) {
7108 printf(LOG_PREFIX
"wakeAbs %qd < nowAbs %qd\n", wakeAbs
, nowAbs
);
7112 absolutetime_to_microtime(wakeAbs
, &wakesecs
, &wakemicrosecs
);
7114 wakesecs
+= nowsecs
;
7115 wakemicrosecs
+= nowmicrosecs
;
7116 if (wakemicrosecs
>= USEC_PER_SEC
) {
7118 wakemicrosecs
-= USEC_PER_SEC
;
7120 if (wakemicrosecs
>= (USEC_PER_SEC
/ 10)) {
7124 IOPMConvertSecondsToCalendar(wakesecs
, &_aotWakeTimeCalendar
);
7126 if (_aotWakeTimeContinuous
!= wakeContinuousTime
) {
7127 _aotWakeTimeContinuous
= wakeContinuousTime
;
7128 IOLog(LOG_PREFIX
"setWakeTime: " YMDTF
"\n", YMDT(&_aotWakeTimeCalendar
));
7130 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeMaintenance
;
7131 _aotWakeTimeUTC
= wakesecs
;
7133 return kIOReturnSuccess
;
7136 // assumes WAKEEVENT_LOCK
7138 IOPMrootDomain::aotShouldExit(bool checkTimeSet
, bool software
)
7141 const char * reason
= "";
7145 _aotMetrics
->softwareRequestCount
++;
7146 reason
= "software request";
7147 } else if (kIOPMWakeEventAOTExitFlags
& _aotPendingFlags
) {
7149 reason
= gWakeReasonString
;
7150 } else if (checkTimeSet
&& (kPMCalendarTypeInvalid
== _aotWakeTimeCalendar
.selector
)) {
7152 _aotMetrics
->noTimeSetCount
++;
7153 reason
= "flipbook expired";
7154 } else if ((kIOPMAOTModeRespectTimers
& _aotMode
) && _scheduledAlarmUTC
) {
7157 clock_get_calendar_microtime(&sec
, &usec
);
7158 if (_scheduledAlarmUTC
<= sec
) {
7160 _aotMetrics
->rtcAlarmsCount
++;
7161 reason
= "user alarm";
7164 exitNow
= (_aotNow
&& _aotExit
);
7167 IOLog(LOG_PREFIX
"AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7169 _aotMetrics
->sleepCount
,
7170 _aotMetrics
->possibleCount
,
7171 _aotMetrics
->confirmedPossibleCount
,
7172 _aotMetrics
->rejectedPossibleCount
,
7173 _aotMetrics
->expiredPossibleCount
,
7174 _aotMetrics
->noTimeSetCount
,
7175 _aotMetrics
->rtcAlarmsCount
);
7181 IOPMrootDomain::aotExit(bool cps
)
7183 _aotTasksSuspended
= false;
7184 _aotReadyToFullWake
= false;
7185 if (_aotTimerScheduled
) {
7186 _aotTimerES
->cancelTimeout();
7187 _aotTimerScheduled
= false;
7189 updateTasksSuspend();
7191 _aotMetrics
->totalTime
+= mach_absolute_time() - _aotLastWakeTime
;
7192 _aotLastWakeTime
= 0;
7193 if (_aotMetrics
->sleepCount
&& (_aotMetrics
->sleepCount
<= kIOPMAOTMetricsKernelWakeCountMax
)) {
7194 strlcpy(&_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
- 1][0],
7196 sizeof(_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
]));
7199 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeInvalid
;
7201 _systemMessageClientMask
= kSystemMessageClientLegacyApp
;
7202 tellClients(kIOMessageSystemWillPowerOn
);
7205 changePowerStateToPriv(getRUN_STATE());
7210 IOPMrootDomain::aotEvaluate(IOTimerEventSource
* timer
)
7214 IOLog("aotEvaluate(%d) 0x%x\n", (timer
!= NULL
), _aotPendingFlags
);
7217 exitNow
= aotShouldExit(false, false);
7218 if (timer
!= NULL
) {
7219 _aotTimerScheduled
= false;
7226 if (_aotLingerTime
) {
7228 IOLog("aot linger before sleep\n");
7229 clock_absolutetime_interval_to_deadline(_aotLingerTime
, &deadline
);
7230 clock_delay_until(deadline
);
7233 privateSleepSystem(kIOPMSleepReasonSoftware
);
7237 //******************************************************************************
7240 // Conditions that affect our wake/sleep decision has changed.
7241 // If conditions dictate that the system must remain awake, clamp power
7242 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7243 // is TRUE, then remove the power clamp and allow the power state to drop
7245 //******************************************************************************
7248 IOPMrootDomain::adjustPowerState( bool sleepASAP
)
7250 DEBUG_LOG("adjustPowerState ps %s, asap %d, idleSleepEnabled %d\n",
7251 getPowerStateString((uint32_t) getPowerState()), sleepASAP
, idleSleepEnabled
);
7258 if (AOT_STATE
!= getPowerState()) {
7262 exitNow
= aotShouldExit(true, false);
7264 && !_aotTimerScheduled
7265 && (kIOPMWakeEventAOTPossibleExit
== (kIOPMWakeEventAOTPossibleFlags
& _aotPendingFlags
))) {
7266 _aotTimerScheduled
= true;
7267 if (_aotLingerTime
) {
7268 _aotTimerES
->setTimeout(_aotLingerTime
);
7270 _aotTimerES
->setTimeout(800, kMillisecondScale
);
7277 _aotReadyToFullWake
= true;
7278 if (!_aotTimerScheduled
) {
7279 privateSleepSystem(kIOPMSleepReasonSoftware
);
7285 if ((!idleSleepEnabled
) || !checkSystemSleepEnabled()) {
7286 changePowerStateToPriv(getRUN_STATE());
7287 } else if (sleepASAP
) {
7288 changePowerStateToPriv(SLEEP_STATE
);
7293 IOPMrootDomain::handleDisplayPowerOn()
7298 if (displayPowerOnRequested
) {
7299 if (!checkSystemCanSustainFullWake()) {
7303 // Force wrangler to max power state. If system is in dark wake
7304 // this alone won't raise the wrangler's power state.
7306 wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMax
);
7308 // System in dark wake, always requesting full wake should
7309 // not have any bad side-effects, even if the request fails.
7311 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
7312 setProperty(kIOPMRootDomainWakeTypeKey
, kIOPMRootDomainWakeTypeNotification
);
7313 requestFullWake( kFullWakeReasonDisplayOn
);
7316 // Relenquish desire to power up display.
7317 // Must first transition to state 1 since wrangler doesn't
7318 // power off the displays at state 0. At state 0 the root
7319 // domain is removed from the wrangler's power client list.
7321 wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMin
+ 1);
7322 wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMin
);
7326 //******************************************************************************
7327 // dispatchPowerEvent
7329 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
7330 //******************************************************************************
7333 IOPMrootDomain::dispatchPowerEvent(
7334 uint32_t event
, void * arg0
, uint64_t arg1
)
7339 case kPowerEventFeatureChanged
:
7340 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7341 messageClients(kIOPMMessageFeatureChange
, this);
7344 case kPowerEventReceivedPowerNotification
:
7345 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7346 handlePowerNotification((UInt32
)(uintptr_t) arg0
);
7349 case kPowerEventSystemBootCompleted
:
7350 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7351 if (systemBooting
) {
7352 systemBooting
= false;
7354 // read noidle setting from Device Tree
7355 IORegistryEntry
*defaults
= IORegistryEntry::fromPath("IODeviceTree:/defaults");
7356 if (defaults
!= NULL
) {
7357 OSData
*data
= OSDynamicCast(OSData
, defaults
->getProperty("no-idle"));
7358 if ((data
!= NULL
) && (data
->getLength() == 4)) {
7359 gNoIdleFlag
= *(uint32_t*)data
->getBytesNoCopy();
7360 DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag
);
7362 defaults
->release();
7364 if (lowBatteryCondition
) {
7365 privateSleepSystem(kIOPMSleepReasonLowPower
);
7367 // The rest is unnecessary since the system is expected
7368 // to sleep immediately. The following wake will update
7373 sleepWakeDebugMemAlloc();
7374 saveFailureData2File();
7376 // If lid is closed, re-send lid closed notification
7377 // now that booting is complete.
7378 if (clamshellClosed
) {
7379 handlePowerNotification(kLocalEvalClamshellCommand
);
7381 evaluatePolicy( kStimulusAllowSystemSleepChanged
);
7385 case kPowerEventSystemShutdown
:
7386 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7387 if (kOSBooleanTrue
== (OSBoolean
*) arg0
) {
7388 /* We set systemShutdown = true during shutdown
7389 * to prevent sleep at unexpected times while loginwindow is trying
7390 * to shutdown apps and while the OS is trying to transition to
7391 * complete power of.
7393 * Set to true during shutdown, as soon as loginwindow shows
7394 * the "shutdown countdown dialog", through individual app
7395 * termination, and through black screen kernel shutdown.
7397 systemShutdown
= true;
7400 * A shutdown was initiated, but then the shutdown
7401 * was cancelled, clearing systemShutdown to false here.
7403 systemShutdown
= false;
7407 case kPowerEventUserDisabledSleep
:
7408 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7409 userDisabledAllSleep
= (kOSBooleanTrue
== (OSBoolean
*) arg0
);
7412 case kPowerEventRegisterSystemCapabilityClient
:
7413 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7414 if (systemCapabilityNotifier
) {
7415 systemCapabilityNotifier
->release();
7416 systemCapabilityNotifier
= NULL
;
7419 systemCapabilityNotifier
= (IONotifier
*) arg0
;
7420 systemCapabilityNotifier
->retain();
7422 /* intentional fall-through */
7423 [[clang::fallthrough]];
7425 case kPowerEventRegisterKernelCapabilityClient
:
7426 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7427 if (!_joinedCapabilityClients
) {
7428 _joinedCapabilityClients
= OSSet::withCapacity(8);
7431 IONotifier
* notify
= (IONotifier
*) arg0
;
7432 if (_joinedCapabilityClients
) {
7433 _joinedCapabilityClients
->setObject(notify
);
7434 synchronizePowerTree( kIOPMSyncNoChildNotify
);
7440 case kPowerEventPolicyStimulus
:
7441 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7443 int stimulus
= (uintptr_t) arg0
;
7444 evaluatePolicy( stimulus
, (uint32_t) arg1
);
7448 case kPowerEventAssertionCreate
:
7449 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7451 pmAssertions
->handleCreateAssertion((OSData
*)arg0
);
7456 case kPowerEventAssertionRelease
:
7457 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7459 pmAssertions
->handleReleaseAssertion(arg1
);
7463 case kPowerEventAssertionSetLevel
:
7464 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7466 pmAssertions
->handleSetAssertionLevel(arg1
, (IOPMDriverAssertionLevel
)(uintptr_t)arg0
);
7470 case kPowerEventQueueSleepWakeUUID
:
7471 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7472 handleQueueSleepWakeUUID((OSObject
*)arg0
);
7474 case kPowerEventPublishSleepWakeUUID
:
7475 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7476 handlePublishSleepWakeUUID((bool)arg0
);
7479 case kPowerEventSetDisplayPowerOn
:
7480 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7485 displayPowerOnRequested
= true;
7487 displayPowerOnRequested
= false;
7489 handleDisplayPowerOn();
7494 //******************************************************************************
7495 // systemPowerEventOccurred
7497 // The power controller is notifying us of a hardware-related power management
7498 // event that we must handle.
7500 // systemPowerEventOccurred covers the same functionality that
7501 // receivePowerNotification does; it simply provides a richer API for conveying
7502 // more information.
7503 //******************************************************************************
7506 IOPMrootDomain::systemPowerEventOccurred(
7507 const OSSymbol
*event
,
7510 IOReturn attempt
= kIOReturnSuccess
;
7511 OSNumber
*newNumber
= NULL
;
7514 return kIOReturnBadArgument
;
7517 newNumber
= OSNumber::withNumber(intValue
, 8 * sizeof(intValue
));
7519 return kIOReturnInternalError
;
7522 attempt
= systemPowerEventOccurred(event
, (OSObject
*)newNumber
);
7524 newNumber
->release();
7530 IOPMrootDomain::setThermalState(OSObject
*value
)
7534 if (gIOPMWorkLoop
->inGate() == false) {
7535 gIOPMWorkLoop
->runAction(
7536 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::setThermalState
),
7542 if (value
&& (num
= OSDynamicCast(OSNumber
, value
))) {
7543 thermalWarningState
= ((num
->unsigned32BitValue() == kIOPMThermalLevelWarning
) ||
7544 (num
->unsigned32BitValue() == kIOPMThermalLevelTrap
)) ? 1 : 0;
7549 IOPMrootDomain::systemPowerEventOccurred(
7550 const OSSymbol
*event
,
7553 OSDictionary
*thermalsDict
= NULL
;
7554 bool shouldUpdate
= true;
7556 if (!event
|| !value
) {
7557 return kIOReturnBadArgument
;
7561 // We reuse featuresDict Lock because it already exists and guards
7562 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
7563 // of stepping on that lock.
7564 if (featuresDictLock
) {
7565 IOLockLock(featuresDictLock
);
7568 thermalsDict
= (OSDictionary
*)getProperty(kIOPMRootDomainPowerStatusKey
);
7570 if (thermalsDict
&& OSDynamicCast(OSDictionary
, thermalsDict
)) {
7571 thermalsDict
= OSDictionary::withDictionary(thermalsDict
);
7573 thermalsDict
= OSDictionary::withCapacity(1);
7576 if (!thermalsDict
) {
7577 shouldUpdate
= false;
7581 thermalsDict
->setObject(event
, value
);
7583 setProperty(kIOPMRootDomainPowerStatusKey
, thermalsDict
);
7585 thermalsDict
->release();
7589 if (featuresDictLock
) {
7590 IOLockUnlock(featuresDictLock
);
7595 event
->isEqualTo(kIOPMThermalLevelWarningKey
)) {
7596 setThermalState(value
);
7598 messageClients(kIOPMMessageSystemPowerEventOccurred
, (void *)NULL
);
7601 return kIOReturnSuccess
;
7604 //******************************************************************************
7605 // receivePowerNotification
7607 // The power controller is notifying us of a hardware-related power management
7608 // event that we must handle. This may be a result of an 'environment' interrupt
7609 // from the power mgt micro.
7610 //******************************************************************************
7613 IOPMrootDomain::receivePowerNotification( UInt32 msg
)
7615 if (msg
& kIOPMPowerButton
) {
7616 uint32_t currentPhase
= pmTracer
->getTracePhase();
7617 if (currentPhase
!= kIOPMTracePointSystemUp
&& currentPhase
> kIOPMTracePointSystemSleep
) {
7618 DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase
);
7619 swd_flags
|= SWD_PWR_BTN_STACKSHOT
;
7620 thread_call_enter(powerButtonDown
);
7622 DEBUG_LOG("power button pressed when system is up\n");
7624 } else if (msg
& kIOPMPowerButtonUp
) {
7625 if (swd_flags
& SWD_PWR_BTN_STACKSHOT
) {
7626 swd_flags
&= ~SWD_PWR_BTN_STACKSHOT
;
7627 thread_call_enter(powerButtonUp
);
7630 pmPowerStateQueue
->submitPowerEvent(
7631 kPowerEventReceivedPowerNotification
, (void *)(uintptr_t) msg
);
7633 return kIOReturnSuccess
;
7637 IOPMrootDomain::handlePowerNotification( UInt32 msg
)
7639 bool eval_clamshell
= false;
7640 bool eval_clamshell_alarm
= false;
7645 * Local (IOPMrootDomain only) eval clamshell command
7647 if (msg
& kLocalEvalClamshellCommand
) {
7648 if (isRTCAlarmWake
) {
7649 eval_clamshell_alarm
= true;
7651 // reset isRTCAlarmWake. This evaluation should happen only once
7652 // on RTC/Alarm wake. Any clamshell events after wake should follow
7653 // the regular evaluation
7654 isRTCAlarmWake
= false;
7656 eval_clamshell
= true;
7663 if (msg
& kIOPMOverTemp
) {
7664 MSG("PowerManagement emergency overtemp signal. Going to sleep!");
7665 privateSleepSystem(kIOPMSleepReasonThermalEmergency
);
7669 * Forward DW thermal notification to client, if system is not going to sleep
7671 if ((msg
& kIOPMDWOverTemp
) && (_systemTransitionType
!= kSystemTransitionSleep
)) {
7672 DLOG("DarkWake thermal limits message received!\n");
7674 messageClients(kIOPMMessageDarkWakeThermalEmergency
);
7680 if (msg
& kIOPMSleepNow
) {
7681 privateSleepSystem(kIOPMSleepReasonSoftware
);
7687 if (msg
& kIOPMPowerEmergency
) {
7688 lowBatteryCondition
= true;
7689 privateSleepSystem(kIOPMSleepReasonLowPower
);
7695 if (msg
& kIOPMClamshellOpened
) {
7696 DLOG("Clamshell opened\n");
7697 // Received clamshel open message from clamshell controlling driver
7698 // Update our internal state and tell general interest clients
7699 clamshellClosed
= false;
7700 clamshellExists
= true;
7702 // Don't issue a hid tickle when lid is open and polled on wake
7703 if (msg
& kIOPMSetValue
) {
7704 setProperty(kIOPMRootDomainWakeTypeKey
, "Lid Open");
7709 informCPUStateChange(kInformLid
, 0);
7711 // Tell general interest clients
7712 sendClientClamshellNotification();
7714 bool aborting
= ((lastSleepReason
== kIOPMSleepReasonClamshell
)
7715 || (lastSleepReason
== kIOPMSleepReasonIdle
)
7716 || (lastSleepReason
== kIOPMSleepReasonMaintenance
));
7718 userActivityCount
++;
7720 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount
, lastSleepReason
);
7725 * Send the clamshell interest notification since the lid is closing.
7727 if (msg
& kIOPMClamshellClosed
) {
7728 if (clamshellClosed
&& clamshellExists
) {
7729 DLOG("Ignoring redundant Clamshell close event\n");
7731 DLOG("Clamshell closed\n");
7732 // Received clamshel open message from clamshell controlling driver
7733 // Update our internal state and tell general interest clients
7734 clamshellClosed
= true;
7735 clamshellExists
= true;
7738 informCPUStateChange(kInformLid
, 1);
7740 // Tell general interest clients
7741 sendClientClamshellNotification();
7743 // And set eval_clamshell = so we can attempt
7744 eval_clamshell
= true;
7749 * Set Desktop mode (sent from graphics)
7751 * -> reevaluate lid state
7753 if (msg
& kIOPMSetDesktopMode
) {
7754 DLOG("Desktop mode\n");
7755 desktopMode
= (0 != (msg
& kIOPMSetValue
));
7756 msg
&= ~(kIOPMSetDesktopMode
| kIOPMSetValue
);
7758 sendClientClamshellNotification();
7760 // Re-evaluate the lid state
7761 eval_clamshell
= true;
7765 * AC Adaptor connected
7767 * -> reevaluate lid state
7769 if (msg
& kIOPMSetACAdaptorConnected
) {
7770 acAdaptorConnected
= (0 != (msg
& kIOPMSetValue
));
7771 msg
&= ~(kIOPMSetACAdaptorConnected
| kIOPMSetValue
);
7774 informCPUStateChange(kInformAC
, !acAdaptorConnected
);
7776 // Tell BSD if AC is connected
7777 // 0 == external power source; 1 == on battery
7778 post_sys_powersource(acAdaptorConnected
? 0:1);
7780 sendClientClamshellNotification();
7782 // Re-evaluate the lid state
7783 eval_clamshell
= true;
7785 // Lack of AC may have latched a display wrangler tickle.
7786 // This mirrors the hardware's USB wake event latch, where a latched
7787 // USB wake event followed by an AC attach will trigger a full wake.
7788 latchDisplayWranglerTickle( false );
7791 // AC presence will reset the standy timer delay adjustment.
7792 _standbyTimerResetSeconds
= 0;
7794 if (!userIsActive
) {
7795 // Reset userActivityTime when power supply is changed(rdr 13789330)
7796 clock_get_uptime(&userActivityTime
);
7801 * Enable Clamshell (external display disappear)
7803 * -> reevaluate lid state
7805 if (msg
& kIOPMEnableClamshell
) {
7806 DLOG("Clamshell enabled\n");
7807 // Re-evaluate the lid state
7808 // System should sleep on external display disappearance
7809 // in lid closed operation.
7810 if (true == clamshellDisabled
) {
7811 eval_clamshell
= true;
7814 clamshellDisabled
= false;
7815 sendClientClamshellNotification();
7819 * Disable Clamshell (external display appeared)
7820 * We don't bother re-evaluating clamshell state. If the system is awake,
7821 * the lid is probably open.
7823 if (msg
& kIOPMDisableClamshell
) {
7824 DLOG("Clamshell disabled\n");
7825 clamshellDisabled
= true;
7826 sendClientClamshellNotification();
7830 * Evaluate clamshell and SLEEP if appropiate
7832 if (eval_clamshell_alarm
&& clamshellClosed
) {
7833 if (shouldSleepOnRTCAlarmWake()) {
7834 privateSleepSystem(kIOPMSleepReasonClamshell
);
7836 } else if (eval_clamshell
&& clamshellClosed
) {
7837 if (shouldSleepOnClamshellClosed()) {
7838 privateSleepSystem(kIOPMSleepReasonClamshell
);
7840 evaluatePolicy( kStimulusDarkWakeEvaluate
);
7844 if (msg
& kIOPMProModeEngaged
) {
7846 DLOG("ProModeEngaged\n");
7847 messageClient(kIOPMMessageProModeStateChange
, systemCapabilityNotifier
, &newState
, sizeof(newState
));
7850 if (msg
& kIOPMProModeDisengaged
) {
7852 DLOG("ProModeDisengaged\n");
7853 messageClient(kIOPMMessageProModeStateChange
, systemCapabilityNotifier
, &newState
, sizeof(newState
));
7857 //******************************************************************************
7860 // Evaluate root-domain policy in response to external changes.
7861 //******************************************************************************
7864 IOPMrootDomain::evaluatePolicy( int stimulus
, uint32_t arg
)
7868 int idleSleepEnabled
: 1;
7869 int idleSleepDisabled
: 1;
7870 int displaySleep
: 1;
7871 int sleepDelayChanged
: 1;
7872 int evaluateDarkWake
: 1;
7873 int adjustPowerState
: 1;
7874 int userBecameInactive
: 1;
7884 case kStimulusDisplayWranglerSleep
:
7885 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7886 if (!wranglerAsleep
) {
7887 // first transition to wrangler sleep or lower
7888 flags
.bit
.displaySleep
= true;
7892 case kStimulusDisplayWranglerWake
:
7893 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7894 displayIdleForDemandSleep
= false;
7895 wranglerAsleep
= false;
7898 case kStimulusEnterUserActiveState
:
7899 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7900 if (_preventUserActive
) {
7901 DLOG("user active dropped\n");
7904 if (!userIsActive
) {
7905 userIsActive
= true;
7906 userWasActive
= true;
7907 clock_get_uptime(&gUserActiveAbsTime
);
7909 // Stay awake after dropping demand for display power on
7910 if (kFullWakeReasonDisplayOn
== fullWakeReason
) {
7911 fullWakeReason
= fFullWakeReasonDisplayOnAndLocalUser
;
7912 DLOG("User activity while in notification wake\n");
7913 changePowerStateWithOverrideTo( getRUN_STATE(), 0);
7916 kdebugTrace(kPMLogUserActiveState
, 0, 1, 0);
7917 setProperty(gIOPMUserIsActiveKey
, kOSBooleanTrue
);
7918 messageClients(kIOPMMessageUserIsActiveChanged
);
7920 flags
.bit
.idleSleepDisabled
= true;
7923 case kStimulusLeaveUserActiveState
:
7924 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7926 clock_get_uptime(&gUserInactiveAbsTime
);
7927 userIsActive
= false;
7928 clock_get_uptime(&userBecameInactiveTime
);
7929 flags
.bit
.userBecameInactive
= true;
7931 kdebugTrace(kPMLogUserActiveState
, 0, 0, 0);
7932 setProperty(gIOPMUserIsActiveKey
, kOSBooleanFalse
);
7933 messageClients(kIOPMMessageUserIsActiveChanged
);
7937 case kStimulusAggressivenessChanged
:
7939 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7940 unsigned long minutesToIdleSleep
= 0;
7941 unsigned long minutesToDisplayDim
= 0;
7942 unsigned long minutesDelta
= 0;
7944 // Fetch latest display and system sleep slider values.
7945 getAggressiveness(kPMMinutesToSleep
, &minutesToIdleSleep
);
7946 getAggressiveness(kPMMinutesToDim
, &minutesToDisplayDim
);
7947 DLOG("aggressiveness changed: system %u->%u, display %u\n",
7948 (uint32_t) sleepSlider
,
7949 (uint32_t) minutesToIdleSleep
,
7950 (uint32_t) minutesToDisplayDim
);
7952 DLOG("idle time -> %ld secs (ena %d)\n",
7953 idleSeconds
, (minutesToIdleSleep
!= 0));
7956 // How long to wait before sleeping the system once
7957 // the displays turns off is indicated by 'extraSleepDelay'.
7959 if (minutesToIdleSleep
> minutesToDisplayDim
) {
7960 minutesDelta
= minutesToIdleSleep
- minutesToDisplayDim
;
7961 } else if (minutesToIdleSleep
== minutesToDisplayDim
) {
7965 if ((!idleSleepEnabled
) && (minutesToIdleSleep
!= 0)) {
7966 idleSleepEnabled
= flags
.bit
.idleSleepEnabled
= true;
7969 if ((idleSleepEnabled
) && (minutesToIdleSleep
== 0)) {
7970 flags
.bit
.idleSleepDisabled
= true;
7971 idleSleepEnabled
= false;
7973 if (0x7fffffff == minutesToIdleSleep
) {
7974 minutesToIdleSleep
= idleSeconds
;
7977 if (((minutesDelta
!= extraSleepDelay
) ||
7978 (userActivityTime
!= userActivityTime_prev
)) &&
7979 !flags
.bit
.idleSleepEnabled
&& !flags
.bit
.idleSleepDisabled
) {
7980 flags
.bit
.sleepDelayChanged
= true;
7983 if (systemDarkWake
&& !darkWakeToSleepASAP
&&
7984 (flags
.bit
.idleSleepEnabled
|| flags
.bit
.idleSleepDisabled
)) {
7985 // Reconsider decision to remain in dark wake
7986 flags
.bit
.evaluateDarkWake
= true;
7989 sleepSlider
= minutesToIdleSleep
;
7990 extraSleepDelay
= minutesDelta
;
7991 userActivityTime_prev
= userActivityTime
;
7994 case kStimulusDemandSystemSleep
:
7995 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7996 displayIdleForDemandSleep
= true;
7997 if (wrangler
&& wranglerIdleSettings
) {
7998 // Request wrangler idle only when demand sleep is triggered
8000 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
8001 wrangler
->setProperties(wranglerIdleSettings
);
8002 DLOG("Requested wrangler idle\n");
8005 // arg = sleepReason
8006 changePowerStateWithOverrideTo( SLEEP_STATE
, arg
);
8009 case kStimulusAllowSystemSleepChanged
:
8010 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8011 flags
.bit
.adjustPowerState
= true;
8014 case kStimulusDarkWakeActivityTickle
:
8015 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8016 // arg == true implies real and not self generated wrangler tickle.
8017 // Update wake type on PM work loop instead of the tickle thread to
8018 // eliminate the possibility of an early tickle clobbering the wake
8019 // type set by the platform driver.
8021 setProperty(kIOPMRootDomainWakeTypeKey
, kIOPMRootDomainWakeTypeHIDActivity
);
8024 if (false == wranglerTickled
) {
8025 if (latchDisplayWranglerTickle(true)) {
8026 DLOG("latched tickle\n");
8030 wranglerTickled
= true;
8031 DLOG("Requesting full wake after dark wake activity tickle\n");
8032 requestFullWake( kFullWakeReasonLocalUser
);
8036 case kStimulusDarkWakeEntry
:
8037 case kStimulusDarkWakeReentry
:
8038 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8039 // Any system transitions since the last dark wake transition
8040 // will invalid the stimulus.
8042 if (arg
== _systemStateGeneration
) {
8043 DLOG("dark wake entry\n");
8044 systemDarkWake
= true;
8046 // Keep wranglerAsleep an invariant when wrangler is absent
8048 wranglerAsleep
= true;
8051 if (kStimulusDarkWakeEntry
== stimulus
) {
8052 clock_get_uptime(&userBecameInactiveTime
);
8053 flags
.bit
.evaluateDarkWake
= true;
8054 if (activitySinceSleep()) {
8055 DLOG("User activity recorded while going to darkwake\n");
8060 // Always accelerate disk spindown while in dark wake,
8061 // even if system does not support/allow sleep.
8063 cancelIdleSleepTimer();
8064 setQuickSpinDownTimeout();
8068 case kStimulusDarkWakeEvaluate
:
8069 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8070 if (systemDarkWake
) {
8071 flags
.bit
.evaluateDarkWake
= true;
8075 case kStimulusNoIdleSleepPreventers
:
8076 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8077 flags
.bit
.adjustPowerState
= true;
8079 } /* switch(stimulus) */
8081 if (flags
.bit
.evaluateDarkWake
&& (kFullWakeReasonNone
== fullWakeReason
)) {
8082 if (darkWakeToSleepASAP
||
8083 (clamshellClosed
&& !(desktopMode
&& acAdaptorConnected
))) {
8084 uint32_t newSleepReason
;
8086 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
8087 // System was previously in full wake. Sleep reason from
8088 // full to dark already recorded in fullToDarkReason.
8090 if (lowBatteryCondition
) {
8091 newSleepReason
= kIOPMSleepReasonLowPower
;
8093 newSleepReason
= fullToDarkReason
;
8096 // In dark wake from system sleep.
8098 if (darkWakeSleepService
) {
8099 newSleepReason
= kIOPMSleepReasonSleepServiceExit
;
8101 newSleepReason
= kIOPMSleepReasonMaintenance
;
8105 if (checkSystemCanSleep(newSleepReason
)) {
8106 privateSleepSystem(newSleepReason
);
8108 } else { // non-maintenance (network) dark wake
8109 if (checkSystemCanSleep(kIOPMSleepReasonIdle
)) {
8110 // Release power clamp, and wait for children idle.
8111 adjustPowerState(true);
8113 changePowerStateToPriv(getRUN_STATE());
8118 if (systemDarkWake
) {
8119 // The rest are irrelevant while system is in dark wake.
8123 if ((flags
.bit
.displaySleep
) &&
8124 (kFullWakeReasonDisplayOn
== fullWakeReason
)) {
8125 // kIOPMSleepReasonMaintenance?
8126 DLOG("Display sleep while in notification wake\n");
8127 changePowerStateWithOverrideTo( SLEEP_STATE
, kIOPMSleepReasonMaintenance
);
8130 if (flags
.bit
.userBecameInactive
|| flags
.bit
.sleepDelayChanged
) {
8131 bool cancelQuickSpindown
= false;
8133 if (flags
.bit
.sleepDelayChanged
) {
8134 // Cancel existing idle sleep timer and quick disk spindown.
8135 // New settings will be applied by the idleSleepEnabled flag
8136 // handler below if idle sleep is enabled.
8138 DLOG("extra sleep timer changed\n");
8139 cancelIdleSleepTimer();
8140 cancelQuickSpindown
= true;
8142 DLOG("user inactive\n");
8145 if (!userIsActive
&& idleSleepEnabled
) {
8146 startIdleSleepTimer(getTimeToIdleSleep());
8149 if (cancelQuickSpindown
) {
8150 restoreUserSpinDownTimeout();
8154 if (flags
.bit
.idleSleepEnabled
) {
8155 DLOG("idle sleep timer enabled\n");
8157 changePowerStateToPriv(getRUN_STATE());
8158 startIdleSleepTimer( idleSeconds
);
8160 // Start idle timer if prefs now allow system sleep
8161 // and user is already inactive. Disk spindown is
8162 // accelerated upon timer expiration.
8164 if (!userIsActive
) {
8165 startIdleSleepTimer(getTimeToIdleSleep());
8170 if (flags
.bit
.idleSleepDisabled
) {
8171 DLOG("idle sleep timer disabled\n");
8172 cancelIdleSleepTimer();
8173 restoreUserSpinDownTimeout();
8177 if (flags
.bit
.adjustPowerState
) {
8178 bool sleepASAP
= false;
8180 if (!systemBooting
&& (0 == idleSleepPreventersCount())) {
8182 changePowerStateToPriv(getRUN_STATE());
8183 if (idleSleepEnabled
) {
8184 // stay awake for at least idleSeconds
8185 startIdleSleepTimer(idleSeconds
);
8187 } else if (!extraSleepDelay
&& !idleSleepTimerPending
&& !systemDarkWake
) {
8192 adjustPowerState(sleepASAP
);
8196 //******************************************************************************
8199 IOPMrootDomain::idleSleepPreventersCount()
8202 unsigned int count __block
;
8204 preventIdleSleepList
->iterateObjects(^bool (OSObject
* obj
)
8206 count
+= (NULL
== obj
->metaCast("AppleARMBacklight"));
8212 return preventIdleSleepList
->getCount();
8216 //******************************************************************************
8219 // Request transition from dark wake to full wake
8220 //******************************************************************************
8223 IOPMrootDomain::requestFullWake( FullWakeReason reason
)
8225 uint32_t options
= 0;
8226 IOService
* pciRoot
= NULL
;
8227 bool promotion
= false;
8229 // System must be in dark wake and a valid reason for entering full wake
8230 if ((kFullWakeReasonNone
== reason
) ||
8231 (kFullWakeReasonNone
!= fullWakeReason
) ||
8232 (CAP_CURRENT(kIOPMSystemCapabilityGraphics
))) {
8236 // Will clear reason upon exit from full wake
8237 fullWakeReason
= reason
;
8239 _desiredCapability
|= (kIOPMSystemCapabilityGraphics
|
8240 kIOPMSystemCapabilityAudio
);
8242 if ((kSystemTransitionWake
== _systemTransitionType
) &&
8243 !(_pendingCapability
& kIOPMSystemCapabilityGraphics
) &&
8244 !graphicsSuppressed
) {
8245 // Promote to full wake while waking up to dark wake due to tickle.
8246 // PM will hold off notifying the graphics subsystem about system wake
8247 // as late as possible, so if a HID tickle does arrive, graphics can
8248 // power up on this same wake cycle. The latency to power up graphics
8249 // on the next cycle can be huge on some systems. However, once any
8250 // graphics suppression has taken effect, it is too late. All other
8251 // graphics devices must be similarly suppressed. But the delay till
8252 // the following cycle should be short.
8254 _pendingCapability
|= (kIOPMSystemCapabilityGraphics
|
8255 kIOPMSystemCapabilityAudio
);
8257 // Immediately bring up audio and graphics
8258 pciRoot
= pciHostBridgeDriver
;
8259 willEnterFullWake();
8263 // Unsafe to cancel once graphics was powered.
8264 // If system woke from dark wake, the return to sleep can
8265 // be cancelled. "awake -> dark -> sleep" transition
8266 // can be canceled also, during the "dark --> sleep" phase
8267 // *prior* to driver power down.
8268 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics
) ||
8269 _pendingCapability
== 0) {
8270 options
|= kIOPMSyncCancelPowerDown
;
8273 synchronizePowerTree(options
, pciRoot
);
8274 if (kFullWakeReasonLocalUser
== fullWakeReason
) {
8275 // IOGraphics doesn't light the display even though graphics is
8276 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
8277 // So, do an explicit activity tickle
8279 wrangler
->activityTickle(0, 0);
8283 // Log a timestamp for the initial full wake request.
8284 // System may not always honor this full wake request.
8285 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
8289 clock_get_uptime(&now
);
8290 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
8291 absolutetime_to_nanoseconds(now
, &nsec
);
8292 MSG("full wake %s (reason %u) %u ms\n",
8293 promotion
? "promotion" : "request",
8294 fullWakeReason
, ((int)((nsec
) / NSEC_PER_MSEC
)));
8298 //******************************************************************************
8299 // willEnterFullWake
8301 // System will enter full wake from sleep, from dark wake, or from dark
8302 // wake promotion. This function aggregate things that are in common to
8303 // all three full wake transitions.
8305 // Assumptions: fullWakeReason was updated
8306 //******************************************************************************
8309 IOPMrootDomain::willEnterFullWake( void )
8311 hibernateRetry
= false;
8312 sleepToStandby
= false;
8313 standbyNixed
= false;
8314 resetTimers
= false;
8315 sleepTimerMaintenance
= false;
8317 _systemMessageClientMask
= kSystemMessageClientPowerd
|
8318 kSystemMessageClientLegacyApp
;
8320 if ((_highestCapability
& kIOPMSystemCapabilityGraphics
) == 0) {
8321 // Initial graphics full power
8322 _systemMessageClientMask
|= kSystemMessageClientKernel
;
8324 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
8325 setProperty(gIOPMUserTriggeredFullWakeKey
,
8326 (kFullWakeReasonLocalUser
== fullWakeReason
) ?
8327 kOSBooleanTrue
: kOSBooleanFalse
);
8330 IOHibernateSetWakeCapabilities(_pendingCapability
);
8333 IOService::setAdvisoryTickleEnable( true );
8334 tellClients(kIOMessageSystemWillPowerOn
);
8335 preventTransitionToUserActive(false);
8338 //******************************************************************************
8339 // fullWakeDelayedWork
8341 // System has already entered full wake. Invoked by a delayed thread call.
8342 //******************************************************************************
8345 IOPMrootDomain::fullWakeDelayedWork( void )
8347 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
8348 // Not gated, don't modify state
8349 if ((kSystemTransitionNone
== _systemTransitionType
) &&
8350 CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
8351 receivePowerNotification( kLocalEvalClamshellCommand
);
8356 //******************************************************************************
8357 // evaluateAssertions
8359 //******************************************************************************
8361 // Bitmask of all kernel assertions that prevent system idle sleep.
8362 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
8363 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
8364 (kIOPMDriverAssertionReservedBit7 | \
8365 kIOPMDriverAssertionPreventSystemIdleSleepBit)
8368 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions
, IOPMDriverAssertionType oldAssertions
)
8370 IOPMDriverAssertionType changedBits
= newAssertions
^ oldAssertions
;
8372 messageClients(kIOPMMessageDriverAssertionsChanged
);
8374 if (changedBits
& kIOPMDriverAssertionPreventDisplaySleepBit
) {
8376 bool value
= (newAssertions
& kIOPMDriverAssertionPreventDisplaySleepBit
) ? true : false;
8378 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value
);
8379 wrangler
->setIgnoreIdleTimer( value
);
8383 if (changedBits
& kIOPMDriverAssertionCPUBit
) {
8385 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit
& newAssertions
)));
8387 evaluatePolicy(_aotNow
? kStimulusNoIdleSleepPreventers
: kStimulusDarkWakeEvaluate
);
8388 if (!assertOnWakeSecs
&& gIOLastWakeAbsTime
) {
8390 clock_usec_t microsecs
;
8391 clock_get_uptime(&now
);
8392 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
8393 absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
);
8394 if (assertOnWakeReport
) {
8395 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
);
8396 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
);
8401 if (changedBits
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) {
8402 if ((newAssertions
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) != 0) {
8403 if ((oldAssertions
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) == 0) {
8404 DLOG("PreventIdleSleep driver assertion raised\n");
8405 bool ok
= updatePreventIdleSleepList(this, true);
8406 if (ok
&& (changedBits
& kIOPMDriverAssertionPreventSystemIdleSleepBit
)) {
8407 // Cancel idle sleep if there is one in progress
8408 cancelIdlePowerDown(this);
8412 DLOG("PreventIdleSleep driver assertion dropped\n");
8413 updatePreventIdleSleepList(this, false);
8421 //******************************************************************************
8424 //******************************************************************************
8427 IOPMrootDomain::pmStatsRecordEvent(
8429 AbsoluteTime timestamp
)
8431 bool starting
= eventIndex
& kIOPMStatsEventStartFlag
? true:false;
8432 bool stopping
= eventIndex
& kIOPMStatsEventStopFlag
? true:false;
8435 OSData
*publishPMStats
= NULL
;
8437 eventIndex
&= ~(kIOPMStatsEventStartFlag
| kIOPMStatsEventStopFlag
);
8439 absolutetime_to_nanoseconds(timestamp
, &nsec
);
8441 switch (eventIndex
) {
8442 case kIOPMStatsHibernateImageWrite
:
8444 gPMStats
.hibWrite
.start
= nsec
;
8445 } else if (stopping
) {
8446 gPMStats
.hibWrite
.stop
= nsec
;
8450 delta
= gPMStats
.hibWrite
.stop
- gPMStats
.hibWrite
.start
;
8451 IOLog("PMStats: Hibernate write took %qd ms\n", delta
/ NSEC_PER_MSEC
);
8454 case kIOPMStatsHibernateImageRead
:
8456 gPMStats
.hibRead
.start
= nsec
;
8457 } else if (stopping
) {
8458 gPMStats
.hibRead
.stop
= nsec
;
8462 delta
= gPMStats
.hibRead
.stop
- gPMStats
.hibRead
.start
;
8463 IOLog("PMStats: Hibernate read took %qd ms\n", delta
/ NSEC_PER_MSEC
);
8465 publishPMStats
= OSData::withBytes(&gPMStats
, sizeof(gPMStats
));
8466 setProperty(kIOPMSleepStatisticsKey
, publishPMStats
);
8467 publishPMStats
->release();
8468 bzero(&gPMStats
, sizeof(gPMStats
));
8475 * Appends a record of the application response to
8476 * IOPMrootDomain::pmStatsAppResponses
8479 IOPMrootDomain::pmStatsRecordApplicationResponse(
8480 const OSSymbol
*response
,
8486 IOPMPowerStateIndex powerState
)
8488 OSDictionary
*responseDescription
= NULL
;
8489 OSNumber
*delayNum
= NULL
;
8490 OSNumber
*powerCaps
= NULL
;
8491 OSNumber
*pidNum
= NULL
;
8492 OSNumber
*msgNum
= NULL
;
8493 const OSSymbol
*appname
;
8494 const OSSymbol
*sleep
= NULL
, *wake
= NULL
;
8495 IOPMServiceInterestNotifier
*notify
= NULL
;
8497 if (object
&& (notify
= OSDynamicCast(IOPMServiceInterestNotifier
, object
))) {
8498 if (response
->isEqualTo(gIOPMStatsResponseTimedOut
)) {
8499 notify
->ackTimeoutCnt
++;
8501 notify
->ackTimeoutCnt
= 0;
8505 if (response
->isEqualTo(gIOPMStatsResponsePrompt
) ||
8506 (_systemTransitionType
== kSystemTransitionNone
) || (_systemTransitionType
== kSystemTransitionNewCapClient
)) {
8511 if (response
->isEqualTo(gIOPMStatsDriverPSChangeSlow
)) {
8512 kdebugTrace(kPMLogDrvPSChangeDelay
, id
, messageType
, delay_ms
);
8513 } else if (notify
) {
8514 // User space app or kernel capability client
8516 kdebugTrace(kPMLogAppResponseDelay
, id
, notify
->msgType
, delay_ms
);
8518 kdebugTrace(kPMLogDrvResponseDelay
, notify
->uuid0
, messageType
, delay_ms
);
8520 notify
->msgType
= 0;
8523 responseDescription
= OSDictionary::withCapacity(5);
8524 if (responseDescription
) {
8526 responseDescription
->setObject(_statsResponseTypeKey
, response
);
8529 msgNum
= OSNumber::withNumber(messageType
, 32);
8531 responseDescription
->setObject(_statsMessageTypeKey
, msgNum
);
8535 if (!name
&& notify
&& notify
->identifier
) {
8536 name
= notify
->identifier
->getCStringNoCopy();
8539 if (name
&& (strlen(name
) > 0)) {
8540 appname
= OSSymbol::withCString(name
);
8542 responseDescription
->setObject(_statsNameKey
, appname
);
8547 if (!id
&& notify
) {
8551 pidNum
= OSNumber::withNumber(id
, 64);
8553 responseDescription
->setObject(_statsPIDKey
, pidNum
);
8558 delayNum
= OSNumber::withNumber(delay_ms
, 32);
8560 responseDescription
->setObject(_statsTimeMSKey
, delayNum
);
8561 delayNum
->release();
8564 if (response
->isEqualTo(gIOPMStatsDriverPSChangeSlow
)) {
8565 powerCaps
= OSNumber::withNumber(powerState
, 32);
8567 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
8568 IOLog("%s::powerStateChange type(%d) to(%lu) async took %d ms\n",
8570 powerState
, delay_ms
);
8573 powerCaps
= OSNumber::withNumber(_pendingCapability
, 32);
8576 responseDescription
->setObject(_statsPowerCapsKey
, powerCaps
);
8577 powerCaps
->release();
8580 sleep
= OSSymbol::withCString("Sleep");
8581 wake
= OSSymbol::withCString("Wake");
8582 if (_systemTransitionType
== kSystemTransitionSleep
) {
8583 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, sleep
);
8584 } else if (_systemTransitionType
== kSystemTransitionWake
) {
8585 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, wake
);
8586 } else if (_systemTransitionType
== kSystemTransitionCapability
) {
8587 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) {
8588 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, sleep
);
8589 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
8590 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, wake
);
8602 IOLockLock(pmStatsLock
);
8603 if (pmStatsAppResponses
&& pmStatsAppResponses
->getCount() < 50) {
8604 pmStatsAppResponses
->setObject(responseDescription
);
8606 IOLockUnlock(pmStatsLock
);
8608 responseDescription
->release();
8615 // MARK: PMTraceWorker
8617 //******************************************************************************
8618 // TracePoint support
8620 //******************************************************************************
8622 #define kIOPMRegisterNVRAMTracePointHandlerKey \
8623 "IOPMRegisterNVRAMTracePointHandler"
8626 IOPMrootDomain::callPlatformFunction(
8627 const OSSymbol
* functionName
,
8628 bool waitForFunction
,
8629 void * param1
, void * param2
,
8630 void * param3
, void * param4
)
8632 uint32_t bootFailureCode
= 0xffffffff;
8633 if (pmTracer
&& functionName
&&
8634 functionName
->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey
) &&
8635 !pmTracer
->tracePointHandler
&& !pmTracer
->tracePointTarget
) {
8636 uint32_t tracePointPhases
, tracePointPCI
;
8637 uint64_t statusCode
;
8639 pmTracer
->tracePointHandler
= (IOPMTracePointHandler
) param1
;
8640 pmTracer
->tracePointTarget
= (void *) param2
;
8641 tracePointPCI
= (uint32_t)(uintptr_t) param3
;
8642 tracePointPhases
= (uint32_t)(uintptr_t) param4
;
8643 if ((tracePointPhases
& 0xff) == kIOPMTracePointSystemSleep
) {
8644 IORegistryEntry
*node
= IORegistryEntry::fromPath( "/chosen", gIODTPlane
);
8646 OSData
*data
= OSDynamicCast( OSData
, node
->getProperty(kIOEFIBootRomFailureKey
));
8647 if (data
&& data
->getLength() == sizeof(bootFailureCode
)) {
8648 memcpy(&bootFailureCode
, data
->getBytesNoCopy(), sizeof(bootFailureCode
));
8652 // Failure code from EFI/BootRom is a four byte structure
8653 tracePointPCI
= OSSwapBigToHostInt32(bootFailureCode
);
8655 statusCode
= (((uint64_t)tracePointPCI
) << 32) | tracePointPhases
;
8656 if ((tracePointPhases
& 0xff) != kIOPMTracePointSystemUp
) {
8657 MSG("Sleep failure code 0x%08x 0x%08x\n",
8658 tracePointPCI
, tracePointPhases
);
8660 setProperty(kIOPMSleepWakeFailureCodeKey
, statusCode
, 64);
8661 pmTracer
->tracePointHandler( pmTracer
->tracePointTarget
, 0, 0 );
8663 return kIOReturnSuccess
;
8666 else if (functionName
&&
8667 functionName
->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey
)) {
8668 if (gSleepPolicyHandler
) {
8669 return kIOReturnExclusiveAccess
;
8672 return kIOReturnBadArgument
;
8674 gSleepPolicyHandler
= (IOPMSystemSleepPolicyHandler
) param1
;
8675 gSleepPolicyTarget
= (void *) param2
;
8676 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue
);
8677 return kIOReturnSuccess
;
8681 return super::callPlatformFunction(
8682 functionName
, waitForFunction
, param1
, param2
, param3
, param4
);
8686 IOPMrootDomain::kdebugTrace(uint32_t event
, uint64_t id
,
8687 uintptr_t param1
, uintptr_t param2
, uintptr_t param3
)
8689 uint32_t code
= IODBG_POWER(event
);
8690 uint64_t regId
= id
;
8692 regId
= getRegistryEntryID();
8694 IOTimeStampConstant(code
, (uintptr_t) regId
, param1
, param2
, param3
);
8699 IOPMrootDomain::tracePoint( uint8_t point
)
8701 if (systemBooting
) {
8705 if (kIOPMTracePointWakeCapabilityClients
== point
) {
8706 acceptSystemWakeEvents(false);
8709 kdebugTrace(kPMLogSleepWakeTracePoint
, 0, point
, 0);
8710 pmTracer
->tracePoint(point
);
8714 IOPMrootDomain::traceDetail(OSObject
*object
, bool start
)
8716 IOPMServiceInterestNotifier
*notifier
;
8718 if (systemBooting
) {
8722 notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, object
);
8728 pmTracer
->traceDetail( notifier
->uuid0
>> 32 );
8729 kdebugTrace(kPMLogSleepWakeMessage
, pmTracer
->getTracePhase(), notifier
->msgType
, notifier
->uuid0
, notifier
->uuid1
);
8730 if (notifier
->identifier
) {
8731 DLOG("trace point 0x%02x msg 0x%x to %s\n", pmTracer
->getTracePhase(), notifier
->msgType
,
8732 notifier
->identifier
->getCStringNoCopy());
8734 DLOG("trace point 0x%02x msg 0x%x\n", pmTracer
->getTracePhase(), notifier
->msgType
);
8736 notifierThread
= current_thread();
8737 notifierObject
= notifier
;
8740 notifierThread
= NULL
;
8741 notifierObject
= NULL
;
8742 notifier
->release();
8748 IOPMrootDomain::traceAckDelay(OSObject
*object
, uint32_t response
, uint32_t delay_ms
)
8750 IOPMServiceInterestNotifier
*notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, object
);
8752 DLOG("Unknown notifier\n");
8756 if (!systemBooting
) {
8757 kdebugTrace(kPMLogDrvResponseDelay
, notifier
->uuid0
, notifier
->uuid1
, response
, delay_ms
);
8758 if (notifier
->identifier
) {
8759 DLOG("Response from %s took %d ms(response:%d)\n",
8760 notifier
->identifier
->getCStringNoCopy(), delay_ms
, response
);
8762 DLOG("Response from kext UUID %llx-%llx took %d ms(response:%d)\n",
8763 notifier
->uuid0
, notifier
->uuid1
, delay_ms
, response
);
8769 IOPMrootDomain::traceDetail(uint32_t msgType
, uint32_t msgIndex
, uint32_t delay
)
8771 if (!systemBooting
) {
8772 uint32_t detail
= ((msgType
& 0xffff) << 16) | (delay
& 0xffff);
8773 pmTracer
->traceDetail( detail
);
8774 kdebugTrace(kPMLogSleepWakeTracePoint
, pmTracer
->getTracePhase(), msgType
, delay
);
8775 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer
->getTracePhase(), msgType
, delay
);
8781 IOPMrootDomain::configureReportGated(uint64_t channel_id
, uint64_t action
, void *result
)
8784 void **report
= NULL
;
8787 uint32_t *clientCnt
;
8792 if (channel_id
== kAssertDelayChID
) {
8793 report
= &assertOnWakeReport
;
8794 bktCnt
= kAssertDelayBcktCnt
;
8795 bktSize
= kAssertDelayBcktSize
;
8796 clientCnt
= &assertOnWakeClientCnt
;
8797 } else if (channel_id
== kSleepDelaysChID
) {
8798 report
= &sleepDelaysReport
;
8799 bktCnt
= kSleepDelaysBcktCnt
;
8800 bktSize
= kSleepDelaysBcktSize
;
8801 clientCnt
= &sleepDelaysClientCnt
;
8805 case kIOReportEnable
:
8812 reportSize
= HISTREPORT_BUFSIZE(bktCnt
);
8813 *report
= IOMalloc(reportSize
);
8814 if (*report
== NULL
) {
8817 bzero(*report
, reportSize
);
8818 HISTREPORT_INIT(bktCnt
, bktSize
, *report
, reportSize
,
8819 getRegistryEntryID(), channel_id
, kIOReportCategoryPower
);
8821 if (channel_id
== kAssertDelayChID
) {
8822 assertOnWakeSecs
= 0;
8827 case kIOReportDisable
:
8828 if (*clientCnt
== 0) {
8831 if (*clientCnt
== 1) {
8832 IOFree(*report
, HISTREPORT_BUFSIZE(bktCnt
));
8837 if (channel_id
== kAssertDelayChID
) {
8838 assertOnWakeSecs
= -1; // Invalid value to prevent updates
8842 case kIOReportGetDimensions
:
8844 HISTREPORT_UPDATERES(*report
, kIOReportGetDimensions
, result
);
8853 IOPMrootDomain::configureReport(IOReportChannelList
*channelList
,
8854 IOReportConfigureAction action
,
8859 uint64_t configAction
= (uint64_t)action
;
8861 for (cnt
= 0; cnt
< channelList
->nchannels
; cnt
++) {
8862 if ((channelList
->channels
[cnt
].channel_id
== kSleepCntChID
) ||
8863 (channelList
->channels
[cnt
].channel_id
== kDarkWkCntChID
) ||
8864 (channelList
->channels
[cnt
].channel_id
== kUserWkCntChID
)) {
8865 if (action
!= kIOReportGetDimensions
) {
8868 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
8869 } else if ((channelList
->channels
[cnt
].channel_id
== kAssertDelayChID
) ||
8870 (channelList
->channels
[cnt
].channel_id
== kSleepDelaysChID
)) {
8871 gIOPMWorkLoop
->runAction(
8872 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::configureReportGated
),
8873 (OSObject
*)this, (void *)channelList
->channels
[cnt
].channel_id
,
8874 (void *)configAction
, (void *)result
);
8878 return super::configureReport(channelList
, action
, result
, destination
);
8882 IOPMrootDomain::updateReportGated(uint64_t ch_id
, void *result
, IOBufferMemoryDescriptor
*dest
)
8891 if (ch_id
== kAssertDelayChID
) {
8892 report
= &assertOnWakeReport
;
8893 } else if (ch_id
== kSleepDelaysChID
) {
8894 report
= &sleepDelaysReport
;
8897 if (*report
== NULL
) {
8898 return kIOReturnNotOpen
;
8901 HISTREPORT_UPDATEPREP(*report
, data2cpy
, size2cpy
);
8902 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
8903 return kIOReturnOverrun
;
8906 HISTREPORT_UPDATERES(*report
, kIOReportCopyChannelData
, result
);
8907 dest
->appendBytes(data2cpy
, size2cpy
);
8909 return kIOReturnSuccess
;
8913 IOPMrootDomain::updateReport(IOReportChannelList
*channelList
,
8914 IOReportUpdateAction action
,
8920 uint8_t buf
[SIMPLEREPORT_BUFSIZE
];
8921 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
8925 if (action
!= kIOReportCopyChannelData
) {
8929 for (cnt
= 0; cnt
< channelList
->nchannels
; cnt
++) {
8930 ch_id
= channelList
->channels
[cnt
].channel_id
;
8932 if ((ch_id
== kAssertDelayChID
) || (ch_id
== kSleepDelaysChID
)) {
8933 gIOPMWorkLoop
->runAction(
8934 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::updateReportGated
),
8935 (OSObject
*)this, (void *)ch_id
,
8936 (void *)result
, (void *)dest
);
8938 } else if ((ch_id
== kSleepCntChID
) ||
8939 (ch_id
== kDarkWkCntChID
) || (ch_id
== kUserWkCntChID
)) {
8940 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), ch_id
, kIOReportCategoryPower
);
8945 if (ch_id
== kSleepCntChID
) {
8946 SIMPLEREPORT_SETVALUE(buf
, sleepCnt
);
8947 } else if (ch_id
== kDarkWkCntChID
) {
8948 SIMPLEREPORT_SETVALUE(buf
, darkWakeCnt
);
8949 } else if (ch_id
== kUserWkCntChID
) {
8950 SIMPLEREPORT_SETVALUE(buf
, displayWakeCnt
);
8953 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
8954 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
8955 dest
->appendBytes(data2cpy
, size2cpy
);
8959 return super::updateReport(channelList
, action
, result
, destination
);
8963 //******************************************************************************
8964 // PMTraceWorker Class
8966 //******************************************************************************
8969 #define super OSObject
8970 OSDefineMetaClassAndStructors(PMTraceWorker
, OSObject
)
8972 #define kPMBestGuessPCIDevicesCount 25
8973 #define kPMMaxRTCBitfieldSize 32
8975 PMTraceWorker
* PMTraceWorker::tracer(IOPMrootDomain
* owner
)
8979 me
= OSTypeAlloc( PMTraceWorker
);
8980 if (!me
|| !me
->init()) {
8984 DLOG("PMTraceWorker %p\n", OBFUSCATE(me
));
8986 // Note that we cannot instantiate the PCI device -> bit mappings here, since
8987 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
8988 // this dictionary lazily.
8990 me
->pciDeviceBitMappings
= NULL
;
8991 me
->pmTraceWorkerLock
= IOLockAlloc();
8992 me
->tracePhase
= kIOPMTracePointSystemUp
;
8993 me
->traceData32
= 0;
8994 me
->loginWindowData
= 0;
8995 me
->coreDisplayData
= 0;
8996 me
->coreGraphicsData
= 0;
9001 PMTraceWorker::RTC_TRACE(void)
9003 if (tracePointHandler
&& tracePointTarget
) {
9006 IOLockLock(pmTraceWorkerLock
);
9007 wordA
= (loginWindowData
<< 24) | (coreDisplayData
<< 16) |
9008 (coreGraphicsData
<< 8) | tracePhase
;
9009 IOLockUnlock(pmTraceWorkerLock
);
9011 tracePointHandler( tracePointTarget
, traceData32
, wordA
);
9012 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32
, wordA
);
9014 #if DEVELOPMENT || DEBUG
9015 if ((swd_panic_phase
!= 0) && (swd_panic_phase
== tracePhase
)) {
9016 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase
);
9017 IOLock
*l
= IOLockAlloc();
9025 PMTraceWorker::recordTopLevelPCIDevice(IOService
* pciDevice
)
9027 const OSSymbol
* deviceName
;
9030 IOLockLock(pmTraceWorkerLock
);
9032 if (!pciDeviceBitMappings
) {
9033 pciDeviceBitMappings
= OSArray::withCapacity(kPMBestGuessPCIDevicesCount
);
9034 if (!pciDeviceBitMappings
) {
9039 // Check for bitmask overflow.
9040 if (pciDeviceBitMappings
->getCount() >= kPMMaxRTCBitfieldSize
) {
9044 if ((deviceName
= pciDevice
->copyName()) &&
9045 (pciDeviceBitMappings
->getNextIndexOfObject(deviceName
, 0) == (unsigned int)-1) &&
9046 pciDeviceBitMappings
->setObject(deviceName
)) {
9047 index
= pciDeviceBitMappings
->getCount() - 1;
9048 _LOG("PMTrace PCI array: set object %s => %d\n",
9049 deviceName
->getCStringNoCopy(), index
);
9052 deviceName
->release();
9054 if (!addedToRegistry
&& (index
>= 0)) {
9055 addedToRegistry
= owner
->setProperty("PCITopLevel", this);
9059 IOLockUnlock(pmTraceWorkerLock
);
9064 PMTraceWorker::serialize(OSSerialize
*s
) const
9067 if (pciDeviceBitMappings
) {
9068 IOLockLock(pmTraceWorkerLock
);
9069 ok
= pciDeviceBitMappings
->serialize(s
);
9070 IOLockUnlock(pmTraceWorkerLock
);
9076 PMTraceWorker::tracePoint(uint8_t phase
)
9078 // clear trace detail when phase begins
9079 if (tracePhase
!= phase
) {
9085 DLOG("trace point 0x%02x\n", tracePhase
);
9090 PMTraceWorker::traceDetail(uint32_t detail
)
9092 if (detail
== traceData32
) {
9095 traceData32
= detail
;
9100 PMTraceWorker::traceComponentWakeProgress(uint32_t component
, uint32_t data
)
9102 switch (component
) {
9103 case kIOPMLoginWindowProgress
:
9104 loginWindowData
= data
& kIOPMLoginWindowProgressMask
;
9106 case kIOPMCoreDisplayProgress
:
9107 coreDisplayData
= data
& kIOPMCoreDisplayProgressMask
;
9109 case kIOPMCoreGraphicsProgress
:
9110 coreGraphicsData
= data
& kIOPMCoreGraphicsProgressMask
;
9116 DLOG("component trace point 0x%02x data 0x%08x\n", component
, data
);
9121 PMTraceWorker::tracePCIPowerChange(
9122 change_t type
, IOService
*service
, uint32_t changeFlags
, uint32_t bitNum
)
9125 uint32_t expectedFlag
;
9127 // Ignore PCI changes outside of system sleep/wake.
9128 if ((kIOPMTracePointSleepPowerPlaneDrivers
!= tracePhase
) &&
9129 (kIOPMTracePointWakePowerPlaneDrivers
!= tracePhase
)) {
9133 // Only record the WillChange transition when going to sleep,
9134 // and the DidChange on the way up.
9135 changeFlags
&= (kIOPMDomainWillChange
| kIOPMDomainDidChange
);
9136 expectedFlag
= (kIOPMTracePointSleepPowerPlaneDrivers
== tracePhase
) ?
9137 kIOPMDomainWillChange
: kIOPMDomainDidChange
;
9138 if (changeFlags
!= expectedFlag
) {
9142 // Mark this device off in our bitfield
9143 if (bitNum
< kPMMaxRTCBitfieldSize
) {
9144 bitMask
= (1 << bitNum
);
9146 if (kPowerChangeStart
== type
) {
9147 traceData32
|= bitMask
;
9148 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
9149 service
->getName(), bitNum
, bitMask
, traceData32
);
9150 owner
->kdebugTrace(kPMLogPCIDevChangeStart
, service
->getRegistryEntryID(), traceData32
, 0);
9152 traceData32
&= ~bitMask
;
9153 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
9154 service
->getName(), bitNum
, bitMask
, traceData32
);
9155 owner
->kdebugTrace(kPMLogPCIDevChangeDone
, service
->getRegistryEntryID(), traceData32
, 0);
9158 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase
, traceData32
);
9164 PMTraceWorker::getPMStatusCode()
9166 return ((uint64_t)traceData32
<< 32) | ((uint64_t)tracePhase
);
9170 PMTraceWorker::getTracePhase()
9176 PMTraceWorker::getTraceData()
9182 // MARK: PMHaltWorker
9184 //******************************************************************************
9185 // PMHaltWorker Class
9187 //******************************************************************************
9190 PMHaltWorker::worker( void )
9196 me
= OSTypeAlloc( PMHaltWorker
);
9197 if (!me
|| !me
->init()) {
9201 me
->lock
= IOLockAlloc();
9206 DLOG("PMHaltWorker %p\n", OBFUSCATE(me
));
9207 me
->retain(); // thread holds extra retain
9208 if (KERN_SUCCESS
!= kernel_thread_start(&PMHaltWorker::main
, (void *) me
, &thread
)) {
9212 thread_deallocate(thread
);
9223 PMHaltWorker::free( void )
9225 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
9230 return OSObject::free();
9234 PMHaltWorker::main( void * arg
, wait_result_t waitResult
)
9236 PMHaltWorker
* me
= (PMHaltWorker
*) arg
;
9238 IOLockLock( gPMHaltLock
);
9240 me
->depth
= gPMHaltDepth
;
9241 IOLockUnlock( gPMHaltLock
);
9243 while (me
->depth
>= 0) {
9244 PMHaltWorker::work( me
);
9246 IOLockLock( gPMHaltLock
);
9247 if (++gPMHaltIdleCount
>= gPMHaltBusyCount
) {
9248 // This is the last thread to finish work on this level,
9249 // inform everyone to start working on next lower level.
9251 me
->depth
= gPMHaltDepth
;
9252 gPMHaltIdleCount
= 0;
9253 thread_wakeup((event_t
) &gPMHaltIdleCount
);
9255 // One or more threads are still working on this level,
9256 // this thread must wait.
9257 me
->depth
= gPMHaltDepth
- 1;
9259 IOLockSleep(gPMHaltLock
, &gPMHaltIdleCount
, THREAD_UNINT
);
9260 } while (me
->depth
!= gPMHaltDepth
);
9262 IOLockUnlock( gPMHaltLock
);
9265 // No more work to do, terminate thread
9266 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me
), me
->visits
);
9267 thread_wakeup( &gPMHaltDepth
);
9272 PMHaltWorker::work( PMHaltWorker
* me
)
9274 IOService
* service
;
9276 AbsoluteTime startTime
, elapsedTime
;
9284 // Claim an unit of work from the shared pool
9285 IOLockLock( gPMHaltLock
);
9286 inner
= (OSSet
*)gPMHaltArray
->getObject(me
->depth
);
9288 service
= OSDynamicCast(IOService
, inner
->getAnyObject());
9291 inner
->removeObject(service
);
9294 IOLockUnlock( gPMHaltLock
);
9296 break; // no more work at this depth
9298 clock_get_uptime(&startTime
);
9300 if (!service
->isInactive() &&
9301 service
->setProperty(gPMHaltClientAcknowledgeKey
, me
)) {
9302 IOLockLock(me
->lock
);
9303 me
->startTime
= startTime
;
9304 me
->service
= service
;
9305 me
->timeout
= false;
9306 IOLockUnlock(me
->lock
);
9308 service
->systemWillShutdown( gPMHaltMessageType
);
9310 // Wait for driver acknowledgement
9311 IOLockLock(me
->lock
);
9312 while (service
->getProperty(gPMHaltClientAcknowledgeKey
)) {
9313 IOLockSleep(me
->lock
, me
, THREAD_UNINT
);
9316 timeout
= me
->timeout
;
9317 IOLockUnlock(me
->lock
);
9320 deltaTime
= computeDeltaTimeMS(&startTime
, &elapsedTime
);
9321 if ((deltaTime
> kPMHaltTimeoutMS
) || timeout
) {
9322 LOG("%s driver %s (0x%llx) took %u ms\n",
9323 (gPMHaltMessageType
== kIOMessageSystemWillPowerOff
) ?
9324 "PowerOff" : "Restart",
9325 service
->getName(), service
->getRegistryEntryID(),
9326 (uint32_t) deltaTime
);
9327 halt_log_enter("PowerOff/Restart handler completed",
9328 OSMemberFunctionCast(const void *, service
, &IOService::systemWillShutdown
),
9338 PMHaltWorker::checkTimeout( PMHaltWorker
* me
, AbsoluteTime
* now
)
9341 AbsoluteTime startTime
;
9342 AbsoluteTime endTime
;
9346 IOLockLock(me
->lock
);
9347 if (me
->service
&& !me
->timeout
) {
9348 startTime
= me
->startTime
;
9350 if (CMP_ABSOLUTETIME(&endTime
, &startTime
) > 0) {
9351 SUB_ABSOLUTETIME(&endTime
, &startTime
);
9352 absolutetime_to_nanoseconds(endTime
, &nano
);
9354 if (nano
> 3000000000ULL) {
9357 halt_log_enter("PowerOff/Restart still waiting on handler",
9358 OSMemberFunctionCast(const void *, me
->service
, &IOService::systemWillShutdown
),
9360 MSG("%s still waiting on %s\n",
9361 (gPMHaltMessageType
== kIOMessageSystemWillPowerOff
) ? "PowerOff" : "Restart",
9362 me
->service
->getName());
9365 IOLockUnlock(me
->lock
);
9368 //******************************************************************************
9369 // acknowledgeSystemWillShutdown
9371 // Acknowledgement from drivers that they have prepared for shutdown/restart.
9372 //******************************************************************************
9375 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService
* from
)
9377 PMHaltWorker
* worker
;
9384 //DLOG("%s acknowledged\n", from->getName());
9385 prop
= from
->copyProperty( gPMHaltClientAcknowledgeKey
);
9387 worker
= (PMHaltWorker
*) prop
;
9388 IOLockLock(worker
->lock
);
9389 from
->removeProperty( gPMHaltClientAcknowledgeKey
);
9390 thread_wakeup((event_t
) worker
);
9391 IOLockUnlock(worker
->lock
);
9394 DLOG("%s acknowledged without worker property\n",
9400 //******************************************************************************
9401 // notifySystemShutdown
9403 // Notify all objects in PM tree that system will shutdown or restart
9404 //******************************************************************************
9407 notifySystemShutdown( IOService
* root
, uint32_t messageType
)
9409 #define PLACEHOLDER ((OSSet *)gPMHaltArray)
9410 IORegistryIterator
* iter
;
9411 IORegistryEntry
* entry
;
9414 PMHaltWorker
* workers
[kPMHaltMaxWorkers
];
9415 AbsoluteTime deadline
;
9416 unsigned int totalNodes
= 0;
9418 unsigned int rootDepth
;
9419 unsigned int numWorkers
;
9425 DLOG("%s msgType = 0x%x\n", __FUNCTION__
, messageType
);
9427 baseFunc
= OSMemberFunctionCast(void *, root
, &IOService::systemWillShutdown
);
9429 // Iterate the entire PM tree starting from root
9431 rootDepth
= root
->getDepth( gIOPowerPlane
);
9436 // debug - for repeated test runs
9437 while (PMHaltWorker::metaClass
->getInstanceCount()) {
9441 if (!gPMHaltArray
) {
9442 gPMHaltArray
= OSArray::withCapacity(40);
9443 if (!gPMHaltArray
) {
9447 gPMHaltArray
->flushCollection();
9451 gPMHaltLock
= IOLockAlloc();
9457 if (!gPMHaltClientAcknowledgeKey
) {
9458 gPMHaltClientAcknowledgeKey
=
9459 OSSymbol::withCStringNoCopy("PMShutdown");
9460 if (!gPMHaltClientAcknowledgeKey
) {
9465 gPMHaltMessageType
= messageType
;
9467 // Depth-first walk of PM plane
9469 iter
= IORegistryIterator::iterateOver(
9470 root
, gIOPowerPlane
, kIORegistryIterateRecursively
);
9473 while ((entry
= iter
->getNextObject())) {
9474 node
= OSDynamicCast(IOService
, entry
);
9480 OSMemberFunctionCast(void *, node
, &IOService::systemWillShutdown
)) {
9484 depth
= node
->getDepth( gIOPowerPlane
);
9485 if (depth
<= rootDepth
) {
9491 // adjust to zero based depth
9492 depth
-= (rootDepth
+ 1);
9494 // gPMHaltArray is an array of containers, each container
9495 // refers to nodes with the same depth.
9497 count
= gPMHaltArray
->getCount();
9498 while (depth
>= count
) {
9499 // expand array and insert placeholders
9500 gPMHaltArray
->setObject(PLACEHOLDER
);
9503 count
= gPMHaltArray
->getCount();
9504 if (depth
< count
) {
9505 inner
= (OSSet
*)gPMHaltArray
->getObject(depth
);
9506 if (inner
== PLACEHOLDER
) {
9507 inner
= OSSet::withCapacity(40);
9509 gPMHaltArray
->replaceObject(depth
, inner
);
9514 // PM nodes that appear more than once in the tree will have
9515 // the same depth, OSSet will refuse to add the node twice.
9517 ok
= inner
->setObject(node
);
9521 DLOG("Skipped PM node %s\n", node
->getName());
9528 for (int i
= 0; (inner
= (OSSet
*)gPMHaltArray
->getObject(i
)); i
++) {
9530 if (inner
!= PLACEHOLDER
) {
9531 count
= inner
->getCount();
9533 DLOG("Nodes at depth %u = %u\n", i
, count
);
9536 // strip placeholders (not all depths are populated)
9538 for (int i
= 0; (inner
= (OSSet
*)gPMHaltArray
->getObject(i
));) {
9539 if (inner
== PLACEHOLDER
) {
9540 gPMHaltArray
->removeObject(i
);
9543 count
= inner
->getCount();
9544 if (count
> numWorkers
) {
9547 totalNodes
+= count
;
9551 if (gPMHaltArray
->getCount() == 0 || !numWorkers
) {
9555 gPMHaltBusyCount
= 0;
9556 gPMHaltIdleCount
= 0;
9557 gPMHaltDepth
= gPMHaltArray
->getCount() - 1;
9559 // Create multiple workers (and threads)
9561 if (numWorkers
> kPMHaltMaxWorkers
) {
9562 numWorkers
= kPMHaltMaxWorkers
;
9565 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
9566 totalNodes
, gPMHaltArray
->getCount(), numWorkers
);
9568 for (unsigned int i
= 0; i
< numWorkers
; i
++) {
9569 workers
[i
] = PMHaltWorker::worker();
9572 // Wait for workers to exhaust all available work
9574 IOLockLock(gPMHaltLock
);
9575 while (gPMHaltDepth
>= 0) {
9576 clock_interval_to_deadline(1000, kMillisecondScale
, &deadline
);
9578 waitResult
= IOLockSleepDeadline(
9579 gPMHaltLock
, &gPMHaltDepth
, deadline
, THREAD_UNINT
);
9580 if (THREAD_TIMED_OUT
== waitResult
) {
9582 clock_get_uptime(&now
);
9584 IOLockUnlock(gPMHaltLock
);
9585 for (unsigned int i
= 0; i
< numWorkers
; i
++) {
9587 PMHaltWorker::checkTimeout(workers
[i
], &now
);
9590 IOLockLock(gPMHaltLock
);
9593 IOLockUnlock(gPMHaltLock
);
9595 // Release all workers
9597 for (unsigned int i
= 0; i
< numWorkers
; i
++) {
9599 workers
[i
]->release();
9601 // worker also retained by it's own thread
9605 DLOG("%s done\n", __FUNCTION__
);
9610 // MARK: Kernel Assertion
9612 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
9614 IOPMDriverAssertionID
9615 IOPMrootDomain::createPMAssertion(
9616 IOPMDriverAssertionType whichAssertionBits
,
9617 IOPMDriverAssertionLevel assertionLevel
,
9618 IOService
*ownerService
,
9619 const char *ownerDescription
)
9622 IOPMDriverAssertionID newAssertion
;
9624 if (!pmAssertions
) {
9628 ret
= pmAssertions
->createAssertion(whichAssertionBits
, assertionLevel
, ownerService
, ownerDescription
, &newAssertion
);
9630 if (kIOReturnSuccess
== ret
) {
9631 return newAssertion
;
9638 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion
)
9640 if (!pmAssertions
) {
9641 return kIOReturnInternalError
;
9644 return pmAssertions
->releaseAssertion(releaseAssertion
);
9649 IOPMrootDomain::setPMAssertionLevel(
9650 IOPMDriverAssertionID assertionID
,
9651 IOPMDriverAssertionLevel assertionLevel
)
9653 return pmAssertions
->setAssertionLevel(assertionID
, assertionLevel
);
9656 IOPMDriverAssertionLevel
9657 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion
)
9659 IOPMDriverAssertionType sysLevels
;
9661 if (!pmAssertions
|| whichAssertion
== 0) {
9662 return kIOPMDriverAssertionLevelOff
;
9665 sysLevels
= pmAssertions
->getActivatedAssertions();
9667 // Check that every bit set in argument 'whichAssertion' is asserted
9668 // in the aggregate bits.
9669 if ((sysLevels
& whichAssertion
) == whichAssertion
) {
9670 return kIOPMDriverAssertionLevelOn
;
9672 return kIOPMDriverAssertionLevelOff
;
9677 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels
)
9679 if (!pmAssertions
) {
9680 return kIOReturnNotFound
;
9683 return pmAssertions
->setUserAssertionLevels(inLevels
);
9687 IOPMrootDomain::serializeProperties( OSSerialize
* s
) const
9690 pmAssertions
->publishProperties();
9692 return IOService::serializeProperties(s
);
9696 IOPMrootDomain::copyProperty( const char * aKey
) const
9698 OSObject
*obj
= NULL
;
9699 obj
= IOService::copyProperty(aKey
);
9705 if (!strncmp(aKey
, kIOPMSleepWakeWdogRebootKey
,
9706 sizeof(kIOPMSleepWakeWdogRebootKey
))) {
9707 if (swd_flags
& SWD_BOOT_BY_SW_WDOG
) {
9708 return kOSBooleanTrue
;
9710 return kOSBooleanFalse
;
9714 if (!strncmp(aKey
, kIOPMSleepWakeWdogLogsValidKey
,
9715 sizeof(kIOPMSleepWakeWdogLogsValidKey
))) {
9716 if (swd_flags
& SWD_VALID_LOGS
) {
9717 return kOSBooleanTrue
;
9719 return kOSBooleanFalse
;
9724 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey'
9725 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
9726 * issued by DisplayWrangler on darkwake.
9728 if (!strcmp(aKey
, "DesktopMode")) {
9730 return kOSBooleanTrue
;
9732 return kOSBooleanFalse
;
9735 if (!strcmp(aKey
, "DisplayIdleForDemandSleep")) {
9736 if (displayIdleForDemandSleep
) {
9737 return kOSBooleanTrue
;
9739 return kOSBooleanFalse
;
9743 if (!strcmp(aKey
, kIOPMDriverWakeEventsKey
)) {
9744 OSArray
* array
= NULL
;
9746 if (_systemWakeEventsArray
&& _systemWakeEventsArray
->getCount()) {
9747 OSCollection
*collection
= _systemWakeEventsArray
->copyCollection();
9748 if (collection
&& !(array
= OSDynamicCast(OSArray
, collection
))) {
9749 collection
->release();
9756 if (!strcmp(aKey
, kIOPMSleepStatisticsAppsKey
)) {
9757 OSArray
* array
= NULL
;
9758 IOLockLock(pmStatsLock
);
9759 if (pmStatsAppResponses
&& pmStatsAppResponses
->getCount()) {
9760 OSCollection
*collection
= pmStatsAppResponses
->copyCollection();
9761 if (collection
&& !(array
= OSDynamicCast(OSArray
, collection
))) {
9762 collection
->release();
9764 pmStatsAppResponses
->flushCollection();
9766 IOLockUnlock(pmStatsLock
);
9770 if (!strcmp(aKey
, kIOPMIdleSleepPreventersKey
)) {
9771 OSArray
*idleSleepList
= NULL
;
9772 gRootDomain
->copySleepPreventersList(&idleSleepList
, NULL
);
9773 return idleSleepList
;
9776 if (!strcmp(aKey
, kIOPMSystemSleepPreventersKey
)) {
9777 OSArray
*systemSleepList
= NULL
;
9778 gRootDomain
->copySleepPreventersList(NULL
, &systemSleepList
);
9779 return systemSleepList
;
9782 if (!strcmp(aKey
, kIOPMIdleSleepPreventersWithIDKey
)) {
9783 OSArray
*idleSleepList
= NULL
;
9784 gRootDomain
->copySleepPreventersListWithID(&idleSleepList
, NULL
);
9785 return idleSleepList
;
9788 if (!strcmp(aKey
, kIOPMSystemSleepPreventersWithIDKey
)) {
9789 OSArray
*systemSleepList
= NULL
;
9790 gRootDomain
->copySleepPreventersListWithID(NULL
, &systemSleepList
);
9791 return systemSleepList
;
9797 // MARK: Wake Event Reporting
9800 IOPMrootDomain::copyWakeReasonString( char * outBuf
, size_t bufSize
)
9803 strlcpy(outBuf
, gWakeReasonString
, bufSize
);
9807 //******************************************************************************
9808 // acceptSystemWakeEvents
9810 // Private control for the acceptance of driver wake event claims.
9811 //******************************************************************************
9814 IOPMrootDomain::acceptSystemWakeEvents( bool accept
)
9816 bool logWakeReason
= false;
9820 if (!_systemWakeEventsArray
) {
9821 _systemWakeEventsArray
= OSArray::withCapacity(4);
9823 _acceptSystemWakeEvents
= (_systemWakeEventsArray
!= NULL
);
9824 if (!(_aotNow
&& (kIOPMWakeEventAOTExitFlags
& _aotPendingFlags
))) {
9825 gWakeReasonString
[0] = '\0';
9826 if (_systemWakeEventsArray
) {
9827 _systemWakeEventsArray
->flushCollection();
9831 _acceptSystemWakeEvents
= false;
9833 logWakeReason
= gWakeReasonSysctlRegistered
;
9835 static int panic_allowed
= -1;
9837 if ((panic_allowed
== -1) &&
9838 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed
, sizeof(panic_allowed
)) == false)) {
9842 if (panic_allowed
) {
9844 // Panic if wake reason is null or empty
9845 for (i
= 0; (i
< strlen(gWakeReasonString
)); i
++) {
9846 if ((gWakeReasonString
[i
] != ' ') && (gWakeReasonString
[i
] != '\t')) {
9850 if (i
>= strlen(gWakeReasonString
)) {
9851 panic("Wake reason is empty\n");
9859 if (logWakeReason
) {
9860 MSG("system wake events:%s\n", gWakeReasonString
);
9864 //******************************************************************************
9865 // claimSystemWakeEvent
9867 // For a driver to claim a device is the source/conduit of a system wake event.
9868 //******************************************************************************
9871 IOPMrootDomain::claimSystemWakeEvent(
9874 const char * reason
,
9875 OSObject
* details
)
9877 const OSSymbol
* deviceName
= NULL
;
9878 OSNumber
* deviceRegId
= NULL
;
9879 OSNumber
* claimTime
= NULL
;
9880 OSData
* flagsData
= NULL
;
9881 OSString
* reasonString
= NULL
;
9882 OSDictionary
* d
= NULL
;
9887 pmEventTimeStamp(×tamp
);
9889 if (!device
|| !reason
) {
9893 IOOptionBits aotFlags
= 0;
9894 bool needAOTEvaluate
= FALSE
;
9896 if (kIOPMAOTModeAddEventFlags
& _aotMode
) {
9897 if (!strcmp("hold", reason
)
9898 || !strcmp("help", reason
)
9899 || !strcmp("menu", reason
)
9900 || !strcmp("stockholm", reason
)
9901 || !strcmp("ringer", reason
)
9902 || !strcmp("ringerab", reason
)
9903 || !strcmp("smc0", reason
)
9904 || !strcmp("AOP.RTPWakeupAP", reason
)
9905 || !strcmp("BT.OutboxNotEmpty", reason
)
9906 || !strcmp("WL.OutboxNotEmpty", reason
)) {
9907 flags
|= kIOPMWakeEventAOTExit
;
9911 #if DEVELOPMENT || DEBUG
9912 if (_aotLingerTime
&& !strcmp("rtc", reason
)) {
9913 flags
|= kIOPMWakeEventAOTPossibleExit
;
9915 #endif /* DEVELOPMENT || DEBUG */
9917 deviceName
= device
->copyName(gIOServicePlane
);
9918 deviceRegId
= OSNumber::withNumber(device
->getRegistryEntryID(), 64);
9919 claimTime
= OSNumber::withNumber(timestamp
, 64);
9920 flagsData
= OSData::withBytes(&flags
, sizeof(flags
));
9921 reasonString
= OSString::withCString(reason
);
9922 d
= OSDictionary::withCapacity(5 + (details
? 1 : 0));
9923 if (!deviceName
|| !deviceRegId
|| !claimTime
|| !flagsData
|| !reasonString
) {
9927 d
->setObject(gIONameKey
, deviceName
);
9928 d
->setObject(gIORegistryEntryIDKey
, deviceRegId
);
9929 d
->setObject(kIOPMWakeEventTimeKey
, claimTime
);
9930 d
->setObject(kIOPMWakeEventFlagsKey
, flagsData
);
9931 d
->setObject(kIOPMWakeEventReasonKey
, reasonString
);
9933 d
->setObject(kIOPMWakeEventDetailsKey
, details
);
9937 addWakeReason
= _acceptSystemWakeEvents
;
9939 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason
, deviceName
->getCStringNoCopy(), (int)flags
, _aotPendingFlags
, _aotReadyToFullWake
);
9941 aotFlags
= (kIOPMWakeEventAOTFlags
& flags
);
9942 aotFlags
= (aotFlags
& ~_aotPendingFlags
);
9943 needAOTEvaluate
= false;
9944 if (_aotNow
&& aotFlags
) {
9945 if (kIOPMWakeEventAOTPossibleExit
& flags
) {
9946 _aotMetrics
->possibleCount
++;
9948 if (kIOPMWakeEventAOTConfirmedPossibleExit
& flags
) {
9949 _aotMetrics
->confirmedPossibleCount
++;
9951 if (kIOPMWakeEventAOTRejectedPossibleExit
& flags
) {
9952 _aotMetrics
->rejectedPossibleCount
++;
9954 if (kIOPMWakeEventAOTExpiredPossibleExit
& flags
) {
9955 _aotMetrics
->expiredPossibleCount
++;
9958 _aotPendingFlags
|= aotFlags
;
9959 addWakeReason
= _aotNow
&& _systemWakeEventsArray
&& ((kIOPMWakeEventAOTExitFlags
& aotFlags
));
9960 needAOTEvaluate
= _aotReadyToFullWake
;
9963 if (!gWakeReasonSysctlRegistered
) {
9964 // Lazy registration until the platform driver stops registering
9966 gWakeReasonSysctlRegistered
= true;
9968 sysctl_register_oid(&sysctl__kern_wakereason
);
9971 if (addWakeReason
) {
9972 ok
= _systemWakeEventsArray
->setObject(d
);
9973 if (gWakeReasonString
[0] != '\0') {
9974 strlcat(gWakeReasonString
, " ", sizeof(gWakeReasonString
));
9976 strlcat(gWakeReasonString
, reason
, sizeof(gWakeReasonString
));
9980 if (needAOTEvaluate
) {
9986 deviceName
->release();
9989 deviceRegId
->release();
9992 claimTime
->release();
9995 flagsData
->release();
9998 reasonString
->release();
10005 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10008 // MARK: PMSettingHandle
10010 OSDefineMetaClassAndStructors( PMSettingHandle
, OSObject
)
10013 PMSettingHandle::free( void )
10016 pmso
->clientHandleFreed();
10025 // MARK: PMSettingObject
10028 #define super OSObject
10029 OSDefineMetaClassAndFinalStructors( PMSettingObject
, OSObject
)
10032 * Static constructor/initializer for PMSettingObject
10034 PMSettingObject
*PMSettingObject::pmSettingObject(
10035 IOPMrootDomain
* parent_arg
,
10036 IOPMSettingControllerCallback handler_arg
,
10037 OSObject
* target_arg
,
10038 uintptr_t refcon_arg
,
10039 uint32_t supportedPowerSources
,
10040 const OSSymbol
* settings
[],
10041 OSObject
* *handle_obj
)
10043 uint32_t settingCount
= 0;
10044 PMSettingObject
*pmso
= NULL
;
10045 PMSettingHandle
*pmsh
= NULL
;
10047 if (!parent_arg
|| !handler_arg
|| !settings
|| !handle_obj
) {
10051 // count OSSymbol entries in NULL terminated settings array
10052 while (settings
[settingCount
]) {
10055 if (0 == settingCount
) {
10059 pmso
= new PMSettingObject
;
10060 if (!pmso
|| !pmso
->init()) {
10064 pmsh
= new PMSettingHandle
;
10065 if (!pmsh
|| !pmsh
->init()) {
10069 queue_init(&pmso
->calloutQueue
);
10070 pmso
->parent
= parent_arg
;
10071 pmso
->func
= handler_arg
;
10072 pmso
->target
= target_arg
;
10073 pmso
->refcon
= refcon_arg
;
10074 pmso
->settingCount
= settingCount
;
10076 pmso
->retain(); // handle holds a retain on pmso
10080 pmso
->publishedFeatureID
= (uint32_t *)IOMalloc(sizeof(uint32_t) * settingCount
);
10081 if (pmso
->publishedFeatureID
) {
10082 for (unsigned int i
= 0; i
< settingCount
; i
++) {
10083 // Since there is now at least one listener to this setting, publish
10084 // PM root domain support for it.
10085 parent_arg
->publishPMSetting( settings
[i
],
10086 supportedPowerSources
, &pmso
->publishedFeatureID
[i
] );
10090 *handle_obj
= pmsh
;
10104 PMSettingObject::free( void )
10106 if (publishedFeatureID
) {
10107 for (uint32_t i
= 0; i
< settingCount
; i
++) {
10108 if (publishedFeatureID
[i
]) {
10109 parent
->removePublishedFeature( publishedFeatureID
[i
] );
10113 IOFree(publishedFeatureID
, sizeof(uint32_t) * settingCount
);
10120 PMSettingObject::dispatchPMSetting( const OSSymbol
* type
, OSObject
* object
)
10122 (*func
)(target
, type
, object
, refcon
);
10126 PMSettingObject::clientHandleFreed( void )
10128 parent
->deregisterPMSettingObject(this);
10132 // MARK: PMAssertionsTracker
10134 //*********************************************************************************
10135 //*********************************************************************************
10136 //*********************************************************************************
10137 // class PMAssertionsTracker Implementation
10139 #define kAssertUniqueIDStart 500
10141 PMAssertionsTracker
*
10142 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain
*rootDomain
)
10144 PMAssertionsTracker
*myself
;
10146 myself
= new PMAssertionsTracker
;
10150 myself
->owner
= rootDomain
;
10151 myself
->issuingUniqueID
= kAssertUniqueIDStart
;
10152 myself
->assertionsArray
= OSArray::withCapacity(5);
10153 myself
->assertionsKernel
= 0;
10154 myself
->assertionsUser
= 0;
10155 myself
->assertionsCombined
= 0;
10156 myself
->assertionsArrayLock
= IOLockAlloc();
10157 myself
->tabulateProducerCount
= myself
->tabulateConsumerCount
= 0;
10159 if (!myself
->assertionsArray
|| !myself
->assertionsArrayLock
) {
10168 * - Update assertionsKernel to reflect the state of all
10169 * assertions in the kernel.
10170 * - Update assertionsCombined to reflect both kernel & user space.
10173 PMAssertionsTracker::tabulate(void)
10177 PMAssertStruct
*_a
= NULL
;
10180 IOPMDriverAssertionType oldKernel
= assertionsKernel
;
10181 IOPMDriverAssertionType oldCombined
= assertionsCombined
;
10185 assertionsKernel
= 0;
10186 assertionsCombined
= 0;
10188 if (!assertionsArray
) {
10192 if ((count
= assertionsArray
->getCount())) {
10193 for (i
= 0; i
< count
; i
++) {
10194 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
10196 _a
= (PMAssertStruct
*)_d
->getBytesNoCopy();
10197 if (_a
&& (kIOPMDriverAssertionLevelOn
== _a
->level
)) {
10198 assertionsKernel
|= _a
->assertionBits
;
10204 tabulateProducerCount
++;
10205 assertionsCombined
= assertionsKernel
| assertionsUser
;
10207 if ((assertionsKernel
!= oldKernel
) ||
10208 (assertionsCombined
!= oldCombined
)) {
10209 owner
->evaluateAssertions(assertionsCombined
, oldCombined
);
10214 PMAssertionsTracker::publishProperties( void )
10216 OSArray
*assertionsSummary
= NULL
;
10218 if (tabulateConsumerCount
!= tabulateProducerCount
) {
10219 IOLockLock(assertionsArrayLock
);
10221 tabulateConsumerCount
= tabulateProducerCount
;
10223 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
10225 assertionsSummary
= copyAssertionsArray();
10226 if (assertionsSummary
) {
10227 owner
->setProperty(kIOPMAssertionsDriverDetailedKey
, assertionsSummary
);
10228 assertionsSummary
->release();
10230 owner
->removeProperty(kIOPMAssertionsDriverDetailedKey
);
10233 /* Publish the IOPMrootDomain property "DriverPMAssertions"
10235 owner
->setProperty(kIOPMAssertionsDriverKey
, assertionsKernel
, 64);
10237 IOLockUnlock(assertionsArrayLock
);
10241 PMAssertionsTracker::PMAssertStruct
*
10242 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id
, int *index
)
10244 PMAssertStruct
*_a
= NULL
;
10250 if (assertionsArray
10251 && (count
= assertionsArray
->getCount())) {
10252 for (i
= 0; i
< count
; i
++) {
10253 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
10255 _a
= (PMAssertStruct
*)_d
->getBytesNoCopy();
10256 if (_a
&& (_id
== _a
->id
)) {
10274 /* PMAssertionsTracker::handleCreateAssertion
10275 * Perform assertion work on the PM workloop. Do not call directly.
10278 PMAssertionsTracker::handleCreateAssertion(OSData
*newAssertion
)
10282 if (newAssertion
) {
10283 IOLockLock(assertionsArrayLock
);
10284 assertionsArray
->setObject(newAssertion
);
10285 IOLockUnlock(assertionsArrayLock
);
10286 newAssertion
->release();
10290 return kIOReturnSuccess
;
10293 /* PMAssertionsTracker::createAssertion
10294 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
10298 PMAssertionsTracker::createAssertion(
10299 IOPMDriverAssertionType which
,
10300 IOPMDriverAssertionLevel level
,
10301 IOService
*serviceID
,
10302 const char *whoItIs
,
10303 IOPMDriverAssertionID
*outID
)
10305 OSData
*dataStore
= NULL
;
10306 PMAssertStruct track
;
10308 // Warning: trillions and trillions of created assertions may overflow the unique ID.
10309 track
.id
= OSIncrementAtomic64((SInt64
*) &issuingUniqueID
);
10310 track
.level
= level
;
10311 track
.assertionBits
= which
;
10312 track
.ownerString
= whoItIs
? OSSymbol::withCString(whoItIs
):NULL
;
10313 track
.ownerService
= serviceID
;
10314 track
.registryEntryID
= serviceID
? serviceID
->getRegistryEntryID():0;
10315 track
.modifiedTime
= 0;
10316 pmEventTimeStamp(&track
.createdTime
);
10318 dataStore
= OSData::withBytes(&track
, sizeof(PMAssertStruct
));
10320 if (track
.ownerString
) {
10321 track
.ownerString
->release();
10323 return kIOReturnNoMemory
;
10328 if (owner
&& owner
->pmPowerStateQueue
) {
10329 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionCreate
, (void *)dataStore
);
10332 return kIOReturnSuccess
;
10335 /* PMAssertionsTracker::handleReleaseAssertion
10336 * Runs in PM workloop. Do not call directly.
10339 PMAssertionsTracker::handleReleaseAssertion(
10340 IOPMDriverAssertionID _id
)
10345 PMAssertStruct
*assertStruct
= detailsForID(_id
, &index
);
10347 if (!assertStruct
) {
10348 return kIOReturnNotFound
;
10351 IOLockLock(assertionsArrayLock
);
10352 if (assertStruct
->ownerString
) {
10353 assertStruct
->ownerString
->release();
10356 assertionsArray
->removeObject(index
);
10357 IOLockUnlock(assertionsArrayLock
);
10360 return kIOReturnSuccess
;
10363 /* PMAssertionsTracker::releaseAssertion
10364 * Releases an assertion and affects system behavior if appropiate.
10365 * Actual work happens on PM workloop.
10368 PMAssertionsTracker::releaseAssertion(
10369 IOPMDriverAssertionID _id
)
10371 if (owner
&& owner
->pmPowerStateQueue
) {
10372 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionRelease
, NULL
, _id
);
10374 return kIOReturnSuccess
;
10377 /* PMAssertionsTracker::handleSetAssertionLevel
10378 * Runs in PM workloop. Do not call directly.
10381 PMAssertionsTracker::handleSetAssertionLevel(
10382 IOPMDriverAssertionID _id
,
10383 IOPMDriverAssertionLevel _level
)
10385 PMAssertStruct
*assertStruct
= detailsForID(_id
, NULL
);
10389 if (!assertStruct
) {
10390 return kIOReturnNotFound
;
10393 IOLockLock(assertionsArrayLock
);
10394 pmEventTimeStamp(&assertStruct
->modifiedTime
);
10395 assertStruct
->level
= _level
;
10396 IOLockUnlock(assertionsArrayLock
);
10399 return kIOReturnSuccess
;
10402 /* PMAssertionsTracker::setAssertionLevel
10405 PMAssertionsTracker::setAssertionLevel(
10406 IOPMDriverAssertionID _id
,
10407 IOPMDriverAssertionLevel _level
)
10409 if (owner
&& owner
->pmPowerStateQueue
) {
10410 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionSetLevel
,
10411 (void *)(uintptr_t)_level
, _id
);
10414 return kIOReturnSuccess
;
10418 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0
)
10420 IOPMDriverAssertionType new_user_levels
= *(IOPMDriverAssertionType
*) arg0
;
10424 if (new_user_levels
!= assertionsUser
) {
10425 assertionsUser
= new_user_levels
;
10426 DLOG("assertionsUser 0x%llx\n", assertionsUser
);
10430 return kIOReturnSuccess
;
10434 PMAssertionsTracker::setUserAssertionLevels(
10435 IOPMDriverAssertionType new_user_levels
)
10437 if (gIOPMWorkLoop
) {
10438 gIOPMWorkLoop
->runAction(
10439 OSMemberFunctionCast(
10440 IOWorkLoop::Action
,
10442 &PMAssertionsTracker::handleSetUserAssertionLevels
),
10444 (void *) &new_user_levels
, NULL
, NULL
, NULL
);
10447 return kIOReturnSuccess
;
10452 PMAssertionsTracker::copyAssertionsArray(void)
10456 OSArray
*outArray
= NULL
;
10458 if (!assertionsArray
||
10459 (0 == (count
= assertionsArray
->getCount())) ||
10460 (NULL
== (outArray
= OSArray::withCapacity(count
)))) {
10464 for (i
= 0; i
< count
; i
++) {
10465 PMAssertStruct
*_a
= NULL
;
10467 OSDictionary
*details
= NULL
;
10469 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
10470 if (_d
&& (_a
= (PMAssertStruct
*)_d
->getBytesNoCopy())) {
10471 OSNumber
*_n
= NULL
;
10473 details
= OSDictionary::withCapacity(7);
10478 outArray
->setObject(details
);
10479 details
->release();
10481 _n
= OSNumber::withNumber(_a
->id
, 64);
10483 details
->setObject(kIOPMDriverAssertionIDKey
, _n
);
10486 _n
= OSNumber::withNumber(_a
->createdTime
, 64);
10488 details
->setObject(kIOPMDriverAssertionCreatedTimeKey
, _n
);
10491 _n
= OSNumber::withNumber(_a
->modifiedTime
, 64);
10493 details
->setObject(kIOPMDriverAssertionModifiedTimeKey
, _n
);
10496 _n
= OSNumber::withNumber((uintptr_t)_a
->registryEntryID
, 64);
10498 details
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, _n
);
10501 _n
= OSNumber::withNumber(_a
->level
, 64);
10503 details
->setObject(kIOPMDriverAssertionLevelKey
, _n
);
10506 _n
= OSNumber::withNumber(_a
->assertionBits
, 64);
10508 details
->setObject(kIOPMDriverAssertionAssertedKey
, _n
);
10512 if (_a
->ownerString
) {
10513 details
->setObject(kIOPMDriverAssertionOwnerStringKey
, _a
->ownerString
);
10522 IOPMDriverAssertionType
10523 PMAssertionsTracker::getActivatedAssertions(void)
10525 return assertionsCombined
;
10528 IOPMDriverAssertionLevel
10529 PMAssertionsTracker::getAssertionLevel(
10530 IOPMDriverAssertionType type
)
10532 if (type
&& ((type
& assertionsKernel
) == assertionsKernel
)) {
10533 return kIOPMDriverAssertionLevelOn
;
10535 return kIOPMDriverAssertionLevelOff
;
10539 //*********************************************************************************
10540 //*********************************************************************************
10541 //*********************************************************************************
10545 pmEventTimeStamp(uint64_t *recordTS
)
10548 clock_usec_t tusec
;
10554 // We assume tsec fits into 32 bits; 32 bits holds enough
10555 // seconds for 136 years since the epoch in 1970.
10556 clock_get_calendar_microtime(&tsec
, &tusec
);
10559 // Pack the sec & microsec calendar time into a uint64_t, for fun.
10561 *recordTS
|= (uint32_t)tusec
;
10562 *recordTS
|= ((uint64_t)tsec
<< 32);
10568 // MARK: IORootParent
10570 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10572 OSDefineMetaClassAndFinalStructors(IORootParent
, IOService
)
10574 // The reason that root domain needs a root parent is to facilitate demand
10575 // sleep, since a power change from the root parent cannot be vetoed.
10577 // The above statement is no longer true since root domain now performs
10578 // demand sleep using overrides. But root parent remains to avoid changing
10579 // the power tree stacking. Root parent is parked at the max power state.
10582 static IOPMPowerState patriarchPowerStates
[2] =
10584 {1, 0, ON_POWER
, 0, 0, 0, 0, 0, 0, 0, 0, 0},
10585 {1, 0, ON_POWER
, 0, 0, 0, 0, 0, 0, 0, 0, 0},
10589 IORootParent::initialize( void )
10592 gIOPMPSExternalConnectedKey
= OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey
);
10593 gIOPMPSExternalChargeCapableKey
= OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey
);
10594 gIOPMPSBatteryInstalledKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey
);
10595 gIOPMPSIsChargingKey
= OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey
);
10596 gIOPMPSAtWarnLevelKey
= OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey
);
10597 gIOPMPSAtCriticalLevelKey
= OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey
);
10598 gIOPMPSCurrentCapacityKey
= OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey
);
10599 gIOPMPSMaxCapacityKey
= OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey
);
10600 gIOPMPSDesignCapacityKey
= OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey
);
10601 gIOPMPSTimeRemainingKey
= OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey
);
10602 gIOPMPSAmperageKey
= OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey
);
10603 gIOPMPSVoltageKey
= OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey
);
10604 gIOPMPSCycleCountKey
= OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey
);
10605 gIOPMPSMaxErrKey
= OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey
);
10606 gIOPMPSAdapterInfoKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey
);
10607 gIOPMPSLocationKey
= OSSymbol::withCStringNoCopy(kIOPMPSLocationKey
);
10608 gIOPMPSErrorConditionKey
= OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey
);
10609 gIOPMPSManufacturerKey
= OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey
);
10610 gIOPMPSManufactureDateKey
= OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey
);
10611 gIOPMPSModelKey
= OSSymbol::withCStringNoCopy(kIOPMPSModelKey
);
10612 gIOPMPSSerialKey
= OSSymbol::withCStringNoCopy(kIOPMPSSerialKey
);
10613 gIOPMPSLegacyBatteryInfoKey
= OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey
);
10614 gIOPMPSBatteryHealthKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey
);
10615 gIOPMPSHealthConfidenceKey
= OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey
);
10616 gIOPMPSCapacityEstimatedKey
= OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey
);
10617 gIOPMPSBatteryChargeStatusKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey
);
10618 gIOPMPSBatteryTemperatureKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey
);
10619 gIOPMPSAdapterDetailsKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey
);
10620 gIOPMPSChargerConfigurationKey
= OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey
);
10621 gIOPMPSAdapterDetailsIDKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey
);
10622 gIOPMPSAdapterDetailsWattsKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey
);
10623 gIOPMPSAdapterDetailsRevisionKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey
);
10624 gIOPMPSAdapterDetailsSerialNumberKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey
);
10625 gIOPMPSAdapterDetailsFamilyKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey
);
10626 gIOPMPSAdapterDetailsAmperageKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey
);
10627 gIOPMPSAdapterDetailsDescriptionKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey
);
10628 gIOPMPSAdapterDetailsPMUConfigurationKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey
);
10629 gIOPMPSAdapterDetailsSourceIDKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey
);
10630 gIOPMPSAdapterDetailsErrorFlagsKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey
);
10631 gIOPMPSAdapterDetailsSharedSourceKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey
);
10632 gIOPMPSAdapterDetailsCloakedKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey
);
10633 gIOPMPSInvalidWakeSecondsKey
= OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey
);
10634 gIOPMPSPostChargeWaitSecondsKey
= OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey
);
10635 gIOPMPSPostDishargeWaitSecondsKey
= OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey
);
10639 IORootParent::start( IOService
* nub
)
10641 IOService::start(nub
);
10642 attachToParent( getRegistryRoot(), gIOPowerPlane
);
10644 registerPowerDriver(this, patriarchPowerStates
, 2);
10650 IORootParent::shutDownSystem( void )
10655 IORootParent::restartSystem( void )
10660 IORootParent::sleepSystem( void )
10665 IORootParent::dozeSystem( void )
10670 IORootParent::sleepToDoze( void )
10675 IORootParent::wakeSystem( void )
10680 IORootParent::copyProperty( const char * aKey
) const
10682 return IOService::copyProperty(aKey
);
10686 IOPMrootDomain::getWatchdogTimeout()
10688 if (gSwdSleepWakeTimeout
) {
10689 gSwdSleepTimeout
= gSwdWakeTimeout
= gSwdSleepWakeTimeout
;
10691 if ((pmTracer
->getTracePhase() < kIOPMTracePointSystemSleep
) ||
10692 (pmTracer
->getTracePhase() == kIOPMTracePointDarkWakeEntry
)) {
10693 return gSwdSleepTimeout
? gSwdSleepTimeout
: WATCHDOG_SLEEP_TIMEOUT
;
10695 return gSwdWakeTimeout
? gSwdWakeTimeout
: WATCHDOG_WAKE_TIMEOUT
;
10700 #if defined(__i386__) || defined(__x86_64__)
10702 IOPMrootDomain::restartWithStackshot()
10704 takeStackshot(true);
10706 return kIOReturnSuccess
;
10710 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger
)
10712 takeStackshot(wdogTrigger
);
10716 IOPMrootDomain::tracePhase2String(uint32_t tracePhase
, const char **phaseString
, const char **description
)
10718 switch (tracePhase
) {
10719 case kIOPMTracePointSleepStarted
:
10720 *phaseString
= "kIOPMTracePointSleepStarted";
10721 *description
= "starting sleep";
10724 case kIOPMTracePointSleepApplications
:
10725 *phaseString
= "kIOPMTracePointSleepApplications";
10726 *description
= "notifying applications";
10729 case kIOPMTracePointSleepPriorityClients
:
10730 *phaseString
= "kIOPMTracePointSleepPriorityClients";
10731 *description
= "notifying clients about upcoming system capability changes";
10734 case kIOPMTracePointSleepWillChangeInterests
:
10735 *phaseString
= "kIOPMTracePointSleepWillChangeInterests";
10736 *description
= "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
10739 case kIOPMTracePointSleepPowerPlaneDrivers
:
10740 *phaseString
= "kIOPMTracePointSleepPowerPlaneDrivers";
10741 *description
= "calling power state change callbacks";
10744 case kIOPMTracePointSleepDidChangeInterests
:
10745 *phaseString
= "kIOPMTracePointSleepDidChangeInterests";
10746 *description
= "calling rootDomain's clients about rootDomain's state changes";
10749 case kIOPMTracePointSleepCapabilityClients
:
10750 *phaseString
= "kIOPMTracePointSleepCapabilityClients";
10751 *description
= "notifying clients about current system capabilities";
10754 case kIOPMTracePointSleepPlatformActions
:
10755 *phaseString
= "kIOPMTracePointSleepPlatformActions";
10756 *description
= "calling Quiesce/Sleep action callbacks";
10759 case kIOPMTracePointSleepCPUs
:
10761 *phaseString
= "kIOPMTracePointSleepCPUs";
10762 #if defined(__i386__) || defined(__x86_64__)
10764 * We cannot use the getCPUNumber() method to get the cpu number, since
10765 * that cpu number is unrelated to the cpu number we need (we need the cpu
10766 * number as enumerated by the scheduler, NOT the CPU number enumerated
10767 * by ACPIPlatform as the CPUs are enumerated in MADT order).
10768 * Instead, pass the Mach processor pointer associated with the current
10769 * shutdown target so its associated cpu_id can be used in
10770 * processor_to_datastring.
10772 if (currentShutdownTarget
!= NULL
&&
10773 currentShutdownTarget
->getMachProcessor() != NULL
) {
10774 const char *sbuf
= processor_to_datastring("halting all non-boot CPUs",
10775 currentShutdownTarget
->getMachProcessor());
10776 *description
= sbuf
;
10778 *description
= "halting all non-boot CPUs";
10781 *description
= "halting all non-boot CPUs";
10785 case kIOPMTracePointSleepPlatformDriver
:
10786 *phaseString
= "kIOPMTracePointSleepPlatformDriver";
10787 *description
= "executing platform specific code";
10790 case kIOPMTracePointHibernate
:
10791 *phaseString
= "kIOPMTracePointHibernate";
10792 *description
= "writing the hibernation image";
10795 case kIOPMTracePointSystemSleep
:
10796 *phaseString
= "kIOPMTracePointSystemSleep";
10797 *description
= "in EFI/Bootrom after last point of entry to sleep";
10800 case kIOPMTracePointWakePlatformDriver
:
10801 *phaseString
= "kIOPMTracePointWakePlatformDriver";
10802 *description
= "executing platform specific code";
10806 case kIOPMTracePointWakePlatformActions
:
10807 *phaseString
= "kIOPMTracePointWakePlatformActions";
10808 *description
= "calling Wake action callbacks";
10811 case kIOPMTracePointWakeCPUs
:
10812 *phaseString
= "kIOPMTracePointWakeCPUs";
10813 *description
= "starting non-boot CPUs";
10816 case kIOPMTracePointWakeWillPowerOnClients
:
10817 *phaseString
= "kIOPMTracePointWakeWillPowerOnClients";
10818 *description
= "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
10821 case kIOPMTracePointWakeWillChangeInterests
:
10822 *phaseString
= "kIOPMTracePointWakeWillChangeInterests";
10823 *description
= "calling rootDomain's clients about upcoming rootDomain's state changes";
10826 case kIOPMTracePointWakeDidChangeInterests
:
10827 *phaseString
= "kIOPMTracePointWakeDidChangeInterests";
10828 *description
= "calling rootDomain's clients about completed rootDomain's state changes";
10831 case kIOPMTracePointWakePowerPlaneDrivers
:
10832 *phaseString
= "kIOPMTracePointWakePowerPlaneDrivers";
10833 *description
= "calling power state change callbacks";
10836 case kIOPMTracePointWakeCapabilityClients
:
10837 *phaseString
= "kIOPMTracePointWakeCapabilityClients";
10838 *description
= "informing clients about current system capabilities";
10841 case kIOPMTracePointWakeApplications
:
10842 *phaseString
= "kIOPMTracePointWakeApplications";
10843 *description
= "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
10846 case kIOPMTracePointDarkWakeEntry
:
10847 *phaseString
= "kIOPMTracePointDarkWakeEntry";
10848 *description
= "entering darkwake on way to sleep";
10851 case kIOPMTracePointDarkWakeExit
:
10852 *phaseString
= "kIOPMTracePointDarkWakeExit";
10853 *description
= "entering fullwake from darkwake";
10857 *phaseString
= NULL
;
10858 *description
= NULL
;
10863 IOPMrootDomain::saveFailureData2File()
10865 unsigned int len
= 0;
10866 char failureStr
[512];
10869 OSNumber
*statusCode
;
10870 uint64_t pmStatusCode
= 0;
10871 uint32_t phaseData
= 0;
10872 uint32_t phaseDetail
= 0;
10873 bool efiFailure
= false;
10875 statusCode
= OSDynamicCast(OSNumber
, getProperty(kIOPMSleepWakeFailureCodeKey
));
10877 pmStatusCode
= statusCode
->unsigned64BitValue();
10878 phaseData
= pmStatusCode
& 0xFFFFFFFF;
10879 phaseDetail
= (pmStatusCode
>> 32) & 0xFFFFFFFF;
10880 if ((phaseData
& 0xFF) == kIOPMTracePointSystemSleep
) {
10881 LOG("Sleep Wake failure in EFI\n");
10884 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
);
10885 len
= strlen(failureStr
);
10890 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic
, NULL
, &len
)) {
10891 swd_flags
|= SWD_BOOT_BY_SW_WDOG
;
10892 PERemoveNVRAMProperty(kIOSleepWakeFailurePanic
);
10893 // dump panic will handle saving nvram data
10897 /* Keeping this around for capturing data during power
10900 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString
, NULL
, &len
)) {
10901 DLOG("No sleep wake failure string\n");
10905 DLOG("Ignoring zero byte SleepWake failure string\n");
10909 // if PMStatus code is zero, delete stackshot and return
10911 if (((pmStatusCode
& 0xFFFFFFFF) & 0xFF) == 0) {
10912 // there was no sleep wake failure
10913 // this can happen if delete stackshot was called
10914 // before take stackshot completed. Let us delete any
10915 // sleep wake failure data in nvram
10916 DLOG("Deleting stackshot on successful wake\n");
10922 if (len
> sizeof(failureStr
)) {
10923 len
= sizeof(failureStr
);
10926 PEReadNVRAMProperty(kIOSleepWakeFailureString
, failureStr
, &len
);
10928 if (failureStr
[0] != 0) {
10929 error
= sleepWakeDebugSaveFile(kSleepWakeFailureStringFile
, failureStr
, len
);
10931 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error
);
10933 DLOG("Saved SleepWake failure string to file.\n");
10937 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
10942 unsigned int len
= 0;
10944 char nvram_var_name_buffer
[20];
10945 unsigned int concat_len
= 0;
10946 swd_hdr
*hdr
= NULL
;
10949 hdr
= (swd_hdr
*)swd_buffer
;
10950 outbuf
= (char *)hdr
+ hdr
->spindump_offset
;
10952 for (int i
= 0; i
< 8; i
++) {
10953 snprintf(nvram_var_name_buffer
, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, i
+ 1);
10954 if (!PEReadNVRAMProperty(nvram_var_name_buffer
, NULL
, &len
)) {
10955 LOG("No SleepWake blob to read beyond chunk %d\n", i
);
10958 if (PEReadNVRAMProperty(nvram_var_name_buffer
, outbuf
+ concat_len
, &len
) == FALSE
) {
10959 PERemoveNVRAMProperty(nvram_var_name_buffer
);
10960 LOG("Could not read the property :-(\n");
10963 PERemoveNVRAMProperty(nvram_var_name_buffer
);
10966 LOG("Concatenated length for the SWD blob %d\n", concat_len
);
10969 error
= sleepWakeDebugSaveFile(kSleepWakeStacksFilename
, outbuf
, concat_len
);
10971 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error
);
10973 LOG("Saved SleepWake zipped data to file.\n");
10976 // There is a sleep wake failure string but no stackshot
10977 // Write a placeholder stacks file so that swd runs
10978 snprintf(outbuf
, 20, "%s", "No stackshot data\n");
10979 error
= sleepWakeDebugSaveFile(kSleepWakeStacksFilename
, outbuf
, 20);
10981 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error
);
10983 LOG("Saved SleepWake zipped data to file.\n");
10987 LOG("No buffer allocated to save failure stackshot\n");
10991 gRootDomain
->swd_lock
= 0;
10993 PERemoveNVRAMProperty(kIOSleepWakeFailureString
);
10999 IOPMrootDomain::getFailureData(thread_t
*thread
, char *failureStr
, size_t strLen
)
11001 IORegistryIterator
* iter
;
11002 IORegistryEntry
* entry
;
11004 bool nodeFound
= false;
11006 const void * callMethod
= NULL
;
11007 const char * objectName
= NULL
;
11008 uint32_t timeout
= getWatchdogTimeout();
11009 const char * phaseString
= NULL
;
11010 const char * phaseDescription
= NULL
;
11012 IOPMServiceInterestNotifier
*notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, notifierObject
);
11013 uint32_t tracePhase
= pmTracer
->getTracePhase();
11016 if ((tracePhase
< kIOPMTracePointSystemSleep
) || (tracePhase
== kIOPMTracePointDarkWakeEntry
)) {
11017 snprintf(failureStr
, strLen
, "%sSleep transition timed out after %d seconds", failureStr
, timeout
);
11019 snprintf(failureStr
, strLen
, "%sWake transition timed out after %d seconds", failureStr
, timeout
);
11021 tracePhase2String(tracePhase
, &phaseString
, &phaseDescription
);
11023 if (notifierThread
) {
11024 if (notifier
&& (notifier
->identifier
)) {
11025 objectName
= notifier
->identifier
->getCStringNoCopy();
11027 *thread
= notifierThread
;
11029 iter
= IORegistryIterator::iterateOver(
11030 getPMRootDomain(), gIOPowerPlane
, kIORegistryIterateRecursively
);
11033 while ((entry
= iter
->getNextObject())) {
11034 node
= OSDynamicCast(IOService
, entry
);
11038 if (OSDynamicCast(IOPowerConnection
, node
)) {
11042 if (node
->getBlockingDriverCall(thread
, &callMethod
)) {
11050 OSKext
*kext
= OSKext::lookupKextWithAddress((vm_address_t
)callMethod
);
11052 objectName
= kext
->getIdentifierCString();
11057 if (phaseDescription
) {
11058 snprintf(failureStr
, strLen
, "%s while %s.", failureStr
, phaseDescription
);
11061 snprintf(failureStr
, strLen
, "%s Suspected bundle: %s.", failureStr
, objectName
);
11064 snprintf(failureStr
, strLen
, "%s Thread 0x%llx.", failureStr
, thread_tid(*thread
));
11067 DLOG("%s\n", failureStr
);
11070 struct swd_stackshot_compressed_data
{
11071 z_output_func zoutput
;
11073 uint64_t totalbytes
;
11074 uint64_t lastpercent
;
11076 unsigned outremain
;
11081 struct swd_stackshot_compressed_data swd_zip_var
= { };
11084 swd_zs_alloc(void *__unused ref
, u_int items
, u_int size
)
11087 LOG("Alloc in zipping %d items of size %d\n", items
, size
);
11089 result
= (void *)(swd_zs_zmem
+ swd_zs_zoffset
);
11090 swd_zs_zoffset
+= ~31L & (31 + (items
* size
)); // 32b align for vector crc
11091 LOG("Offset %zu\n", swd_zs_zoffset
);
11096 swd_zinput(z_streamp strm
, Bytef
*buf
, unsigned size
)
11100 len
= strm
->avail_in
;
11109 if (strm
->next_in
!= (Bytef
*) strm
) {
11110 memcpy(buf
, strm
->next_in
, len
);
11115 strm
->adler
= z_crc32(strm
->adler
, buf
, len
);
11117 strm
->avail_in
-= len
;
11118 strm
->next_in
+= len
;
11119 strm
->total_in
+= len
;
11125 swd_zoutput(z_streamp strm
, Bytef
*buf
, unsigned len
)
11127 unsigned int i
= 0;
11128 // if outlen > max size don't add to the buffer
11130 if (swd_zip_var
.outlen
+ len
> SWD_COMPRESSED_BUFSIZE
) {
11131 LOG("No space to GZIP... not writing to NVRAM\n");
11135 for (i
= 0; i
< len
; i
++) {
11136 *(swd_zip_var
.outbuf
+ swd_zip_var
.outlen
+ i
) = *(buf
+ i
);
11138 swd_zip_var
.outlen
+= len
;
11142 swd_zs_free(void * __unused ref
, void * __unused ptr
)
11147 swd_compress(char *inPtr
, char *outPtr
, size_t numBytes
)
11152 if (!swd_zs
.zalloc
) {
11153 swd_zs
.zalloc
= swd_zs_alloc
;
11154 swd_zs
.zfree
= swd_zs_free
;
11155 if (deflateInit2(&swd_zs
, Z_BEST_SPEED
, Z_DEFLATED
, wbits
+ 16, memlevel
, Z_DEFAULT_STRATEGY
)) {
11156 // allocation failed
11157 bzero(&swd_zs
, sizeof(swd_zs
));
11158 // swd_zs_zoffset = 0;
11160 LOG("PMRD inited the zlib allocation routines\n");
11166 swd_zip_var
.zipped
= 0;
11167 swd_zip_var
.totalbytes
= 0; // should this be the max that we have?
11168 swd_zip_var
.lastpercent
= 0;
11169 swd_zip_var
.error
= kIOReturnSuccess
;
11170 swd_zip_var
.outremain
= 0;
11171 swd_zip_var
.outlen
= 0;
11172 swd_zip_var
.writes
= 0;
11173 swd_zip_var
.outbuf
= (Bytef
*)outPtr
;
11175 swd_zip_var
.totalbytes
= numBytes
;
11177 swd_zs
.avail_in
= 0;
11178 swd_zs
.next_in
= NULL
;
11179 swd_zs
.avail_out
= 0;
11180 swd_zs
.next_out
= NULL
;
11182 deflateResetWithIO(&swd_zs
, swd_zinput
, swd_zoutput
);
11190 while (swd_zip_var
.error
>= 0) {
11191 if (!zs
->avail_in
) {
11192 zs
->next_in
= (unsigned char *)inPtr
? (Bytef
*)inPtr
: (Bytef
*)zs
; /* zero marker? */
11193 zs
->avail_in
= numBytes
;
11195 if (!zs
->avail_out
) {
11196 zs
->next_out
= (Bytef
*)zs
;
11197 zs
->avail_out
= UINT32_MAX
;
11199 zr
= deflate(zs
, Z_NO_FLUSH
);
11200 if (Z_STREAM_END
== zr
) {
11204 LOG("ZERR %d\n", zr
);
11205 swd_zip_var
.error
= zr
;
11207 if (zs
->total_in
== numBytes
) {
11213 //now flush the stream
11214 while (swd_zip_var
.error
>= 0) {
11215 if (!zs
->avail_out
) {
11216 zs
->next_out
= (Bytef
*)zs
;
11217 zs
->avail_out
= UINT32_MAX
;
11219 zr
= deflate(zs
, Z_FINISH
);
11220 if (Z_STREAM_END
== zr
) {
11224 LOG("ZERR %d\n", zr
);
11225 swd_zip_var
.error
= zr
;
11227 if (zs
->total_in
== numBytes
) {
11228 LOG("Total output size %d\n", swd_zip_var
.outlen
);
11234 return swd_zip_var
.outlen
;
11238 IOPMrootDomain::deleteStackshot()
11240 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11241 // takeStackshot hasn't completed
11244 LOG("Deleting any sleepwake failure data in nvram\n");
11246 PERemoveNVRAMProperty(kIOSleepWakeFailureString
);
11247 char nvram_var_name_buf
[20];
11248 for (int i
= 0; i
< 8; i
++) {
11249 snprintf(nvram_var_name_buf
, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, i
+ 1);
11250 if (PERemoveNVRAMProperty(nvram_var_name_buf
) == false) {
11251 LOG("Removing %s returned false\n", nvram_var_name_buf
);
11254 // force NVRAM sync
11255 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey
, kIONVRAMSyncNowPropertyKey
, strlen(kIONVRAMSyncNowPropertyKey
)) == false) {
11256 DLOG("Failed to force nvram sync\n");
11258 gRootDomain
->swd_lock
= 0;
11261 IOPMrootDomain::takeStackshot(bool wdogTrigger
)
11263 swd_hdr
* hdr
= NULL
;
11267 kern_return_t kr
= KERN_SUCCESS
;
11272 uint32_t bytesRemaining
;
11273 unsigned bytesWritten
= 0;
11275 char failureStr
[512];
11276 thread_t thread
= NULL
;
11277 const char * swfPanic
= "swfPanic";
11283 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11288 if ((kIOSleepWakeWdogOff
& gIOKitDebug
) || systemBooting
|| systemShutdown
|| gWillShutdown
) {
11293 getFailureData(&thread
, failureStr
, sizeof(failureStr
));
11295 if (PEGetCoprocessorVersion() >= kCoprocessorVersion2
) {
11296 goto skip_stackshot
;
11301 clock_get_uptime(&now
);
11302 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
11303 absolutetime_to_nanoseconds(now
, &nsec
);
11304 snprintf(failureStr
, sizeof(failureStr
), "%sPower button pressed during wake transition after %u ms.\n", failureStr
, ((int)((nsec
) / NSEC_PER_MSEC
)));
11307 if (swd_buffer
== NULL
) {
11308 sleepWakeDebugMemAlloc();
11309 if (swd_buffer
== NULL
) {
11313 hdr
= (swd_hdr
*)swd_buffer
;
11314 bufSize
= hdr
->alloc_size
;;
11319 dstAddr
= (char*)hdr
+ hdr
->spindump_offset
;
11320 flags
= STACKSHOT_KCDATA_FORMAT
| STACKSHOT_NO_IO_STATS
| STACKSHOT_SAVE_KEXT_LOADINFO
| STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY
| STACKSHOT_THREAD_WAITINFO
;
11321 /* If not wdogTrigger only take kernel tasks stackshot
11329 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
11330 * If we run out of space, take stackshot with only kernel task
11332 while (success
== 0 && cnt
< max_cnt
) {
11333 bytesRemaining
= bufSize
- hdr
->spindump_offset
;
11335 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining
);
11337 size
= bytesRemaining
;
11338 kr
= stack_snapshot_from_kernel(pid
, dstAddr
, size
, flags
, 0, &bytesWritten
);
11339 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%x bytesWritten: %d\n",
11340 kr
, pid
, size
, flags
, bytesWritten
);
11341 if (kr
== KERN_INSUFFICIENT_BUFFER_SIZE
) {
11345 LOG("Insufficient buffer size for only kernel task\n");
11349 if (kr
== KERN_SUCCESS
) {
11350 if (bytesWritten
== 0) {
11351 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%x\n", kr
, size
, flags
);
11354 bytesRemaining
-= bytesWritten
;
11355 hdr
->spindump_size
= (bufSize
- bytesRemaining
- hdr
->spindump_offset
);
11357 memset(hdr
->reason
, 0x20, sizeof(hdr
->reason
));
11359 // Compress stackshot and save to NVRAM
11361 char *outbuf
= (char *)swd_compressed_buffer
;
11363 int num_chunks
= 0;
11364 int max_chunks
= 0;
11366 char nvram_var_name_buffer
[20];
11368 outlen
= swd_compress((char*)hdr
+ hdr
->spindump_offset
, outbuf
, bytesWritten
);
11371 max_chunks
= outlen
/ (2096 - 200);
11372 leftover
= outlen
% (2096 - 200);
11374 if (max_chunks
< 8) {
11375 for (num_chunks
= 0; num_chunks
< max_chunks
; num_chunks
++) {
11376 snprintf(nvram_var_name_buffer
, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, num_chunks
+ 1);
11377 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer
, (outbuf
+ (num_chunks
* (2096 - 200))), (2096 - 200)) == FALSE
) {
11378 LOG("Failed to update NVRAM %d\n", num_chunks
);
11383 snprintf(nvram_var_name_buffer
, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, num_chunks
+ 1);
11384 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer
, (outbuf
+ (num_chunks
* (2096 - 200))), leftover
) == FALSE
) {
11385 LOG("Failed to update NVRAM with leftovers\n");
11389 LOG("Successfully saved stackshot to NVRAM\n");
11391 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen
);
11395 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen
);
11404 if (failureStr
[0]) {
11405 // append sleep-wake failure code
11406 snprintf(failureStr
, sizeof(failureStr
), "%s\nFailure code:: 0x%08x %08x\n",
11407 failureStr
, pmTracer
->getTraceData(), pmTracer
->getTracePhase());
11408 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString
, failureStr
, strlen(failureStr
)) == false) {
11409 DLOG("Failed to write SleepWake failure string\n");
11413 // force NVRAM sync
11414 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey
, kIONVRAMSyncNowPropertyKey
, strlen(kIONVRAMSyncNowPropertyKey
)) == false) {
11415 DLOG("Failed to force nvram sync\n");
11420 if (PEGetCoprocessorVersion() < kCoprocessorVersion2
) {
11421 if (swd_flags
& SWD_BOOT_BY_SW_WDOG
) {
11422 // If current boot is due to this watch dog trigger restart in previous boot,
11423 // then don't trigger again until at least 1 successful sleep & wake.
11424 if (!(sleepCnt
&& (displayWakeCnt
|| darkWakeCnt
))) {
11425 LOG("Shutting down due to repeated Sleep/Wake failures\n");
11426 if (!tasksSuspended
) {
11427 tasksSuspended
= TRUE
;
11428 updateTasksSuspend();
11430 PEHaltRestart(kPEHaltCPU
);
11434 if (gSwdPanic
== 0) {
11435 LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
11436 if (!tasksSuspended
) {
11437 tasksSuspended
= TRUE
;
11438 updateTasksSuspend();
11440 PEHaltRestart(kPERestartCPU
);
11443 if (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic
, swfPanic
, strlen(swfPanic
)) == false) {
11444 DLOG("Failed to write SleepWake failure panic key\n");
11447 panic_with_thread_context(0, NULL
, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT
, thread
, "%s", failureStr
);
11449 panic_with_options(0, NULL
, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT
, "%s", failureStr
);
11452 gRootDomain
->swd_lock
= 0;
11458 IOPMrootDomain::sleepWakeDebugMemAlloc()
11460 vm_size_t size
= SWD_STACKSHOT_SIZE
+ SWD_COMPRESSED_BUFSIZE
+ SWD_ZLIB_BUFSIZE
;
11462 swd_hdr
*hdr
= NULL
;
11463 void *bufPtr
= NULL
;
11465 IOBufferMemoryDescriptor
*memDesc
= NULL
;
11468 if (kIOSleepWakeWdogOff
& gIOKitDebug
) {
11472 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11476 memDesc
= IOBufferMemoryDescriptor::inTaskWithOptions(
11477 kernel_task
, kIODirectionIn
| kIOMemoryMapperNone
,
11479 if (memDesc
== NULL
) {
11480 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
11484 bufPtr
= memDesc
->getBytesNoCopy();
11486 // Carve out memory for zlib routines
11487 swd_zs_zmem
= (vm_offset_t
)bufPtr
;
11488 bufPtr
= (char *)bufPtr
+ SWD_ZLIB_BUFSIZE
;
11490 // Carve out memory for compressed stackshots
11491 swd_compressed_buffer
= bufPtr
;
11492 bufPtr
= (char *)bufPtr
+ SWD_COMPRESSED_BUFSIZE
;
11494 // Remaining is used for holding stackshot
11495 hdr
= (swd_hdr
*)bufPtr
;
11496 memset(hdr
, 0, sizeof(swd_hdr
));
11498 hdr
->signature
= SWD_HDR_SIGNATURE
;
11499 hdr
->alloc_size
= SWD_STACKSHOT_SIZE
;
11501 hdr
->spindump_offset
= sizeof(swd_hdr
);
11502 swd_buffer
= (void *)hdr
;
11503 swd_memDesc
= memDesc
;
11504 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr
->alloc_size
, hdr
->spindump_offset
);
11507 gRootDomain
->swd_lock
= 0;
11511 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
11513 vm_size_t size
= SWD_SPINDUMP_SIZE
;
11515 swd_hdr
*hdr
= NULL
;
11517 IOBufferMemoryDescriptor
*memDesc
= NULL
;
11519 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11523 memDesc
= IOBufferMemoryDescriptor::inTaskWithOptions(
11524 kernel_task
, kIODirectionIn
| kIOMemoryMapperNone
,
11525 SWD_SPINDUMP_SIZE
);
11527 if (memDesc
== NULL
) {
11528 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
11533 hdr
= (swd_hdr
*)memDesc
->getBytesNoCopy();
11534 memset(hdr
, 0, sizeof(swd_hdr
));
11536 hdr
->signature
= SWD_HDR_SIGNATURE
;
11537 hdr
->alloc_size
= size
;
11539 hdr
->spindump_offset
= sizeof(swd_hdr
);
11540 swd_spindump_buffer
= (void *)hdr
;
11543 gRootDomain
->swd_lock
= 0;
11547 IOPMrootDomain::sleepWakeDebugEnableWdog()
11552 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
11554 return !systemBooting
&& !systemShutdown
&& !gWillShutdown
;
11558 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
11560 swd_hdr
*hdr
= NULL
;
11561 errno_t error
= EIO
;
11563 if (swd_spindump_buffer
&& gSpinDumpBufferFull
) {
11564 hdr
= (swd_hdr
*)swd_spindump_buffer
;
11566 error
= sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
11567 (char*)hdr
+ hdr
->spindump_offset
, hdr
->spindump_size
);
11573 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
11574 (char*)hdr
+ offsetof(swd_hdr
, UUID
),
11575 sizeof(swd_hdr
) - offsetof(swd_hdr
, UUID
));
11577 gSpinDumpBufferFull
= false;
11582 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name
, char *buf
, int len
)
11584 struct vnode
*vp
= NULL
;
11585 vfs_context_t ctx
= vfs_context_create(vfs_context_current());
11586 kauth_cred_t cred
= vfs_context_ucred(ctx
);
11587 struct vnode_attr va
;
11588 errno_t error
= EIO
;
11590 if (vnode_open(name
, (O_CREAT
| FWRITE
| O_NOFOLLOW
),
11591 S_IRUSR
| S_IRGRP
| S_IROTH
, VNODE_LOOKUP_NOFOLLOW
, &vp
, ctx
) != 0) {
11592 LOG("Failed to open the file %s\n", name
);
11593 swd_flags
|= SWD_FILEOP_ERROR
;
11597 VATTR_WANTED(&va
, va_nlink
);
11598 /* Don't dump to non-regular files or files with links. */
11599 if (vp
->v_type
!= VREG
||
11600 vnode_getattr(vp
, &va
, ctx
) || va
.va_nlink
!= 1) {
11601 LOG("Bailing as this is not a regular file\n");
11602 swd_flags
|= SWD_FILEOP_ERROR
;
11606 VATTR_SET(&va
, va_data_size
, 0);
11607 vnode_setattr(vp
, &va
, ctx
);
11611 error
= vn_rdwr(UIO_WRITE
, vp
, buf
, len
, 0,
11612 UIO_SYSSPACE
, IO_NODELOCKED
| IO_UNIT
, cred
, (int *) NULL
, vfs_context_proc(ctx
));
11614 LOG("Failed to save sleep wake log. err 0x%x\n", error
);
11615 swd_flags
|= SWD_FILEOP_ERROR
;
11617 DLOG("Saved %d bytes to file %s\n", len
, name
);
11623 vnode_close(vp
, FWRITE
, ctx
);
11626 vfs_context_rele(ctx
);
11636 IOPMrootDomain::sleepWakeDebugTrig(bool restart
)
11639 if (gSwdPanic
== 0) {
11642 panic("Sleep/Wake hang detected");
11648 IOPMrootDomain::takeStackshot(bool restart
)
11650 #pragma unused(restart)
11653 IOPMrootDomain::deleteStackshot()
11657 IOPMrootDomain::sleepWakeDebugMemAlloc()
11661 IOPMrootDomain::saveFailureData2File()
11666 IOPMrootDomain::sleepWakeDebugEnableWdog()
11671 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
11677 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name
, char *buf
, int len
)