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 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
328 .capabilityFlags
= kIOPMAOTCapability
,
329 .outputPowerCharacter
= kIOPMAOTPower
,
330 .inputPowerRequirement
= ON_POWER
},
331 #else /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
332 .capabilityFlags
= 0,
333 .outputPowerCharacter
= 0,
334 .inputPowerRequirement
= 0xFFFFFFFF },
335 #endif /* (defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
337 .capabilityFlags
= kIOPMPowerOn
,
338 .outputPowerCharacter
= kIOPMPowerOn
,
339 .inputPowerRequirement
= ON_POWER
},
342 #define kIOPMRootDomainWakeTypeSleepService "SleepService"
343 #define kIOPMRootDomainWakeTypeMaintenance "Maintenance"
344 #define kIOPMRootDomainWakeTypeSleepTimer "SleepTimer"
345 #define kIOPMrootDomainWakeTypeLowBattery "LowBattery"
346 #define kIOPMRootDomainWakeTypeUser "User"
347 #define kIOPMRootDomainWakeTypeAlarm "Alarm"
348 #define kIOPMRootDomainWakeTypeNetwork "Network"
349 #define kIOPMRootDomainWakeTypeHIDActivity "HID Activity"
350 #define kIOPMRootDomainWakeTypeNotification "Notification"
351 #define kIOPMRootDomainWakeTypeHibernateError "HibernateError"
353 // Special interest that entitles the interested client from receiving
354 // all system messages. Only used by powerd.
356 #define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest"
358 // Entitlement required for root domain clients
359 #define kRootDomainEntitlementSetProperty "com.apple.private.iokit.rootdomain-set-property"
361 #define WAKEEVENT_LOCK() IOLockLock(wakeEventLock)
362 #define WAKEEVENT_UNLOCK() IOLockUnlock(wakeEventLock)
367 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock)
368 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock)
370 #define kAggressivesMinValue 1
373 getAggressivenessTypeString( uint32_t type
)
375 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
377 static const IONamedValue aggressivenessTypes
[] = {
378 AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness
),
379 AGGRESSIVENESS_TYPE( kPMMinutesToDim
),
380 AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown
),
381 AGGRESSIVENESS_TYPE( kPMMinutesToSleep
),
382 AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings
),
383 AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed
),
384 AGGRESSIVENESS_TYPE( kPMPowerSource
),
385 AGGRESSIVENESS_TYPE( kPMMotionSensor
),
386 AGGRESSIVENESS_TYPE( kPMLastAggressivenessType
),
389 return IOFindNameForValue(type
, aggressivenessTypes
);
393 kAggressivesStateBusy
= 0x01,
394 kAggressivesStateQuickSpindown
= 0x02
397 struct AggressivesRecord
{
403 struct AggressivesRequest
{
409 AggressivesRecord record
;
414 kAggressivesRequestTypeService
= 1,
415 kAggressivesRequestTypeRecord
419 kAggressivesOptionSynchronous
= 0x00000001,
420 kAggressivesOptionQuickSpindownEnable
= 0x00000100,
421 kAggressivesOptionQuickSpindownDisable
= 0x00000200,
422 kAggressivesOptionQuickSpindownMask
= 0x00000300
426 kAggressivesRecordFlagModified
= 0x00000001,
427 kAggressivesRecordFlagMinValue
= 0x00000002
430 // System Sleep Preventers
433 kPMUserDisabledAllSleep
= 1,
434 kPMSystemRestartBootingInProgress
,
435 kPMConfigPreventSystemSleep
,
436 kPMChildPreventSystemSleep
,
442 getSystemSleepPreventerString( uint32_t preventer
)
444 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x}
445 static const IONamedValue systemSleepPreventers
[] = {
446 SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep
),
447 SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress
),
448 SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep
),
449 SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep
),
450 SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion
),
451 SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported
),
454 return IOFindNameForValue(preventer
, systemSleepPreventers
);
459 kDarkWakeFlagHIDTickleEarly
= 0x01,// hid tickle before gfx suppression
460 kDarkWakeFlagHIDTickleLate
= 0x02,// hid tickle after gfx suppression
461 kDarkWakeFlagHIDTickleNone
= 0x03,// hid tickle is not posted
462 kDarkWakeFlagHIDTickleMask
= 0x03,
463 kDarkWakeFlagAlarmIsDark
= 0x0100,
464 kDarkWakeFlagGraphicsPowerState1
= 0x0200,
465 kDarkWakeFlagAudioNotSuppressed
= 0x0400
468 static IOPMrootDomain
* gRootDomain
;
469 static IONotifier
* gSysPowerDownNotifier
= NULL
;
470 static UInt32 gSleepOrShutdownPending
= 0;
471 static UInt32 gWillShutdown
= 0;
472 static UInt32 gPagingOff
= 0;
473 static UInt32 gSleepWakeUUIDIsSet
= false;
474 static uint32_t gAggressivesState
= 0;
475 static uint32_t gHaltTimeMaxLog
;
476 static uint32_t gHaltTimeMaxPanic
;
477 IOLock
* gHaltLogLock
;
478 static char * gHaltLog
;
479 enum { kHaltLogSize
= 2048 };
480 static size_t gHaltLogPos
;
481 static uint64_t gHaltStartTime
;
484 uuid_string_t bootsessionuuid_string
;
486 static uint32_t gDarkWakeFlags
= kDarkWakeFlagHIDTickleNone
;
487 static uint32_t gNoIdleFlag
= 0;
488 static uint32_t gSwdPanic
= 1;
489 static uint32_t gSwdSleepTimeout
= 0;
490 static uint32_t gSwdWakeTimeout
= 0;
491 static uint32_t gSwdSleepWakeTimeout
= 0;
492 static PMStatsStruct gPMStats
;
493 #if DEVELOPMENT || DEBUG
494 static uint32_t swd_panic_phase
;
499 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler
= NULL
;
500 static IOPMSystemSleepPolicyVariables
* gSleepPolicyVars
= NULL
;
501 static void * gSleepPolicyTarget
;
504 struct timeval gIOLastSleepTime
;
505 struct timeval gIOLastWakeTime
;
507 struct timeval gIOLastUserSleepTime
;
509 static char gWakeReasonString
[128];
510 static bool gWakeReasonSysctlRegistered
= false;
511 static AbsoluteTime gIOLastWakeAbsTime
;
512 static AbsoluteTime gIOLastSleepAbsTime
;
513 static AbsoluteTime gUserActiveAbsTime
;
514 static AbsoluteTime gUserInactiveAbsTime
;
516 #if defined(__i386__) || defined(__x86_64__)
517 static bool gSpinDumpBufferFull
= false;
521 vm_offset_t swd_zs_zmem
;
522 //size_t swd_zs_zsize;
523 size_t swd_zs_zoffset
;
524 #if defined(__i386__) || defined(__x86_64__)
525 IOCPU
*currentShutdownTarget
= NULL
;
528 static unsigned int gPMHaltBusyCount
;
529 static unsigned int gPMHaltIdleCount
;
530 static int gPMHaltDepth
;
531 static uint32_t gPMHaltMessageType
;
532 static IOLock
* gPMHaltLock
= NULL
;
533 static OSArray
* gPMHaltArray
= NULL
;
534 static const OSSymbol
* gPMHaltClientAcknowledgeKey
= NULL
;
535 static bool gPMQuiesced
;
537 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
538 #define kCPUUnknownIndex 9999999
545 const OSSymbol
*gIOPMStatsResponseTimedOut
;
546 const OSSymbol
*gIOPMStatsResponseCancel
;
547 const OSSymbol
*gIOPMStatsResponseSlow
;
548 const OSSymbol
*gIOPMStatsResponsePrompt
;
549 const OSSymbol
*gIOPMStatsDriverPSChangeSlow
;
551 #define kBadPMFeatureID 0
555 * Opaque handle passed to clients of registerPMSettingController()
557 class PMSettingHandle
: public OSObject
559 OSDeclareFinalStructors( PMSettingHandle
);
560 friend class PMSettingObject
;
563 PMSettingObject
*pmso
;
564 void free(void) APPLE_KEXT_OVERRIDE
;
569 * Internal object to track each PM setting controller
571 class PMSettingObject
: public OSObject
573 OSDeclareFinalStructors( PMSettingObject
);
574 friend class IOPMrootDomain
;
577 queue_head_t calloutQueue
;
579 IOPMrootDomain
*parent
;
580 PMSettingHandle
*pmsh
;
581 IOPMSettingControllerCallback func
;
584 uint32_t *publishedFeatureID
;
585 uint32_t settingCount
;
588 void free(void) APPLE_KEXT_OVERRIDE
;
591 static PMSettingObject
*pmSettingObject(
592 IOPMrootDomain
*parent_arg
,
593 IOPMSettingControllerCallback handler_arg
,
594 OSObject
*target_arg
,
595 uintptr_t refcon_arg
,
596 uint32_t supportedPowerSources
,
597 const OSSymbol
*settings
[],
598 OSObject
**handle_obj
);
600 void dispatchPMSetting(const OSSymbol
*type
, OSObject
*object
);
601 void clientHandleFreed(void);
604 struct PMSettingCallEntry
{
609 #define PMSETTING_LOCK() IOLockLock(settingsCtrlLock)
610 #define PMSETTING_UNLOCK() IOLockUnlock(settingsCtrlLock)
611 #define PMSETTING_WAIT(p) IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
612 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
616 * Internal helper object for logging trace points to RTC
617 * IOPMrootDomain and only IOPMrootDomain should instantiate
618 * exactly one of these.
621 typedef void (*IOPMTracePointHandler
)(
622 void * target
, uint32_t code
, uint32_t data
);
624 class PMTraceWorker
: public OSObject
626 OSDeclareDefaultStructors(PMTraceWorker
);
628 typedef enum { kPowerChangeStart
, kPowerChangeCompleted
} change_t
;
630 static PMTraceWorker
*tracer( IOPMrootDomain
* );
631 void tracePCIPowerChange(change_t
, IOService
*, uint32_t, uint32_t);
632 void tracePoint(uint8_t phase
);
633 void traceDetail(uint32_t detail
);
634 void traceComponentWakeProgress(uint32_t component
, uint32_t data
);
635 int recordTopLevelPCIDevice(IOService
*);
636 void RTC_TRACE(void);
637 virtual bool serialize(OSSerialize
*s
) const APPLE_KEXT_OVERRIDE
;
639 IOPMTracePointHandler tracePointHandler
;
640 void * tracePointTarget
;
641 uint64_t getPMStatusCode();
642 uint8_t getTracePhase();
643 uint32_t getTraceData();
645 IOPMrootDomain
*owner
;
646 IOLock
*pmTraceWorkerLock
;
647 OSArray
*pciDeviceBitMappings
;
649 uint8_t addedToRegistry
;
651 uint32_t traceData32
;
652 uint8_t loginWindowData
;
653 uint8_t coreDisplayData
;
654 uint8_t coreGraphicsData
;
658 * PMAssertionsTracker
659 * Tracks kernel and user space PM assertions
661 class PMAssertionsTracker
: public OSObject
663 OSDeclareFinalStructors(PMAssertionsTracker
);
665 static PMAssertionsTracker
*pmAssertionsTracker( IOPMrootDomain
* );
667 IOReturn
createAssertion(IOPMDriverAssertionType
, IOPMDriverAssertionLevel
, IOService
*, const char *, IOPMDriverAssertionID
*);
668 IOReturn
releaseAssertion(IOPMDriverAssertionID
);
669 IOReturn
setAssertionLevel(IOPMDriverAssertionID
, IOPMDriverAssertionLevel
);
670 IOReturn
setUserAssertionLevels(IOPMDriverAssertionType
);
672 OSArray
*copyAssertionsArray(void);
673 IOPMDriverAssertionType
getActivatedAssertions(void);
674 IOPMDriverAssertionLevel
getAssertionLevel(IOPMDriverAssertionType
);
676 IOReturn
handleCreateAssertion(OSData
*);
677 IOReturn
handleReleaseAssertion(IOPMDriverAssertionID
);
678 IOReturn
handleSetAssertionLevel(IOPMDriverAssertionID
, IOPMDriverAssertionLevel
);
679 IOReturn
handleSetUserAssertionLevels(void * arg0
);
680 void publishProperties(void);
684 IOPMDriverAssertionID id
;
685 IOPMDriverAssertionType assertionBits
;
686 uint64_t createdTime
;
687 uint64_t modifiedTime
;
688 const OSSymbol
*ownerString
;
689 IOService
*ownerService
;
690 uint64_t registryEntryID
;
691 IOPMDriverAssertionLevel level
;
694 uint32_t tabulateProducerCount
;
695 uint32_t tabulateConsumerCount
;
697 PMAssertStruct
*detailsForID(IOPMDriverAssertionID
, int *);
700 IOPMrootDomain
*owner
;
701 OSArray
*assertionsArray
;
702 IOLock
*assertionsArrayLock
;
703 IOPMDriverAssertionID issuingUniqueID
__attribute__((aligned(8)));/* aligned for atomic access */
704 IOPMDriverAssertionType assertionsKernel
;
705 IOPMDriverAssertionType assertionsUser
;
706 IOPMDriverAssertionType assertionsCombined
;
709 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker
, OSObject
);
713 * Internal helper object for Shutdown/Restart notifications.
715 #define kPMHaltMaxWorkers 8
716 #define kPMHaltTimeoutMS 100
718 class PMHaltWorker
: public OSObject
720 OSDeclareFinalStructors( PMHaltWorker
);
723 IOService
* service
;// service being worked on
724 AbsoluteTime startTime
; // time when work started
725 int depth
; // work on nubs at this PM-tree depth
726 int visits
; // number of nodes visited (debug)
728 bool timeout
;// service took too long
730 static PMHaltWorker
* worker( void );
731 static void main( void * arg
, wait_result_t waitResult
);
732 static void work( PMHaltWorker
* me
);
733 static void checkTimeout( PMHaltWorker
* me
, AbsoluteTime
* now
);
734 virtual void free( void ) APPLE_KEXT_OVERRIDE
;
737 OSDefineMetaClassAndFinalStructors( PMHaltWorker
, OSObject
)
740 #define super IOService
741 OSDefineMetaClassAndFinalStructors(IOPMrootDomain
, IOService
)
744 IOPMRootDomainGetWillShutdown(void)
746 return gWillShutdown
!= 0;
750 IOPMRootDomainWillShutdown(void)
752 if (OSCompareAndSwap(0, 1, &gWillShutdown
)) {
753 IOService::willShutdown();
754 for (int i
= 0; i
< 100; i
++) {
755 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending
)) {
763 extern "C" IONotifier
*
764 registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
766 return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref
);
769 extern "C" IONotifier
*
770 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
772 return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref
);
776 acknowledgeSleepWakeNotification(void * PMrefcon
)
778 return gRootDomain
->allowPowerChange((unsigned long)PMrefcon
);
782 vetoSleepWakeNotification(void * PMrefcon
)
784 return gRootDomain
->cancelPowerChange((unsigned long)PMrefcon
);
788 rootDomainRestart( void )
790 return gRootDomain
->restartSystem();
794 rootDomainShutdown( void )
796 return gRootDomain
->shutdownSystem();
800 halt_log_putc(char c
)
802 if (gHaltLogPos
>= (kHaltLogSize
- 2)) {
805 gHaltLog
[gHaltLogPos
++] = c
;
809 _doprnt_log(const char *fmt
,
815 halt_log(const char *fmt
, ...)
819 va_start(listp
, fmt
);
820 _doprnt_log(fmt
, &listp
, &halt_log_putc
, 16);
827 halt_log_enter(const char * what
, const void * pc
, uint64_t time
)
829 uint64_t nano
, millis
;
834 absolutetime_to_nanoseconds(time
, &nano
);
835 millis
= nano
/ NSEC_PER_MSEC
;
840 IOLockLock(gHaltLogLock
);
842 halt_log("%s: %qd ms @ 0x%lx, ", what
, millis
, VM_KERNEL_UNSLIDE(pc
));
843 OSKext::printKextsInBacktrace((vm_offset_t
*) &pc
, 1, &halt_log
,
844 OSKext::kPrintKextsLock
| OSKext::kPrintKextsUnslide
| OSKext::kPrintKextsTerse
);
846 halt_log("%s: %qd ms\n", what
, millis
);
849 gHaltLog
[gHaltLogPos
] = 0;
850 IOLockUnlock(gHaltLogLock
);
853 extern uint32_t gFSState
;
856 IOSystemShutdownNotification(int stage
)
860 if (kIOSystemShutdownNotificationStageRootUnmount
== stage
) {
862 uint64_t nano
, millis
;
863 startTime
= mach_absolute_time();
864 IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC
);
865 absolutetime_to_nanoseconds(mach_absolute_time() - startTime
, &nano
);
866 millis
= nano
/ NSEC_PER_MSEC
;
867 if (gHaltTimeMaxLog
&& (millis
>= gHaltTimeMaxLog
)) {
868 printf("waitQuiet() for unmount %qd ms\n", millis
);
874 assert(kIOSystemShutdownNotificationStageProcessExit
== stage
);
876 IOLockLock(gHaltLogLock
);
878 gHaltLog
= IONew(char, kHaltLogSize
);
879 gHaltStartTime
= mach_absolute_time();
884 IOLockUnlock(gHaltLogLock
);
886 startTime
= mach_absolute_time();
887 IOPMRootDomainWillShutdown();
888 halt_log_enter("IOPMRootDomainWillShutdown", NULL
, mach_absolute_time() - startTime
);
890 startTime
= mach_absolute_time();
891 IOHibernateSystemPostWake(true);
892 halt_log_enter("IOHibernateSystemPostWake", NULL
, mach_absolute_time() - startTime
);
894 if (OSCompareAndSwap(0, 1, &gPagingOff
)) {
895 gRootDomain
->handlePlatformHaltRestart(kPEPagingOff
);
900 extern "C" int sync_internal(void);
903 * A device is always in the highest power state which satisfies its driver,
904 * its policy-maker, and any power children it has, but within the constraint
905 * of the power state provided by its parent. The driver expresses its desire by
906 * calling changePowerStateTo(), the policy-maker expresses its desire by calling
907 * changePowerStateToPriv(), and the children express their desires by calling
908 * requestPowerDomainState().
910 * The Root Power Domain owns the policy for idle and demand sleep for the system.
911 * It is a power-managed IOService just like the others in the system.
912 * It implements several power states which map to what we see as Sleep and On.
914 * The sleep policy is as follows:
915 * 1. Sleep is prevented if the case is open so that nobody will think the machine
916 * is off and plug/unplug cards.
917 * 2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
918 * 3. System cannot Sleep if some object in the tree is in a power state marked
919 * kIOPMPreventSystemSleep.
921 * These three conditions are enforced using the "driver clamp" by calling
922 * changePowerStateTo(). For example, if the case is opened,
923 * changePowerStateTo(ON_STATE) is called to hold the system on regardless
924 * of the desires of the children of the root or the state of the other clamp.
926 * Demand Sleep is initiated by pressing the front panel power button, closing
927 * the clamshell, or selecting the menu item. In this case the root's parent
928 * actually initiates the power state change so that the root domain has no
929 * choice and does not give applications the opportunity to veto the change.
931 * Idle Sleep occurs if no objects in the tree are in a state marked
932 * kIOPMPreventIdleSleep. When this is true, the root's children are not holding
933 * the root on, so it sets the "policy-maker clamp" by calling
934 * changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
935 * This timer is set for the difference between the sleep timeout slider and the
936 * display dim timeout slider. When the timer expires, it releases its clamp and
937 * now nothing is holding it awake, so it falls asleep.
939 * Demand sleep is prevented when the system is booting. When preferences are
940 * transmitted by the loginwindow at the end of boot, a flag is cleared,
941 * and this allows subsequent Demand Sleep.
944 //******************************************************************************
947 IOPMrootDomain::construct( void )
949 IOPMrootDomain
*root
;
951 root
= new IOPMrootDomain
;
959 //******************************************************************************
960 // updateConsoleUsersCallout
962 //******************************************************************************
965 updateConsoleUsersCallout(thread_call_param_t p0
, thread_call_param_t p1
)
967 IOPMrootDomain
* rootDomain
= (IOPMrootDomain
*) p0
;
968 rootDomain
->updateConsoleUsers();
972 IOPMrootDomain::updateConsoleUsers(void)
974 IOService::updateConsoleUsers(NULL
, kIOMessageSystemHasPoweredOn
);
975 if (tasksSuspended
) {
976 tasksSuspended
= FALSE
;
977 updateTasksSuspend();
982 IOPMrootDomain::updateTasksSuspend(void)
986 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
987 newSuspend
= (tasksSuspended
|| _aotTasksSuspended
);
988 #else /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
989 newSuspend
= tasksSuspended
;
990 #endif /* (defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
991 if (newSuspend
== tasksSuspendState
) {
994 tasksSuspendState
= newSuspend
;
995 tasks_system_suspend(newSuspend
);
998 //******************************************************************************
1001 disk_sync_callout( thread_call_param_t p0
, thread_call_param_t p1
)
1003 IOService
* rootDomain
= (IOService
*) p0
;
1004 uint32_t notifyRef
= (uint32_t)(uintptr_t) p1
;
1005 uint32_t powerState
= rootDomain
->getPowerState();
1007 DLOG("disk_sync_callout ps=%u\n", powerState
);
1009 if (ON_STATE
== powerState
) {
1013 // Block sleep until trim issued on previous wake path is completed.
1014 IOHibernateSystemPostWake(true);
1019 IOHibernateSystemPostWake(false);
1022 gRootDomain
->sleepWakeDebugSaveSpinDumpFile();
1027 rootDomain
->allowPowerChange(notifyRef
);
1028 DLOG("disk_sync_callout finish\n");
1031 //******************************************************************************
1033 computeDeltaTimeMS( const AbsoluteTime
* startTime
, AbsoluteTime
* elapsedTime
)
1035 AbsoluteTime endTime
;
1038 clock_get_uptime(&endTime
);
1039 if (CMP_ABSOLUTETIME(&endTime
, startTime
) <= 0) {
1042 SUB_ABSOLUTETIME(&endTime
, startTime
);
1043 absolutetime_to_nanoseconds(endTime
, &nano
);
1044 *elapsedTime
= endTime
;
1047 return (UInt32
)(nano
/ NSEC_PER_MSEC
);
1050 //******************************************************************************
1053 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1055 struct timeval
*swt
= (struct timeval
*)arg1
;
1056 struct proc
*p
= req
->p
;
1058 if (p
== kernproc
) {
1059 return sysctl_io_opaque(req
, swt
, sizeof(*swt
), NULL
);
1060 } else if (proc_is64bit(p
)) {
1061 struct user64_timeval t
= {};
1062 t
.tv_sec
= swt
->tv_sec
;
1063 t
.tv_usec
= swt
->tv_usec
;
1064 return sysctl_io_opaque(req
, &t
, sizeof(t
), NULL
);
1066 struct user32_timeval t
= {};
1067 t
.tv_sec
= swt
->tv_sec
;
1068 t
.tv_usec
= swt
->tv_usec
;
1069 return sysctl_io_opaque(req
, &t
, sizeof(t
), NULL
);
1073 static SYSCTL_PROC(_kern
, OID_AUTO
, sleeptime
,
1074 CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1075 &gIOLastUserSleepTime
, 0, sysctl_sleepwaketime
, "S,timeval", "");
1077 static SYSCTL_PROC(_kern
, OID_AUTO
, waketime
,
1078 CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1079 &gIOLastWakeTime
, 0, sysctl_sleepwaketime
, "S,timeval", "");
1081 SYSCTL_QUAD(_kern
, OID_AUTO
, wake_abs_time
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &gIOLastWakeAbsTime
, "");
1082 SYSCTL_QUAD(_kern
, OID_AUTO
, sleep_abs_time
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &gIOLastSleepAbsTime
, "");
1083 SYSCTL_QUAD(_kern
, OID_AUTO
, useractive_abs_time
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &gUserActiveAbsTime
, "");
1084 SYSCTL_QUAD(_kern
, OID_AUTO
, userinactive_abs_time
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &gUserInactiveAbsTime
, "");
1088 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1090 int new_value
, changed
;
1091 int error
= sysctl_io_number(req
, gWillShutdown
, sizeof(int), &new_value
, &changed
);
1093 if (!gWillShutdown
&& (new_value
== 1)) {
1094 IOPMRootDomainWillShutdown();
1102 static SYSCTL_PROC(_kern
, OID_AUTO
, willshutdown
,
1103 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1104 NULL
, 0, sysctl_willshutdown
, "I", "");
1106 extern struct sysctl_oid sysctl__kern_iokittest
;
1107 extern struct sysctl_oid sysctl__debug_iokit
;
1109 #if !CONFIG_EMBEDDED
1112 sysctl_progressmeterenable
1113 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1116 int new_value
, changed
;
1118 error
= sysctl_io_number(req
, vc_progressmeter_enable
, sizeof(int), &new_value
, &changed
);
1121 vc_enable_progressmeter(new_value
);
1128 sysctl_progressmeter
1129 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1132 int new_value
, changed
;
1134 error
= sysctl_io_number(req
, vc_progressmeter_value
, sizeof(int), &new_value
, &changed
);
1137 vc_set_progressmeter(new_value
);
1143 static SYSCTL_PROC(_kern
, OID_AUTO
, progressmeterenable
,
1144 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1145 NULL
, 0, sysctl_progressmeterenable
, "I", "");
1147 static SYSCTL_PROC(_kern
, OID_AUTO
, progressmeter
,
1148 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1149 NULL
, 0, sysctl_progressmeter
, "I", "");
1151 #endif /* !CONFIG_EMBEDDED */
1156 sysctl_consoleoptions
1157 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1162 error
= sysctl_io_number(req
, vc_user_options
.options
, sizeof(uint32_t), &new_value
, &changed
);
1165 vc_user_options
.options
= new_value
;
1171 static SYSCTL_PROC(_kern
, OID_AUTO
, consoleoptions
,
1172 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1173 NULL
, 0, sysctl_consoleoptions
, "I", "");
1177 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1179 return sysctl_io_opaque(req
, &vc_user_options
, sizeof(vc_user_options
), NULL
);
1182 static SYSCTL_PROC(_kern
, OID_AUTO
, progressoptions
,
1183 CTLTYPE_STRUCT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
| CTLFLAG_ANYBODY
,
1184 NULL
, 0, sysctl_progressoptions
, "S,vc_progress_user_options", "");
1188 sysctl_wakereason SYSCTL_HANDLER_ARGS
1190 char wr
[sizeof(gWakeReasonString
)];
1194 gRootDomain
->copyWakeReasonString(wr
, sizeof(wr
));
1197 return sysctl_io_string(req
, wr
, 0, 0, NULL
);
1200 SYSCTL_PROC(_kern
, OID_AUTO
, wakereason
,
1201 CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1202 NULL
, 0, sysctl_wakereason
, "A", "wakereason");
1205 sysctl_targettype SYSCTL_HANDLER_ARGS
1213 root
= IOService::getServiceRoot();
1214 if (root
&& (obj
= root
->copyProperty(gIODTTargetTypeKey
))) {
1215 if ((data
= OSDynamicCast(OSData
, obj
))) {
1216 strlcpy(tt
, (const char *) data
->getBytesNoCopy(), sizeof(tt
));
1220 return sysctl_io_string(req
, tt
, 0, 0, NULL
);
1223 SYSCTL_PROC(_hw
, OID_AUTO
, targettype
,
1224 CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1225 NULL
, 0, sysctl_targettype
, "A", "targettype");
1227 static SYSCTL_INT(_debug
, OID_AUTO
, darkwake
, CTLFLAG_RW
, &gDarkWakeFlags
, 0, "");
1228 static SYSCTL_INT(_debug
, OID_AUTO
, noidle
, CTLFLAG_RW
, &gNoIdleFlag
, 0, "");
1229 static SYSCTL_INT(_debug
, OID_AUTO
, swd_sleep_timeout
, CTLFLAG_RW
, &gSwdSleepTimeout
, 0, "");
1230 static SYSCTL_INT(_debug
, OID_AUTO
, swd_wake_timeout
, CTLFLAG_RW
, &gSwdWakeTimeout
, 0, "");
1231 static SYSCTL_INT(_debug
, OID_AUTO
, swd_timeout
, CTLFLAG_RW
, &gSwdSleepWakeTimeout
, 0, "");
1232 static SYSCTL_INT(_debug
, OID_AUTO
, swd_panic
, CTLFLAG_RW
, &gSwdPanic
, 0, "");
1233 #if DEVELOPMENT || DEBUG
1234 static SYSCTL_INT(_debug
, OID_AUTO
, swd_panic_phase
, CTLFLAG_RW
, &swd_panic_phase
, 0, "");
1237 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
1238 //******************************************************************************
1242 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1244 if (NULL
== gRootDomain
) {
1247 if (NULL
== gRootDomain
->_aotMetrics
) {
1250 return sysctl_io_opaque(req
, gRootDomain
->_aotMetrics
, sizeof(IOPMAOTMetrics
), NULL
);
1253 static SYSCTL_PROC(_kern
, OID_AUTO
, aotmetrics
,
1254 CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
| CTLFLAG_ANYBODY
,
1255 NULL
, 0, sysctl_aotmetrics
, "S,IOPMAOTMetrics", "");
1259 update_aotmode(uint32_t mode
)
1263 if (!gIOPMWorkLoop
) {
1266 result
= gIOPMWorkLoop
->runActionBlock(^IOReturn (void) {
1267 unsigned int oldCount
;
1269 if (mode
&& !gRootDomain
->_aotMetrics
) {
1270 gRootDomain
->_aotMetrics
= IONewZero(IOPMAOTMetrics
, 1);
1271 if (!gRootDomain
->_aotMetrics
) {
1276 oldCount
= gRootDomain
->idleSleepPreventersCount();
1277 gRootDomain
->_aotMode
= mode
;
1278 gRootDomain
->updatePreventIdleSleepListInternal(NULL
, false, oldCount
);
1286 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1291 if (NULL
== gRootDomain
) {
1294 error
= sysctl_io_number(req
, gRootDomain
->_aotMode
, sizeof(uint32_t), &new_value
, &changed
);
1295 if (changed
&& gIOPMWorkLoop
) {
1296 error
= update_aotmode(new_value
);
1302 static SYSCTL_PROC(_kern
, OID_AUTO
, aotmodebits
,
1303 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1304 NULL
, 0, sysctl_aotmodebits
, "I", "");
1308 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1313 if (NULL
== gRootDomain
) {
1316 error
= sysctl_io_number(req
, gRootDomain
->_aotMode
, sizeof(uint32_t), &new_value
, &changed
);
1317 if (changed
&& gIOPMWorkLoop
) {
1319 new_value
= kIOPMAOTModeDefault
; // & ~kIOPMAOTModeRespectTimers;
1321 error
= update_aotmode(new_value
);
1327 static SYSCTL_PROC(_kern
, OID_AUTO
, aotmode
,
1328 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
| CTLFLAG_ANYBODY
,
1329 NULL
, 0, sysctl_aotmode
, "I", "");
1331 //******************************************************************************
1332 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
1335 static const OSSymbol
* gIOPMSettingAutoWakeCalendarKey
;
1336 static const OSSymbol
* gIOPMSettingAutoWakeSecondsKey
;
1337 static const OSSymbol
* gIOPMSettingAutoPowerCalendarKey
;
1338 static const OSSymbol
* gIOPMSettingAutoPowerSecondsKey
;
1339 static const OSSymbol
* gIOPMSettingDebugWakeRelativeKey
;
1340 static const OSSymbol
* gIOPMSettingDebugPowerRelativeKey
;
1341 static const OSSymbol
* gIOPMSettingMaintenanceWakeCalendarKey
;
1342 static const OSSymbol
* gIOPMSettingSleepServiceWakeCalendarKey
;
1343 static const OSSymbol
* gIOPMSettingSilentRunningKey
;
1344 static const OSSymbol
* gIOPMUserTriggeredFullWakeKey
;
1345 static const OSSymbol
* gIOPMUserIsActiveKey
;
1347 //******************************************************************************
1350 //******************************************************************************
1352 #define kRootDomainSettingsCount 17
1355 IOPMrootDomain::start( IOService
* nub
)
1357 OSIterator
*psIterator
;
1358 OSDictionary
*tmpDict
;
1359 IORootParent
* patriarch
;
1364 gIOPMSettingAutoWakeCalendarKey
= OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey
);
1365 gIOPMSettingAutoWakeSecondsKey
= OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey
);
1366 gIOPMSettingAutoPowerCalendarKey
= OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey
);
1367 gIOPMSettingAutoPowerSecondsKey
= OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey
);
1368 gIOPMSettingDebugWakeRelativeKey
= OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey
);
1369 gIOPMSettingDebugPowerRelativeKey
= OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey
);
1370 gIOPMSettingMaintenanceWakeCalendarKey
= OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey
);
1371 gIOPMSettingSleepServiceWakeCalendarKey
= OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey
);
1372 gIOPMSettingSilentRunningKey
= OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey
);
1373 gIOPMUserTriggeredFullWakeKey
= OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey
);
1374 gIOPMUserIsActiveKey
= OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey
);
1376 gIOPMStatsResponseTimedOut
= OSSymbol::withCString(kIOPMStatsResponseTimedOut
);
1377 gIOPMStatsResponseCancel
= OSSymbol::withCString(kIOPMStatsResponseCancel
);
1378 gIOPMStatsResponseSlow
= OSSymbol::withCString(kIOPMStatsResponseSlow
);
1379 gIOPMStatsResponsePrompt
= OSSymbol::withCString(kIOPMStatsResponsePrompt
);
1380 gIOPMStatsDriverPSChangeSlow
= OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow
);
1382 sleepSupportedPEFunction
= OSSymbol::withCString("IOPMSetSleepSupported");
1383 sleepMessagePEFunction
= OSSymbol::withCString("IOPMSystemSleepMessage");
1385 const OSSymbol
*settingsArr
[kRootDomainSettingsCount
] =
1387 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey
),
1388 gIOPMSettingAutoWakeSecondsKey
,
1389 gIOPMSettingAutoPowerSecondsKey
,
1390 gIOPMSettingAutoWakeCalendarKey
,
1391 gIOPMSettingAutoPowerCalendarKey
,
1392 gIOPMSettingDebugWakeRelativeKey
,
1393 gIOPMSettingDebugPowerRelativeKey
,
1394 OSSymbol::withCString(kIOPMSettingWakeOnRingKey
),
1395 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
),
1396 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey
),
1397 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey
),
1398 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey
),
1399 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey
),
1400 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey
),
1401 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey
),
1402 OSSymbol::withCString(kIOPMStateConsoleShutdown
),
1403 gIOPMSettingSilentRunningKey
1406 PE_parse_boot_argn("darkwake", &gDarkWakeFlags
, sizeof(gDarkWakeFlags
));
1407 PE_parse_boot_argn("noidle", &gNoIdleFlag
, sizeof(gNoIdleFlag
));
1408 PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout
, sizeof(gSwdSleepTimeout
));
1409 PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout
, sizeof(gSwdWakeTimeout
));
1410 PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout
, sizeof(gSwdSleepWakeTimeout
));
1411 PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic
, sizeof(gHaltTimeMaxPanic
));
1412 PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog
, sizeof(gHaltTimeMaxLog
));
1414 queue_init(&aggressivesQueue
);
1415 aggressivesThreadCall
= thread_call_allocate(handleAggressivesFunction
, this);
1416 aggressivesData
= OSData::withCapacity(
1417 sizeof(AggressivesRecord
) * (kPMLastAggressivenessType
+ 4));
1419 featuresDictLock
= IOLockAlloc();
1420 settingsCtrlLock
= IOLockAlloc();
1421 wakeEventLock
= IOLockAlloc();
1422 gHaltLogLock
= IOLockAlloc();
1423 setPMRootDomain(this);
1425 extraSleepTimer
= thread_call_allocate(
1426 idleSleepTimerExpired
,
1427 (thread_call_param_t
) this);
1429 powerButtonDown
= thread_call_allocate(
1430 powerButtonDownCallout
,
1431 (thread_call_param_t
) this);
1433 powerButtonUp
= thread_call_allocate(
1434 powerButtonUpCallout
,
1435 (thread_call_param_t
) this);
1437 diskSyncCalloutEntry
= thread_call_allocate(
1439 (thread_call_param_t
) this);
1440 updateConsoleUsersEntry
= thread_call_allocate(
1441 &updateConsoleUsersCallout
,
1442 (thread_call_param_t
) this);
1444 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
1445 fullWakeThreadCall
= thread_call_allocate(
1446 OSMemberFunctionCast(thread_call_func_t
, this,
1447 &IOPMrootDomain::fullWakeDelayedWork
),
1448 (thread_call_param_t
) this);
1451 setProperty(kIOSleepSupportedKey
, true);
1453 bzero(&gPMStats
, sizeof(gPMStats
));
1455 pmTracer
= PMTraceWorker::tracer(this);
1457 pmAssertions
= PMAssertionsTracker::pmAssertionsTracker(this);
1459 userDisabledAllSleep
= false;
1460 systemBooting
= true;
1461 idleSleepEnabled
= false;
1463 idleSleepTimerPending
= false;
1465 clamshellClosed
= false;
1466 clamshellExists
= false;
1467 clamshellDisabled
= true;
1468 acAdaptorConnected
= true;
1469 clamshellSleepDisabled
= false;
1470 gWakeReasonString
[0] = '\0';
1472 // Initialize to user active.
1473 // Will never transition to user inactive w/o wrangler.
1474 fullWakeReason
= kFullWakeReasonLocalUser
;
1475 userIsActive
= userWasActive
= true;
1476 clock_get_uptime(&gUserActiveAbsTime
);
1477 setProperty(gIOPMUserIsActiveKey
, kOSBooleanTrue
);
1479 // Set the default system capabilities at boot.
1480 _currentCapability
= kIOPMSystemCapabilityCPU
|
1481 kIOPMSystemCapabilityGraphics
|
1482 kIOPMSystemCapabilityAudio
|
1483 kIOPMSystemCapabilityNetwork
;
1485 _pendingCapability
= _currentCapability
;
1486 _desiredCapability
= _currentCapability
;
1487 _highestCapability
= _currentCapability
;
1488 setProperty(kIOPMSystemCapabilitiesKey
, _currentCapability
, 64);
1490 queuedSleepWakeUUIDString
= NULL
;
1491 initializeBootSessionUUID();
1492 pmStatsAppResponses
= OSArray::withCapacity(5);
1493 _statsNameKey
= OSSymbol::withCString(kIOPMStatsNameKey
);
1494 _statsPIDKey
= OSSymbol::withCString(kIOPMStatsPIDKey
);
1495 _statsTimeMSKey
= OSSymbol::withCString(kIOPMStatsTimeMSKey
);
1496 _statsResponseTypeKey
= OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey
);
1497 _statsMessageTypeKey
= OSSymbol::withCString(kIOPMStatsMessageTypeKey
);
1498 _statsPowerCapsKey
= OSSymbol::withCString(kIOPMStatsPowerCapabilityKey
);
1499 assertOnWakeSecs
= -1;// Invalid value to prevent updates
1501 pmStatsLock
= IOLockAlloc();
1502 idxPMCPUClamshell
= kCPUUnknownIndex
;
1503 idxPMCPULimitedPower
= kCPUUnknownIndex
;
1505 tmpDict
= OSDictionary::withCapacity(1);
1506 setProperty(kRootDomainSupportedFeatures
, tmpDict
);
1509 settingsCallbacks
= OSDictionary::withCapacity(1);
1511 // Create a list of the valid PM settings that we'll relay to
1512 // interested clients in setProperties() => setPMSetting()
1513 allowedPMSettings
= OSArray::withObjects(
1514 (const OSObject
**)settingsArr
,
1515 kRootDomainSettingsCount
,
1518 // List of PM settings that should not automatically publish itself
1519 // as a feature when registered by a listener.
1520 noPublishPMSettings
= OSArray::withObjects(
1521 (const OSObject
**) &gIOPMSettingSilentRunningKey
, 1, 0);
1523 fPMSettingsDict
= OSDictionary::withCapacity(5);
1524 preventIdleSleepList
= OSSet::withCapacity(8);
1525 preventSystemSleepList
= OSSet::withCapacity(2);
1527 PMinit(); // creates gIOPMWorkLoop
1528 gIOPMWorkLoop
= getIOPMWorkloop();
1530 // Create IOPMPowerStateQueue used to queue external power
1531 // events, and to handle those events on the PM work loop.
1532 pmPowerStateQueue
= IOPMPowerStateQueue::PMPowerStateQueue(
1533 this, OSMemberFunctionCast(IOEventSource::Action
, this,
1534 &IOPMrootDomain::dispatchPowerEvent
));
1535 gIOPMWorkLoop
->addEventSource(pmPowerStateQueue
);
1537 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
1539 _aotTimerES
= IOTimerEventSource::timerEventSource(this,
1540 OSMemberFunctionCast(IOTimerEventSource::Action
,
1541 this, &IOPMrootDomain::aotEvaluate
));
1542 gIOPMWorkLoop
->addEventSource(_aotTimerES
);
1543 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
1545 // create our power parent
1546 patriarch
= new IORootParent
;
1548 patriarch
->attach(this);
1549 patriarch
->start(this);
1550 patriarch
->addPowerChild(this);
1552 registerPowerDriver(this, ourPowerStates
, NUM_POWER_STATES
);
1553 changePowerStateToPriv(ON_STATE
);
1555 // install power change handler
1556 gSysPowerDownNotifier
= registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, NULL
);
1559 // Register for a notification when IODisplayWrangler is published
1560 if ((tmpDict
= serviceMatching("IODisplayWrangler"))) {
1561 _displayWranglerNotifier
= addMatchingNotification(
1562 gIOPublishNotification
, tmpDict
,
1563 (IOServiceMatchingNotificationHandler
) & displayWranglerMatchPublished
,
1569 #if defined(__i386__) || defined(__x86_64__)
1571 wranglerIdleSettings
= NULL
;
1572 OSNumber
* wranglerIdlePeriod
= NULL
;
1573 wranglerIdleSettings
= OSDictionary::withCapacity(1);
1574 wranglerIdlePeriod
= OSNumber::withNumber(kDefaultWranglerIdlePeriod
, 32);
1576 if (wranglerIdleSettings
&& wranglerIdlePeriod
) {
1577 wranglerIdleSettings
->setObject(kIORequestWranglerIdleKey
,
1578 wranglerIdlePeriod
);
1581 if (wranglerIdlePeriod
) {
1582 wranglerIdlePeriod
->release();
1586 const OSSymbol
*ucClassName
= OSSymbol::withCStringNoCopy("RootDomainUserClient");
1587 setProperty(gIOUserClientClassKey
, (OSObject
*) ucClassName
);
1588 ucClassName
->release();
1590 // IOBacklightDisplay can take a long time to load at boot, or it may
1591 // not load at all if you're booting with clamshell closed. We publish
1592 // 'DisplayDims' here redundantly to get it published early and at all.
1593 OSDictionary
* matching
;
1594 matching
= serviceMatching("IOPMPowerSource");
1595 psIterator
= getMatchingServices( matching
);
1597 matching
->release();
1599 if (psIterator
&& psIterator
->getNextObject()) {
1600 // There's at least one battery on the system, so we publish
1601 // 'DisplayDims' support for the LCD.
1602 publishFeature("DisplayDims");
1605 psIterator
->release();
1608 // read swd_panic boot-arg
1609 PE_parse_boot_argn("swd_panic", &gSwdPanic
, sizeof(gSwdPanic
));
1610 sysctl_register_oid(&sysctl__kern_sleeptime
);
1611 sysctl_register_oid(&sysctl__kern_waketime
);
1612 sysctl_register_oid(&sysctl__kern_willshutdown
);
1613 sysctl_register_oid(&sysctl__kern_iokittest
);
1614 sysctl_register_oid(&sysctl__debug_iokit
);
1615 sysctl_register_oid(&sysctl__hw_targettype
);
1617 #if !CONFIG_EMBEDDED
1618 sysctl_register_oid(&sysctl__kern_progressmeterenable
);
1619 sysctl_register_oid(&sysctl__kern_progressmeter
);
1620 sysctl_register_oid(&sysctl__kern_wakereason
);
1621 #endif /* !CONFIG_EMBEDDED */
1622 sysctl_register_oid(&sysctl__kern_consoleoptions
);
1623 sysctl_register_oid(&sysctl__kern_progressoptions
);
1625 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
1626 sysctl_register_oid(&sysctl__kern_aotmode
);
1627 sysctl_register_oid(&sysctl__kern_aotmodebits
);
1628 sysctl_register_oid(&sysctl__kern_aotmetrics
);
1629 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
1632 IOHibernateSystemInit(this);
1635 registerService(); // let clients find us
1640 //******************************************************************************
1643 // Receive a setProperty call
1644 // The "System Boot" property means the system is completely booted.
1645 //******************************************************************************
1648 IOPMrootDomain::setProperties( OSObject
* props_obj
)
1650 IOReturn return_value
= kIOReturnSuccess
;
1651 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, props_obj
);
1654 const OSSymbol
*key
;
1656 OSCollectionIterator
* iter
= NULL
;
1659 return kIOReturnBadArgument
;
1662 bool clientEntitled
= false;
1663 obj
= IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty
);
1664 clientEntitled
= (obj
== kOSBooleanTrue
);
1665 OSSafeReleaseNULL(obj
);
1667 if (!clientEntitled
) {
1668 const char * errorSuffix
= NULL
;
1670 // IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1671 // That API can set 6 possible keys that are checked below.
1672 if ((dict
->getCount() == 1) &&
1673 (dict
->getObject(gIOPMSettingAutoWakeSecondsKey
) ||
1674 dict
->getObject(gIOPMSettingAutoPowerSecondsKey
) ||
1675 dict
->getObject(gIOPMSettingAutoWakeCalendarKey
) ||
1676 dict
->getObject(gIOPMSettingAutoPowerCalendarKey
) ||
1677 dict
->getObject(gIOPMSettingDebugWakeRelativeKey
) ||
1678 dict
->getObject(gIOPMSettingDebugPowerRelativeKey
))) {
1679 return_value
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
1680 if (return_value
!= kIOReturnSuccess
) {
1681 errorSuffix
= "privileged";
1684 return_value
= kIOReturnNotPermitted
;
1685 errorSuffix
= "entitled";
1688 if (return_value
!= kIOReturnSuccess
) {
1689 OSString
* procName
= IOCopyLogNameForPID(proc_selfpid());
1690 DLOG("%s failed, process %s is not %s\n", __func__
,
1691 procName
? procName
->getCStringNoCopy() : "", errorSuffix
);
1692 OSSafeReleaseNULL(procName
);
1693 return return_value
;
1697 const OSSymbol
*publish_simulated_battery_string
= OSSymbol::withCString("SoftwareSimulatedBatteries");
1698 const OSSymbol
*boot_complete_string
= OSSymbol::withCString("System Boot Complete");
1699 const OSSymbol
*sys_shutdown_string
= OSSymbol::withCString("System Shutdown");
1700 const OSSymbol
*stall_halt_string
= OSSymbol::withCString("StallSystemAtHalt");
1701 const OSSymbol
*battery_warning_disabled_string
= OSSymbol::withCString("BatteryWarningsDisabled");
1702 const OSSymbol
*idle_seconds_string
= OSSymbol::withCString("System Idle Seconds");
1703 const OSSymbol
*sleepdisabled_string
= OSSymbol::withCString("SleepDisabled");
1704 const OSSymbol
*ondeck_sleepwake_uuid_string
= OSSymbol::withCString(kIOPMSleepWakeUUIDKey
);
1705 const OSSymbol
*loginwindow_progress_string
= OSSymbol::withCString(kIOPMLoginWindowProgressKey
);
1706 const OSSymbol
*coredisplay_progress_string
= OSSymbol::withCString(kIOPMCoreDisplayProgressKey
);
1707 const OSSymbol
*coregraphics_progress_string
= OSSymbol::withCString(kIOPMCoreGraphicsProgressKey
);
1709 const OSSymbol
*hibernatemode_string
= OSSymbol::withCString(kIOHibernateModeKey
);
1710 const OSSymbol
*hibernatefile_string
= OSSymbol::withCString(kIOHibernateFileKey
);
1711 const OSSymbol
*hibernatefilemin_string
= OSSymbol::withCString(kIOHibernateFileMinSizeKey
);
1712 const OSSymbol
*hibernatefilemax_string
= OSSymbol::withCString(kIOHibernateFileMaxSizeKey
);
1713 const OSSymbol
*hibernatefreeratio_string
= OSSymbol::withCString(kIOHibernateFreeRatioKey
);
1714 const OSSymbol
*hibernatefreetime_string
= OSSymbol::withCString(kIOHibernateFreeTimeKey
);
1717 iter
= OSCollectionIterator::withCollection(dict
);
1719 return_value
= kIOReturnNoMemory
;
1723 while ((key
= (const OSSymbol
*) iter
->getNextObject()) &&
1724 (obj
= dict
->getObject(key
))) {
1725 if (key
->isEqualTo(publish_simulated_battery_string
)) {
1726 if (OSDynamicCast(OSBoolean
, obj
)) {
1727 publishResource(key
, kOSBooleanTrue
);
1729 } else if (key
->isEqualTo(idle_seconds_string
)) {
1730 if ((n
= OSDynamicCast(OSNumber
, obj
))) {
1731 setProperty(key
, n
);
1732 idleSeconds
= n
->unsigned32BitValue();
1734 } else if (key
->isEqualTo(boot_complete_string
)) {
1735 pmPowerStateQueue
->submitPowerEvent(kPowerEventSystemBootCompleted
);
1736 } else if (key
->isEqualTo(sys_shutdown_string
)) {
1737 if ((b
= OSDynamicCast(OSBoolean
, obj
))) {
1738 pmPowerStateQueue
->submitPowerEvent(kPowerEventSystemShutdown
, (void *) b
);
1740 } else if (key
->isEqualTo(battery_warning_disabled_string
)) {
1741 setProperty(key
, obj
);
1744 else if (key
->isEqualTo(hibernatemode_string
) ||
1745 key
->isEqualTo(hibernatefilemin_string
) ||
1746 key
->isEqualTo(hibernatefilemax_string
) ||
1747 key
->isEqualTo(hibernatefreeratio_string
) ||
1748 key
->isEqualTo(hibernatefreetime_string
)) {
1749 if ((n
= OSDynamicCast(OSNumber
, obj
))) {
1750 setProperty(key
, n
);
1752 } else if (key
->isEqualTo(hibernatefile_string
)) {
1753 OSString
* str
= OSDynamicCast(OSString
, obj
);
1755 setProperty(key
, str
);
1759 else if (key
->isEqualTo(sleepdisabled_string
)) {
1760 if ((b
= OSDynamicCast(OSBoolean
, obj
))) {
1761 setProperty(key
, b
);
1762 pmPowerStateQueue
->submitPowerEvent(kPowerEventUserDisabledSleep
, (void *) b
);
1764 } else if (key
->isEqualTo(ondeck_sleepwake_uuid_string
)) {
1766 pmPowerStateQueue
->submitPowerEvent(kPowerEventQueueSleepWakeUUID
, (void *)obj
);
1767 } else if (key
->isEqualTo(loginwindow_progress_string
)) {
1768 if (pmTracer
&& (n
= OSDynamicCast(OSNumber
, obj
))) {
1769 uint32_t data
= n
->unsigned32BitValue();
1770 pmTracer
->traceComponentWakeProgress(kIOPMLoginWindowProgress
, data
);
1771 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMLoginWindowProgress
, data
);
1773 } else if (key
->isEqualTo(coredisplay_progress_string
)) {
1774 if (pmTracer
&& (n
= OSDynamicCast(OSNumber
, obj
))) {
1775 uint32_t data
= n
->unsigned32BitValue();
1776 pmTracer
->traceComponentWakeProgress(kIOPMCoreDisplayProgress
, data
);
1777 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMCoreDisplayProgress
, data
);
1779 } else if (key
->isEqualTo(coregraphics_progress_string
)) {
1780 if (pmTracer
&& (n
= OSDynamicCast(OSNumber
, obj
))) {
1781 uint32_t data
= n
->unsigned32BitValue();
1782 pmTracer
->traceComponentWakeProgress(kIOPMCoreGraphicsProgress
, data
);
1783 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMCoreGraphicsProgress
, data
);
1785 } else if (key
->isEqualTo(kIOPMDeepSleepEnabledKey
) ||
1786 key
->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey
) ||
1787 key
->isEqualTo(kIOPMAutoPowerOffEnabledKey
) ||
1788 key
->isEqualTo(stall_halt_string
)) {
1789 if ((b
= OSDynamicCast(OSBoolean
, obj
))) {
1790 setProperty(key
, b
);
1792 } else if (key
->isEqualTo(kIOPMDeepSleepDelayKey
) ||
1793 key
->isEqualTo(kIOPMDeepSleepTimerKey
) ||
1794 key
->isEqualTo(kIOPMAutoPowerOffDelayKey
) ||
1795 key
->isEqualTo(kIOPMAutoPowerOffTimerKey
)) {
1796 if ((n
= OSDynamicCast(OSNumber
, obj
))) {
1797 setProperty(key
, n
);
1799 } else if (key
->isEqualTo(kIOPMUserWakeAlarmScheduledKey
)) {
1800 if (kOSBooleanTrue
== obj
) {
1801 OSBitOrAtomic(kIOPMAlarmBitCalendarWake
, &_userScheduledAlarm
);
1803 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake
, &_userScheduledAlarm
);
1805 DLOG("_userScheduledAlarm = 0x%x\n", (uint32_t) _userScheduledAlarm
);
1807 // Relay our allowed PM settings onto our registered PM clients
1808 else if ((allowedPMSettings
->getNextIndexOfObject(key
, 0) != (unsigned int) -1)) {
1809 return_value
= setPMSetting(key
, obj
);
1810 if (kIOReturnSuccess
!= return_value
) {
1814 if (gIOPMSettingDebugWakeRelativeKey
== key
) {
1815 if ((n
= OSDynamicCast(OSNumber
, obj
)) &&
1816 (_debugWakeSeconds
= n
->unsigned32BitValue())) {
1817 OSBitOrAtomic(kIOPMAlarmBitDebugWake
, &_scheduledAlarms
);
1819 _debugWakeSeconds
= 0;
1820 OSBitAndAtomic(~kIOPMAlarmBitDebugWake
, &_scheduledAlarms
);
1822 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms
);
1823 } else if (gIOPMSettingAutoWakeCalendarKey
== key
) {
1825 if ((data
= OSDynamicCast(OSData
, obj
)) &&
1826 (data
->getLength() == sizeof(IOPMCalendarStruct
))) {
1827 const IOPMCalendarStruct
* cs
=
1828 (const IOPMCalendarStruct
*) data
->getBytesNoCopy();
1829 IOLog("gIOPMSettingAutoWakeCalendarKey " YMDTF
"\n", YMDT(cs
));
1831 _scheduledAlarmUTC
= IOPMConvertCalendarToSeconds(cs
);
1832 OSBitOrAtomic(kIOPMAlarmBitCalendarWake
, &_scheduledAlarms
);
1834 _scheduledAlarmUTC
= 0;
1835 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake
, &_scheduledAlarms
);
1837 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms
);
1841 DLOG("setProperties(%s) not handled\n", key
->getCStringNoCopy());
1846 if (publish_simulated_battery_string
) {
1847 publish_simulated_battery_string
->release();
1849 if (boot_complete_string
) {
1850 boot_complete_string
->release();
1852 if (sys_shutdown_string
) {
1853 sys_shutdown_string
->release();
1855 if (stall_halt_string
) {
1856 stall_halt_string
->release();
1858 if (battery_warning_disabled_string
) {
1859 battery_warning_disabled_string
->release();
1861 if (idle_seconds_string
) {
1862 idle_seconds_string
->release();
1864 if (sleepdisabled_string
) {
1865 sleepdisabled_string
->release();
1867 if (ondeck_sleepwake_uuid_string
) {
1868 ondeck_sleepwake_uuid_string
->release();
1870 if (loginwindow_progress_string
) {
1871 loginwindow_progress_string
->release();
1873 if (coredisplay_progress_string
) {
1874 coredisplay_progress_string
->release();
1876 if (coregraphics_progress_string
) {
1877 coregraphics_progress_string
->release();
1880 if (hibernatemode_string
) {
1881 hibernatemode_string
->release();
1883 if (hibernatefile_string
) {
1884 hibernatefile_string
->release();
1886 if (hibernatefreeratio_string
) {
1887 hibernatefreeratio_string
->release();
1889 if (hibernatefreetime_string
) {
1890 hibernatefreetime_string
->release();
1896 return return_value
;
1900 // MARK: Aggressiveness
1902 //******************************************************************************
1903 // setAggressiveness
1905 // Override IOService::setAggressiveness()
1906 //******************************************************************************
1909 IOPMrootDomain::setAggressiveness(
1911 unsigned long value
)
1913 return setAggressiveness( type
, value
, 0 );
1917 * Private setAggressiveness() with an internal options argument.
1920 IOPMrootDomain::setAggressiveness(
1922 unsigned long value
,
1923 IOOptionBits options
)
1925 AggressivesRequest
* entry
;
1926 AggressivesRequest
* request
;
1929 if (type
== kPMMinutesToDim
|| type
== kPMMinutesToSleep
) {
1930 DLOG("setAggressiveness(%x) %s = %u\n",
1931 (uint32_t) options
, getAggressivenessTypeString((uint32_t) type
), (uint32_t) value
);
1933 DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
1934 (uint32_t) options
, getAggressivenessTypeString((uint32_t) type
), (uint32_t) value
);
1937 request
= IONew(AggressivesRequest
, 1);
1939 return kIOReturnNoMemory
;
1942 memset(request
, 0, sizeof(*request
));
1943 request
->options
= options
;
1944 request
->dataType
= kAggressivesRequestTypeRecord
;
1945 request
->data
.record
.type
= (uint32_t) type
;
1946 request
->data
.record
.value
= (uint32_t) value
;
1950 // Update disk quick spindown flag used by getAggressiveness().
1951 // Never merge requests with quick spindown flags set.
1953 if (options
& kAggressivesOptionQuickSpindownEnable
) {
1954 gAggressivesState
|= kAggressivesStateQuickSpindown
;
1955 } else if (options
& kAggressivesOptionQuickSpindownDisable
) {
1956 gAggressivesState
&= ~kAggressivesStateQuickSpindown
;
1958 // Coalesce requests with identical aggressives types.
1959 // Deal with callers that calls us too "aggressively".
1961 queue_iterate(&aggressivesQueue
, entry
, AggressivesRequest
*, chain
)
1963 if ((entry
->dataType
== kAggressivesRequestTypeRecord
) &&
1964 (entry
->data
.record
.type
== type
) &&
1965 ((entry
->options
& kAggressivesOptionQuickSpindownMask
) == 0)) {
1966 entry
->data
.record
.value
= value
;
1974 queue_enter(&aggressivesQueue
, request
, AggressivesRequest
*, chain
);
1977 AGGRESSIVES_UNLOCK();
1980 IODelete(request
, AggressivesRequest
, 1);
1983 if (options
& kAggressivesOptionSynchronous
) {
1984 handleAggressivesRequests(); // not truly synchronous
1986 thread_call_enter(aggressivesThreadCall
);
1989 return kIOReturnSuccess
;
1992 //******************************************************************************
1993 // getAggressiveness
1995 // Override IOService::setAggressiveness()
1996 // Fetch the aggressiveness factor with the given type.
1997 //******************************************************************************
2000 IOPMrootDomain::getAggressiveness(
2002 unsigned long * outLevel
)
2008 return kIOReturnBadArgument
;
2013 // Disk quick spindown in effect, report value = 1
2015 if ((gAggressivesState
& kAggressivesStateQuickSpindown
) &&
2016 (type
== kPMMinutesToSpinDown
)) {
2017 value
= kAggressivesMinValue
;
2021 // Consult the pending request queue.
2024 AggressivesRequest
* entry
;
2026 queue_iterate(&aggressivesQueue
, entry
, AggressivesRequest
*, chain
)
2028 if ((entry
->dataType
== kAggressivesRequestTypeRecord
) &&
2029 (entry
->data
.record
.type
== type
) &&
2030 ((entry
->options
& kAggressivesOptionQuickSpindownMask
) == 0)) {
2031 value
= entry
->data
.record
.value
;
2038 // Consult the backend records.
2040 if (!source
&& aggressivesData
) {
2041 AggressivesRecord
* record
;
2044 count
= aggressivesData
->getLength() / sizeof(AggressivesRecord
);
2045 record
= (AggressivesRecord
*) aggressivesData
->getBytesNoCopy();
2047 for (i
= 0; i
< count
; i
++, record
++) {
2048 if (record
->type
== type
) {
2049 value
= record
->value
;
2056 AGGRESSIVES_UNLOCK();
2059 *outLevel
= (unsigned long) value
;
2060 return kIOReturnSuccess
;
2062 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type
);
2063 *outLevel
= 0; // default return = 0, driver may not check for error
2064 return kIOReturnInvalid
;
2068 //******************************************************************************
2069 // joinAggressiveness
2071 // Request from IOService to join future aggressiveness broadcasts.
2072 //******************************************************************************
2075 IOPMrootDomain::joinAggressiveness(
2076 IOService
* service
)
2078 AggressivesRequest
* request
;
2080 if (!service
|| (service
== this)) {
2081 return kIOReturnBadArgument
;
2084 DEBUG_LOG("joinAggressiveness %s %p\n", service
->getName(), OBFUSCATE(service
));
2086 request
= IONew(AggressivesRequest
, 1);
2088 return kIOReturnNoMemory
;
2091 service
->retain(); // released by synchronizeAggressives()
2093 memset(request
, 0, sizeof(*request
));
2094 request
->dataType
= kAggressivesRequestTypeService
;
2095 request
->data
.service
= service
;
2098 queue_enter(&aggressivesQueue
, request
, AggressivesRequest
*, chain
);
2099 AGGRESSIVES_UNLOCK();
2101 thread_call_enter(aggressivesThreadCall
);
2103 return kIOReturnSuccess
;
2106 //******************************************************************************
2107 // handleAggressivesRequests
2109 // Backend thread processes all incoming aggressiveness requests in the queue.
2110 //******************************************************************************
2113 handleAggressivesFunction(
2114 thread_call_param_t param1
,
2115 thread_call_param_t param2
)
2118 ((IOPMrootDomain
*) param1
)->handleAggressivesRequests();
2123 IOPMrootDomain::handleAggressivesRequests( void )
2125 AggressivesRecord
* start
;
2126 AggressivesRecord
* record
;
2127 AggressivesRequest
* request
;
2128 queue_head_t joinedQueue
;
2132 bool pingSelf
= false;
2136 if ((gAggressivesState
& kAggressivesStateBusy
) || !aggressivesData
||
2137 queue_empty(&aggressivesQueue
)) {
2141 gAggressivesState
|= kAggressivesStateBusy
;
2142 count
= aggressivesData
->getLength() / sizeof(AggressivesRecord
);
2143 start
= (AggressivesRecord
*) aggressivesData
->getBytesNoCopy();
2147 queue_init(&joinedQueue
);
2150 // Remove request from the incoming queue in FIFO order.
2151 queue_remove_first(&aggressivesQueue
, request
, AggressivesRequest
*, chain
);
2152 switch (request
->dataType
) {
2153 case kAggressivesRequestTypeRecord
:
2154 // Update existing record if found.
2156 for (i
= 0, record
= start
; i
< count
; i
++, record
++) {
2157 if (record
->type
== request
->data
.record
.type
) {
2160 if (request
->options
& kAggressivesOptionQuickSpindownEnable
) {
2161 if ((record
->flags
& kAggressivesRecordFlagMinValue
) == 0) {
2163 record
->flags
|= (kAggressivesRecordFlagMinValue
|
2164 kAggressivesRecordFlagModified
);
2165 DLOG("disk spindown accelerated, was %u min\n",
2168 } else if (request
->options
& kAggressivesOptionQuickSpindownDisable
) {
2169 if (record
->flags
& kAggressivesRecordFlagMinValue
) {
2171 record
->flags
|= kAggressivesRecordFlagModified
;
2172 record
->flags
&= ~kAggressivesRecordFlagMinValue
;
2173 DLOG("disk spindown restored to %u min\n",
2176 } else if (record
->value
!= request
->data
.record
.value
) {
2177 record
->value
= request
->data
.record
.value
;
2178 if ((record
->flags
& kAggressivesRecordFlagMinValue
) == 0) {
2180 record
->flags
|= kAggressivesRecordFlagModified
;
2187 // No matching record, append a new record.
2189 ((request
->options
& kAggressivesOptionQuickSpindownDisable
) == 0)) {
2190 AggressivesRecord newRecord
;
2192 newRecord
.flags
= kAggressivesRecordFlagModified
;
2193 newRecord
.type
= request
->data
.record
.type
;
2194 newRecord
.value
= request
->data
.record
.value
;
2195 if (request
->options
& kAggressivesOptionQuickSpindownEnable
) {
2196 newRecord
.flags
|= kAggressivesRecordFlagMinValue
;
2197 DLOG("disk spindown accelerated\n");
2200 aggressivesData
->appendBytes(&newRecord
, sizeof(newRecord
));
2202 // OSData may have switched to another (larger) buffer.
2203 count
= aggressivesData
->getLength() / sizeof(AggressivesRecord
);
2204 start
= (AggressivesRecord
*) aggressivesData
->getBytesNoCopy();
2208 // Finished processing the request, release it.
2209 IODelete(request
, AggressivesRequest
, 1);
2212 case kAggressivesRequestTypeService
:
2213 // synchronizeAggressives() will free request.
2214 queue_enter(&joinedQueue
, request
, AggressivesRequest
*, chain
);
2218 panic("bad aggressives request type %x\n", request
->dataType
);
2221 } while (!queue_empty(&aggressivesQueue
));
2223 // Release the lock to perform work, with busy flag set.
2224 if (!queue_empty(&joinedQueue
) || broadcast
) {
2225 AGGRESSIVES_UNLOCK();
2226 if (!queue_empty(&joinedQueue
)) {
2227 synchronizeAggressives(&joinedQueue
, start
, count
);
2230 broadcastAggressives(start
, count
);
2235 // Remove the modified flag from all records.
2236 for (i
= 0, record
= start
; i
< count
; i
++, record
++) {
2237 if ((record
->flags
& kAggressivesRecordFlagModified
) &&
2238 ((record
->type
== kPMMinutesToDim
) ||
2239 (record
->type
== kPMMinutesToSleep
))) {
2243 record
->flags
&= ~kAggressivesRecordFlagModified
;
2246 // Check the incoming queue again since new entries may have been
2247 // added while lock was released above.
2248 } while (!queue_empty(&aggressivesQueue
));
2250 gAggressivesState
&= ~kAggressivesStateBusy
;
2253 AGGRESSIVES_UNLOCK();
2255 // Root domain is interested in system and display sleep slider changes.
2256 // Submit a power event to handle those changes on the PM work loop.
2258 if (pingSelf
&& pmPowerStateQueue
) {
2259 pmPowerStateQueue
->submitPowerEvent(
2260 kPowerEventPolicyStimulus
,
2261 (void *) kStimulusAggressivenessChanged
);
2265 //******************************************************************************
2266 // synchronizeAggressives
2268 // Push all known aggressiveness records to one or more IOService.
2269 //******************************************************************************
2272 IOPMrootDomain::synchronizeAggressives(
2273 queue_head_t
* joinedQueue
,
2274 const AggressivesRecord
* array
,
2277 IOService
* service
;
2278 AggressivesRequest
* request
;
2279 const AggressivesRecord
* record
;
2280 IOPMDriverCallEntry callEntry
;
2284 while (!queue_empty(joinedQueue
)) {
2285 queue_remove_first(joinedQueue
, request
, AggressivesRequest
*, chain
);
2286 if (request
->dataType
== kAggressivesRequestTypeService
) {
2287 service
= request
->data
.service
;
2292 IODelete(request
, AggressivesRequest
, 1);
2296 if (service
->assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetAggressive
)) {
2297 for (i
= 0, record
= array
; i
< count
; i
++, record
++) {
2298 value
= record
->value
;
2299 if (record
->flags
& kAggressivesRecordFlagMinValue
) {
2300 value
= kAggressivesMinValue
;
2303 _LOG("synchronizeAggressives 0x%x = %u to %s\n",
2304 record
->type
, value
, service
->getName());
2305 service
->setAggressiveness(record
->type
, value
);
2307 service
->deassertPMDriverCall(&callEntry
);
2309 service
->release(); // retained by joinAggressiveness()
2314 //******************************************************************************
2315 // broadcastAggressives
2317 // Traverse PM tree and call setAggressiveness() for records that have changed.
2318 //******************************************************************************
2321 IOPMrootDomain::broadcastAggressives(
2322 const AggressivesRecord
* array
,
2325 IORegistryIterator
* iter
;
2326 IORegistryEntry
* entry
;
2327 IOPowerConnection
* connect
;
2328 IOService
* service
;
2329 const AggressivesRecord
* record
;
2330 IOPMDriverCallEntry callEntry
;
2334 iter
= IORegistryIterator::iterateOver(
2335 this, gIOPowerPlane
, kIORegistryIterateRecursively
);
2339 while ((entry
= iter
->getNextObject())) {
2340 connect
= OSDynamicCast(IOPowerConnection
, entry
);
2341 if (!connect
|| !connect
->getReadyFlag()) {
2345 if ((service
= OSDynamicCast(IOService
, connect
->copyChildEntry(gIOPowerPlane
)))) {
2346 if (service
->assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetAggressive
)) {
2347 for (i
= 0, record
= array
; i
< count
; i
++, record
++) {
2348 if (record
->flags
& kAggressivesRecordFlagModified
) {
2349 value
= record
->value
;
2350 if (record
->flags
& kAggressivesRecordFlagMinValue
) {
2351 value
= kAggressivesMinValue
;
2353 _LOG("broadcastAggressives %x = %u to %s\n",
2354 record
->type
, value
, service
->getName());
2355 service
->setAggressiveness(record
->type
, value
);
2358 service
->deassertPMDriverCall(&callEntry
);
2363 }while (!entry
&& !iter
->isValid());
2368 //*****************************************
2369 // stackshot on power button press
2370 // ***************************************
2372 powerButtonDownCallout(thread_call_param_t us
, thread_call_param_t
)
2374 /* Power button pressed during wake
2377 DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2378 ((IOPMrootDomain
*)us
)->takeStackshot(false);
2382 powerButtonUpCallout(thread_call_param_t us
, thread_call_param_t
)
2384 /* Power button released.
2385 * Delete any stackshot data
2387 DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2388 ((IOPMrootDomain
*)us
)->deleteStackshot();
2390 //*************************************************************************
2394 // MARK: System Sleep
2396 //******************************************************************************
2397 // startIdleSleepTimer
2399 //******************************************************************************
2402 IOPMrootDomain::startIdleSleepTimer( uint32_t inSeconds
)
2404 AbsoluteTime deadline
;
2408 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag
);
2412 clock_interval_to_deadline(inSeconds
, kSecondScale
, &deadline
);
2413 thread_call_enter_delayed(extraSleepTimer
, deadline
);
2414 idleSleepTimerPending
= true;
2416 thread_call_enter(extraSleepTimer
);
2418 DLOG("idle timer set for %u seconds\n", inSeconds
);
2421 //******************************************************************************
2422 // cancelIdleSleepTimer
2424 //******************************************************************************
2427 IOPMrootDomain::cancelIdleSleepTimer( void )
2430 if (idleSleepTimerPending
) {
2431 DLOG("idle timer cancelled\n");
2432 thread_call_cancel(extraSleepTimer
);
2433 idleSleepTimerPending
= false;
2435 if (!assertOnWakeSecs
&& gIOLastWakeAbsTime
) {
2437 clock_usec_t microsecs
;
2438 clock_get_uptime(&now
);
2439 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
2440 absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
);
2441 if (assertOnWakeReport
) {
2442 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
);
2443 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
);
2449 //******************************************************************************
2450 // idleSleepTimerExpired
2452 //******************************************************************************
2455 idleSleepTimerExpired(
2456 thread_call_param_t us
, thread_call_param_t
)
2458 ((IOPMrootDomain
*)us
)->handleSleepTimerExpiration();
2461 //******************************************************************************
2462 // handleSleepTimerExpiration
2464 // The time between the sleep idle timeout and the next longest one has elapsed.
2465 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2466 //******************************************************************************
2469 IOPMrootDomain::handleSleepTimerExpiration( void )
2471 if (!gIOPMWorkLoop
->inGate()) {
2472 gIOPMWorkLoop
->runAction(
2473 OSMemberFunctionCast(IOWorkLoop::Action
, this,
2474 &IOPMrootDomain::handleSleepTimerExpiration
),
2481 DLOG("sleep timer expired\n");
2484 idleSleepTimerPending
= false;
2486 clock_get_uptime(&time
);
2487 setQuickSpinDownTimeout();
2488 adjustPowerState(true);
2491 //******************************************************************************
2492 // getTimeToIdleSleep
2494 // Returns number of seconds left before going into idle sleep.
2495 // Caller has to make sure that idle sleep is allowed at the time of calling
2497 //******************************************************************************
2500 IOPMrootDomain::getTimeToIdleSleep( void )
2502 AbsoluteTime now
, lastActivityTime
;
2504 uint32_t minutesSinceUserInactive
= 0;
2505 uint32_t sleepDelay
= 0;
2507 if (!idleSleepEnabled
) {
2511 if (userActivityTime
) {
2512 lastActivityTime
= userActivityTime
;
2514 lastActivityTime
= userBecameInactiveTime
;
2517 clock_get_uptime(&now
);
2518 if (CMP_ABSOLUTETIME(&now
, &lastActivityTime
) > 0) {
2519 SUB_ABSOLUTETIME(&now
, &lastActivityTime
);
2520 absolutetime_to_nanoseconds(now
, &nanos
);
2521 minutesSinceUserInactive
= nanos
/ (60000000000ULL);
2523 if (minutesSinceUserInactive
>= sleepSlider
) {
2526 sleepDelay
= sleepSlider
- minutesSinceUserInactive
;
2529 sleepDelay
= sleepSlider
;
2532 DLOG("user inactive %u min, time to idle sleep %u min\n",
2533 minutesSinceUserInactive
, sleepDelay
);
2535 return sleepDelay
* 60;
2538 //******************************************************************************
2539 // setQuickSpinDownTimeout
2541 //******************************************************************************
2544 IOPMrootDomain::setQuickSpinDownTimeout( void )
2548 kPMMinutesToSpinDown
, 0, kAggressivesOptionQuickSpindownEnable
);
2551 //******************************************************************************
2552 // restoreUserSpinDownTimeout
2554 //******************************************************************************
2557 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2561 kPMMinutesToSpinDown
, 0, kAggressivesOptionQuickSpindownDisable
);
2564 //******************************************************************************
2567 //******************************************************************************
2571 IOPMrootDomain::sleepSystem( void )
2573 return sleepSystemOptions(NULL
);
2578 IOPMrootDomain::sleepSystemOptions( OSDictionary
*options
)
2580 OSObject
*obj
= NULL
;
2581 OSString
*reason
= NULL
;
2582 /* sleepSystem is a public function, and may be called by any kernel driver.
2583 * And that's bad - drivers should sleep the system by calling
2584 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2586 * Note that user space app calls to IOPMSleepSystem() will also travel
2587 * this code path and thus be correctly identified as software sleeps.
2590 if (options
&& options
->getObject("OSSwitch")) {
2591 // Log specific sleep cause for OS Switch hibernation
2592 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate
);
2595 if (options
&& (obj
= options
->getObject("Sleep Reason"))) {
2596 reason
= OSDynamicCast(OSString
, obj
);
2597 if (reason
&& reason
->isEqualTo(kIOPMDarkWakeThermalEmergencyKey
)) {
2598 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency
);
2602 return privateSleepSystem( kIOPMSleepReasonSoftware
);
2607 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason
)
2609 /* Called from both gated and non-gated context */
2611 if (!checkSystemSleepEnabled() || !pmPowerStateQueue
) {
2612 return kIOReturnNotPermitted
;
2615 pmPowerStateQueue
->submitPowerEvent(
2616 kPowerEventPolicyStimulus
,
2617 (void *) kStimulusDemandSystemSleep
,
2620 return kIOReturnSuccess
;
2623 //******************************************************************************
2626 // This overrides powerChangeDone in IOService.
2627 //******************************************************************************
2629 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState
)
2631 #if !__i386__ && !__x86_64__
2632 uint64_t timeSinceReset
= 0;
2635 unsigned long newState
;
2637 clock_usec_t microsecs
;
2638 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
2639 clock_sec_t adjWakeTime
;
2640 IOPMCalendarStruct nowCalendar
;
2641 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
2644 newState
= getPowerState();
2645 DLOG("PowerChangeDone: %s->%s\n",
2646 getPowerStateString((uint32_t) previousPowerState
), getPowerStateString((uint32_t) getPowerState()));
2648 if (previousPowerState
== newState
) {
2652 notifierThread
= current_thread();
2653 switch (getPowerState()) {
2655 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
2656 if (kPMCalendarTypeInvalid
!= _aotWakeTimeCalendar
.selector
) {
2659 PEGetUTCTimeOfDay(&secs
, µsecs
);
2662 if ((kIOPMAOTModeRespectTimers
& _aotMode
) && (_scheduledAlarmUTC
< _aotWakeTimeUTC
)) {
2663 IOLog("use _scheduledAlarmUTC\n");
2664 adjWakeTime
= _scheduledAlarmUTC
;
2665 } else if (_aotExit
|| (kIOPMWakeEventAOTExitFlags
& _aotPendingFlags
)) {
2666 IOLog("accelerate _aotWakeTime for exit\n");
2668 } else if (kIOPMDriverAssertionLevelOn
== getPMAssertionLevel(kIOPMDriverAssertionCPUBit
)) {
2669 IOLog("accelerate _aotWakeTime for assertion\n");
2673 IOPMConvertSecondsToCalendar(adjWakeTime
, &_aotWakeTimeCalendar
);
2676 IOPMConvertSecondsToCalendar(secs
, &nowCalendar
);
2677 IOLog("aotSleep at " YMDTF
" sched: " YMDTF
"\n", YMDT(&nowCalendar
), YMDT(&_aotWakeTimeCalendar
));
2679 IOReturn __unused ret
= setMaintenanceWakeCalendar(&_aotWakeTimeCalendar
);
2680 assert(kIOReturnSuccess
== ret
);
2682 if (_aotLastWakeTime
) {
2683 _aotMetrics
->totalTime
+= mach_absolute_time() - _aotLastWakeTime
;
2684 if (_aotMetrics
->sleepCount
&& (_aotMetrics
->sleepCount
<= kIOPMAOTMetricsKernelWakeCountMax
)) {
2685 strlcpy(&_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
- 1][0],
2687 sizeof(_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
]));
2690 _aotPendingFlags
&= ~kIOPMWakeEventAOTPerCycleFlags
;
2691 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
2692 acceptSystemWakeEvents(true);
2694 // re-enable this timer for next sleep
2695 cancelIdleSleepTimer();
2697 clock_get_calendar_absolute_and_microtime(&secs
, µsecs
, &now
);
2699 gIOLastSleepTime
.tv_sec
= secs
;
2700 gIOLastSleepTime
.tv_usec
= microsecs
;
2701 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
2702 if (!_aotLastWakeTime
) {
2703 gIOLastUserSleepTime
= gIOLastSleepTime
;
2706 gIOLastUserSleepTime
= gIOLastSleepTime
;
2707 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
2709 gIOLastWakeTime
.tv_sec
= 0;
2710 gIOLastWakeTime
.tv_usec
= 0;
2711 gIOLastSleepAbsTime
= now
;
2713 if (wake2DarkwakeDelay
&& sleepDelaysReport
) {
2714 clock_sec_t wake2DarkwakeSecs
, darkwake2SleepSecs
;
2715 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2717 SUB_ABSOLUTETIME(&now
, &ts_sleepStart
);
2718 absolutetime_to_microtime(now
, &darkwake2SleepSecs
, µsecs
);
2719 absolutetime_to_microtime(wake2DarkwakeDelay
, &wake2DarkwakeSecs
, µsecs
);
2720 HISTREPORT_TALLYVALUE(sleepDelaysReport
,
2721 (int64_t)(wake2DarkwakeSecs
+ darkwake2SleepSecs
));
2723 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs
, (unsigned long)darkwake2SleepSecs
);
2724 wake2DarkwakeDelay
= 0;
2727 LOG("System %sSleep\n", gIOHibernateState
? "Safe" : "");
2729 IOHibernateSystemHasSlept();
2731 evaluateSystemSleepPolicyFinal();
2733 LOG("System Sleep\n");
2735 if (thermalWarningState
) {
2736 const OSSymbol
*event
= OSSymbol::withCString(kIOPMThermalLevelWarningKey
);
2738 systemPowerEventOccurred(event
, kIOPMThermalLevelUnknown
);
2742 assertOnWakeSecs
= 0;
2743 lowBatteryCondition
= false;
2745 #if DEVELOPMENT || DEBUG
2746 extern int g_should_log_clock_adjustments
;
2747 if (g_should_log_clock_adjustments
) {
2748 clock_sec_t secs
= 0;
2749 clock_usec_t microsecs
= 0;
2750 uint64_t now_b
= mach_absolute_time();
2754 PEGetUTCTimeOfDay(&secs
, µsecs
);
2756 uint64_t now_a
= mach_absolute_time();
2757 os_log(OS_LOG_DEFAULT
, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
2758 __func__
, (unsigned long)secs
, microsecs
, now_b
, now_a
);
2762 getPlatform()->sleepKernel();
2764 // The CPU(s) are off at this point,
2765 // Code will resume execution here upon wake.
2767 clock_get_uptime(&gIOLastWakeAbsTime
);
2768 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime
);
2769 _highestCapability
= 0;
2772 IOHibernateSystemWake();
2775 // sleep transition complete
2776 gSleepOrShutdownPending
= 0;
2778 // trip the reset of the calendar clock
2779 clock_wakeup_calendar();
2780 clock_get_calendar_microtime(&secs
, µsecs
);
2781 gIOLastWakeTime
.tv_sec
= secs
;
2782 gIOLastWakeTime
.tv_usec
= microsecs
;
2784 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
2786 if (_aotWakeTimeCalendar
.selector
!= kPMCalendarTypeInvalid
) {
2787 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeInvalid
;
2790 PEGetUTCTimeOfDay(&secs
, µsecs
);
2791 IOPMConvertSecondsToCalendar(secs
, &nowCalendar
);
2792 IOLog("aotWake at " YMDTF
" sched: " YMDTF
"\n", YMDT(&nowCalendar
), YMDT(&_aotWakeTimeCalendar
));
2793 _aotMetrics
->sleepCount
++;
2794 _aotLastWakeTime
= gIOLastWakeAbsTime
;
2795 if (_aotMetrics
->sleepCount
<= kIOPMAOTMetricsKernelWakeCountMax
) {
2796 _aotMetrics
->kernelSleepTime
[_aotMetrics
->sleepCount
- 1]
2797 = (((uint64_t) gIOLastSleepTime
.tv_sec
) << 10) + (gIOLastSleepTime
.tv_usec
/ 1000);
2798 _aotMetrics
->kernelWakeTime
[_aotMetrics
->sleepCount
- 1]
2799 = (((uint64_t) gIOLastWakeTime
.tv_sec
) << 10) + (gIOLastWakeTime
.tv_usec
/ 1000);
2803 if (_aotWakeTimeUTC
<= secs
) {
2804 _aotTestTime
= _aotTestTime
+ _aotTestInterval
;
2806 setWakeTime(_aotTestTime
);
2809 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
2812 LOG("System %sWake\n", gIOHibernateState
? "SafeSleep " : "");
2815 lastSleepReason
= 0;
2817 _lastDebugWakeSeconds
= _debugWakeSeconds
;
2818 _debugWakeSeconds
= 0;
2819 _scheduledAlarms
= 0;
2821 #if defined(__i386__) || defined(__x86_64__)
2822 kdebugTrace(kPMLogSystemWake
, 0, 0, 0);
2823 wranglerTickled
= false;
2824 graphicsSuppressed
= false;
2825 darkWakePostTickle
= false;
2826 darkWakeHibernateError
= false;
2827 darkWakeToSleepASAP
= true;
2828 logGraphicsClamp
= true;
2829 sleepTimerMaintenance
= false;
2830 sleepToStandby
= false;
2831 wranglerTickleLatched
= false;
2832 userWasActive
= false;
2833 isRTCAlarmWake
= false;
2834 fullWakeReason
= kFullWakeReasonNone
;
2836 OSString
* wakeType
= OSDynamicCast(
2837 OSString
, getProperty(kIOPMRootDomainWakeTypeKey
));
2838 OSString
* wakeReason
= OSDynamicCast(
2839 OSString
, getProperty(kIOPMRootDomainWakeReasonKey
));
2841 if (wakeReason
&& (wakeReason
->getLength() >= 2) &&
2842 gWakeReasonString
[0] == '\0') {
2843 // Until the platform driver can claim its wake reasons
2844 strlcat(gWakeReasonString
, wakeReason
->getCStringNoCopy(),
2845 sizeof(gWakeReasonString
));
2848 if (wakeType
&& wakeType
->isEqualTo(kIOPMrootDomainWakeTypeLowBattery
)) {
2849 lowBatteryCondition
= true;
2850 darkWakeMaintenance
= true;
2851 } else if ((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) != 0) {
2853 OSNumber
* hibOptions
= OSDynamicCast(
2854 OSNumber
, getProperty(kIOHibernateOptionsKey
));
2855 if (hibernateAborted
|| ((hibOptions
&&
2856 !(hibOptions
->unsigned32BitValue() & kIOHibernateOptionDarkWake
)))) {
2857 // Hibernate aborted, or EFI brought up graphics
2858 wranglerTickled
= true;
2859 if (hibernateAborted
) {
2860 DLOG("Hibernation aborted\n");
2862 DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions
->unsigned32BitValue());
2867 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeUser
) ||
2868 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeAlarm
))) {
2869 // User wake or RTC alarm
2870 wranglerTickled
= true;
2871 if (wakeType
->isEqualTo(kIOPMRootDomainWakeTypeAlarm
)) {
2872 isRTCAlarmWake
= true;
2874 } else if (wakeType
&&
2875 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer
)) {
2876 // SMC standby timer trumps SleepX
2877 darkWakeMaintenance
= true;
2878 sleepTimerMaintenance
= true;
2879 } else if ((_lastDebugWakeSeconds
!= 0) &&
2880 ((gDarkWakeFlags
& kDarkWakeFlagAlarmIsDark
) == 0)) {
2881 // SleepX before maintenance
2882 wranglerTickled
= true;
2883 } else if (wakeType
&&
2884 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeMaintenance
)) {
2885 darkWakeMaintenance
= true;
2886 } else if (wakeType
&&
2887 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepService
)) {
2888 darkWakeMaintenance
= true;
2889 darkWakeSleepService
= true;
2891 if (kIOHibernateStateWakingFromHibernate
== gIOHibernateState
) {
2892 sleepToStandby
= true;
2895 } else if (wakeType
&&
2896 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeHibernateError
)) {
2897 darkWakeMaintenance
= true;
2898 darkWakeHibernateError
= true;
2900 // Unidentified wake source, resume to full wake if debug
2901 // alarm is pending.
2903 if (_lastDebugWakeSeconds
&&
2904 (!wakeReason
|| wakeReason
->isEqualTo(""))) {
2905 wranglerTickled
= true;
2910 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer
)) {
2911 darkWakeMaintenance
= true;
2912 sleepTimerMaintenance
= true;
2913 } else if (hibernateAborted
|| !wakeType
||
2914 !wakeType
->isEqualTo(kIOPMRootDomainWakeTypeMaintenance
) ||
2915 !wakeReason
|| !wakeReason
->isEqualTo("RTC")) {
2916 // Post a HID tickle immediately - except for RTC maintenance wake.
2917 wranglerTickled
= true;
2919 darkWakeMaintenance
= true;
2923 if (wranglerTickled
) {
2924 darkWakeToSleepASAP
= false;
2925 fullWakeReason
= kFullWakeReasonLocalUser
;
2927 } else if (displayPowerOnRequested
&& checkSystemCanSustainFullWake()) {
2928 handleDisplayPowerOn();
2929 } else if (!darkWakeMaintenance
) {
2930 // Early/late tickle for non-maintenance wake.
2931 if (((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) ==
2932 kDarkWakeFlagHIDTickleEarly
) ||
2933 ((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) ==
2934 kDarkWakeFlagHIDTickleLate
)) {
2935 darkWakePostTickle
= true;
2938 #else /* !__i386__ && !__x86_64__ */
2939 timeSinceReset
= ml_get_time_since_reset();
2941 kdebugTrace(kPMLogSystemWake
, 0, timeSinceReset
>> 32, timeSinceReset
);
2942 // stay awake for at least 30 seconds
2943 wranglerTickled
= true;
2944 fullWakeReason
= kFullWakeReasonLocalUser
;
2945 startIdleSleepTimer(30);
2949 thread_call_enter(updateConsoleUsersEntry
);
2951 changePowerStateToPriv(getRUN_STATE());
2954 #if !__i386__ && !__x86_64__
2958 DLOG("Force re-evaluating aggressiveness\n");
2959 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
2960 pmPowerStateQueue
->submitPowerEvent(
2961 kPowerEventPolicyStimulus
,
2962 (void *) kStimulusNoIdleSleepPreventers
);
2964 // After changing to ON_STATE, invalidate any previously queued
2965 // request to change to a state less than ON_STATE. This isn't
2966 // necessary for AOT_STATE or if the device has only one running
2967 // state since the changePowerStateToPriv() issued at the tail
2968 // end of SLEEP_STATE case should take care of that.
2969 if (getPowerState() == ON_STATE
) {
2970 changePowerStateToPriv(ON_STATE
);
2974 #endif /* !__i386__ && !__x86_64__ */
2976 notifierThread
= NULL
;
2979 //******************************************************************************
2980 // requestPowerDomainState
2982 // Extend implementation in IOService. Running on PM work loop thread.
2983 //******************************************************************************
2986 IOPMrootDomain::requestPowerDomainState(
2987 IOPMPowerFlags childDesire
,
2988 IOPowerConnection
* childConnection
,
2989 unsigned long specification
)
2991 // Idle and system sleep prevention flags affects driver desire.
2992 // Children desire are irrelevant so they are cleared.
2994 return super::requestPowerDomainState(0, childConnection
, specification
);
2998 //******************************************************************************
2999 // updatePreventIdleSleepList
3001 // Called by IOService on PM work loop.
3002 // Returns true if PM policy recognized the driver's desire to prevent idle
3003 // sleep and updated the list of idle sleep preventers. Returns false otherwise
3004 //******************************************************************************
3007 IOPMrootDomain::updatePreventIdleSleepList(
3008 IOService
* service
, bool addNotRemove
)
3010 unsigned int oldCount
;
3012 oldCount
= idleSleepPreventersCount();
3013 return updatePreventIdleSleepListInternal(service
, addNotRemove
, oldCount
);
3017 IOPMrootDomain::updatePreventIdleSleepListInternal(
3018 IOService
* service
, bool addNotRemove
, unsigned int oldCount
)
3020 unsigned int newCount
;
3024 #if defined(__i386__) || defined(__x86_64__)
3025 // Disregard disk I/O (besides the display wrangler) as a factor preventing
3026 // idle sleep, except in the case of legacy disk I/O
3027 if (service
&& (service
!= wrangler
) && (service
!= this)) {
3034 preventIdleSleepList
->setObject(service
);
3035 DLOG("prevent idle sleep list: %s+ (%u)\n",
3036 service
->getName(), preventIdleSleepList
->getCount());
3037 } else if (preventIdleSleepList
->member(service
)) {
3038 preventIdleSleepList
->removeObject(service
);
3039 DLOG("prevent idle sleep list: %s- (%u)\n",
3040 service
->getName(), preventIdleSleepList
->getCount());
3043 newCount
= idleSleepPreventersCount();
3045 if ((oldCount
== 0) && (newCount
!= 0)) {
3046 // Driver added to empty prevent list.
3047 // Update the driver desire to prevent idle sleep.
3048 // Driver desire does not prevent demand sleep.
3050 changePowerStateTo(getRUN_STATE());
3051 } else if ((oldCount
!= 0) && (newCount
== 0)) {
3052 // Last driver removed from prevent list.
3053 // Drop the driver clamp to allow idle sleep.
3055 changePowerStateTo(SLEEP_STATE
);
3056 evaluatePolicy( kStimulusNoIdleSleepPreventers
);
3058 messageClient(kIOPMMessageIdleSleepPreventers
, systemCapabilityNotifier
,
3059 &newCount
, sizeof(newCount
));
3061 #if defined(__i386__) || defined(__x86_64__)
3062 if (addNotRemove
&& (service
== wrangler
) && !checkSystemCanSustainFullWake()) {
3063 DLOG("Cannot cancel idle sleep\n");
3064 return false; // do not idle-cancel
3071 //******************************************************************************
3073 //******************************************************************************
3076 IOPMrootDomain::startSpinDump(uint32_t spindumpKind
)
3078 messageClients(kIOPMMessageLaunchBootSpinDump
, (void *)(uintptr_t)spindumpKind
);
3081 //******************************************************************************
3082 // preventSystemSleepListUpdate
3084 // Called by IOService on PM work loop.
3085 //******************************************************************************
3088 IOPMrootDomain::updatePreventSystemSleepList(
3089 IOService
* service
, bool addNotRemove
)
3091 unsigned int oldCount
, newCount
;
3094 if (this == service
) {
3098 oldCount
= preventSystemSleepList
->getCount();
3100 preventSystemSleepList
->setObject(service
);
3101 DLOG("prevent system sleep list: %s+ (%u)\n",
3102 service
->getName(), preventSystemSleepList
->getCount());
3103 if (!assertOnWakeSecs
&& gIOLastWakeAbsTime
) {
3105 clock_usec_t microsecs
;
3106 clock_get_uptime(&now
);
3107 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
3108 absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
);
3109 if (assertOnWakeReport
) {
3110 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
);
3111 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
);
3114 } else if (preventSystemSleepList
->member(service
)) {
3115 preventSystemSleepList
->removeObject(service
);
3116 DLOG("prevent system sleep list: %s- (%u)\n",
3117 service
->getName(), preventSystemSleepList
->getCount());
3119 if ((oldCount
!= 0) && (preventSystemSleepList
->getCount() == 0)) {
3120 // Lost all system sleep preventers.
3121 // Send stimulus if system sleep was blocked, and is in dark wake.
3122 evaluatePolicy( kStimulusDarkWakeEvaluate
);
3125 newCount
= preventSystemSleepList
->getCount();
3126 messageClient(kIOPMMessageSystemSleepPreventers
, systemCapabilityNotifier
,
3127 &newCount
, sizeof(newCount
));
3131 IOPMrootDomain::copySleepPreventersList(OSArray
**idleSleepList
, OSArray
**systemSleepList
)
3133 OSCollectionIterator
*iterator
= NULL
;
3134 OSObject
*object
= NULL
;
3135 OSArray
*array
= NULL
;
3137 if (!gIOPMWorkLoop
->inGate()) {
3138 gIOPMWorkLoop
->runAction(
3139 OSMemberFunctionCast(IOWorkLoop::Action
, this,
3140 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList
),
3141 this, (void *)idleSleepList
, (void *)systemSleepList
);
3145 if (idleSleepList
&& preventIdleSleepList
&& (preventIdleSleepList
->getCount() != 0)) {
3146 iterator
= OSCollectionIterator::withCollection(preventIdleSleepList
);
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 *idleSleepList
= array
;
3160 if (systemSleepList
&& preventSystemSleepList
&& (preventSystemSleepList
->getCount() != 0)) {
3161 iterator
= OSCollectionIterator::withCollection(preventSystemSleepList
);
3162 array
= OSArray::withCapacity(5);
3164 while ((object
= iterator
->getNextObject())) {
3165 IOService
*service
= OSDynamicCast(IOService
, object
);
3167 array
->setObject(OSSymbol::withCString(service
->getName()));
3171 iterator
->release();
3172 *systemSleepList
= array
;
3177 IOPMrootDomain::copySleepPreventersListWithID(OSArray
**idleSleepList
, OSArray
**systemSleepList
)
3179 OSCollectionIterator
*iterator
= NULL
;
3180 OSObject
*object
= NULL
;
3181 OSArray
*array
= NULL
;
3183 if (!gIOPMWorkLoop
->inGate()) {
3184 gIOPMWorkLoop
->runAction(
3185 OSMemberFunctionCast(IOWorkLoop::Action
, this,
3186 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID
),
3187 this, (void *)idleSleepList
, (void *)systemSleepList
);
3191 if (idleSleepList
&& preventIdleSleepList
&& (preventIdleSleepList
->getCount() != 0)) {
3192 iterator
= OSCollectionIterator::withCollection(preventIdleSleepList
);
3193 array
= OSArray::withCapacity(5);
3195 while ((object
= iterator
->getNextObject())) {
3196 IOService
*service
= OSDynamicCast(IOService
, object
);
3198 OSDictionary
*dict
= OSDictionary::withCapacity(2);
3200 OSNumber
*id
= OSNumber::withNumber(service
->getRegistryEntryID(), 64);
3201 dict
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, id
);
3202 dict
->setObject(kIOPMDriverAssertionOwnerStringKey
, OSSymbol::withCString(service
->getName()));
3203 array
->setObject(dict
);
3210 iterator
->release();
3211 *idleSleepList
= array
;
3214 if (systemSleepList
&& preventSystemSleepList
&& (preventSystemSleepList
->getCount() != 0)) {
3215 iterator
= OSCollectionIterator::withCollection(preventSystemSleepList
);
3216 array
= OSArray::withCapacity(5);
3218 while ((object
= iterator
->getNextObject())) {
3219 IOService
*service
= OSDynamicCast(IOService
, object
);
3221 OSDictionary
*dict
= OSDictionary::withCapacity(2);
3223 OSNumber
*id
= OSNumber::withNumber(service
->getRegistryEntryID(), 64);
3224 dict
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, id
);
3225 dict
->setObject(kIOPMDriverAssertionOwnerStringKey
, OSSymbol::withCString(service
->getName()));
3226 array
->setObject(dict
);
3233 iterator
->release();
3234 *systemSleepList
= array
;
3238 //******************************************************************************
3241 // Override the superclass implementation to send a different message type.
3242 //******************************************************************************
3245 IOPMrootDomain::tellChangeDown( unsigned long stateNum
)
3247 DLOG("tellChangeDown %s->%s\n",
3248 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3250 if (SLEEP_STATE
== stateNum
) {
3251 // Legacy apps were already told in the full->dark transition
3252 if (!ignoreTellChangeDown
) {
3253 tracePoint( kIOPMTracePointSleepApplications
);
3255 tracePoint( kIOPMTracePointSleepPriorityClients
);
3259 if (!ignoreTellChangeDown
) {
3260 userActivityAtSleep
= userActivityCount
;
3261 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep
);
3263 if (SLEEP_STATE
== stateNum
) {
3264 hibernateAborted
= false;
3266 // Direct callout into OSKext so it can disable kext unloads
3267 // during sleep/wake to prevent deadlocks.
3268 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep
);
3270 IOService::updateConsoleUsers(NULL
, kIOMessageSystemWillSleep
);
3272 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3273 // But tellClientsWithResponse() must be called for both.
3274 ignoreTellChangeDown
= true;
3278 return super::tellClientsWithResponse( kIOMessageSystemWillSleep
);
3281 //******************************************************************************
3284 // Override the superclass implementation to send a different message type.
3285 // This must be idle sleep since we don't ask during any other power change.
3286 //******************************************************************************
3289 IOPMrootDomain::askChangeDown( unsigned long stateNum
)
3291 DLOG("askChangeDown %s->%s\n",
3292 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3294 // Don't log for dark wake entry
3295 if (kSystemTransitionSleep
== _systemTransitionType
) {
3296 tracePoint( kIOPMTracePointSleepApplications
);
3299 return super::tellClientsWithResponse( kIOMessageCanSystemSleep
);
3302 //******************************************************************************
3303 // askChangeDownDone
3305 // An opportunity for root domain to cancel the power transition,
3306 // possibily due to an assertion created by powerd in response to
3307 // kIOMessageCanSystemSleep.
3310 // full -> dark wake transition
3311 // 1. Notify apps and powerd with kIOMessageCanSystemSleep
3312 // 2. askChangeDownDone()
3313 // dark -> sleep transition
3314 // 1. Notify powerd with kIOMessageCanSystemSleep
3315 // 2. askChangeDownDone()
3318 // full -> dark wake transition
3319 // 1. Notify powerd with kIOMessageCanSystemSleep
3320 // 2. askChangeDownDone()
3321 // dark -> sleep transition
3322 // 1. Notify powerd with kIOMessageCanSystemSleep
3323 // 2. askChangeDownDone()
3324 //******************************************************************************
3327 IOPMrootDomain::askChangeDownDone(
3328 IOPMPowerChangeFlags
* inOutChangeFlags
, bool * cancel
)
3330 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3331 *inOutChangeFlags
, *cancel
,
3332 _systemTransitionType
,
3333 _currentCapability
, _pendingCapability
);
3335 if ((false == *cancel
) && (kSystemTransitionSleep
== _systemTransitionType
)) {
3336 // Dark->Sleep transition.
3337 // Check if there are any deny sleep assertions.
3338 // lastSleepReason already set by handleOurPowerChangeStart()
3340 if (!checkSystemCanSleep(lastSleepReason
)) {
3341 // Cancel dark wake to sleep transition.
3342 // Must re-scan assertions upon entering dark wake.
3345 DLOG("cancel dark->sleep\n");
3347 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
3348 if (_aotMode
&& (kPMCalendarTypeInvalid
!= _aotWakeTimeCalendar
.selector
)) {
3349 uint64_t now
= mach_continuous_time();
3350 if (((now
+ _aotWakePreWindow
) >= _aotWakeTimeContinuous
)
3351 && (now
< (_aotWakeTimeContinuous
+ _aotWakePostWindow
))) {
3353 IOLog("AOT wake window cancel: %qd, %qd\n", now
, _aotWakeTimeContinuous
);
3356 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
3360 //******************************************************************************
3361 // systemDidNotSleep
3363 // Work common to both canceled or aborted sleep.
3364 //******************************************************************************
3367 IOPMrootDomain::systemDidNotSleep( void )
3369 // reset console lock state
3370 thread_call_enter(updateConsoleUsersEntry
);
3373 if (idleSleepEnabled
) {
3374 // stay awake for at least idleSeconds
3375 startIdleSleepTimer(idleSeconds
);
3378 if (idleSleepEnabled
&& !userIsActive
) {
3379 // Manually start the idle sleep timer besides waiting for
3380 // the user to become inactive.
3381 startIdleSleepTimer( kIdleSleepRetryInterval
);
3385 preventTransitionToUserActive(false);
3386 IOService::setAdvisoryTickleEnable( true );
3388 // After idle revert and cancel, send a did-change message to powerd
3389 // to balance the previous will-change message. Kernel clients do not
3390 // need this since sleep cannot be canceled once they are notified.
3392 if (toldPowerdCapWillChange
&& systemCapabilityNotifier
&&
3393 (_pendingCapability
!= _currentCapability
) &&
3394 ((_systemMessageClientMask
& kSystemMessageClientPowerd
) != 0)) {
3395 // Differs from a real capability gain change where notifyRef != 0,
3396 // but it is zero here since no response is expected.
3398 IOPMSystemCapabilityChangeParameters params
;
3400 bzero(¶ms
, sizeof(params
));
3401 params
.fromCapabilities
= _pendingCapability
;
3402 params
.toCapabilities
= _currentCapability
;
3403 params
.changeFlags
= kIOPMSystemCapabilityDidChange
;
3405 DLOG("MESG cap %x->%x did change\n",
3406 params
.fromCapabilities
, params
.toCapabilities
);
3407 messageClient(kIOMessageSystemCapabilityChange
, systemCapabilityNotifier
,
3408 ¶ms
, sizeof(params
));
3412 //******************************************************************************
3415 // Notify registered applications and kernel clients that we are not dropping
3418 // We override the superclass implementation so we can send a different message
3419 // type to the client or application being notified.
3421 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3422 //******************************************************************************
3425 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum
)
3427 DLOG("tellNoChangeDown %s->%s\n",
3428 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3430 // Sleep canceled, clear the sleep trace point.
3431 tracePoint(kIOPMTracePointSystemUp
);
3433 systemDidNotSleep();
3434 return tellClients( kIOMessageSystemWillNotSleep
);
3437 //******************************************************************************
3440 // Notify registered applications and kernel clients that we are raising power.
3442 // We override the superclass implementation so we can send a different message
3443 // type to the client or application being notified.
3444 //******************************************************************************
3447 IOPMrootDomain::tellChangeUp( unsigned long stateNum
)
3449 DLOG("tellChangeUp %s->%s\n",
3450 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3452 ignoreTellChangeDown
= false;
3454 if (stateNum
== ON_STATE
) {
3455 // Direct callout into OSKext so it can disable kext unloads
3456 // during sleep/wake to prevent deadlocks.
3457 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn
);
3459 // Notify platform that sleep was cancelled or resumed.
3460 getPlatform()->callPlatformFunction(
3461 sleepMessagePEFunction
, false,
3462 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn
,
3465 if (getPowerState() == ON_STATE
) {
3466 // Sleep was cancelled by idle cancel or revert
3467 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
3468 // rdar://problem/50363791
3469 // If system is in dark wake and sleep is cancelled, do not
3470 // send SystemWillPowerOn/HasPoweredOn messages to kernel
3471 // priority clients. They haven't yet seen a SystemWillSleep
3472 // message before the cancellation. So make sure the kernel
3473 // client bit is cleared in _systemMessageClientMask before
3474 // invoking the tellClients() below. This bit may have been
3475 // set by handleOurPowerChangeStart() anticipating a successful
3476 // sleep and setting the filter mask ahead of time allows the
3477 // SystemWillSleep message to go through.
3478 _systemMessageClientMask
&= ~kSystemMessageClientKernel
;
3481 systemDidNotSleep();
3482 tellClients( kIOMessageSystemWillPowerOn
);
3485 tracePoint( kIOPMTracePointWakeApplications
);
3486 tellClients( kIOMessageSystemHasPoweredOn
);
3490 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3491 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3492 ((params)->fromCapabilities & (flag)) && \
3493 (((params)->toCapabilities & (flag)) == 0))
3495 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3496 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3497 ((params)->toCapabilities & (flag)) && \
3498 (((params)->fromCapabilities & (flag)) == 0))
3500 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3501 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3502 ((params)->fromCapabilities & (flag)) && \
3503 (((params)->toCapabilities & (flag)) == 0))
3505 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3506 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3507 ((params)->toCapabilities & (flag)) && \
3508 (((params)->fromCapabilities & (flag)) == 0))
3510 //******************************************************************************
3511 // sysPowerDownHandler
3513 // Perform a vfs sync before system sleep.
3514 //******************************************************************************
3517 IOPMrootDomain::sysPowerDownHandler(
3518 void * target
, void * refCon
,
3519 UInt32 messageType
, IOService
* service
,
3520 void * messageArgs
, vm_size_t argSize
)
3522 static UInt32 lastSystemMessageType
= 0;
3525 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType
));
3527 // rdar://problem/50363791
3528 // Sanity check to make sure the SystemWill/Has message types are
3529 // received in the expected order for all kernel priority clients.
3530 if (messageType
== kIOMessageSystemWillSleep
||
3531 messageType
== kIOMessageSystemWillPowerOn
||
3532 messageType
== kIOMessageSystemHasPoweredOn
) {
3533 switch (messageType
) {
3534 case kIOMessageSystemWillPowerOn
:
3535 assert(lastSystemMessageType
== kIOMessageSystemWillSleep
);
3537 case kIOMessageSystemHasPoweredOn
:
3538 assert(lastSystemMessageType
== kIOMessageSystemWillPowerOn
);
3542 lastSystemMessageType
= messageType
;
3546 return kIOReturnUnsupported
;
3549 if (messageType
== kIOMessageSystemCapabilityChange
) {
3550 IOPMSystemCapabilityChangeParameters
* params
=
3551 (IOPMSystemCapabilityChangeParameters
*) messageArgs
;
3553 // Interested applications have been notified of an impending power
3554 // change and have acked (when applicable).
3555 // This is our chance to save whatever state we can before powering
3557 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3560 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3561 params
->fromCapabilities
, params
->toCapabilities
,
3562 params
->changeFlags
);
3564 if (CAP_WILL_CHANGE_TO_OFF(params
, kIOPMSystemCapabilityCPU
)) {
3565 // We will ack within 20 seconds
3566 params
->maxWaitForReply
= 20 * 1000 * 1000;
3569 gRootDomain
->evaluateSystemSleepPolicyEarly();
3571 // add in time we could spend freeing pages
3572 if (gRootDomain
->hibernateMode
&& !gRootDomain
->hibernateDisabled
) {
3573 params
->maxWaitForReply
= kCapabilityClientMaxWait
;
3575 DLOG("sysPowerDownHandler max wait %d s\n",
3576 (int) (params
->maxWaitForReply
/ 1000 / 1000));
3579 // Notify platform that sleep has begun, after the early
3580 // sleep policy evaluation.
3581 getPlatform()->callPlatformFunction(
3582 sleepMessagePEFunction
, false,
3583 (void *)(uintptr_t) kIOMessageSystemWillSleep
,
3586 if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
)) {
3587 // Purposely delay the ack and hope that shutdown occurs quickly.
3588 // Another option is not to schedule the thread and wait for
3590 AbsoluteTime deadline
;
3591 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
3592 thread_call_enter1_delayed(
3593 gRootDomain
->diskSyncCalloutEntry
,
3594 (thread_call_param_t
)(uintptr_t) params
->notifyRef
,
3598 gRootDomain
->diskSyncCalloutEntry
,
3599 (thread_call_param_t
)(uintptr_t) params
->notifyRef
);
3603 else if (CAP_DID_CHANGE_TO_ON(params
, kIOPMSystemCapabilityCPU
)) {
3604 // We will ack within 110 seconds
3605 params
->maxWaitForReply
= 110 * 1000 * 1000;
3608 gRootDomain
->diskSyncCalloutEntry
,
3609 (thread_call_param_t
)(uintptr_t) params
->notifyRef
);
3612 ret
= kIOReturnSuccess
;
3618 //******************************************************************************
3619 // handleQueueSleepWakeUUID
3621 // Called from IOPMrootDomain when we're initiating a sleep,
3622 // or indirectly from PM configd when PM decides to clear the UUID.
3623 // PM clears the UUID several minutes after successful wake from sleep,
3624 // so that we might associate App spindumps with the immediately previous
3627 // @param obj has a retain on it. We're responsible for releasing that retain.
3628 //******************************************************************************
3631 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject
*obj
)
3633 OSString
*str
= NULL
;
3635 if (kOSBooleanFalse
== obj
) {
3636 handlePublishSleepWakeUUID(NULL
);
3637 } else if ((str
= OSDynamicCast(OSString
, obj
))) {
3638 // This branch caches the UUID for an upcoming sleep/wake
3639 if (queuedSleepWakeUUIDString
) {
3640 queuedSleepWakeUUIDString
->release();
3641 queuedSleepWakeUUIDString
= NULL
;
3643 queuedSleepWakeUUIDString
= str
;
3644 queuedSleepWakeUUIDString
->retain();
3646 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString
->getCStringNoCopy());
3654 //******************************************************************************
3655 // handlePublishSleepWakeUUID
3657 // Called from IOPMrootDomain when we're initiating a sleep,
3658 // or indirectly from PM configd when PM decides to clear the UUID.
3659 // PM clears the UUID several minutes after successful wake from sleep,
3660 // so that we might associate App spindumps with the immediately previous
3662 //******************************************************************************
3665 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish
)
3670 * Clear the current UUID
3672 if (gSleepWakeUUIDIsSet
) {
3673 DLOG("SleepWake UUID cleared\n");
3675 gSleepWakeUUIDIsSet
= false;
3677 removeProperty(kIOPMSleepWakeUUIDKey
);
3678 messageClients(kIOPMMessageSleepWakeUUIDChange
, kIOPMMessageSleepWakeUUIDCleared
);
3682 * Optionally, publish a new UUID
3684 if (queuedSleepWakeUUIDString
&& shouldPublish
) {
3685 OSString
*publishThisUUID
= NULL
;
3687 publishThisUUID
= queuedSleepWakeUUIDString
;
3688 publishThisUUID
->retain();
3690 if (publishThisUUID
) {
3691 setProperty(kIOPMSleepWakeUUIDKey
, publishThisUUID
);
3692 publishThisUUID
->release();
3695 gSleepWakeUUIDIsSet
= true;
3696 messageClients(kIOPMMessageSleepWakeUUIDChange
, kIOPMMessageSleepWakeUUIDSet
);
3698 queuedSleepWakeUUIDString
->release();
3699 queuedSleepWakeUUIDString
= NULL
;
3703 //******************************************************************************
3704 // IOPMGetSleepWakeUUIDKey
3706 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
3707 // To get the full key -- a C string -- the buffer must large enough for
3708 // the end-of-string character.
3709 // The key is expected to be an UUID string
3710 //******************************************************************************
3713 IOPMCopySleepWakeUUIDKey(char *buffer
, size_t buf_len
)
3715 if (!gSleepWakeUUIDIsSet
) {
3719 if (buffer
!= NULL
) {
3722 string
= (OSString
*)
3723 gRootDomain
->copyProperty(kIOPMSleepWakeUUIDKey
);
3725 if (string
== NULL
) {
3728 strlcpy(buffer
, string
->getCStringNoCopy(), buf_len
);
3737 //******************************************************************************
3738 // initializeBootSessionUUID
3740 // Initialize the boot session uuid at boot up and sets it into registry.
3741 //******************************************************************************
3744 IOPMrootDomain::initializeBootSessionUUID(void)
3747 uuid_string_t new_uuid_string
;
3749 uuid_generate(new_uuid
);
3750 uuid_unparse_upper(new_uuid
, new_uuid_string
);
3751 memcpy(bootsessionuuid_string
, new_uuid_string
, sizeof(uuid_string_t
));
3753 setProperty(kIOPMBootSessionUUIDKey
, new_uuid_string
);
3756 //******************************************************************************
3757 // changePowerStateTo & changePowerStateToPriv
3759 // Override of these methods for logging purposes.
3760 //******************************************************************************
3763 IOPMrootDomain::changePowerStateTo( unsigned long ordinal
)
3765 DLOG("changePowerStateTo(%u)\n", (uint32_t) ordinal
);
3767 if ((ordinal
!= ON_STATE
) && (ordinal
!= AOT_STATE
) && (ordinal
!= SLEEP_STATE
)) {
3768 return kIOReturnUnsupported
;
3771 return super::changePowerStateTo(ordinal
);
3775 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal
)
3777 DLOG("changePowerStateToPriv(%u)\n", (uint32_t) ordinal
);
3779 if ((ordinal
!= ON_STATE
) && (ordinal
!= AOT_STATE
) && (ordinal
!= SLEEP_STATE
)) {
3780 return kIOReturnUnsupported
;
3783 return super::changePowerStateToPriv(ordinal
);
3786 //******************************************************************************
3789 //******************************************************************************
3792 IOPMrootDomain::activitySinceSleep(void)
3794 return userActivityCount
!= userActivityAtSleep
;
3798 IOPMrootDomain::abortHibernation(void)
3800 bool ret
= activitySinceSleep();
3802 if (ret
&& !hibernateAborted
&& checkSystemCanSustainFullWake()) {
3803 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount
, userActivityAtSleep
);
3804 hibernateAborted
= true;
3810 hibernate_should_abort(void)
3813 return gRootDomain
->abortHibernation();
3819 //******************************************************************************
3820 // willNotifyPowerChildren
3822 // Called after all interested drivers have all acknowledged the power change,
3823 // but before any power children is informed. Dispatched though a thread call,
3824 // so it is safe to perform work that might block on a sleeping disk. PM state
3825 // machine (not thread) will block w/o timeout until this function returns.
3826 //******************************************************************************
3829 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState
)
3834 if (SLEEP_STATE
== newPowerState
) {
3835 notifierThread
= current_thread();
3836 if (!tasksSuspended
) {
3837 AbsoluteTime deadline
;
3838 tasksSuspended
= TRUE
;
3839 updateTasksSuspend();
3841 clock_interval_to_deadline(10, kSecondScale
, &deadline
);
3842 #if !CONFIG_EMBEDDED
3843 vm_pageout_wait(AbsoluteTime_to_scalar(&deadline
));
3844 #endif /* !CONFIG_EMBEDDED */
3847 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
3848 _aotReadyToFullWake
= false;
3850 if (_aotLingerTime
) {
3852 IOLog("aot linger no return\n");
3853 clock_absolutetime_interval_to_deadline(_aotLingerTime
, &deadline
);
3854 clock_delay_until(deadline
);
3859 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeInvalid
;
3861 bzero(_aotMetrics
, sizeof(IOPMAOTMetrics
));
3863 } else if (!_aotNow
&& !_debugWakeSeconds
) {
3866 _aotPendingFlags
= 0;
3867 _aotTasksSuspended
= true;
3868 _aotLastWakeTime
= 0;
3869 bzero(_aotMetrics
, sizeof(IOPMAOTMetrics
));
3870 if (kIOPMAOTModeCycle
& _aotMode
) {
3871 clock_interval_to_absolutetime_interval(60, kSecondScale
, &_aotTestInterval
);
3872 _aotTestTime
= mach_continuous_time() + _aotTestInterval
;
3873 setWakeTime(_aotTestTime
);
3875 uint32_t lingerSecs
;
3876 if (!PE_parse_boot_argn("aotlinger", &lingerSecs
, sizeof(lingerSecs
))) {
3879 clock_interval_to_absolutetime_interval(lingerSecs
, kSecondScale
, &_aotLingerTime
);
3880 clock_interval_to_absolutetime_interval(2000, kMillisecondScale
, &_aotWakePreWindow
);
3881 clock_interval_to_absolutetime_interval(1100, kMillisecondScale
, &_aotWakePostWindow
);
3883 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
3886 IOHibernateSystemSleep();
3887 IOHibernateIOKitSleep();
3889 if (gRootDomain
->activitySinceSleep()) {
3890 dict
= OSDictionary::withCapacity(1);
3891 secs
= OSNumber::withNumber(1, 32);
3894 dict
->setObject(gIOPMSettingDebugWakeRelativeKey
, secs
);
3895 gRootDomain
->setProperties(dict
);
3896 MSG("Reverting sleep with relative wake\n");
3906 notifierThread
= NULL
;
3910 //******************************************************************************
3911 // sleepOnClamshellClosed
3913 // contains the logic to determine if the system should sleep when the clamshell
3915 //******************************************************************************
3918 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
3920 if (!clamshellExists
) {
3924 DLOG("clamshell closed %d, disabled %d, desktopMode %d, ac %d sleepDisabled %d\n",
3925 clamshellClosed
, clamshellDisabled
, desktopMode
, acAdaptorConnected
, clamshellSleepDisabled
);
3927 return !clamshellDisabled
&& !(desktopMode
&& acAdaptorConnected
) && !clamshellSleepDisabled
;
3931 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
3933 // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
3934 // closed && battery
3935 if (!clamshellExists
) {
3939 DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d, desktopMode %d, ac %d sleepDisabled %d\n",
3940 clamshellClosed
, clamshellDisabled
, desktopMode
, acAdaptorConnected
, clamshellSleepDisabled
);
3942 return !acAdaptorConnected
&& !clamshellSleepDisabled
;
3946 IOPMrootDomain::sendClientClamshellNotification( void )
3948 /* Only broadcast clamshell alert if clamshell exists. */
3949 if (!clamshellExists
) {
3953 setProperty(kAppleClamshellStateKey
,
3954 clamshellClosed
? kOSBooleanTrue
: kOSBooleanFalse
);
3956 setProperty(kAppleClamshellCausesSleepKey
,
3957 shouldSleepOnClamshellClosed() ? kOSBooleanTrue
: kOSBooleanFalse
);
3959 /* Argument to message is a bitfiel of
3960 * ( kClamshellStateBit | kClamshellSleepBit )
3962 messageClients(kIOPMMessageClamshellStateChange
,
3963 (void *)(uintptr_t) ((clamshellClosed
? kClamshellStateBit
: 0)
3964 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit
: 0)));
3967 //******************************************************************************
3968 // getSleepSupported
3971 //******************************************************************************
3974 IOPMrootDomain::getSleepSupported( void )
3976 return platformSleepSupport
;
3979 //******************************************************************************
3980 // setSleepSupported
3983 //******************************************************************************
3986 IOPMrootDomain::setSleepSupported( IOOptionBits flags
)
3988 DLOG("setSleepSupported(%x)\n", (uint32_t) flags
);
3989 OSBitOrAtomic(flags
, &platformSleepSupport
);
3992 //******************************************************************************
3993 // setDisableClamShellSleep
3995 //******************************************************************************
3998 IOPMrootDomain::setDisableClamShellSleep( bool val
)
4000 if (gIOPMWorkLoop
->inGate() == false) {
4001 gIOPMWorkLoop
->runAction(
4002 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::setDisableClamShellSleep
),
4008 DLOG("setDisableClamShellSleep(%x)\n", (uint32_t) val
);
4009 if (clamshellSleepDisabled
!= val
) {
4010 clamshellSleepDisabled
= val
;
4011 // If clamshellSleepDisabled is reset to 0, reevaluate if
4012 // system need to go to sleep due to clamshell state
4013 if (!clamshellSleepDisabled
&& clamshellClosed
) {
4014 handlePowerNotification(kLocalEvalClamshellCommand
);
4020 //******************************************************************************
4024 //******************************************************************************
4027 IOPMrootDomain::wakeFromDoze( void )
4029 // Preserve symbol for familes (IOUSBFamily and IOGraphics)
4035 //******************************************************************************
4038 // Adds a new feature to the supported features dictionary
4039 //******************************************************************************
4042 IOPMrootDomain::publishFeature( const char * feature
)
4044 publishFeature(feature
, kRD_AllPowerSources
, NULL
);
4047 //******************************************************************************
4048 // publishFeature (with supported power source specified)
4050 // Adds a new feature to the supported features dictionary
4051 //******************************************************************************
4054 IOPMrootDomain::publishFeature(
4055 const char *feature
,
4056 uint32_t supportedWhere
,
4057 uint32_t *uniqueFeatureID
)
4059 static uint16_t next_feature_id
= 500;
4061 OSNumber
*new_feature_data
= NULL
;
4062 OSNumber
*existing_feature
= NULL
;
4063 OSArray
*existing_feature_arr
= NULL
;
4064 OSObject
*osObj
= NULL
;
4065 uint32_t feature_value
= 0;
4067 supportedWhere
&= kRD_AllPowerSources
; // mask off any craziness!
4069 if (!supportedWhere
) {
4070 // Feature isn't supported anywhere!
4074 if (next_feature_id
> 5000) {
4075 // Far, far too many features!
4079 if (featuresDictLock
) {
4080 IOLockLock(featuresDictLock
);
4083 OSDictionary
*features
=
4084 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
4086 // Create new features dict if necessary
4087 if (features
&& OSDynamicCast(OSDictionary
, features
)) {
4088 features
= OSDictionary::withDictionary(features
);
4090 features
= OSDictionary::withCapacity(1);
4093 // Create OSNumber to track new feature
4095 next_feature_id
+= 1;
4096 if (uniqueFeatureID
) {
4097 // We don't really mind if the calling kext didn't give us a place
4098 // to stash their unique id. Many kexts don't plan to unload, and thus
4099 // have no need to remove themselves later.
4100 *uniqueFeatureID
= next_feature_id
;
4103 feature_value
= (uint32_t)next_feature_id
;
4104 feature_value
<<= 16;
4105 feature_value
+= supportedWhere
;
4107 new_feature_data
= OSNumber::withNumber(
4108 (unsigned long long)feature_value
, 32);
4110 // Does features object already exist?
4111 if ((osObj
= features
->getObject(feature
))) {
4112 if ((existing_feature
= OSDynamicCast(OSNumber
, osObj
))) {
4113 // We need to create an OSArray to hold the now 2 elements.
4114 existing_feature_arr
= OSArray::withObjects(
4115 (const OSObject
**)&existing_feature
, 1, 2);
4116 } else if ((existing_feature_arr
= OSDynamicCast(OSArray
, osObj
))) {
4117 // Add object to existing array
4118 existing_feature_arr
= OSArray::withArray(
4119 existing_feature_arr
,
4120 existing_feature_arr
->getCount() + 1);
4123 if (existing_feature_arr
) {
4124 existing_feature_arr
->setObject(new_feature_data
);
4125 features
->setObject(feature
, existing_feature_arr
);
4126 existing_feature_arr
->release();
4127 existing_feature_arr
= NULL
;
4130 // The easy case: no previously existing features listed. We simply
4131 // set the OSNumber at key 'feature' and we're on our way.
4132 features
->setObject(feature
, new_feature_data
);
4135 new_feature_data
->release();
4137 setProperty(kRootDomainSupportedFeatures
, features
);
4139 features
->release();
4141 if (featuresDictLock
) {
4142 IOLockUnlock(featuresDictLock
);
4145 // Notify EnergySaver and all those in user space so they might
4146 // re-populate their feature specific UI
4147 if (pmPowerStateQueue
) {
4148 pmPowerStateQueue
->submitPowerEvent( kPowerEventFeatureChanged
);
4152 //******************************************************************************
4153 // removePublishedFeature
4155 // Removes previously published feature
4156 //******************************************************************************
4159 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID
)
4161 IOReturn ret
= kIOReturnError
;
4162 uint32_t feature_value
= 0;
4163 uint16_t feature_id
= 0;
4164 bool madeAChange
= false;
4166 OSSymbol
*dictKey
= NULL
;
4167 OSCollectionIterator
*dictIterator
= NULL
;
4168 OSArray
*arrayMember
= NULL
;
4169 OSNumber
*numberMember
= NULL
;
4170 OSObject
*osObj
= NULL
;
4171 OSNumber
*osNum
= NULL
;
4172 OSArray
*arrayMemberCopy
;
4174 if (kBadPMFeatureID
== removeFeatureID
) {
4175 return kIOReturnNotFound
;
4178 if (featuresDictLock
) {
4179 IOLockLock(featuresDictLock
);
4182 OSDictionary
*features
=
4183 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
4185 if (features
&& OSDynamicCast(OSDictionary
, features
)) {
4186 // Any modifications to the dictionary are made to the copy to prevent
4187 // races & crashes with userland clients. Dictionary updated
4188 // automically later.
4189 features
= OSDictionary::withDictionary(features
);
4192 ret
= kIOReturnNotFound
;
4196 // We iterate 'features' dictionary looking for an entry tagged
4197 // with 'removeFeatureID'. If found, we remove it from our tracking
4198 // structures and notify the OS via a general interest message.
4200 dictIterator
= OSCollectionIterator::withCollection(features
);
4201 if (!dictIterator
) {
4205 while ((dictKey
= OSDynamicCast(OSSymbol
, dictIterator
->getNextObject()))) {
4206 osObj
= features
->getObject(dictKey
);
4208 // Each Feature is either tracked by an OSNumber
4209 if (osObj
&& (numberMember
= OSDynamicCast(OSNumber
, osObj
))) {
4210 feature_value
= numberMember
->unsigned32BitValue();
4211 feature_id
= (uint16_t)(feature_value
>> 16);
4213 if (feature_id
== (uint16_t)removeFeatureID
) {
4215 features
->removeObject(dictKey
);
4220 // Or tracked by an OSArray of OSNumbers
4221 } else if (osObj
&& (arrayMember
= OSDynamicCast(OSArray
, osObj
))) {
4222 unsigned int arrayCount
= arrayMember
->getCount();
4224 for (unsigned int i
= 0; i
< arrayCount
; i
++) {
4225 osNum
= OSDynamicCast(OSNumber
, arrayMember
->getObject(i
));
4230 feature_value
= osNum
->unsigned32BitValue();
4231 feature_id
= (uint16_t)(feature_value
>> 16);
4233 if (feature_id
== (uint16_t)removeFeatureID
) {
4235 if (1 == arrayCount
) {
4236 // If the array only contains one element, remove
4238 features
->removeObject(dictKey
);
4240 // Otherwise remove the element from a copy of the array.
4241 arrayMemberCopy
= OSArray::withArray(arrayMember
);
4242 if (arrayMemberCopy
) {
4243 arrayMemberCopy
->removeObject(i
);
4244 features
->setObject(dictKey
, arrayMemberCopy
);
4245 arrayMemberCopy
->release();
4256 dictIterator
->release();
4259 ret
= kIOReturnSuccess
;
4261 setProperty(kRootDomainSupportedFeatures
, features
);
4263 // Notify EnergySaver and all those in user space so they might
4264 // re-populate their feature specific UI
4265 if (pmPowerStateQueue
) {
4266 pmPowerStateQueue
->submitPowerEvent( kPowerEventFeatureChanged
);
4269 ret
= kIOReturnNotFound
;
4274 features
->release();
4276 if (featuresDictLock
) {
4277 IOLockUnlock(featuresDictLock
);
4282 //******************************************************************************
4283 // publishPMSetting (private)
4285 // Should only be called by PMSettingObject to publish a PM Setting as a
4286 // supported feature.
4287 //******************************************************************************
4290 IOPMrootDomain::publishPMSetting(
4291 const OSSymbol
* feature
, uint32_t where
, uint32_t * featureID
)
4293 if (noPublishPMSettings
&&
4294 (noPublishPMSettings
->getNextIndexOfObject(feature
, 0) != (unsigned int)-1)) {
4295 // Setting found in noPublishPMSettings array
4296 *featureID
= kBadPMFeatureID
;
4301 feature
->getCStringNoCopy(), where
, featureID
);
4304 //******************************************************************************
4305 // setPMSetting (private)
4307 // Internal helper to relay PM settings changes from user space to individual
4308 // drivers. Should be called only by IOPMrootDomain::setProperties.
4309 //******************************************************************************
4312 IOPMrootDomain::setPMSetting(
4313 const OSSymbol
*type
,
4316 PMSettingCallEntry
*entries
= NULL
;
4317 OSArray
*chosen
= NULL
;
4318 const OSArray
*array
;
4319 PMSettingObject
*pmso
;
4320 thread_t thisThread
;
4321 int i
, j
, count
, capacity
;
4324 return kIOReturnBadArgument
;
4329 // Update settings dict so changes are visible from copyPMSetting().
4330 fPMSettingsDict
->setObject(type
, object
);
4332 // Prep all PMSetting objects with the given 'type' for callout.
4333 array
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(type
));
4334 if (!array
|| ((capacity
= array
->getCount()) == 0)) {
4338 // Array to retain PMSetting objects targeted for callout.
4339 chosen
= OSArray::withCapacity(capacity
);
4341 goto unlock_exit
; // error
4343 entries
= IONew(PMSettingCallEntry
, capacity
);
4345 goto unlock_exit
; // error
4347 memset(entries
, 0, sizeof(PMSettingCallEntry
) * capacity
);
4349 thisThread
= current_thread();
4351 for (i
= 0, j
= 0; i
< capacity
; i
++) {
4352 pmso
= (PMSettingObject
*) array
->getObject(i
);
4353 if (pmso
->disabled
) {
4356 entries
[j
].thread
= thisThread
;
4357 queue_enter(&pmso
->calloutQueue
, &entries
[j
], PMSettingCallEntry
*, link
);
4358 chosen
->setObject(pmso
);
4368 // Call each pmso in the chosen array.
4369 for (i
= 0; i
< count
; i
++) {
4370 pmso
= (PMSettingObject
*) chosen
->getObject(i
);
4371 pmso
->dispatchPMSetting(type
, object
);
4375 for (i
= 0; i
< count
; i
++) {
4376 pmso
= (PMSettingObject
*) chosen
->getObject(i
);
4377 queue_remove(&pmso
->calloutQueue
, &entries
[i
], PMSettingCallEntry
*, link
);
4378 if (pmso
->waitThread
) {
4379 PMSETTING_WAKEUP(pmso
);
4389 IODelete(entries
, PMSettingCallEntry
, capacity
);
4392 return kIOReturnSuccess
;
4395 //******************************************************************************
4396 // copyPMSetting (public)
4398 // Allows kexts to safely read setting values, without being subscribed to
4400 //******************************************************************************
4403 IOPMrootDomain::copyPMSetting(
4404 OSSymbol
*whichSetting
)
4406 OSObject
*obj
= NULL
;
4408 if (!whichSetting
) {
4413 obj
= fPMSettingsDict
->getObject(whichSetting
);
4422 //******************************************************************************
4423 // registerPMSettingController (public)
4425 // direct wrapper to registerPMSettingController with uint32_t power source arg
4426 //******************************************************************************
4429 IOPMrootDomain::registerPMSettingController(
4430 const OSSymbol
* settings
[],
4431 IOPMSettingControllerCallback func
,
4436 return registerPMSettingController(
4438 (kIOPMSupportedOnAC
| kIOPMSupportedOnBatt
| kIOPMSupportedOnUPS
),
4439 func
, target
, refcon
, handle
);
4442 //******************************************************************************
4443 // registerPMSettingController (public)
4445 // Kexts may register for notifications when a particular setting is changed.
4446 // A list of settings is available in IOPM.h.
4448 // * settings - An OSArray containing OSSymbols. Caller should populate this
4449 // array with a list of settings caller wants notifications from.
4450 // * func - A C function callback of the type IOPMSettingControllerCallback
4451 // * target - caller may provide an OSObject *, which PM will pass as an
4452 // target to calls to "func"
4453 // * refcon - caller may provide an void *, which PM will pass as an
4454 // argument to calls to "func"
4455 // * handle - This is a return argument. We will populate this pointer upon
4456 // call success. Hold onto this and pass this argument to
4457 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
4459 // kIOReturnSuccess on success
4460 //******************************************************************************
4463 IOPMrootDomain::registerPMSettingController(
4464 const OSSymbol
* settings
[],
4465 uint32_t supportedPowerSources
,
4466 IOPMSettingControllerCallback func
,
4471 PMSettingObject
*pmso
= NULL
;
4472 OSObject
*pmsh
= NULL
;
4473 OSArray
*list
= NULL
;
4476 if (NULL
== settings
||
4479 return kIOReturnBadArgument
;
4482 pmso
= PMSettingObject::pmSettingObject(
4483 (IOPMrootDomain
*) this, func
, target
,
4484 refcon
, supportedPowerSources
, settings
, &pmsh
);
4488 return kIOReturnInternalError
;
4492 for (i
= 0; settings
[i
]; i
++) {
4493 list
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(settings
[i
]));
4495 // New array of callbacks for this setting
4496 list
= OSArray::withCapacity(1);
4497 settingsCallbacks
->setObject(settings
[i
], list
);
4501 // Add caller to the callback list
4502 list
->setObject(pmso
);
4506 // Return handle to the caller, the setting object is private.
4509 return kIOReturnSuccess
;
4512 //******************************************************************************
4513 // deregisterPMSettingObject (private)
4515 // Only called from PMSettingObject.
4516 //******************************************************************************
4519 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject
* pmso
)
4521 thread_t thisThread
= current_thread();
4522 PMSettingCallEntry
*callEntry
;
4523 OSCollectionIterator
*iter
;
4531 pmso
->disabled
= true;
4533 // Wait for all callout threads to finish.
4536 queue_iterate(&pmso
->calloutQueue
, callEntry
, PMSettingCallEntry
*, link
)
4538 if (callEntry
->thread
!= thisThread
) {
4544 assert(NULL
== pmso
->waitThread
);
4545 pmso
->waitThread
= thisThread
;
4546 PMSETTING_WAIT(pmso
);
4547 pmso
->waitThread
= NULL
;
4551 // Search each PM settings array in the kernel.
4552 iter
= OSCollectionIterator::withCollection(settingsCallbacks
);
4554 while ((sym
= OSDynamicCast(OSSymbol
, iter
->getNextObject()))) {
4555 array
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(sym
));
4556 index
= array
->getNextIndexOfObject(pmso
, 0);
4558 array
->removeObject(index
);
4569 //******************************************************************************
4570 // informCPUStateChange
4572 // Call into PM CPU code so that CPU power savings may dynamically adjust for
4573 // running on battery, with the lid closed, etc.
4575 // informCPUStateChange is a no-op on non x86 systems
4576 // only x86 has explicit support in the IntelCPUPowerManagement kext
4577 //******************************************************************************
4580 IOPMrootDomain::informCPUStateChange(
4584 #if defined(__i386__) || defined(__x86_64__)
4586 pmioctlVariableInfo_t varInfoStruct
;
4588 const char *varNameStr
= NULL
;
4589 int32_t *varIndex
= NULL
;
4591 if (kInformAC
== type
) {
4592 varNameStr
= kIOPMRootDomainBatPowerCString
;
4593 varIndex
= &idxPMCPULimitedPower
;
4594 } else if (kInformLid
== type
) {
4595 varNameStr
= kIOPMRootDomainLidCloseCString
;
4596 varIndex
= &idxPMCPUClamshell
;
4601 // Set the new value!
4602 // pmCPUControl will assign us a new ID if one doesn't exist yet
4603 bzero(&varInfoStruct
, sizeof(pmioctlVariableInfo_t
));
4604 varInfoStruct
.varID
= *varIndex
;
4605 varInfoStruct
.varType
= vBool
;
4606 varInfoStruct
.varInitValue
= value
;
4607 varInfoStruct
.varCurValue
= value
;
4608 strlcpy((char *)varInfoStruct
.varName
,
4609 (const char *)varNameStr
,
4610 sizeof(varInfoStruct
.varName
));
4613 pmCPUret
= pmCPUControl( PMIOCSETVARINFO
, (void *)&varInfoStruct
);
4615 // pmCPU only assigns numerical id's when a new varName is specified
4617 && (*varIndex
== kCPUUnknownIndex
)) {
4618 // pmCPUControl has assigned us a new variable ID.
4619 // Let's re-read the structure we just SET to learn that ID.
4620 pmCPUret
= pmCPUControl( PMIOCGETVARNAMEINFO
, (void *)&varInfoStruct
);
4622 if (0 == pmCPUret
) {
4623 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
4624 *varIndex
= varInfoStruct
.varID
;
4630 #endif /* __i386__ || __x86_64__ */
4634 // MARK: Deep Sleep Policy
4638 //******************************************************************************
4639 // evaluateSystemSleepPolicy
4640 //******************************************************************************
4642 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
4646 kIOPMSleepFlagHibernate
= 0x00000001,
4647 kIOPMSleepFlagSleepTimerEnable
= 0x00000002
4650 struct IOPMSystemSleepPolicyEntry
{
4651 uint32_t factorMask
;
4652 uint32_t factorBits
;
4653 uint32_t sleepFlags
;
4654 uint32_t wakeEvents
;
4655 } __attribute__((packed
));
4657 struct IOPMSystemSleepPolicyTable
{
4660 uint16_t entryCount
;
4661 IOPMSystemSleepPolicyEntry entries
[];
4662 } __attribute__((packed
));
4665 kIOPMSleepAttributeHibernateSetup
= 0x00000001,
4666 kIOPMSleepAttributeHibernateSleep
= 0x00000002
4670 getSleepTypeAttributes( uint32_t sleepType
)
4672 static const uint32_t sleepTypeAttributes
[kIOPMSleepTypeLast
] =
4677 /* safesleep */ kIOPMSleepAttributeHibernateSetup
,
4678 /* hibernate */ kIOPMSleepAttributeHibernateSetup
| kIOPMSleepAttributeHibernateSleep
,
4679 /* standby */ kIOPMSleepAttributeHibernateSetup
| kIOPMSleepAttributeHibernateSleep
,
4680 /* poweroff */ kIOPMSleepAttributeHibernateSetup
| kIOPMSleepAttributeHibernateSleep
,
4684 if (sleepType
>= kIOPMSleepTypeLast
) {
4688 return sleepTypeAttributes
[sleepType
];
4692 IOPMrootDomain::evaluateSystemSleepPolicy(
4693 IOPMSystemSleepParameters
* params
, int sleepPhase
, uint32_t * hibMode
)
4695 const IOPMSystemSleepPolicyTable
* pt
;
4696 OSObject
* prop
= NULL
;
4697 OSData
* policyData
;
4698 uint64_t currentFactors
= 0;
4699 char currentFactorsBuf
[512];
4700 uint32_t standbyDelay
= 0;
4701 uint32_t powerOffDelay
= 0;
4702 uint32_t powerOffTimer
= 0;
4703 uint32_t standbyTimer
= 0;
4705 bool standbyEnabled
;
4706 bool powerOffEnabled
;
4709 // Get platform's sleep policy table
4710 if (!gSleepPolicyHandler
) {
4711 prop
= getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey
);
4717 // Fetch additional settings
4718 standbyEnabled
= (getSleepOption(kIOPMDeepSleepDelayKey
, &standbyDelay
)
4719 && (getProperty(kIOPMDeepSleepEnabledKey
) == kOSBooleanTrue
));
4720 powerOffEnabled
= (getSleepOption(kIOPMAutoPowerOffDelayKey
, &powerOffDelay
)
4721 && (getProperty(kIOPMAutoPowerOffEnabledKey
) == kOSBooleanTrue
));
4722 if (!getSleepOption(kIOPMAutoPowerOffTimerKey
, &powerOffTimer
)) {
4723 powerOffTimer
= powerOffDelay
;
4725 if (!getSleepOption(kIOPMDeepSleepTimerKey
, &standbyTimer
)) {
4726 standbyTimer
= standbyDelay
;
4729 DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
4730 sleepPhase
, standbyEnabled
, standbyDelay
, standbyTimer
,
4731 powerOffEnabled
, powerOffDelay
, powerOffTimer
, *hibMode
);
4733 currentFactorsBuf
[0] = 0;
4734 // pmset level overrides
4735 if ((*hibMode
& kIOHibernateModeOn
) == 0) {
4736 if (!gSleepPolicyHandler
) {
4737 standbyEnabled
= false;
4738 powerOffEnabled
= false;
4740 } else if (!(*hibMode
& kIOHibernateModeSleep
)) {
4741 // Force hibernate (i.e. mode 25)
4742 // If standby is enabled, force standy.
4743 // If poweroff is enabled, force poweroff.
4744 if (standbyEnabled
) {
4745 currentFactors
|= kIOPMSleepFactorStandbyForced
;
4746 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "StandbyForced");
4747 } else if (powerOffEnabled
) {
4748 currentFactors
|= kIOPMSleepFactorAutoPowerOffForced
;
4749 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "AutoPowerOffForced");
4751 currentFactors
|= kIOPMSleepFactorHibernateForced
;
4752 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "HibernateForced");
4756 // Current factors based on environment and assertions
4757 if (sleepTimerMaintenance
) {
4758 currentFactors
|= kIOPMSleepFactorSleepTimerWake
;
4759 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "SleepTimerWake");
4761 if (standbyEnabled
&& sleepToStandby
&& !gSleepPolicyHandler
) {
4762 currentFactors
|= kIOPMSleepFactorSleepTimerWake
;
4763 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "SleepTimerWake");
4765 if (!clamshellClosed
) {
4766 currentFactors
|= kIOPMSleepFactorLidOpen
;
4767 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "LidOpen");
4769 if (acAdaptorConnected
) {
4770 currentFactors
|= kIOPMSleepFactorACPower
;
4771 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ACPower");
4773 if (lowBatteryCondition
) {
4774 currentFactors
|= kIOPMSleepFactorBatteryLow
;
4775 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "BatteryLow");
4777 if (!standbyDelay
|| !standbyTimer
) {
4778 currentFactors
|= kIOPMSleepFactorStandbyNoDelay
;
4779 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "StandbyNoDelay");
4781 if (standbyNixed
|| !standbyEnabled
) {
4782 currentFactors
|= kIOPMSleepFactorStandbyDisabled
;
4783 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "StandbyDisabled");
4786 currentFactors
|= kIOPMSleepFactorLocalUserActivity
;
4787 currentFactors
&= ~kIOPMSleepFactorSleepTimerWake
;
4788 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "LocalUserActivity, !SleepTimerWake");
4790 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit
) !=
4791 kIOPMDriverAssertionLevelOff
) {
4792 currentFactors
|= kIOPMSleepFactorUSBExternalDevice
;
4793 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "USBExternalDevice");
4795 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit
) !=
4796 kIOPMDriverAssertionLevelOff
) {
4797 currentFactors
|= kIOPMSleepFactorBluetoothHIDDevice
;
4798 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "BluetoothHIDDevice");
4800 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit
) !=
4801 kIOPMDriverAssertionLevelOff
) {
4802 currentFactors
|= kIOPMSleepFactorExternalMediaMounted
;
4803 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ExternalMediaMounted");
4805 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5
) !=
4806 kIOPMDriverAssertionLevelOff
) {
4807 currentFactors
|= kIOPMSleepFactorThunderboltDevice
;
4808 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ThunderboltDevice");
4810 if (_scheduledAlarms
!= 0) {
4811 currentFactors
|= kIOPMSleepFactorRTCAlarmScheduled
;
4812 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "RTCAlaramScheduled");
4814 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit
) !=
4815 kIOPMDriverAssertionLevelOff
) {
4816 currentFactors
|= kIOPMSleepFactorMagicPacketWakeEnabled
;
4817 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "MagicPacketWakeEnabled");
4819 #define TCPKEEPALIVE 1
4821 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit
) !=
4822 kIOPMDriverAssertionLevelOff
) {
4823 currentFactors
|= kIOPMSleepFactorNetworkKeepAliveActive
;
4824 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "NetworkKeepAliveActive");
4827 if (!powerOffEnabled
) {
4828 currentFactors
|= kIOPMSleepFactorAutoPowerOffDisabled
;
4829 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "AutoPowerOffDisabled");
4832 currentFactors
|= kIOPMSleepFactorExternalDisplay
;
4833 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ExternalDisplay");
4835 if (userWasActive
) {
4836 currentFactors
|= kIOPMSleepFactorLocalUserActivity
;
4837 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "LocalUserActivity");
4839 if (darkWakeHibernateError
&& !CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
4840 currentFactors
|= kIOPMSleepFactorHibernateFailed
;
4841 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "HibernateFailed");
4843 if (thermalWarningState
) {
4844 currentFactors
|= kIOPMSleepFactorThermalWarning
;
4845 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ThermalWarning");
4848 DLOG("sleep factors 0x%llx %s\n", currentFactors
, currentFactorsBuf
);
4850 if (gSleepPolicyHandler
) {
4851 uint32_t savedHibernateMode
;
4854 if (!gSleepPolicyVars
) {
4855 gSleepPolicyVars
= IONew(IOPMSystemSleepPolicyVariables
, 1);
4856 if (!gSleepPolicyVars
) {
4859 bzero(gSleepPolicyVars
, sizeof(*gSleepPolicyVars
));
4861 gSleepPolicyVars
->signature
= kIOPMSystemSleepPolicySignature
;
4862 gSleepPolicyVars
->version
= kIOPMSystemSleepPolicyVersion
;
4863 gSleepPolicyVars
->currentCapability
= _currentCapability
;
4864 gSleepPolicyVars
->highestCapability
= _highestCapability
;
4865 gSleepPolicyVars
->sleepFactors
= currentFactors
;
4866 gSleepPolicyVars
->sleepReason
= lastSleepReason
;
4867 gSleepPolicyVars
->sleepPhase
= sleepPhase
;
4868 gSleepPolicyVars
->standbyDelay
= standbyDelay
;
4869 gSleepPolicyVars
->standbyTimer
= standbyTimer
;
4870 gSleepPolicyVars
->poweroffDelay
= powerOffDelay
;
4871 gSleepPolicyVars
->scheduledAlarms
= _scheduledAlarms
| _userScheduledAlarm
;
4872 gSleepPolicyVars
->poweroffTimer
= powerOffTimer
;
4874 if (kIOPMSleepPhase0
== sleepPhase
) {
4875 // preserve hibernateMode
4876 savedHibernateMode
= gSleepPolicyVars
->hibernateMode
;
4877 gSleepPolicyVars
->hibernateMode
= *hibMode
;
4878 } else if (kIOPMSleepPhase1
== sleepPhase
) {
4879 // use original hibernateMode for phase2
4880 gSleepPolicyVars
->hibernateMode
= *hibMode
;
4883 result
= gSleepPolicyHandler(gSleepPolicyTarget
, gSleepPolicyVars
, params
);
4885 if (kIOPMSleepPhase0
== sleepPhase
) {
4886 // restore hibernateMode
4887 gSleepPolicyVars
->hibernateMode
= savedHibernateMode
;
4890 if ((result
!= kIOReturnSuccess
) ||
4891 (kIOPMSleepTypeInvalid
== params
->sleepType
) ||
4892 (params
->sleepType
>= kIOPMSleepTypeLast
) ||
4893 (kIOPMSystemSleepParametersVersion
!= params
->version
)) {
4894 MSG("sleep policy handler error\n");
4898 if ((getSleepTypeAttributes(params
->sleepType
) &
4899 kIOPMSleepAttributeHibernateSetup
) &&
4900 ((*hibMode
& kIOHibernateModeOn
) == 0)) {
4901 *hibMode
|= (kIOHibernateModeOn
| kIOHibernateModeSleep
);
4904 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
4905 params
->version
, params
->sleepType
, params
->sleepFlags
,
4906 params
->ecWakeEvents
, params
->ecWakeTimer
, params
->ecPoweroffTimer
);
4911 // Policy table is meaningless without standby enabled
4912 if (!standbyEnabled
) {
4916 // Validate the sleep policy table
4917 policyData
= OSDynamicCast(OSData
, prop
);
4918 if (!policyData
|| (policyData
->getLength() <= sizeof(IOPMSystemSleepPolicyTable
))) {
4922 pt
= (const IOPMSystemSleepPolicyTable
*) policyData
->getBytesNoCopy();
4923 if ((pt
->signature
!= kIOPMSystemSleepPolicySignature
) ||
4924 (pt
->version
!= 1) || (0 == pt
->entryCount
)) {
4928 if (((policyData
->getLength() - sizeof(IOPMSystemSleepPolicyTable
)) !=
4929 (sizeof(IOPMSystemSleepPolicyEntry
) * pt
->entryCount
))) {
4933 for (uint32_t i
= 0; i
< pt
->entryCount
; i
++) {
4934 const IOPMSystemSleepPolicyEntry
* entry
= &pt
->entries
[i
];
4935 mismatch
= (((uint32_t)currentFactors
^ entry
->factorBits
) & entry
->factorMask
);
4937 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
4938 entry
->factorMask
, entry
->factorBits
,
4939 entry
->sleepFlags
, entry
->wakeEvents
, mismatch
);
4944 DLOG("^ found match\n");
4947 params
->version
= kIOPMSystemSleepParametersVersion
;
4948 params
->reserved1
= 1;
4949 if (entry
->sleepFlags
& kIOPMSleepFlagHibernate
) {
4950 params
->sleepType
= kIOPMSleepTypeStandby
;
4952 params
->sleepType
= kIOPMSleepTypeNormalSleep
;
4955 params
->ecWakeEvents
= entry
->wakeEvents
;
4956 if (entry
->sleepFlags
& kIOPMSleepFlagSleepTimerEnable
) {
4957 if (kIOPMSleepPhase2
== sleepPhase
) {
4958 clock_sec_t now_secs
= gIOLastSleepTime
.tv_sec
;
4960 if (!_standbyTimerResetSeconds
||
4961 (now_secs
<= _standbyTimerResetSeconds
)) {
4962 // Reset standby timer adjustment
4963 _standbyTimerResetSeconds
= now_secs
;
4964 DLOG("standby delay %u, reset %u\n",
4965 standbyDelay
, (uint32_t) _standbyTimerResetSeconds
);
4966 } else if (standbyDelay
) {
4967 // Shorten the standby delay timer
4968 clock_sec_t elapsed
= now_secs
- _standbyTimerResetSeconds
;
4969 if (standbyDelay
> elapsed
) {
4970 standbyDelay
-= elapsed
;
4972 standbyDelay
= 1; // must be > 0
4974 DLOG("standby delay %u, elapsed %u\n",
4975 standbyDelay
, (uint32_t) elapsed
);
4978 params
->ecWakeTimer
= standbyDelay
;
4979 } else if (kIOPMSleepPhase2
== sleepPhase
) {
4980 // A sleep that does not enable the sleep timer will reset
4981 // the standby delay adjustment.
4982 _standbyTimerResetSeconds
= 0;
4995 static IOPMSystemSleepParameters gEarlySystemSleepParams
;
4998 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5000 // Evaluate early (priority interest phase), before drivers sleep.
5002 DLOG("%s\n", __FUNCTION__
);
5003 removeProperty(kIOPMSystemSleepParametersKey
);
5005 // Full wake resets the standby timer delay adjustment
5006 if (_highestCapability
& kIOPMSystemCapabilityGraphics
) {
5007 _standbyTimerResetSeconds
= 0;
5010 hibernateDisabled
= false;
5012 getSleepOption(kIOHibernateModeKey
, &hibernateMode
);
5014 // Save for late evaluation if sleep is aborted
5015 bzero(&gEarlySystemSleepParams
, sizeof(gEarlySystemSleepParams
));
5017 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams
, kIOPMSleepPhase1
,
5019 if (!hibernateRetry
&&
5020 ((getSleepTypeAttributes(gEarlySystemSleepParams
.sleepType
) &
5021 kIOPMSleepAttributeHibernateSetup
) == 0)) {
5022 // skip hibernate setup
5023 hibernateDisabled
= true;
5027 // Publish IOPMSystemSleepType
5028 uint32_t sleepType
= gEarlySystemSleepParams
.sleepType
;
5029 if (sleepType
== kIOPMSleepTypeInvalid
) {
5031 sleepType
= kIOPMSleepTypeNormalSleep
;
5032 if (hibernateMode
& kIOHibernateModeOn
) {
5033 sleepType
= (hibernateMode
& kIOHibernateModeSleep
) ?
5034 kIOPMSleepTypeSafeSleep
: kIOPMSleepTypeHibernate
;
5036 } else if ((sleepType
== kIOPMSleepTypeStandby
) &&
5037 (gEarlySystemSleepParams
.ecPoweroffTimer
)) {
5038 // report the lowest possible sleep state
5039 sleepType
= kIOPMSleepTypePowerOff
;
5042 setProperty(kIOPMSystemSleepTypeKey
, sleepType
, 32);
5046 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5048 IOPMSystemSleepParameters params
;
5049 OSData
* paramsData
;
5051 // Evaluate sleep policy after sleeping drivers but before platform sleep.
5053 DLOG("%s\n", __FUNCTION__
);
5055 bzero(¶ms
, sizeof(params
));
5057 if (evaluateSystemSleepPolicy(¶ms
, kIOPMSleepPhase2
, &hibernateMode
)) {
5058 if ((kIOPMSleepTypeStandby
== params
.sleepType
)
5059 && gIOHibernateStandbyDisabled
&& gSleepPolicyVars
5060 && (!((kIOPMSleepFactorStandbyForced
| kIOPMSleepFactorAutoPowerOffForced
| kIOPMSleepFactorHibernateForced
)
5061 & gSleepPolicyVars
->sleepFactors
))) {
5062 standbyNixed
= true;
5066 || ((hibernateDisabled
|| hibernateAborted
) &&
5067 (getSleepTypeAttributes(params
.sleepType
) &
5068 kIOPMSleepAttributeHibernateSetup
))) {
5069 // Final evaluation picked a state requiring hibernation,
5070 // but hibernate isn't going to proceed. Arm a short sleep using
5071 // the early non-hibernate sleep parameters.
5072 bcopy(&gEarlySystemSleepParams
, ¶ms
, sizeof(params
));
5073 params
.sleepType
= kIOPMSleepTypeAbortedSleep
;
5074 params
.ecWakeTimer
= 1;
5078 // Set hibernateRetry flag to force hibernate setup on the
5080 hibernateRetry
= true;
5082 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5083 params
.ecWakeTimer
, hibernateDisabled
, hibernateAborted
, standbyNixed
);
5085 hibernateRetry
= false;
5088 if (kIOPMSleepTypeAbortedSleep
!= params
.sleepType
) {
5089 resetTimers
= false;
5092 paramsData
= OSData::withBytes(¶ms
, sizeof(params
));
5094 setProperty(kIOPMSystemSleepParametersKey
, paramsData
);
5095 paramsData
->release();
5098 if (getSleepTypeAttributes(params
.sleepType
) &
5099 kIOPMSleepAttributeHibernateSleep
) {
5100 // Disable sleep to force hibernation
5101 gIOHibernateMode
&= ~kIOHibernateModeSleep
;
5107 IOPMrootDomain::getHibernateSettings(
5108 uint32_t * hibernateModePtr
,
5109 uint32_t * hibernateFreeRatio
,
5110 uint32_t * hibernateFreeTime
)
5112 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5113 // has updated the hibernateDisabled flag.
5115 bool ok
= getSleepOption(kIOHibernateModeKey
, hibernateModePtr
);
5116 getSleepOption(kIOHibernateFreeRatioKey
, hibernateFreeRatio
);
5117 getSleepOption(kIOHibernateFreeTimeKey
, hibernateFreeTime
);
5118 if (hibernateDisabled
) {
5119 *hibernateModePtr
= 0;
5120 } else if (gSleepPolicyHandler
) {
5121 *hibernateModePtr
= hibernateMode
;
5123 DLOG("hibernateMode 0x%x\n", *hibernateModePtr
);
5128 IOPMrootDomain::getSleepOption( const char * key
, uint32_t * option
)
5130 OSObject
* optionsProp
;
5131 OSDictionary
* optionsDict
;
5132 OSObject
* obj
= NULL
;
5136 optionsProp
= copyProperty(kRootDomainSleepOptionsKey
);
5137 optionsDict
= OSDynamicCast(OSDictionary
, optionsProp
);
5140 obj
= optionsDict
->getObject(key
);
5146 obj
= copyProperty(key
);
5149 if ((num
= OSDynamicCast(OSNumber
, obj
))) {
5150 *option
= num
->unsigned32BitValue();
5152 } else if (OSDynamicCast(OSBoolean
, obj
)) {
5153 *option
= (obj
== kOSBooleanTrue
) ? 1 : 0;
5162 optionsProp
->release();
5167 #endif /* HIBERNATION */
5170 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType
, uint32_t * standbyTimer
)
5173 IOPMSystemSleepParameters params
;
5174 uint32_t hibMode
= 0;
5177 if (gIOPMWorkLoop
->inGate() == false) {
5178 IOReturn ret
= gIOPMWorkLoop
->runAction(
5179 OSMemberFunctionCast(IOWorkLoop::Action
, this,
5180 &IOPMrootDomain::getSystemSleepType
),
5182 (void *) sleepType
, (void *) standbyTimer
);
5186 getSleepOption(kIOHibernateModeKey
, &hibMode
);
5187 bzero(¶ms
, sizeof(params
));
5189 ok
= evaluateSystemSleepPolicy(¶ms
, kIOPMSleepPhase0
, &hibMode
);
5191 *sleepType
= params
.sleepType
;
5192 if (!getSleepOption(kIOPMDeepSleepTimerKey
, standbyTimer
) &&
5193 !getSleepOption(kIOPMDeepSleepDelayKey
, standbyTimer
)) {
5194 DLOG("Standby delay is not set\n");
5197 return kIOReturnSuccess
;
5201 return kIOReturnUnsupported
;
5205 // MARK: Shutdown and Restart
5207 //******************************************************************************
5208 // handlePlatformHaltRestart
5210 //******************************************************************************
5212 // Phases while performing shutdown/restart
5215 kNotifyPriorityClients
= 0x10,
5216 kNotifyPowerPlaneDrivers
= 0x20,
5217 kNotifyHaltRestartAction
= 0x30,
5222 struct HaltRestartApplierContext
{
5223 IOPMrootDomain
* RootDomain
;
5224 unsigned long PowerState
;
5225 IOPMPowerFlags PowerFlags
;
5228 const char * LogString
;
5229 shutdownPhase_t phase
;
5231 IOServiceInterestHandler handler
;
5235 shutdownPhase2String(shutdownPhase_t phase
)
5239 return "Notifications completed";
5240 case kNotifyPriorityClients
:
5241 return "Notifying priority clients";
5242 case kNotifyPowerPlaneDrivers
:
5243 return "Notifying power plane drivers";
5244 case kNotifyHaltRestartAction
:
5245 return "Notifying HaltRestart action handlers";
5247 return "Quiescing PM";
5254 platformHaltRestartApplier( OSObject
* object
, void * context
)
5256 IOPowerStateChangeNotification notify
;
5257 HaltRestartApplierContext
* ctx
;
5258 AbsoluteTime startTime
, elapsedTime
;
5261 ctx
= (HaltRestartApplierContext
*) context
;
5263 _IOServiceInterestNotifier
* notifier
;
5264 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
5265 memset(¬ify
, 0, sizeof(notify
));
5266 notify
.powerRef
= (void *)(uintptr_t)ctx
->Counter
;
5267 notify
.returnValue
= 0;
5268 notify
.stateNumber
= ctx
->PowerState
;
5269 notify
.stateFlags
= ctx
->PowerFlags
;
5272 ctx
->handler
= notifier
->handler
;
5275 clock_get_uptime(&startTime
);
5276 ctx
->RootDomain
->messageClient( ctx
->MessageType
, object
, (void *)¬ify
);
5277 deltaTime
= computeDeltaTimeMS(&startTime
, &elapsedTime
);
5279 if ((deltaTime
> kPMHaltTimeoutMS
) && notifier
) {
5280 LOG("%s handler %p took %u ms\n",
5281 ctx
->LogString
, OBFUSCATE(notifier
->handler
), deltaTime
);
5282 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier
->handler
, elapsedTime
);
5285 ctx
->handler
= NULL
;
5290 quiescePowerTreeCallback( void * target
, void * param
)
5292 IOLockLock(gPMHaltLock
);
5294 thread_wakeup(param
);
5295 IOLockUnlock(gPMHaltLock
);
5299 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type
)
5301 AbsoluteTime startTime
, elapsedTime
;
5304 memset(&gHaltRestartCtx
, 0, sizeof(gHaltRestartCtx
));
5305 gHaltRestartCtx
.RootDomain
= this;
5307 clock_get_uptime(&startTime
);
5310 case kPEUPSDelayHaltCPU
:
5311 gHaltRestartCtx
.PowerState
= OFF_STATE
;
5312 gHaltRestartCtx
.MessageType
= kIOMessageSystemWillPowerOff
;
5313 gHaltRestartCtx
.LogString
= "PowerOff";
5317 gHaltRestartCtx
.PowerState
= RESTART_STATE
;
5318 gHaltRestartCtx
.MessageType
= kIOMessageSystemWillRestart
;
5319 gHaltRestartCtx
.LogString
= "Restart";
5323 gHaltRestartCtx
.PowerState
= ON_STATE
;
5324 gHaltRestartCtx
.MessageType
= kIOMessageSystemPagingOff
;
5325 gHaltRestartCtx
.LogString
= "PagingOff";
5326 IOService::updateConsoleUsers(NULL
, kIOMessageSystemPagingOff
);
5328 IOHibernateSystemRestart();
5336 gHaltRestartCtx
.phase
= kNotifyPriorityClients
;
5337 // Notify legacy clients
5338 applyToInterested(gIOPriorityPowerStateInterest
, platformHaltRestartApplier
, &gHaltRestartCtx
);
5340 // For normal shutdown, turn off File Server Mode.
5341 if (kPEHaltCPU
== pe_type
) {
5342 const OSSymbol
* setting
= OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
);
5343 OSNumber
* num
= OSNumber::withNumber((unsigned long long) 0, 32);
5344 if (setting
&& num
) {
5345 setPMSetting(setting
, num
);
5352 if (kPEPagingOff
!= pe_type
) {
5353 gHaltRestartCtx
.phase
= kNotifyPowerPlaneDrivers
;
5354 // Notify in power tree order
5355 notifySystemShutdown(this, gHaltRestartCtx
.MessageType
);
5358 gHaltRestartCtx
.phase
= kNotifyHaltRestartAction
;
5359 #if !CONFIG_EMBEDDED
5360 IOCPURunPlatformHaltRestartActions(pe_type
);
5362 if (kPEPagingOff
!= pe_type
) {
5363 IOCPURunPlatformHaltRestartActions(pe_type
);
5367 // Wait for PM to quiesce
5368 if ((kPEPagingOff
!= pe_type
) && gPMHaltLock
) {
5369 gHaltRestartCtx
.phase
= kQuiescePM
;
5370 AbsoluteTime quiesceTime
= mach_absolute_time();
5372 IOLockLock(gPMHaltLock
);
5373 gPMQuiesced
= false;
5374 if (quiescePowerTree(this, &quiescePowerTreeCallback
, &gPMQuiesced
) ==
5376 while (!gPMQuiesced
) {
5377 IOLockSleep(gPMHaltLock
, &gPMQuiesced
, THREAD_UNINT
);
5380 IOLockUnlock(gPMHaltLock
);
5381 deltaTime
= computeDeltaTimeMS(&quiesceTime
, &elapsedTime
);
5382 DLOG("PM quiesce took %u ms\n", deltaTime
);
5383 halt_log_enter("Quiesce", NULL
, elapsedTime
);
5385 gHaltRestartCtx
.phase
= kNotifyDone
;
5387 deltaTime
= computeDeltaTimeMS(&startTime
, &elapsedTime
);
5388 LOG("%s all drivers took %u ms\n", gHaltRestartCtx
.LogString
, deltaTime
);
5390 halt_log_enter(gHaltRestartCtx
.LogString
, NULL
, elapsedTime
);
5392 deltaTime
= computeDeltaTimeMS(&gHaltStartTime
, &elapsedTime
);
5393 LOG("%s total %u ms\n", gHaltRestartCtx
.LogString
, deltaTime
);
5395 if (gHaltLog
&& gHaltTimeMaxLog
&& (deltaTime
>= gHaltTimeMaxLog
)) {
5396 printf("%s total %d ms:%s\n", gHaltRestartCtx
.LogString
, deltaTime
, gHaltLog
);
5399 checkShutdownTimeout();
5403 IOPMrootDomain::checkShutdownTimeout()
5405 AbsoluteTime elapsedTime
;
5406 uint32_t deltaTime
= computeDeltaTimeMS(&gHaltStartTime
, &elapsedTime
);
5408 if (gHaltTimeMaxPanic
&& (deltaTime
>= gHaltTimeMaxPanic
)) {
5415 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs
)
5418 if ((gHaltRestartCtx
.phase
== kNotifyPriorityClients
) && gHaltRestartCtx
.handler
) {
5419 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx
.handler
, mach_absolute_time() - gHaltStartTime
);
5421 panic("%s timed out in phase '%s'. Total %d ms:%s",
5422 gHaltRestartCtx
.LogString
, shutdownPhase2String(gHaltRestartCtx
.phase
), timeoutInMs
, gHaltLog
);
5424 panic("%s timed out in phase \'%s\'. Total %d ms",
5425 gHaltRestartCtx
.LogString
, shutdownPhase2String(gHaltRestartCtx
.phase
), timeoutInMs
);
5429 //******************************************************************************
5432 //******************************************************************************
5435 IOPMrootDomain::shutdownSystem( void )
5437 return kIOReturnUnsupported
;
5440 //******************************************************************************
5443 //******************************************************************************
5446 IOPMrootDomain::restartSystem( void )
5448 return kIOReturnUnsupported
;
5452 // MARK: System Capability
5454 //******************************************************************************
5455 // tagPowerPlaneService
5457 // Running on PM work loop thread.
5458 //******************************************************************************
5461 IOPMrootDomain::tagPowerPlaneService(
5462 IOService
* service
,
5463 IOPMActions
* actions
)
5466 bool isDisplayWrangler
;
5468 memset(actions
, 0, sizeof(*actions
));
5469 actions
->target
= this;
5471 if (service
== this) {
5472 actions
->actionPowerChangeStart
=
5473 OSMemberFunctionCast(
5474 IOPMActionPowerChangeStart
, this,
5475 &IOPMrootDomain::handleOurPowerChangeStart
);
5477 actions
->actionPowerChangeDone
=
5478 OSMemberFunctionCast(
5479 IOPMActionPowerChangeDone
, this,
5480 &IOPMrootDomain::handleOurPowerChangeDone
);
5482 actions
->actionPowerChangeOverride
=
5483 OSMemberFunctionCast(
5484 IOPMActionPowerChangeOverride
, this,
5485 &IOPMrootDomain::overrideOurPowerChange
);
5490 isDisplayWrangler
= (NULL
!= service
->metaCast("IODisplayWrangler"));
5491 if (isDisplayWrangler
) {
5493 // found the display wrangler, check for any display assertions already created
5494 if (pmAssertions
->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit
) {
5495 DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
5496 wrangler
->setIgnoreIdleTimer( true );
5500 isDisplayWrangler
= false;
5503 #if defined(__i386__) || defined(__x86_64__)
5504 if (isDisplayWrangler
) {
5505 flags
|= kPMActionsFlagIsDisplayWrangler
;
5507 if (service
->getProperty("IOPMStrictTreeOrder")) {
5508 flags
|= kPMActionsFlagIsGraphicsDevice
;
5510 if (service
->getProperty("IOPMUnattendedWakePowerState")) {
5511 flags
|= kPMActionsFlagIsAudioDevice
;
5515 // Find the power connection object that is a child of the PCI host
5516 // bridge, and has a graphics/audio device attached below. Mark the
5517 // power branch for delayed child notifications.
5520 IORegistryEntry
* child
= service
;
5521 IORegistryEntry
* parent
= child
->getParentEntry(gIOPowerPlane
);
5523 while (child
!= this) {
5524 if (child
->getProperty("IOPCITunnelled") == kOSBooleanTrue
) {
5525 // Skip delaying notifications and clamping power on external graphics and audio devices.
5526 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service
->getRegistryEntryID(), flags
);
5530 if ((parent
== pciHostBridgeDriver
) ||
5532 if (OSDynamicCast(IOPowerConnection
, child
)) {
5533 IOPowerConnection
* conn
= (IOPowerConnection
*) child
;
5534 conn
->delayChildNotification
= true;
5535 DLOG("delayChildNotification for 0x%llx\n", conn
->getRegistryEntryID());
5540 parent
= child
->getParentEntry(gIOPowerPlane
);
5545 DLOG("%s tag flags %x\n", service
->getName(), flags
);
5546 actions
->parameter
|= flags
;
5547 actions
->actionPowerChangeOverride
=
5548 OSMemberFunctionCast(
5549 IOPMActionPowerChangeOverride
, this,
5550 &IOPMrootDomain::overridePowerChangeForUIService
);
5552 if (flags
& kPMActionsFlagIsDisplayWrangler
) {
5553 actions
->actionActivityTickle
=
5554 OSMemberFunctionCast(
5555 IOPMActionActivityTickle
, this,
5556 &IOPMrootDomain::handleActivityTickleForDisplayWrangler
);
5558 actions
->actionUpdatePowerClient
=
5559 OSMemberFunctionCast(
5560 IOPMActionUpdatePowerClient
, this,
5561 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler
);
5566 // Locate the first PCI host bridge for PMTrace.
5567 if (!pciHostBridgeDevice
&& service
->metaCast("IOPCIBridge")) {
5568 IOService
* provider
= service
->getProvider();
5569 if (OSDynamicCast(IOPlatformDevice
, provider
) &&
5570 provider
->inPlane(gIODTPlane
)) {
5571 pciHostBridgeDevice
= provider
;
5572 pciHostBridgeDriver
= service
;
5573 DLOG("PMTrace found PCI host bridge %s->%s\n",
5574 provider
->getName(), service
->getName());
5578 // Tag top-level PCI devices. The order of PMinit() call does not
5579 // change across boots and is used as the PCI bit number.
5580 if (pciHostBridgeDevice
&& service
->metaCast("IOPCIDevice")) {
5581 // Would prefer to check built-in property, but tagPowerPlaneService()
5582 // is called before pciDevice->registerService().
5583 IORegistryEntry
* parent
= service
->getParentEntry(gIODTPlane
);
5584 if ((parent
== pciHostBridgeDevice
) && service
->getProperty("acpi-device")) {
5585 int bit
= pmTracer
->recordTopLevelPCIDevice( service
);
5587 // Save the assigned bit for fast lookup.
5588 actions
->parameter
|= (bit
& kPMActionsPCIBitNumberMask
);
5590 actions
->actionPowerChangeStart
=
5591 OSMemberFunctionCast(
5592 IOPMActionPowerChangeStart
, this,
5593 &IOPMrootDomain::handlePowerChangeStartForPCIDevice
);
5595 actions
->actionPowerChangeDone
=
5596 OSMemberFunctionCast(
5597 IOPMActionPowerChangeDone
, this,
5598 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice
);
5604 //******************************************************************************
5605 // PM actions for root domain
5606 //******************************************************************************
5609 IOPMrootDomain::overrideOurPowerChange(
5610 IOService
* service
,
5611 IOPMActions
* actions
,
5612 IOPMPowerStateIndex
* inOutPowerState
,
5613 IOPMPowerChangeFlags
* inOutChangeFlags
,
5614 IOPMRequestTag requestTag
)
5616 uint32_t powerState
= (uint32_t) *inOutPowerState
;
5617 uint32_t changeFlags
= *inOutChangeFlags
;
5618 uint32_t currentPowerState
= (uint32_t) getPowerState();
5620 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
5621 if ((AOT_STATE
== powerState
) && (ON_STATE
== currentPowerState
)) {
5622 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
5623 *inOutChangeFlags
|= kIOPMNotDone
;
5626 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
5628 if (changeFlags
& kIOPMParentInitiated
) {
5629 // Root parent is permanently pegged at max power,
5630 // a parent initiated power change is unexpected.
5631 *inOutChangeFlags
|= kIOPMNotDone
;
5635 if (powerState
< currentPowerState
) {
5636 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
5637 // Root domain is dropping power state ON->SLEEP.
5638 // If system is in full wake, first enter dark wake by
5639 // converting the power drop to a capability change.
5640 // Once in dark wake, transition to sleep state ASAP.
5642 darkWakeToSleepASAP
= true;
5644 // Drop graphics and audio capability
5645 _desiredCapability
&= ~(
5646 kIOPMSystemCapabilityGraphics
|
5647 kIOPMSystemCapabilityAudio
);
5649 // Convert to capability change (ON->ON)
5650 *inOutPowerState
= getRUN_STATE();
5651 *inOutChangeFlags
|= kIOPMSynchronize
;
5653 // Revert device desire from SLEEP to ON
5654 changePowerStateToPriv(getRUN_STATE());
5656 // System is in dark wake, ok to drop power state.
5657 // Broadcast root powering down to entire tree.
5658 *inOutChangeFlags
|= kIOPMRootChangeDown
;
5660 } else if (powerState
> currentPowerState
) {
5661 if ((_currentCapability
& kIOPMSystemCapabilityCPU
) == 0) {
5662 // Broadcast power up when waking from sleep, but not for the
5663 // initial power change at boot by checking for cpu capability.
5664 *inOutChangeFlags
|= kIOPMRootChangeUp
;
5670 IOPMrootDomain::handleOurPowerChangeStart(
5671 IOService
* service
,
5672 IOPMActions
* actions
,
5673 IOPMPowerStateIndex powerState
,
5674 IOPMPowerChangeFlags
* inOutChangeFlags
,
5675 IOPMRequestTag requestTag
)
5677 uint32_t changeFlags
= *inOutChangeFlags
;
5678 uint32_t currentPowerState
= (uint32_t) getPowerState();
5679 uint32_t sleepReason
= requestTag
? requestTag
: kIOPMSleepReasonIdle
;
5680 bool publishSleepReason
= false;
5682 _systemTransitionType
= kSystemTransitionNone
;
5683 _systemMessageClientMask
= 0;
5684 capabilityLoss
= false;
5685 toldPowerdCapWillChange
= false;
5687 if (lowBatteryCondition
) {
5688 // Low battery notification may arrive after the initial sleep request
5689 // has been queued. Override the sleep reason so powerd and others can
5690 // treat this as an emergency sleep.
5691 sleepReason
= kIOPMSleepReasonLowPower
;
5694 // 1. Explicit capability change.
5696 if (changeFlags
& kIOPMSynchronize
) {
5697 if (powerState
== ON_STATE
) {
5698 if (changeFlags
& kIOPMSyncNoChildNotify
) {
5699 _systemTransitionType
= kSystemTransitionNewCapClient
;
5701 _systemTransitionType
= kSystemTransitionCapability
;
5705 // 2. Going to sleep (cancellation still possible).
5706 else if (powerState
< currentPowerState
) {
5707 _systemTransitionType
= kSystemTransitionSleep
;
5709 // 3. Woke from (idle or demand) sleep.
5710 else if (!systemBooting
&&
5711 (changeFlags
& kIOPMSelfInitiated
) &&
5712 (powerState
> currentPowerState
)) {
5713 _systemTransitionType
= kSystemTransitionWake
;
5714 _desiredCapability
= kIOPMSystemCapabilityCPU
|
5715 kIOPMSystemCapabilityNetwork
;
5717 // Early exit from dark wake to full (e.g. LID open)
5718 if (kFullWakeReasonNone
!= fullWakeReason
) {
5719 _desiredCapability
|= (
5720 kIOPMSystemCapabilityGraphics
|
5721 kIOPMSystemCapabilityAudio
);
5724 IOHibernateSetWakeCapabilities(_desiredCapability
);
5728 // Update pending wake capability at the beginning of every
5729 // state transition (including synchronize). This will become
5730 // the current capability at the end of the transition.
5732 if (kSystemTransitionSleep
== _systemTransitionType
) {
5733 _pendingCapability
= 0;
5734 capabilityLoss
= true;
5735 } else if (kSystemTransitionNewCapClient
!= _systemTransitionType
) {
5736 _pendingCapability
= _desiredCapability
|
5737 kIOPMSystemCapabilityCPU
|
5738 kIOPMSystemCapabilityNetwork
;
5740 if (_pendingCapability
& kIOPMSystemCapabilityGraphics
) {
5741 _pendingCapability
|= kIOPMSystemCapabilityAudio
;
5744 if ((kSystemTransitionCapability
== _systemTransitionType
) &&
5745 (_pendingCapability
== _currentCapability
)) {
5746 // Cancel the PM state change.
5747 _systemTransitionType
= kSystemTransitionNone
;
5748 *inOutChangeFlags
|= kIOPMNotDone
;
5750 if (__builtin_popcount(_pendingCapability
) <
5751 __builtin_popcount(_currentCapability
)) {
5752 capabilityLoss
= true;
5756 // 1. Capability change.
5758 if (kSystemTransitionCapability
== _systemTransitionType
) {
5759 // Dark to Full transition.
5760 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
5761 tracePoint( kIOPMTracePointDarkWakeExit
);
5763 willEnterFullWake();
5766 // Full to Dark transition.
5767 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) {
5768 // Clear previous stats
5769 IOLockLock(pmStatsLock
);
5770 if (pmStatsAppResponses
) {
5771 pmStatsAppResponses
->release();
5772 pmStatsAppResponses
= OSArray::withCapacity(5);
5774 IOLockUnlock(pmStatsLock
);
5777 tracePoint( kIOPMTracePointDarkWakeEntry
);
5778 *inOutChangeFlags
|= kIOPMSyncTellPowerDown
;
5779 _systemMessageClientMask
= kSystemMessageClientPowerd
|
5780 kSystemMessageClientLegacyApp
;
5784 // Prevent user active transitions before notifying clients
5785 // that system will sleep.
5786 preventTransitionToUserActive(true);
5788 IOService::setAdvisoryTickleEnable( false );
5790 // Publish the sleep reason for full to dark wake
5791 publishSleepReason
= true;
5792 lastSleepReason
= fullToDarkReason
= sleepReason
;
5794 // Publish a UUID for the Sleep --> Wake cycle
5795 handlePublishSleepWakeUUID(true);
5796 if (sleepDelaysReport
) {
5797 clock_get_uptime(&ts_sleepStart
);
5798 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart
);
5801 wranglerTickled
= false;
5805 else if (kSystemTransitionSleep
== _systemTransitionType
) {
5806 // Beginning of a system sleep transition.
5807 // Cancellation is still possible.
5808 tracePoint( kIOPMTracePointSleepStarted
);
5810 _systemMessageClientMask
= kSystemMessageClientAll
;
5811 if ((_currentCapability
& kIOPMSystemCapabilityGraphics
) == 0) {
5812 _systemMessageClientMask
&= ~kSystemMessageClientLegacyApp
;
5814 if ((_highestCapability
& kIOPMSystemCapabilityGraphics
) == 0) {
5815 // Kernel priority clients are only notified on the initial
5816 // transition to full wake, so don't notify them unless system
5817 // has gained graphics capability since the last system wake.
5818 _systemMessageClientMask
&= ~kSystemMessageClientKernel
;
5821 gIOHibernateState
= 0;
5824 // Record the reason for dark wake back to sleep
5825 // System may not have ever achieved full wake
5827 publishSleepReason
= true;
5828 lastSleepReason
= sleepReason
;
5829 if (sleepDelaysReport
) {
5830 clock_get_uptime(&ts_sleepStart
);
5831 DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart
);
5835 else if (kSystemTransitionWake
== _systemTransitionType
) {
5836 tracePoint( kIOPMTracePointWakeWillPowerOnClients
);
5837 // Clear stats about sleep
5839 if (AOT_STATE
== powerState
) {
5840 _pendingCapability
= 0;
5843 if (_pendingCapability
& kIOPMSystemCapabilityGraphics
) {
5844 willEnterFullWake();
5846 // Message powerd only
5847 _systemMessageClientMask
= kSystemMessageClientPowerd
;
5848 tellClients(kIOMessageSystemWillPowerOn
);
5852 // The only location where the sleep reason is published. At this point
5853 // sleep can still be cancelled, but sleep reason should be published
5854 // early for logging purposes.
5856 if (publishSleepReason
) {
5857 static const char * IOPMSleepReasons
[] =
5859 kIOPMClamshellSleepKey
,
5860 kIOPMPowerButtonSleepKey
,
5861 kIOPMSoftwareSleepKey
,
5862 kIOPMOSSwitchHibernationKey
,
5864 kIOPMLowPowerSleepKey
,
5865 kIOPMThermalEmergencySleepKey
,
5866 kIOPMMaintenanceSleepKey
,
5867 kIOPMSleepServiceExitKey
,
5868 kIOPMDarkWakeThermalEmergencyKey
5871 // Record sleep cause in IORegistry
5872 uint32_t reasonIndex
= sleepReason
- kIOPMSleepReasonClamshell
;
5873 if (reasonIndex
< sizeof(IOPMSleepReasons
) / sizeof(IOPMSleepReasons
[0])) {
5874 DLOG("sleep reason %s\n", IOPMSleepReasons
[reasonIndex
]);
5875 setProperty(kRootDomainSleepReasonKey
, IOPMSleepReasons
[reasonIndex
]);
5879 if ((kSystemTransitionNone
!= _systemTransitionType
) &&
5880 (kSystemTransitionNewCapClient
!= _systemTransitionType
)) {
5881 _systemStateGeneration
++;
5882 systemDarkWake
= false;
5884 DLOG("=== START (%s->%s, 0x%x) type %u, gen %u, msg %x, "
5886 getPowerStateString(currentPowerState
), getPowerStateString((uint32_t) powerState
), *inOutChangeFlags
,
5887 _systemTransitionType
, _systemStateGeneration
,
5888 _systemMessageClientMask
,
5889 _desiredCapability
, _currentCapability
, _pendingCapability
);
5892 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
5893 if ((AOT_STATE
== powerState
) && (SLEEP_STATE
!= currentPowerState
)) {
5894 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState
));
5896 if (_aotNow
&& (ON_STATE
== powerState
)) {
5897 aotShouldExit(false, true);
5900 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
5904 IOPMrootDomain::handleOurPowerChangeDone(
5905 IOService
* service
,
5906 IOPMActions
* actions
,
5907 IOPMPowerStateIndex powerState
,
5908 IOPMPowerChangeFlags changeFlags
,
5909 IOPMRequestTag requestTag __unused
)
5911 if (kSystemTransitionNewCapClient
== _systemTransitionType
) {
5912 _systemTransitionType
= kSystemTransitionNone
;
5916 if (_systemTransitionType
!= kSystemTransitionNone
) {
5917 uint32_t currentPowerState
= (uint32_t) getPowerState();
5919 if (changeFlags
& kIOPMNotDone
) {
5920 // Power down was cancelled or vetoed.
5921 _pendingCapability
= _currentCapability
;
5922 lastSleepReason
= 0;
5924 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
) &&
5925 CAP_CURRENT(kIOPMSystemCapabilityCPU
)) {
5926 #if !CONFIG_EMBEDDED
5927 pmPowerStateQueue
->submitPowerEvent(
5928 kPowerEventPolicyStimulus
,
5929 (void *) kStimulusDarkWakeReentry
,
5930 _systemStateGeneration
);
5932 // On embedded, there are no factors that can prolong a
5933 // "darkWake" when a power down is vetoed. We need to
5934 // promote to "fullWake" at least once so that factors
5935 // that prevent idle sleep can assert themselves if required
5936 pmPowerStateQueue
->submitPowerEvent(
5937 kPowerEventPolicyStimulus
,
5938 (void *) kStimulusDarkWakeActivityTickle
);
5942 // Revert device desire to max.
5943 changePowerStateToPriv(getRUN_STATE());
5945 // Send message on dark wake to full wake promotion.
5946 // tellChangeUp() handles the normal SLEEP->ON case.
5948 if (kSystemTransitionCapability
== _systemTransitionType
) {
5949 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
5950 lastSleepReason
= 0; // stop logging wrangler tickles
5951 tellClients(kIOMessageSystemHasPoweredOn
);
5953 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) {
5954 // Going dark, reset full wake state
5955 // userIsActive will be cleared by wrangler powering down
5956 fullWakeReason
= kFullWakeReasonNone
;
5958 if (ts_sleepStart
) {
5959 clock_get_uptime(&wake2DarkwakeDelay
);
5960 SUB_ABSOLUTETIME(&wake2DarkwakeDelay
, &ts_sleepStart
);
5961 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay
);
5967 // Reset state after exiting from dark wake.
5969 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
) ||
5970 CAP_LOSS(kIOPMSystemCapabilityCPU
)) {
5971 darkWakeMaintenance
= false;
5972 darkWakeToSleepASAP
= false;
5973 pciCantSleepValid
= false;
5974 darkWakeSleepService
= false;
5976 if (CAP_LOSS(kIOPMSystemCapabilityCPU
)) {
5977 // Remove the influence of display power assertion
5978 // before next system wake.
5980 wrangler
->changePowerStateForRootDomain(
5981 kWranglerPowerStateMin
);
5983 removeProperty(gIOPMUserTriggeredFullWakeKey
);
5987 // Entered dark mode.
5989 if (((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0) &&
5990 (_pendingCapability
& kIOPMSystemCapabilityCPU
)) {
5991 // Queue an evaluation of whether to remain in dark wake,
5992 // and for how long. This serves the purpose of draining
5993 // any assertions from the queue.
5995 pmPowerStateQueue
->submitPowerEvent(
5996 kPowerEventPolicyStimulus
,
5997 (void *) kStimulusDarkWakeEntry
,
5998 _systemStateGeneration
);
6002 DLOG("=== FINISH (%s->%s, 0x%x) type %u, gen %u, msg %x, "
6003 "dcp %x:%x:%x, dbgtimer %u\n",
6004 getPowerStateString(currentPowerState
), getPowerStateString((uint32_t) powerState
), changeFlags
,
6005 _systemTransitionType
, _systemStateGeneration
,
6006 _systemMessageClientMask
,
6007 _desiredCapability
, _currentCapability
, _pendingCapability
,
6008 _lastDebugWakeSeconds
);
6010 if (_pendingCapability
& kIOPMSystemCapabilityGraphics
) {
6012 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
6013 if (clamshellExists
&& fullWakeThreadCall
&&
6014 CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
6015 // Not the initial graphics full power, graphics won't
6016 // send a power notification to trigger a lid state
6019 AbsoluteTime deadline
;
6020 clock_interval_to_deadline(45, kSecondScale
, &deadline
);
6021 thread_call_enter_delayed(fullWakeThreadCall
, deadline
);
6024 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU
)) {
6028 // Update current system capability.
6029 if (_currentCapability
!= _pendingCapability
) {
6030 _currentCapability
= _pendingCapability
;
6033 // Update highest system capability.
6035 _highestCapability
|= _currentCapability
;
6037 if (darkWakePostTickle
&&
6038 (kSystemTransitionWake
== _systemTransitionType
) &&
6039 (gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) ==
6040 kDarkWakeFlagHIDTickleLate
) {
6041 darkWakePostTickle
= false;
6043 } else if (wranglerTickled
) {
6044 requestFullWake( kFullWakeReasonLocalUser
);
6047 // Reset tracepoint at completion of capability change,
6048 // completion of wake transition, and aborted sleep transition.
6050 if ((_systemTransitionType
== kSystemTransitionCapability
) ||
6051 (_systemTransitionType
== kSystemTransitionWake
) ||
6052 ((_systemTransitionType
== kSystemTransitionSleep
) &&
6053 (changeFlags
& kIOPMNotDone
))) {
6054 setProperty(kIOPMSystemCapabilitiesKey
, _currentCapability
, 64);
6055 tracePoint( kIOPMTracePointSystemUp
);
6058 _systemTransitionType
= kSystemTransitionNone
;
6059 _systemMessageClientMask
= 0;
6060 toldPowerdCapWillChange
= false;
6062 logGraphicsClamp
= false;
6064 if (lowBatteryCondition
) {
6065 privateSleepSystem(kIOPMSleepReasonLowPower
);
6066 } else if ((fullWakeReason
== kFullWakeReasonDisplayOn
) && (!displayPowerOnRequested
)) {
6067 // Request for full wake is removed while system is waking up to full wake
6068 DLOG("DisplayOn fullwake request is removed\n");
6069 handleDisplayPowerOn();
6072 if (isRTCAlarmWake
) {
6073 pmPowerStateQueue
->submitPowerEvent(
6074 kPowerEventReceivedPowerNotification
, (void *)(uintptr_t) kLocalEvalClamshellCommand
);
6079 //******************************************************************************
6080 // PM actions for graphics and audio.
6081 //******************************************************************************
6084 IOPMrootDomain::overridePowerChangeForUIService(
6085 IOService
* service
,
6086 IOPMActions
* actions
,
6087 IOPMPowerStateIndex
* inOutPowerState
,
6088 IOPMPowerChangeFlags
* inOutChangeFlags
)
6090 uint32_t powerState
= (uint32_t) *inOutPowerState
;
6091 uint32_t changeFlags
= (uint32_t) *inOutChangeFlags
;
6093 if (kSystemTransitionNone
== _systemTransitionType
) {
6094 // Not in midst of a system transition.
6095 // Do not modify power limit enable state.
6096 } else if ((actions
->parameter
& kPMActionsFlagLimitPower
) == 0) {
6097 // Activate power limiter.
6099 if ((actions
->parameter
& kPMActionsFlagIsDisplayWrangler
) &&
6100 ((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0) &&
6101 (changeFlags
& kIOPMSynchronize
)) {
6102 actions
->parameter
|= kPMActionsFlagLimitPower
;
6103 } else if ((actions
->parameter
& kPMActionsFlagIsAudioDevice
) &&
6104 ((gDarkWakeFlags
& kDarkWakeFlagAudioNotSuppressed
) == 0) &&
6105 ((_pendingCapability
& kIOPMSystemCapabilityAudio
) == 0) &&
6106 (changeFlags
& kIOPMSynchronize
)) {
6107 actions
->parameter
|= kPMActionsFlagLimitPower
;
6108 } else if ((actions
->parameter
& kPMActionsFlagIsGraphicsDevice
) &&
6109 (_systemTransitionType
== kSystemTransitionSleep
)) {
6110 // For graphics devices, arm the limiter when entering
6111 // system sleep. Not when dropping to dark wake.
6112 actions
->parameter
|= kPMActionsFlagLimitPower
;
6115 if (actions
->parameter
& kPMActionsFlagLimitPower
) {
6116 DLOG("+ plimit %s %p\n",
6117 service
->getName(), OBFUSCATE(service
));
6120 // Remove power limit.
6122 if ((actions
->parameter
& (
6123 kPMActionsFlagIsDisplayWrangler
|
6124 kPMActionsFlagIsGraphicsDevice
)) &&
6125 (_pendingCapability
& kIOPMSystemCapabilityGraphics
)) {
6126 actions
->parameter
&= ~kPMActionsFlagLimitPower
;
6127 } else if ((actions
->parameter
& kPMActionsFlagIsAudioDevice
) &&
6128 (_pendingCapability
& kIOPMSystemCapabilityAudio
)) {
6129 actions
->parameter
&= ~kPMActionsFlagLimitPower
;
6132 if ((actions
->parameter
& kPMActionsFlagLimitPower
) == 0) {
6133 DLOG("- plimit %s %p\n",
6134 service
->getName(), OBFUSCATE(service
));
6138 if (actions
->parameter
& kPMActionsFlagLimitPower
) {
6139 uint32_t maxPowerState
= (uint32_t)(-1);
6141 if (changeFlags
& (kIOPMDomainDidChange
| kIOPMDomainWillChange
)) {
6142 // Enforce limit for system power/cap transitions.
6145 if ((service
->getPowerState() > maxPowerState
) &&
6146 (actions
->parameter
& kPMActionsFlagIsDisplayWrangler
)) {
6149 // Remove lingering effects of any tickle before entering
6150 // dark wake. It will take a new tickle to return to full
6151 // wake, so the existing tickle state is useless.
6153 if (changeFlags
& kIOPMDomainDidChange
) {
6154 *inOutChangeFlags
|= kIOPMExpireIdleTimer
;
6156 } else if (actions
->parameter
& kPMActionsFlagIsGraphicsDevice
) {
6160 // Deny all self-initiated changes when power is limited.
6161 // Wrangler tickle should never defeat the limiter.
6163 maxPowerState
= service
->getPowerState();
6166 if (powerState
> maxPowerState
) {
6167 DLOG("> plimit %s %p (%u->%u, 0x%x)\n",
6168 service
->getName(), OBFUSCATE(service
), powerState
, maxPowerState
,
6170 *inOutPowerState
= maxPowerState
;
6172 if (darkWakePostTickle
&&
6173 (actions
->parameter
& kPMActionsFlagIsDisplayWrangler
) &&
6174 (changeFlags
& kIOPMDomainWillChange
) &&
6175 ((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) ==
6176 kDarkWakeFlagHIDTickleEarly
)) {
6177 darkWakePostTickle
= false;
6182 if (!graphicsSuppressed
&& (changeFlags
& kIOPMDomainDidChange
)) {
6183 if (logGraphicsClamp
) {
6187 clock_get_uptime(&now
);
6188 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
6189 absolutetime_to_nanoseconds(now
, &nsec
);
6190 if (kIOLogPMRootDomain
& gIOKitDebug
) {
6191 MSG("Graphics suppressed %u ms\n",
6192 ((int)((nsec
) / NSEC_PER_MSEC
)));
6195 graphicsSuppressed
= true;
6201 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
6202 IOService
* service
,
6203 IOPMActions
* actions
)
6206 // Warning: Not running in PM work loop context - don't modify state !!!
6207 // Trap tickle directed to IODisplayWrangler while running with graphics
6208 // capability suppressed.
6210 assert(service
== wrangler
);
6212 clock_get_uptime(&userActivityTime
);
6213 bool aborting
= ((lastSleepReason
== kIOPMSleepReasonIdle
)
6214 || (lastSleepReason
== kIOPMSleepReasonMaintenance
)
6215 || (lastSleepReason
== kIOPMSleepReasonSoftware
));
6217 userActivityCount
++;
6218 DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
6219 userActivityCount
, lastSleepReason
);
6222 if (!wranglerTickled
&&
6223 ((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0)) {
6224 DLOG("display wrangler tickled\n");
6225 if (kIOLogPMRootDomain
& gIOKitDebug
) {
6226 OSReportWithBacktrace("Dark wake display tickle");
6228 if (pmPowerStateQueue
) {
6229 pmPowerStateQueue
->submitPowerEvent(
6230 kPowerEventPolicyStimulus
,
6231 (void *) kStimulusDarkWakeActivityTickle
,
6232 true /* set wake type */ );
6239 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
6240 IOService
* service
,
6241 IOPMActions
* actions
,
6242 const OSSymbol
* powerClient
,
6243 IOPMPowerStateIndex oldPowerState
,
6244 IOPMPowerStateIndex newPowerState
)
6247 assert(service
== wrangler
);
6249 // This function implements half of the user active detection
6250 // by monitoring changes to the display wrangler's device desire.
6252 // User becomes active when either:
6253 // 1. Wrangler's DeviceDesire increases to max, but wrangler is already
6254 // in max power state. This desire change in absence of a power state
6255 // change is detected within. This handles the case when user becomes
6256 // active while the display is already lit by setDisplayPowerOn().
6258 // 2. Power state change to max, and DeviceDesire is also at max.
6259 // Handled by displayWranglerNotification().
6261 // User becomes inactive when DeviceDesire drops to sleep state or below.
6263 DLOG("wrangler %s (ps %u, %u->%u)\n",
6264 powerClient
->getCStringNoCopy(),
6265 (uint32_t) service
->getPowerState(),
6266 (uint32_t) oldPowerState
, (uint32_t) newPowerState
);
6268 if (powerClient
== gIOPMPowerClientDevice
) {
6269 if ((newPowerState
> oldPowerState
) &&
6270 (newPowerState
== kWranglerPowerStateMax
) &&
6271 (service
->getPowerState() == kWranglerPowerStateMax
)) {
6272 evaluatePolicy( kStimulusEnterUserActiveState
);
6273 } else if ((newPowerState
< oldPowerState
) &&
6274 (newPowerState
<= kWranglerPowerStateSleep
)) {
6275 evaluatePolicy( kStimulusLeaveUserActiveState
);
6279 if (newPowerState
<= kWranglerPowerStateSleep
) {
6280 evaluatePolicy( kStimulusDisplayWranglerSleep
);
6281 } else if (newPowerState
== kWranglerPowerStateMax
) {
6282 evaluatePolicy( kStimulusDisplayWranglerWake
);
6287 //******************************************************************************
6288 // User active state management
6289 //******************************************************************************
6292 IOPMrootDomain::preventTransitionToUserActive( bool prevent
)
6295 _preventUserActive
= prevent
;
6296 if (wrangler
&& !_preventUserActive
) {
6297 // Allowing transition to user active, but the wrangler may have
6298 // already powered ON in case of sleep cancel/revert. Poll the
6299 // same conditions checked for in displayWranglerNotification()
6300 // to bring the user active state up to date.
6302 if ((wrangler
->getPowerState() == kWranglerPowerStateMax
) &&
6303 (wrangler
->getPowerStateForClient(gIOPMPowerClientDevice
) ==
6304 kWranglerPowerStateMax
)) {
6305 evaluatePolicy( kStimulusEnterUserActiveState
);
6311 //******************************************************************************
6312 // Approve usage of delayed child notification by PM.
6313 //******************************************************************************
6316 IOPMrootDomain::shouldDelayChildNotification(
6317 IOService
* service
)
6319 if (((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) != 0) &&
6320 (kFullWakeReasonNone
== fullWakeReason
) &&
6321 (kSystemTransitionWake
== _systemTransitionType
)) {
6322 DLOG("%s: delay child notify\n", service
->getName());
6328 //******************************************************************************
6329 // PM actions for PCI device.
6330 //******************************************************************************
6333 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
6334 IOService
* service
,
6335 IOPMActions
* actions
,
6336 IOPMPowerStateIndex powerState
,
6337 IOPMPowerChangeFlags
* inOutChangeFlags
)
6339 pmTracer
->tracePCIPowerChange(
6340 PMTraceWorker::kPowerChangeStart
,
6341 service
, *inOutChangeFlags
,
6342 (actions
->parameter
& kPMActionsPCIBitNumberMask
));
6346 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
6347 IOService
* service
,
6348 IOPMActions
* actions
,
6349 IOPMPowerStateIndex powerState
,
6350 IOPMPowerChangeFlags changeFlags
)
6352 pmTracer
->tracePCIPowerChange(
6353 PMTraceWorker::kPowerChangeCompleted
,
6354 service
, changeFlags
,
6355 (actions
->parameter
& kPMActionsPCIBitNumberMask
));
6358 //******************************************************************************
6361 // Override IOService::registerInterest() to intercept special clients.
6362 //******************************************************************************
6364 class IOPMServiceInterestNotifier
: public _IOServiceInterestNotifier
6366 friend class IOPMrootDomain
;
6367 OSDeclareDefaultStructors(IOPMServiceInterestNotifier
);
6370 uint32_t ackTimeoutCnt
;
6371 uint32_t msgType
;// Message pending ack
6375 const OSSymbol
*identifier
;
6378 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier
, _IOServiceInterestNotifier
)
6380 IONotifier
* IOPMrootDomain::registerInterest(
6381 const OSSymbol
* typeOfInterest
,
6382 IOServiceInterestHandler handler
,
6383 void * target
, void * ref
)
6385 IOPMServiceInterestNotifier
*notifier
= NULL
;
6386 bool isSystemCapabilityClient
;
6387 bool isKernelCapabilityClient
;
6388 IOReturn rc
= kIOReturnError
;;
6390 isSystemCapabilityClient
=
6392 typeOfInterest
->isEqualTo(kIOPMSystemCapabilityInterest
);
6394 isKernelCapabilityClient
=
6396 typeOfInterest
->isEqualTo(gIOPriorityPowerStateInterest
);
6398 if (isSystemCapabilityClient
) {
6399 typeOfInterest
= gIOAppPowerStateInterest
;
6402 notifier
= new IOPMServiceInterestNotifier
;
6407 if (notifier
->init()) {
6408 rc
= super::registerInterestForNotifier(notifier
, typeOfInterest
, handler
, target
, ref
);
6410 if (rc
!= kIOReturnSuccess
) {
6411 notifier
->release();
6416 if (pmPowerStateQueue
) {
6417 notifier
->ackTimeoutCnt
= 0;
6418 if (isSystemCapabilityClient
) {
6420 if (pmPowerStateQueue
->submitPowerEvent(
6421 kPowerEventRegisterSystemCapabilityClient
, notifier
) == false) {
6422 notifier
->release();
6426 if (isKernelCapabilityClient
) {
6428 if (pmPowerStateQueue
->submitPowerEvent(
6429 kPowerEventRegisterKernelCapabilityClient
, notifier
) == false) {
6430 notifier
->release();
6435 OSData
*data
= NULL
;
6436 uint8_t *uuid
= NULL
;
6437 OSKext
*kext
= OSKext::lookupKextWithAddress((vm_address_t
)handler
);
6439 data
= kext
->copyUUID();
6441 if (data
&& (data
->getLength() == sizeof(uuid_t
))) {
6442 uuid
= (uint8_t *)(data
->getBytesNoCopy());
6444 notifier
->uuid0
= ((uint64_t)(uuid
[0]) << 56) | ((uint64_t)(uuid
[1]) << 48) | ((uint64_t)(uuid
[2]) << 40) |
6445 ((uint64_t)(uuid
[3]) << 32) | ((uint64_t)(uuid
[4]) << 24) | ((uint64_t)(uuid
[5]) << 16) |
6446 ((uint64_t)(uuid
[6]) << 8) | (uuid
[7]);
6447 notifier
->uuid1
= ((uint64_t)(uuid
[8]) << 56) | ((uint64_t)(uuid
[9]) << 48) | ((uint64_t)(uuid
[10]) << 40) |
6448 ((uint64_t)(uuid
[11]) << 32) | ((uint64_t)(uuid
[12]) << 24) | ((uint64_t)(uuid
[13]) << 16) |
6449 ((uint64_t)(uuid
[14]) << 8) | (uuid
[15]);
6451 notifier
->identifier
= kext
->getIdentifier();
6463 //******************************************************************************
6464 // systemMessageFilter
6466 //******************************************************************************
6469 IOPMrootDomain::systemMessageFilter(
6470 void * object
, void * arg1
, void * arg2
, void * arg3
)
6472 const IOPMInterestContext
* context
= (const IOPMInterestContext
*) arg1
;
6473 bool isCapMsg
= (context
->messageType
== kIOMessageSystemCapabilityChange
);
6474 bool isCapClient
= false;
6476 IOPMServiceInterestNotifier
*notifier
;
6478 notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, (OSObject
*)object
);
6481 if ((kSystemTransitionNewCapClient
== _systemTransitionType
) &&
6482 (!isCapMsg
|| !_joinedCapabilityClients
||
6483 !_joinedCapabilityClients
->containsObject((OSObject
*) object
))) {
6487 // Capability change message for app and kernel clients.
6490 if ((context
->notifyType
== kNotifyPriority
) ||
6491 (context
->notifyType
== kNotifyCapabilityChangePriority
)) {
6495 if ((context
->notifyType
== kNotifyCapabilityChangeApps
) &&
6496 (object
== (void *) systemCapabilityNotifier
)) {
6502 IOPMSystemCapabilityChangeParameters
* capArgs
=
6503 (IOPMSystemCapabilityChangeParameters
*) arg2
;
6505 if (kSystemTransitionNewCapClient
== _systemTransitionType
) {
6506 capArgs
->fromCapabilities
= 0;
6507 capArgs
->toCapabilities
= _currentCapability
;
6508 capArgs
->changeFlags
= 0;
6510 capArgs
->fromCapabilities
= _currentCapability
;
6511 capArgs
->toCapabilities
= _pendingCapability
;
6513 if (context
->isPreChange
) {
6514 capArgs
->changeFlags
= kIOPMSystemCapabilityWillChange
;
6516 capArgs
->changeFlags
= kIOPMSystemCapabilityDidChange
;
6519 if ((object
== (void *) systemCapabilityNotifier
) &&
6520 context
->isPreChange
) {
6521 toldPowerdCapWillChange
= true;
6525 // Capability change messages only go to the PM configd plugin.
6526 // Wait for response post-change if capabilitiy is increasing.
6527 // Wait for response pre-change if capability is decreasing.
6529 if ((context
->notifyType
== kNotifyCapabilityChangeApps
) && arg3
&&
6530 ((capabilityLoss
&& context
->isPreChange
) ||
6531 (!capabilityLoss
&& !context
->isPreChange
))) {
6532 // app has not replied yet, wait for it
6533 *((OSObject
**) arg3
) = kOSBooleanFalse
;
6540 // Capability client will always see kIOMessageCanSystemSleep,
6541 // even for demand sleep. It will also have a chance to veto
6542 // sleep one last time after all clients have responded to
6543 // kIOMessageSystemWillSleep
6545 if ((kIOMessageCanSystemSleep
== context
->messageType
) ||
6546 (kIOMessageSystemWillNotSleep
== context
->messageType
)) {
6547 if (object
== (OSObject
*) systemCapabilityNotifier
) {
6552 // Not idle sleep, don't ask apps.
6553 if (context
->changeFlags
& kIOPMSkipAskPowerDown
) {
6558 if (kIOPMMessageLastCallBeforeSleep
== context
->messageType
) {
6559 if ((object
== (OSObject
*) systemCapabilityNotifier
) &&
6560 CAP_HIGHEST(kIOPMSystemCapabilityGraphics
) &&
6561 (fullToDarkReason
== kIOPMSleepReasonIdle
)) {
6567 // Reject capability change messages for legacy clients.
6568 // Reject legacy system sleep messages for capability client.
6570 if (isCapMsg
|| (object
== (OSObject
*) systemCapabilityNotifier
)) {
6574 // Filter system sleep messages.
6576 if ((context
->notifyType
== kNotifyApps
) &&
6577 (_systemMessageClientMask
& kSystemMessageClientLegacyApp
)) {
6582 if (notifier
->ackTimeoutCnt
>= 3) {
6583 *((OSObject
**) arg3
) = kOSBooleanFalse
;
6585 *((OSObject
**) arg3
) = kOSBooleanTrue
;
6589 } else if ((context
->notifyType
== kNotifyPriority
) &&
6590 (_systemMessageClientMask
& kSystemMessageClientKernel
)) {
6595 if (allow
&& isCapMsg
&& _joinedCapabilityClients
) {
6596 _joinedCapabilityClients
->removeObject((OSObject
*) object
);
6597 if (_joinedCapabilityClients
->getCount() == 0) {
6598 DLOG("destroyed capability client set %p\n",
6599 OBFUSCATE(_joinedCapabilityClients
));
6600 _joinedCapabilityClients
->release();
6601 _joinedCapabilityClients
= NULL
;
6605 notifier
->msgType
= context
->messageType
;
6611 //******************************************************************************
6612 // setMaintenanceWakeCalendar
6614 //******************************************************************************
6617 IOPMrootDomain::setMaintenanceWakeCalendar(
6618 const IOPMCalendarStruct
* calendar
)
6624 return kIOReturnBadArgument
;
6627 data
= OSData::withBytes((void *) calendar
, sizeof(*calendar
));
6629 return kIOReturnNoMemory
;
6632 if (kPMCalendarTypeMaintenance
== calendar
->selector
) {
6633 ret
= setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey
, data
);
6634 if (kIOReturnSuccess
== ret
) {
6635 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake
, &_scheduledAlarms
);
6637 } else if (kPMCalendarTypeSleepService
== calendar
->selector
) {
6638 ret
= setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey
, data
);
6639 if (kIOReturnSuccess
== ret
) {
6640 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake
, &_scheduledAlarms
);
6643 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms
);
6650 // MARK: Display Wrangler
6652 //******************************************************************************
6653 // displayWranglerNotification
6655 // Handle the notification when the IODisplayWrangler changes power state.
6656 //******************************************************************************
6659 IOPMrootDomain::displayWranglerNotification(
6660 void * target
, void * refCon
,
6661 UInt32 messageType
, IOService
* service
,
6662 void * messageArgument
, vm_size_t argSize
)
6665 int displayPowerState
;
6666 IOPowerStateChangeNotification
* params
=
6667 (IOPowerStateChangeNotification
*) messageArgument
;
6669 if ((messageType
!= kIOMessageDeviceWillPowerOff
) &&
6670 (messageType
!= kIOMessageDeviceHasPoweredOn
)) {
6671 return kIOReturnUnsupported
;
6676 return kIOReturnUnsupported
;
6679 displayPowerState
= params
->stateNumber
;
6680 DLOG("wrangler %s ps %d\n",
6681 getIOMessageString(messageType
), displayPowerState
);
6683 switch (messageType
) {
6684 case kIOMessageDeviceWillPowerOff
:
6685 // Display wrangler has dropped power due to display idle
6686 // or force system sleep.
6688 // 4 Display ON kWranglerPowerStateMax
6689 // 3 Display Dim kWranglerPowerStateDim
6690 // 2 Display Sleep kWranglerPowerStateSleep
6691 // 1 Not visible to user
6692 // 0 Not visible to user kWranglerPowerStateMin
6694 if (displayPowerState
<= kWranglerPowerStateSleep
) {
6695 gRootDomain
->evaluatePolicy( kStimulusDisplayWranglerSleep
);
6699 case kIOMessageDeviceHasPoweredOn
:
6700 // Display wrangler has powered on due to user activity
6701 // or wake from sleep.
6703 if (kWranglerPowerStateMax
== displayPowerState
) {
6704 gRootDomain
->evaluatePolicy( kStimulusDisplayWranglerWake
);
6706 // See comment in handleUpdatePowerClientForDisplayWrangler
6707 if (service
->getPowerStateForClient(gIOPMPowerClientDevice
) ==
6708 kWranglerPowerStateMax
) {
6709 gRootDomain
->evaluatePolicy( kStimulusEnterUserActiveState
);
6715 return kIOReturnUnsupported
;
6718 //******************************************************************************
6719 // displayWranglerMatchPublished
6721 // Receives a notification when the IODisplayWrangler is published.
6722 // When it's published we install a power state change handler.
6723 //******************************************************************************
6726 IOPMrootDomain::displayWranglerMatchPublished(
6729 IOService
* newService
,
6730 IONotifier
* notifier __unused
)
6733 // install a handler
6734 if (!newService
->registerInterest( gIOGeneralInterest
,
6735 &displayWranglerNotification
, target
, NULL
)) {
6742 //******************************************************************************
6745 //******************************************************************************
6748 IOPMrootDomain::reportUserInput( void )
6752 OSDictionary
* matching
;
6755 matching
= serviceMatching("IODisplayWrangler");
6756 iter
= getMatchingServices(matching
);
6758 matching
->release();
6761 wrangler
= OSDynamicCast(IOService
, iter
->getNextObject());
6767 wrangler
->activityTickle(0, 0);
6772 //******************************************************************************
6773 // latchDisplayWranglerTickle
6774 //******************************************************************************
6777 IOPMrootDomain::latchDisplayWranglerTickle( bool latch
)
6781 if (!(_currentCapability
& kIOPMSystemCapabilityGraphics
) &&
6782 !(_pendingCapability
& kIOPMSystemCapabilityGraphics
) &&
6783 !checkSystemCanSustainFullWake()) {
6784 // Currently in dark wake, and not transitioning to full wake.
6785 // Full wake is unsustainable, so latch the tickle to prevent
6786 // the display from lighting up momentarily.
6787 wranglerTickleLatched
= true;
6789 wranglerTickleLatched
= false;
6791 } else if (wranglerTickleLatched
&& checkSystemCanSustainFullWake()) {
6792 wranglerTickleLatched
= false;
6794 pmPowerStateQueue
->submitPowerEvent(
6795 kPowerEventPolicyStimulus
,
6796 (void *) kStimulusDarkWakeActivityTickle
);
6799 return wranglerTickleLatched
;
6805 //******************************************************************************
6806 // setDisplayPowerOn
6808 // For root domain user client
6809 //******************************************************************************
6812 IOPMrootDomain::setDisplayPowerOn( uint32_t options
)
6814 pmPowerStateQueue
->submitPowerEvent( kPowerEventSetDisplayPowerOn
,
6815 (void *) NULL
, options
);
6821 //******************************************************************************
6824 // Notification on battery class IOPowerSource appearance
6825 //******************************************************************************
6828 IOPMrootDomain::batteryPublished(
6831 IOService
* resourceService
,
6832 IONotifier
* notifier __unused
)
6834 // rdar://2936060&4435589
6835 // All laptops have dimmable LCD displays
6836 // All laptops have batteries
6837 // So if this machine has a battery, publish the fact that the backlight
6838 // supports dimming.
6839 ((IOPMrootDomain
*)root_domain
)->publishFeature("DisplayDims");
6845 // MARK: System PM Policy
6847 //******************************************************************************
6848 // checkSystemSleepAllowed
6850 //******************************************************************************
6853 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options
,
6854 uint32_t sleepReason
)
6858 // Conditions that prevent idle and demand system sleep.
6861 if (userDisabledAllSleep
) {
6862 err
= kPMUserDisabledAllSleep
; // 1. user-space sleep kill switch
6866 if (systemBooting
|| systemShutdown
|| gWillShutdown
) {
6867 err
= kPMSystemRestartBootingInProgress
; // 2. restart or shutdown in progress
6875 // Conditions above pegs the system at full wake.
6876 // Conditions below prevent system sleep but does not prevent
6877 // dark wake, and must be called from gated context.
6880 err
= kPMConfigPreventSystemSleep
; // 3. config does not support sleep
6884 if (lowBatteryCondition
|| thermalWarningState
) {
6885 break; // always sleep on low battery or when in thermal warning state
6888 if (sleepReason
== kIOPMSleepReasonDarkWakeThermalEmergency
) {
6889 break; // always sleep on dark wake thermal emergencies
6892 if (preventSystemSleepList
->getCount() != 0) {
6893 err
= kPMChildPreventSystemSleep
; // 4. child prevent system sleep clamp
6897 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit
) ==
6898 kIOPMDriverAssertionLevelOn
) {
6899 err
= kPMCPUAssertion
; // 5. CPU assertion
6903 if (pciCantSleepValid
) {
6904 if (pciCantSleepFlag
) {
6905 err
= kPMPCIUnsupported
; // 6. PCI card does not support PM (cached)
6908 } else if (sleepSupportedPEFunction
&&
6909 CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
6911 OSBitAndAtomic(~kPCICantSleep
, &platformSleepSupport
);
6912 ret
= getPlatform()->callPlatformFunction(
6913 sleepSupportedPEFunction
, false,
6914 NULL
, NULL
, NULL
, NULL
);
6915 pciCantSleepValid
= true;
6916 pciCantSleepFlag
= false;
6917 if ((platformSleepSupport
& kPCICantSleep
) ||
6918 ((ret
!= kIOReturnSuccess
) && (ret
!= kIOReturnUnsupported
))) {
6919 err
= 6; // 6. PCI card does not support PM
6920 pciCantSleepFlag
= true;
6927 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err
));
6934 IOPMrootDomain::checkSystemSleepEnabled( void )
6936 return checkSystemSleepAllowed(0, 0);
6940 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason
)
6943 return checkSystemSleepAllowed(1, sleepReason
);
6946 //******************************************************************************
6947 // checkSystemCanSustainFullWake
6948 //******************************************************************************
6951 IOPMrootDomain::checkSystemCanSustainFullWake( void )
6954 if (lowBatteryCondition
|| thermalWarningState
) {
6955 // Low battery wake, or received a low battery notification
6956 // while system is awake. This condition will persist until
6957 // the following wake.
6961 if (clamshellExists
&& clamshellClosed
&& !clamshellSleepDisabled
) {
6962 // Graphics state is unknown and external display might not be probed.
6963 // Do not incorporate state that requires graphics to be in max power
6964 // such as desktopMode or clamshellDisabled.
6966 if (!acAdaptorConnected
) {
6967 DLOG("full wake check: no AC\n");
6975 //******************************************************************************
6977 //******************************************************************************
6982 IOPMrootDomain::mustHibernate( void )
6984 return lowBatteryCondition
|| thermalWarningState
;
6987 #endif /* HIBERNATION */
6989 //******************************************************************************
6991 //******************************************************************************
6993 // Tables for accumulated days in year by month, latter used for leap years
6995 static const int daysbymonth
[] =
6996 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
6998 static const int lydaysbymonth
[] =
6999 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7002 IOPMConvertSecondsToCalendar(long secs
, IOPMCalendarStruct
* dt
)
7004 const int * dbm
= daysbymonth
;
7011 // Calculate seconds, minutes and hours
7013 n
= secs
% (24 * 3600);
7014 dt
->second
= n
% 60;
7016 dt
->minute
= n
% 60;
7019 // Calculate day of week
7021 n
= secs
/ (24 * 3600);
7022 // dt->dayWeek = (n + 4) % 7;
7025 // Rebase from days since Unix epoch (1/1/1970) store in 'n',
7026 // to days since 1/1/1968 to start on 4 year cycle, beginning
7031 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7032 // Valid before 2100, since 2100 is not a leap year.
7034 x
= n
/ 1461; // number of 4 year cycles
7035 y
= n
% 1461; // days into current 4 year cycle
7038 // Add in years in the current 4 year cycle
7041 y
-= 366; // days after the leap year
7042 n
= y
% 365; // days into the current year
7043 z
+= (1 + y
/ 365); // years after the past 4-yr cycle
7046 dbm
= lydaysbymonth
;
7054 // Adjust remaining days value to start at 1
7060 for (x
= 1; n
> dbm
[x
]; x
++) {
7065 // Calculate day of month
7067 dt
->day
= n
- dbm
[x
- 1];
7073 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct
* dt
)
7075 const int * dbm
= daysbymonth
;
7078 if (dt
->year
< 1970) {
7082 // Seconds elapsed in the current day
7084 secs
= dt
->second
+ 60 * dt
->minute
+ 3600 * dt
->hour
;
7086 // Number of days from 1/1/70 to beginning of current year
7087 // Account for extra day every 4 years starting at 1973
7089 y
= dt
->year
- 1970;
7090 days
= (y
* 365) + ((y
+ 1) / 4);
7092 // Change table if current year is a leap year
7094 if ((dt
->year
% 4) == 0) {
7095 dbm
= lydaysbymonth
;
7098 // Add in days elapsed in the current year
7100 days
+= (dt
->day
- 1) + dbm
[dt
->month
- 1];
7102 // Add accumulated days to accumulated seconds
7104 secs
+= 24 * 3600 * days
;
7109 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
7112 IOPMrootDomain::getRUN_STATE(void)
7114 return _aotNow
? AOT_STATE
: ON_STATE
;
7118 IOPMrootDomain::isAOTMode()
7124 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime
)
7126 clock_sec_t nowsecs
, wakesecs
;
7127 clock_usec_t nowmicrosecs
, wakemicrosecs
;
7128 uint64_t nowAbs
, wakeAbs
;
7130 clock_gettimeofday_and_absolute_time(&nowsecs
, &nowmicrosecs
, &nowAbs
);
7131 wakeAbs
= continuoustime_to_absolutetime(wakeContinuousTime
);
7132 if (wakeAbs
< nowAbs
) {
7133 printf(LOG_PREFIX
"wakeAbs %qd < nowAbs %qd\n", wakeAbs
, nowAbs
);
7137 absolutetime_to_microtime(wakeAbs
, &wakesecs
, &wakemicrosecs
);
7139 wakesecs
+= nowsecs
;
7140 wakemicrosecs
+= nowmicrosecs
;
7141 if (wakemicrosecs
>= USEC_PER_SEC
) {
7143 wakemicrosecs
-= USEC_PER_SEC
;
7145 if (wakemicrosecs
>= (USEC_PER_SEC
/ 10)) {
7149 IOPMConvertSecondsToCalendar(wakesecs
, &_aotWakeTimeCalendar
);
7151 if (_aotWakeTimeContinuous
!= wakeContinuousTime
) {
7152 _aotWakeTimeContinuous
= wakeContinuousTime
;
7153 IOLog(LOG_PREFIX
"setWakeTime: " YMDTF
"\n", YMDT(&_aotWakeTimeCalendar
));
7155 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeMaintenance
;
7156 _aotWakeTimeUTC
= wakesecs
;
7158 return kIOReturnSuccess
;
7161 // assumes WAKEEVENT_LOCK
7163 IOPMrootDomain::aotShouldExit(bool checkTimeSet
, bool software
)
7166 const char * reason
= "";
7170 _aotMetrics
->softwareRequestCount
++;
7171 reason
= "software request";
7172 } else if (kIOPMWakeEventAOTExitFlags
& _aotPendingFlags
) {
7174 reason
= gWakeReasonString
;
7175 } else if (checkTimeSet
&& (kPMCalendarTypeInvalid
== _aotWakeTimeCalendar
.selector
)) {
7177 _aotMetrics
->noTimeSetCount
++;
7178 reason
= "flipbook expired";
7179 } else if ((kIOPMAOTModeRespectTimers
& _aotMode
) && _scheduledAlarmUTC
) {
7182 clock_get_calendar_microtime(&sec
, &usec
);
7183 if (_scheduledAlarmUTC
<= sec
) {
7185 _aotMetrics
->rtcAlarmsCount
++;
7186 reason
= "user alarm";
7189 exitNow
= (_aotNow
&& _aotExit
);
7192 IOLog(LOG_PREFIX
"AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7194 _aotMetrics
->sleepCount
,
7195 _aotMetrics
->possibleCount
,
7196 _aotMetrics
->confirmedPossibleCount
,
7197 _aotMetrics
->rejectedPossibleCount
,
7198 _aotMetrics
->expiredPossibleCount
,
7199 _aotMetrics
->noTimeSetCount
,
7200 _aotMetrics
->rtcAlarmsCount
);
7206 IOPMrootDomain::aotExit(bool cps
)
7208 _aotTasksSuspended
= false;
7209 _aotReadyToFullWake
= false;
7210 if (_aotTimerScheduled
) {
7211 _aotTimerES
->cancelTimeout();
7212 _aotTimerScheduled
= false;
7214 updateTasksSuspend();
7216 _aotMetrics
->totalTime
+= mach_absolute_time() - _aotLastWakeTime
;
7217 _aotLastWakeTime
= 0;
7218 if (_aotMetrics
->sleepCount
&& (_aotMetrics
->sleepCount
<= kIOPMAOTMetricsKernelWakeCountMax
)) {
7219 strlcpy(&_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
- 1][0],
7221 sizeof(_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
]));
7224 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeInvalid
;
7226 _systemMessageClientMask
= kSystemMessageClientLegacyApp
;
7227 tellClients(kIOMessageSystemWillPowerOn
);
7230 changePowerStateToPriv(getRUN_STATE());
7235 IOPMrootDomain::aotEvaluate(IOTimerEventSource
* timer
)
7239 IOLog("aotEvaluate(%d) 0x%x\n", (timer
!= NULL
), _aotPendingFlags
);
7242 exitNow
= aotShouldExit(false, false);
7243 if (timer
!= NULL
) {
7244 _aotTimerScheduled
= false;
7251 if (_aotLingerTime
) {
7253 IOLog("aot linger before sleep\n");
7254 clock_absolutetime_interval_to_deadline(_aotLingerTime
, &deadline
);
7255 clock_delay_until(deadline
);
7258 privateSleepSystem(kIOPMSleepReasonSoftware
);
7262 #else /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
7265 IOPMrootDomain::getRUN_STATE(void)
7271 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime
)
7273 return kIOReturnUnsupported
;
7276 #endif /* (defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
7278 //******************************************************************************
7281 // Conditions that affect our wake/sleep decision has changed.
7282 // If conditions dictate that the system must remain awake, clamp power
7283 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7284 // is TRUE, then remove the power clamp and allow the power state to drop
7286 //******************************************************************************
7289 IOPMrootDomain::adjustPowerState( bool sleepASAP
)
7291 DEBUG_LOG("adjustPowerState ps %s, asap %d, idleSleepEnabled %d\n",
7292 getPowerStateString((uint32_t) getPowerState()), sleepASAP
, idleSleepEnabled
);
7296 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
7300 if (AOT_STATE
!= getPowerState()) {
7304 exitNow
= aotShouldExit(true, false);
7306 && !_aotTimerScheduled
7307 && (kIOPMWakeEventAOTPossibleExit
== (kIOPMWakeEventAOTPossibleFlags
& _aotPendingFlags
))) {
7308 _aotTimerScheduled
= true;
7309 if (_aotLingerTime
) {
7310 _aotTimerES
->setTimeout(_aotLingerTime
);
7312 _aotTimerES
->setTimeout(800, kMillisecondScale
);
7319 _aotReadyToFullWake
= true;
7320 if (!_aotTimerScheduled
) {
7321 privateSleepSystem(kIOPMSleepReasonSoftware
);
7326 #endif /* (defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
7328 if ((!idleSleepEnabled
) || !checkSystemSleepEnabled()) {
7329 changePowerStateToPriv(getRUN_STATE());
7330 } else if (sleepASAP
) {
7331 changePowerStateToPriv(SLEEP_STATE
);
7336 IOPMrootDomain::handleDisplayPowerOn()
7341 if (displayPowerOnRequested
) {
7342 if (!checkSystemCanSustainFullWake()) {
7346 // Force wrangler to max power state. If system is in dark wake
7347 // this alone won't raise the wrangler's power state.
7349 wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMax
);
7351 // System in dark wake, always requesting full wake should
7352 // not have any bad side-effects, even if the request fails.
7354 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
7355 setProperty(kIOPMRootDomainWakeTypeKey
, kIOPMRootDomainWakeTypeNotification
);
7356 requestFullWake( kFullWakeReasonDisplayOn
);
7359 // Relenquish desire to power up display.
7360 // Must first transition to state 1 since wrangler doesn't
7361 // power off the displays at state 0. At state 0 the root
7362 // domain is removed from the wrangler's power client list.
7364 wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMin
+ 1);
7365 wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMin
);
7369 //******************************************************************************
7370 // dispatchPowerEvent
7372 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
7373 //******************************************************************************
7376 IOPMrootDomain::dispatchPowerEvent(
7377 uint32_t event
, void * arg0
, uint64_t arg1
)
7382 case kPowerEventFeatureChanged
:
7383 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7384 messageClients(kIOPMMessageFeatureChange
, this);
7387 case kPowerEventReceivedPowerNotification
:
7388 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7389 handlePowerNotification((UInt32
)(uintptr_t) arg0
);
7392 case kPowerEventSystemBootCompleted
:
7393 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7394 if (systemBooting
) {
7395 systemBooting
= false;
7397 // read noidle setting from Device Tree
7398 IORegistryEntry
*defaults
= IORegistryEntry::fromPath("IODeviceTree:/defaults");
7399 if (defaults
!= NULL
) {
7400 OSData
*data
= OSDynamicCast(OSData
, defaults
->getProperty("no-idle"));
7401 if ((data
!= NULL
) && (data
->getLength() == 4)) {
7402 gNoIdleFlag
= *(uint32_t*)data
->getBytesNoCopy();
7403 DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag
);
7405 defaults
->release();
7407 if (lowBatteryCondition
) {
7408 privateSleepSystem(kIOPMSleepReasonLowPower
);
7410 // The rest is unnecessary since the system is expected
7411 // to sleep immediately. The following wake will update
7416 sleepWakeDebugMemAlloc();
7417 saveFailureData2File();
7419 // If lid is closed, re-send lid closed notification
7420 // now that booting is complete.
7421 if (clamshellClosed
) {
7422 handlePowerNotification(kLocalEvalClamshellCommand
);
7424 evaluatePolicy( kStimulusAllowSystemSleepChanged
);
7428 case kPowerEventSystemShutdown
:
7429 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7430 if (kOSBooleanTrue
== (OSBoolean
*) arg0
) {
7431 /* We set systemShutdown = true during shutdown
7432 * to prevent sleep at unexpected times while loginwindow is trying
7433 * to shutdown apps and while the OS is trying to transition to
7434 * complete power of.
7436 * Set to true during shutdown, as soon as loginwindow shows
7437 * the "shutdown countdown dialog", through individual app
7438 * termination, and through black screen kernel shutdown.
7440 systemShutdown
= true;
7443 * A shutdown was initiated, but then the shutdown
7444 * was cancelled, clearing systemShutdown to false here.
7446 systemShutdown
= false;
7450 case kPowerEventUserDisabledSleep
:
7451 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7452 userDisabledAllSleep
= (kOSBooleanTrue
== (OSBoolean
*) arg0
);
7455 case kPowerEventRegisterSystemCapabilityClient
:
7456 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7457 if (systemCapabilityNotifier
) {
7458 systemCapabilityNotifier
->release();
7459 systemCapabilityNotifier
= NULL
;
7462 systemCapabilityNotifier
= (IONotifier
*) arg0
;
7463 systemCapabilityNotifier
->retain();
7465 /* intentional fall-through */
7466 [[clang::fallthrough]];
7468 case kPowerEventRegisterKernelCapabilityClient
:
7469 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7470 if (!_joinedCapabilityClients
) {
7471 _joinedCapabilityClients
= OSSet::withCapacity(8);
7474 IONotifier
* notify
= (IONotifier
*) arg0
;
7475 if (_joinedCapabilityClients
) {
7476 _joinedCapabilityClients
->setObject(notify
);
7477 synchronizePowerTree( kIOPMSyncNoChildNotify
);
7483 case kPowerEventPolicyStimulus
:
7484 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7486 int stimulus
= (uintptr_t) arg0
;
7487 evaluatePolicy( stimulus
, (uint32_t) arg1
);
7491 case kPowerEventAssertionCreate
:
7492 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7494 pmAssertions
->handleCreateAssertion((OSData
*)arg0
);
7499 case kPowerEventAssertionRelease
:
7500 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7502 pmAssertions
->handleReleaseAssertion(arg1
);
7506 case kPowerEventAssertionSetLevel
:
7507 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7509 pmAssertions
->handleSetAssertionLevel(arg1
, (IOPMDriverAssertionLevel
)(uintptr_t)arg0
);
7513 case kPowerEventQueueSleepWakeUUID
:
7514 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7515 handleQueueSleepWakeUUID((OSObject
*)arg0
);
7517 case kPowerEventPublishSleepWakeUUID
:
7518 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7519 handlePublishSleepWakeUUID((bool)arg0
);
7522 case kPowerEventSetDisplayPowerOn
:
7523 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7528 displayPowerOnRequested
= true;
7530 displayPowerOnRequested
= false;
7532 handleDisplayPowerOn();
7537 //******************************************************************************
7538 // systemPowerEventOccurred
7540 // The power controller is notifying us of a hardware-related power management
7541 // event that we must handle.
7543 // systemPowerEventOccurred covers the same functionality that
7544 // receivePowerNotification does; it simply provides a richer API for conveying
7545 // more information.
7546 //******************************************************************************
7549 IOPMrootDomain::systemPowerEventOccurred(
7550 const OSSymbol
*event
,
7553 IOReturn attempt
= kIOReturnSuccess
;
7554 OSNumber
*newNumber
= NULL
;
7557 return kIOReturnBadArgument
;
7560 newNumber
= OSNumber::withNumber(intValue
, 8 * sizeof(intValue
));
7562 return kIOReturnInternalError
;
7565 attempt
= systemPowerEventOccurred(event
, (OSObject
*)newNumber
);
7567 newNumber
->release();
7573 IOPMrootDomain::setThermalState(OSObject
*value
)
7577 if (gIOPMWorkLoop
->inGate() == false) {
7578 gIOPMWorkLoop
->runAction(
7579 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::setThermalState
),
7585 if (value
&& (num
= OSDynamicCast(OSNumber
, value
))) {
7586 thermalWarningState
= ((num
->unsigned32BitValue() == kIOPMThermalLevelWarning
) ||
7587 (num
->unsigned32BitValue() == kIOPMThermalLevelTrap
)) ? 1 : 0;
7592 IOPMrootDomain::systemPowerEventOccurred(
7593 const OSSymbol
*event
,
7596 OSDictionary
*thermalsDict
= NULL
;
7597 bool shouldUpdate
= true;
7599 if (!event
|| !value
) {
7600 return kIOReturnBadArgument
;
7604 // We reuse featuresDict Lock because it already exists and guards
7605 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
7606 // of stepping on that lock.
7607 if (featuresDictLock
) {
7608 IOLockLock(featuresDictLock
);
7611 thermalsDict
= (OSDictionary
*)getProperty(kIOPMRootDomainPowerStatusKey
);
7613 if (thermalsDict
&& OSDynamicCast(OSDictionary
, thermalsDict
)) {
7614 thermalsDict
= OSDictionary::withDictionary(thermalsDict
);
7616 thermalsDict
= OSDictionary::withCapacity(1);
7619 if (!thermalsDict
) {
7620 shouldUpdate
= false;
7624 thermalsDict
->setObject(event
, value
);
7626 setProperty(kIOPMRootDomainPowerStatusKey
, thermalsDict
);
7628 thermalsDict
->release();
7632 if (featuresDictLock
) {
7633 IOLockUnlock(featuresDictLock
);
7638 event
->isEqualTo(kIOPMThermalLevelWarningKey
)) {
7639 setThermalState(value
);
7641 messageClients(kIOPMMessageSystemPowerEventOccurred
, (void *)NULL
);
7644 return kIOReturnSuccess
;
7647 //******************************************************************************
7648 // receivePowerNotification
7650 // The power controller is notifying us of a hardware-related power management
7651 // event that we must handle. This may be a result of an 'environment' interrupt
7652 // from the power mgt micro.
7653 //******************************************************************************
7656 IOPMrootDomain::receivePowerNotification( UInt32 msg
)
7658 if (msg
& kIOPMPowerButton
) {
7659 uint32_t currentPhase
= pmTracer
->getTracePhase();
7660 if (currentPhase
!= kIOPMTracePointSystemUp
&& currentPhase
> kIOPMTracePointSystemSleep
) {
7661 DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase
);
7662 swd_flags
|= SWD_PWR_BTN_STACKSHOT
;
7663 thread_call_enter(powerButtonDown
);
7665 DEBUG_LOG("power button pressed when system is up\n");
7667 } else if (msg
& kIOPMPowerButtonUp
) {
7668 if (swd_flags
& SWD_PWR_BTN_STACKSHOT
) {
7669 swd_flags
&= ~SWD_PWR_BTN_STACKSHOT
;
7670 thread_call_enter(powerButtonUp
);
7673 pmPowerStateQueue
->submitPowerEvent(
7674 kPowerEventReceivedPowerNotification
, (void *)(uintptr_t) msg
);
7676 return kIOReturnSuccess
;
7680 IOPMrootDomain::handlePowerNotification( UInt32 msg
)
7682 bool eval_clamshell
= false;
7683 bool eval_clamshell_alarm
= false;
7688 * Local (IOPMrootDomain only) eval clamshell command
7690 if (msg
& kLocalEvalClamshellCommand
) {
7691 if (isRTCAlarmWake
) {
7692 eval_clamshell_alarm
= true;
7694 // reset isRTCAlarmWake. This evaluation should happen only once
7695 // on RTC/Alarm wake. Any clamshell events after wake should follow
7696 // the regular evaluation
7697 isRTCAlarmWake
= false;
7699 eval_clamshell
= true;
7706 if (msg
& kIOPMOverTemp
) {
7707 MSG("PowerManagement emergency overtemp signal. Going to sleep!");
7708 privateSleepSystem(kIOPMSleepReasonThermalEmergency
);
7712 * Forward DW thermal notification to client, if system is not going to sleep
7714 if ((msg
& kIOPMDWOverTemp
) && (_systemTransitionType
!= kSystemTransitionSleep
)) {
7715 DLOG("DarkWake thermal limits message received!\n");
7717 messageClients(kIOPMMessageDarkWakeThermalEmergency
);
7723 if (msg
& kIOPMSleepNow
) {
7724 privateSleepSystem(kIOPMSleepReasonSoftware
);
7730 if (msg
& kIOPMPowerEmergency
) {
7731 lowBatteryCondition
= true;
7732 privateSleepSystem(kIOPMSleepReasonLowPower
);
7738 if (msg
& kIOPMClamshellOpened
) {
7739 DLOG("Clamshell opened\n");
7740 // Received clamshel open message from clamshell controlling driver
7741 // Update our internal state and tell general interest clients
7742 clamshellClosed
= false;
7743 clamshellExists
= true;
7745 // Don't issue a hid tickle when lid is open and polled on wake
7746 if (msg
& kIOPMSetValue
) {
7747 setProperty(kIOPMRootDomainWakeTypeKey
, "Lid Open");
7752 informCPUStateChange(kInformLid
, 0);
7754 // Tell general interest clients
7755 sendClientClamshellNotification();
7757 bool aborting
= ((lastSleepReason
== kIOPMSleepReasonClamshell
)
7758 || (lastSleepReason
== kIOPMSleepReasonIdle
)
7759 || (lastSleepReason
== kIOPMSleepReasonMaintenance
));
7761 userActivityCount
++;
7763 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount
, lastSleepReason
);
7768 * Send the clamshell interest notification since the lid is closing.
7770 if (msg
& kIOPMClamshellClosed
) {
7771 if (clamshellClosed
&& clamshellExists
) {
7772 DLOG("Ignoring redundant Clamshell close event\n");
7774 DLOG("Clamshell closed\n");
7775 // Received clamshel open message from clamshell controlling driver
7776 // Update our internal state and tell general interest clients
7777 clamshellClosed
= true;
7778 clamshellExists
= true;
7781 informCPUStateChange(kInformLid
, 1);
7783 // Tell general interest clients
7784 sendClientClamshellNotification();
7786 // And set eval_clamshell = so we can attempt
7787 eval_clamshell
= true;
7792 * Set Desktop mode (sent from graphics)
7794 * -> reevaluate lid state
7796 if (msg
& kIOPMSetDesktopMode
) {
7797 DLOG("Desktop mode\n");
7798 desktopMode
= (0 != (msg
& kIOPMSetValue
));
7799 msg
&= ~(kIOPMSetDesktopMode
| kIOPMSetValue
);
7801 sendClientClamshellNotification();
7803 // Re-evaluate the lid state
7804 eval_clamshell
= true;
7808 * AC Adaptor connected
7810 * -> reevaluate lid state
7812 if (msg
& kIOPMSetACAdaptorConnected
) {
7813 acAdaptorConnected
= (0 != (msg
& kIOPMSetValue
));
7814 msg
&= ~(kIOPMSetACAdaptorConnected
| kIOPMSetValue
);
7817 informCPUStateChange(kInformAC
, !acAdaptorConnected
);
7819 // Tell BSD if AC is connected
7820 // 0 == external power source; 1 == on battery
7821 post_sys_powersource(acAdaptorConnected
? 0:1);
7823 sendClientClamshellNotification();
7825 // Re-evaluate the lid state
7826 eval_clamshell
= true;
7828 // Lack of AC may have latched a display wrangler tickle.
7829 // This mirrors the hardware's USB wake event latch, where a latched
7830 // USB wake event followed by an AC attach will trigger a full wake.
7831 latchDisplayWranglerTickle( false );
7834 // AC presence will reset the standy timer delay adjustment.
7835 _standbyTimerResetSeconds
= 0;
7837 if (!userIsActive
) {
7838 // Reset userActivityTime when power supply is changed(rdr 13789330)
7839 clock_get_uptime(&userActivityTime
);
7844 * Enable Clamshell (external display disappear)
7846 * -> reevaluate lid state
7848 if (msg
& kIOPMEnableClamshell
) {
7849 DLOG("Clamshell enabled\n");
7850 // Re-evaluate the lid state
7851 // System should sleep on external display disappearance
7852 // in lid closed operation.
7853 if (true == clamshellDisabled
) {
7854 eval_clamshell
= true;
7857 clamshellDisabled
= false;
7858 sendClientClamshellNotification();
7862 * Disable Clamshell (external display appeared)
7863 * We don't bother re-evaluating clamshell state. If the system is awake,
7864 * the lid is probably open.
7866 if (msg
& kIOPMDisableClamshell
) {
7867 DLOG("Clamshell disabled\n");
7868 clamshellDisabled
= true;
7869 sendClientClamshellNotification();
7873 * Evaluate clamshell and SLEEP if appropiate
7875 if (eval_clamshell_alarm
&& clamshellClosed
) {
7876 if (shouldSleepOnRTCAlarmWake()) {
7877 privateSleepSystem(kIOPMSleepReasonClamshell
);
7879 } else if (eval_clamshell
&& clamshellClosed
) {
7880 if (shouldSleepOnClamshellClosed()) {
7881 privateSleepSystem(kIOPMSleepReasonClamshell
);
7883 evaluatePolicy( kStimulusDarkWakeEvaluate
);
7888 //******************************************************************************
7891 // Evaluate root-domain policy in response to external changes.
7892 //******************************************************************************
7895 IOPMrootDomain::evaluatePolicy( int stimulus
, uint32_t arg
)
7899 int idleSleepEnabled
: 1;
7900 int idleSleepDisabled
: 1;
7901 int displaySleep
: 1;
7902 int sleepDelayChanged
: 1;
7903 int evaluateDarkWake
: 1;
7904 int adjustPowerState
: 1;
7905 int userBecameInactive
: 1;
7915 case kStimulusDisplayWranglerSleep
:
7916 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7917 if (!wranglerAsleep
) {
7918 // first transition to wrangler sleep or lower
7919 flags
.bit
.displaySleep
= true;
7923 case kStimulusDisplayWranglerWake
:
7924 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7925 displayIdleForDemandSleep
= false;
7926 wranglerAsleep
= false;
7929 case kStimulusEnterUserActiveState
:
7930 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7931 if (_preventUserActive
) {
7932 DLOG("user active dropped\n");
7935 if (!userIsActive
) {
7936 userIsActive
= true;
7937 userWasActive
= true;
7938 clock_get_uptime(&gUserActiveAbsTime
);
7940 // Stay awake after dropping demand for display power on
7941 if (kFullWakeReasonDisplayOn
== fullWakeReason
) {
7942 fullWakeReason
= fFullWakeReasonDisplayOnAndLocalUser
;
7943 DLOG("User activity while in notification wake\n");
7944 changePowerStateWithOverrideTo( getRUN_STATE(), 0);
7947 kdebugTrace(kPMLogUserActiveState
, 0, 1, 0);
7948 setProperty(gIOPMUserIsActiveKey
, kOSBooleanTrue
);
7949 messageClients(kIOPMMessageUserIsActiveChanged
);
7951 flags
.bit
.idleSleepDisabled
= true;
7954 case kStimulusLeaveUserActiveState
:
7955 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7957 clock_get_uptime(&gUserInactiveAbsTime
);
7958 userIsActive
= false;
7959 clock_get_uptime(&userBecameInactiveTime
);
7960 flags
.bit
.userBecameInactive
= true;
7962 kdebugTrace(kPMLogUserActiveState
, 0, 0, 0);
7963 setProperty(gIOPMUserIsActiveKey
, kOSBooleanFalse
);
7964 messageClients(kIOPMMessageUserIsActiveChanged
);
7968 case kStimulusAggressivenessChanged
:
7970 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7971 unsigned long minutesToIdleSleep
= 0;
7972 unsigned long minutesToDisplayDim
= 0;
7973 unsigned long minutesDelta
= 0;
7975 // Fetch latest display and system sleep slider values.
7976 getAggressiveness(kPMMinutesToSleep
, &minutesToIdleSleep
);
7977 getAggressiveness(kPMMinutesToDim
, &minutesToDisplayDim
);
7978 DLOG("aggressiveness changed: system %u->%u, display %u\n",
7979 (uint32_t) sleepSlider
,
7980 (uint32_t) minutesToIdleSleep
,
7981 (uint32_t) minutesToDisplayDim
);
7983 DLOG("idle time -> %ld secs (ena %d)\n",
7984 idleSeconds
, (minutesToIdleSleep
!= 0));
7987 // How long to wait before sleeping the system once
7988 // the displays turns off is indicated by 'extraSleepDelay'.
7990 if (minutesToIdleSleep
> minutesToDisplayDim
) {
7991 minutesDelta
= minutesToIdleSleep
- minutesToDisplayDim
;
7992 } else if (minutesToIdleSleep
== minutesToDisplayDim
) {
7996 if ((!idleSleepEnabled
) && (minutesToIdleSleep
!= 0)) {
7997 idleSleepEnabled
= flags
.bit
.idleSleepEnabled
= true;
8000 if ((idleSleepEnabled
) && (minutesToIdleSleep
== 0)) {
8001 flags
.bit
.idleSleepDisabled
= true;
8002 idleSleepEnabled
= false;
8004 if (0x7fffffff == minutesToIdleSleep
) {
8005 minutesToIdleSleep
= idleSeconds
;
8008 if (((minutesDelta
!= extraSleepDelay
) ||
8009 (userActivityTime
!= userActivityTime_prev
)) &&
8010 !flags
.bit
.idleSleepEnabled
&& !flags
.bit
.idleSleepDisabled
) {
8011 flags
.bit
.sleepDelayChanged
= true;
8014 if (systemDarkWake
&& !darkWakeToSleepASAP
&&
8015 (flags
.bit
.idleSleepEnabled
|| flags
.bit
.idleSleepDisabled
)) {
8016 // Reconsider decision to remain in dark wake
8017 flags
.bit
.evaluateDarkWake
= true;
8020 sleepSlider
= minutesToIdleSleep
;
8021 extraSleepDelay
= minutesDelta
;
8022 userActivityTime_prev
= userActivityTime
;
8025 case kStimulusDemandSystemSleep
:
8026 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8027 displayIdleForDemandSleep
= true;
8028 if (wrangler
&& wranglerIdleSettings
) {
8029 // Request wrangler idle only when demand sleep is triggered
8031 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
8032 wrangler
->setProperties(wranglerIdleSettings
);
8033 DLOG("Requested wrangler idle\n");
8036 // arg = sleepReason
8037 changePowerStateWithOverrideTo( SLEEP_STATE
, arg
);
8040 case kStimulusAllowSystemSleepChanged
:
8041 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8042 flags
.bit
.adjustPowerState
= true;
8045 case kStimulusDarkWakeActivityTickle
:
8046 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8047 // arg == true implies real and not self generated wrangler tickle.
8048 // Update wake type on PM work loop instead of the tickle thread to
8049 // eliminate the possibility of an early tickle clobbering the wake
8050 // type set by the platform driver.
8052 setProperty(kIOPMRootDomainWakeTypeKey
, kIOPMRootDomainWakeTypeHIDActivity
);
8055 if (false == wranglerTickled
) {
8056 if (latchDisplayWranglerTickle(true)) {
8057 DLOG("latched tickle\n");
8061 wranglerTickled
= true;
8062 DLOG("Requesting full wake after dark wake activity tickle\n");
8063 requestFullWake( kFullWakeReasonLocalUser
);
8067 case kStimulusDarkWakeEntry
:
8068 case kStimulusDarkWakeReentry
:
8069 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8070 // Any system transitions since the last dark wake transition
8071 // will invalid the stimulus.
8073 if (arg
== _systemStateGeneration
) {
8074 DLOG("dark wake entry\n");
8075 systemDarkWake
= true;
8077 // Keep wranglerAsleep an invariant when wrangler is absent
8079 wranglerAsleep
= true;
8082 if (kStimulusDarkWakeEntry
== stimulus
) {
8083 clock_get_uptime(&userBecameInactiveTime
);
8084 flags
.bit
.evaluateDarkWake
= true;
8085 if (activitySinceSleep()) {
8086 DLOG("User activity recorded while going to darkwake\n");
8091 // Always accelerate disk spindown while in dark wake,
8092 // even if system does not support/allow sleep.
8094 cancelIdleSleepTimer();
8095 setQuickSpinDownTimeout();
8099 case kStimulusDarkWakeEvaluate
:
8100 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8101 if (systemDarkWake
) {
8102 flags
.bit
.evaluateDarkWake
= true;
8106 case kStimulusNoIdleSleepPreventers
:
8107 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8108 flags
.bit
.adjustPowerState
= true;
8110 } /* switch(stimulus) */
8112 if (flags
.bit
.evaluateDarkWake
&& (kFullWakeReasonNone
== fullWakeReason
)) {
8113 if (darkWakeToSleepASAP
||
8114 (clamshellClosed
&& !(desktopMode
&& acAdaptorConnected
))) {
8115 uint32_t newSleepReason
;
8117 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
8118 // System was previously in full wake. Sleep reason from
8119 // full to dark already recorded in fullToDarkReason.
8121 if (lowBatteryCondition
) {
8122 newSleepReason
= kIOPMSleepReasonLowPower
;
8124 newSleepReason
= fullToDarkReason
;
8127 // In dark wake from system sleep.
8129 if (darkWakeSleepService
) {
8130 newSleepReason
= kIOPMSleepReasonSleepServiceExit
;
8132 newSleepReason
= kIOPMSleepReasonMaintenance
;
8136 if (checkSystemCanSleep(newSleepReason
)) {
8137 privateSleepSystem(newSleepReason
);
8139 } else { // non-maintenance (network) dark wake
8140 if (checkSystemCanSleep(kIOPMSleepReasonIdle
)) {
8141 // Release power clamp, and wait for children idle.
8142 adjustPowerState(true);
8144 changePowerStateToPriv(getRUN_STATE());
8149 if (systemDarkWake
) {
8150 // The rest are irrelevant while system is in dark wake.
8154 if ((flags
.bit
.displaySleep
) &&
8155 (kFullWakeReasonDisplayOn
== fullWakeReason
)) {
8156 // kIOPMSleepReasonMaintenance?
8157 DLOG("Display sleep while in notification wake\n");
8158 changePowerStateWithOverrideTo( SLEEP_STATE
, kIOPMSleepReasonMaintenance
);
8161 if (flags
.bit
.userBecameInactive
|| flags
.bit
.sleepDelayChanged
) {
8162 bool cancelQuickSpindown
= false;
8164 if (flags
.bit
.sleepDelayChanged
) {
8165 // Cancel existing idle sleep timer and quick disk spindown.
8166 // New settings will be applied by the idleSleepEnabled flag
8167 // handler below if idle sleep is enabled.
8169 DLOG("extra sleep timer changed\n");
8170 cancelIdleSleepTimer();
8171 cancelQuickSpindown
= true;
8173 DLOG("user inactive\n");
8176 if (!userIsActive
&& idleSleepEnabled
) {
8177 startIdleSleepTimer(getTimeToIdleSleep());
8180 if (cancelQuickSpindown
) {
8181 restoreUserSpinDownTimeout();
8185 if (flags
.bit
.idleSleepEnabled
) {
8186 DLOG("idle sleep timer enabled\n");
8188 changePowerStateToPriv(getRUN_STATE());
8189 startIdleSleepTimer( idleSeconds
);
8191 // Start idle timer if prefs now allow system sleep
8192 // and user is already inactive. Disk spindown is
8193 // accelerated upon timer expiration.
8195 if (!userIsActive
) {
8196 startIdleSleepTimer(getTimeToIdleSleep());
8201 if (flags
.bit
.idleSleepDisabled
) {
8202 DLOG("idle sleep timer disabled\n");
8203 cancelIdleSleepTimer();
8204 restoreUserSpinDownTimeout();
8208 if (flags
.bit
.adjustPowerState
) {
8209 bool sleepASAP
= false;
8211 if (!systemBooting
&& (0 == idleSleepPreventersCount())) {
8213 changePowerStateToPriv(getRUN_STATE());
8214 if (idleSleepEnabled
) {
8215 // stay awake for at least idleSeconds
8216 startIdleSleepTimer(idleSeconds
);
8218 } else if (!extraSleepDelay
&& !idleSleepTimerPending
&& !systemDarkWake
) {
8223 adjustPowerState(sleepASAP
);
8227 //******************************************************************************
8230 IOPMrootDomain::idleSleepPreventersCount()
8232 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
8234 unsigned int count __block
;
8236 preventIdleSleepList
->iterateObjects(^bool (OSObject
* obj
)
8238 count
+= (NULL
== obj
->metaCast("AppleARMBacklight"));
8243 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
8245 return preventIdleSleepList
->getCount();
8249 //******************************************************************************
8252 // Request transition from dark wake to full wake
8253 //******************************************************************************
8256 IOPMrootDomain::requestFullWake( FullWakeReason reason
)
8258 uint32_t options
= 0;
8259 IOService
* pciRoot
= NULL
;
8260 bool promotion
= false;
8262 // System must be in dark wake and a valid reason for entering full wake
8263 if ((kFullWakeReasonNone
== reason
) ||
8264 (kFullWakeReasonNone
!= fullWakeReason
) ||
8265 (CAP_CURRENT(kIOPMSystemCapabilityGraphics
))) {
8269 // Will clear reason upon exit from full wake
8270 fullWakeReason
= reason
;
8272 _desiredCapability
|= (kIOPMSystemCapabilityGraphics
|
8273 kIOPMSystemCapabilityAudio
);
8275 if ((kSystemTransitionWake
== _systemTransitionType
) &&
8276 !(_pendingCapability
& kIOPMSystemCapabilityGraphics
) &&
8277 !graphicsSuppressed
) {
8278 // Promote to full wake while waking up to dark wake due to tickle.
8279 // PM will hold off notifying the graphics subsystem about system wake
8280 // as late as possible, so if a HID tickle does arrive, graphics can
8281 // power up on this same wake cycle. The latency to power up graphics
8282 // on the next cycle can be huge on some systems. However, once any
8283 // graphics suppression has taken effect, it is too late. All other
8284 // graphics devices must be similarly suppressed. But the delay till
8285 // the following cycle should be short.
8287 _pendingCapability
|= (kIOPMSystemCapabilityGraphics
|
8288 kIOPMSystemCapabilityAudio
);
8290 // Immediately bring up audio and graphics
8291 pciRoot
= pciHostBridgeDriver
;
8292 willEnterFullWake();
8296 // Unsafe to cancel once graphics was powered.
8297 // If system woke from dark wake, the return to sleep can
8298 // be cancelled. "awake -> dark -> sleep" transition
8299 // can be canceled also, during the "dark --> sleep" phase
8300 // *prior* to driver power down.
8301 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics
) ||
8302 _pendingCapability
== 0) {
8303 options
|= kIOPMSyncCancelPowerDown
;
8306 synchronizePowerTree(options
, pciRoot
);
8307 if (kFullWakeReasonLocalUser
== fullWakeReason
) {
8308 // IOGraphics doesn't light the display even though graphics is
8309 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
8310 // So, do an explicit activity tickle
8312 wrangler
->activityTickle(0, 0);
8316 // Log a timestamp for the initial full wake request.
8317 // System may not always honor this full wake request.
8318 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
8322 clock_get_uptime(&now
);
8323 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
8324 absolutetime_to_nanoseconds(now
, &nsec
);
8325 MSG("full wake %s (reason %u) %u ms\n",
8326 promotion
? "promotion" : "request",
8327 fullWakeReason
, ((int)((nsec
) / NSEC_PER_MSEC
)));
8331 //******************************************************************************
8332 // willEnterFullWake
8334 // System will enter full wake from sleep, from dark wake, or from dark
8335 // wake promotion. This function aggregate things that are in common to
8336 // all three full wake transitions.
8338 // Assumptions: fullWakeReason was updated
8339 //******************************************************************************
8342 IOPMrootDomain::willEnterFullWake( void )
8344 hibernateRetry
= false;
8345 sleepToStandby
= false;
8346 standbyNixed
= false;
8347 resetTimers
= false;
8348 sleepTimerMaintenance
= false;
8350 _systemMessageClientMask
= kSystemMessageClientPowerd
|
8351 kSystemMessageClientLegacyApp
;
8353 if ((_highestCapability
& kIOPMSystemCapabilityGraphics
) == 0) {
8354 // Initial graphics full power
8355 _systemMessageClientMask
|= kSystemMessageClientKernel
;
8357 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
8358 setProperty(gIOPMUserTriggeredFullWakeKey
,
8359 (kFullWakeReasonLocalUser
== fullWakeReason
) ?
8360 kOSBooleanTrue
: kOSBooleanFalse
);
8363 IOHibernateSetWakeCapabilities(_pendingCapability
);
8366 IOService::setAdvisoryTickleEnable( true );
8367 tellClients(kIOMessageSystemWillPowerOn
);
8368 preventTransitionToUserActive(false);
8371 //******************************************************************************
8372 // fullWakeDelayedWork
8374 // System has already entered full wake. Invoked by a delayed thread call.
8375 //******************************************************************************
8378 IOPMrootDomain::fullWakeDelayedWork( void )
8380 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
8381 // Not gated, don't modify state
8382 if ((kSystemTransitionNone
== _systemTransitionType
) &&
8383 CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
8384 receivePowerNotification( kLocalEvalClamshellCommand
);
8389 //******************************************************************************
8390 // evaluateAssertions
8392 //******************************************************************************
8394 // Bitmask of all kernel assertions that prevent system idle sleep.
8395 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
8396 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
8397 (kIOPMDriverAssertionReservedBit7 | \
8398 kIOPMDriverAssertionPreventSystemIdleSleepBit)
8401 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions
, IOPMDriverAssertionType oldAssertions
)
8403 IOPMDriverAssertionType changedBits
= newAssertions
^ oldAssertions
;
8405 messageClients(kIOPMMessageDriverAssertionsChanged
);
8407 if (changedBits
& kIOPMDriverAssertionPreventDisplaySleepBit
) {
8409 bool value
= (newAssertions
& kIOPMDriverAssertionPreventDisplaySleepBit
) ? true : false;
8411 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value
);
8412 wrangler
->setIgnoreIdleTimer( value
);
8416 if (changedBits
& kIOPMDriverAssertionCPUBit
) {
8417 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
8419 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit
& newAssertions
)));
8421 evaluatePolicy(_aotNow
? kStimulusNoIdleSleepPreventers
: kStimulusDarkWakeEvaluate
);
8423 evaluatePolicy(kStimulusDarkWakeEvaluate
);
8425 if (!assertOnWakeSecs
&& gIOLastWakeAbsTime
) {
8427 clock_usec_t microsecs
;
8428 clock_get_uptime(&now
);
8429 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
8430 absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
);
8431 if (assertOnWakeReport
) {
8432 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
);
8433 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
);
8438 if (changedBits
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) {
8439 if ((newAssertions
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) != 0) {
8440 if ((oldAssertions
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) == 0) {
8441 DLOG("PreventIdleSleep driver assertion raised\n");
8442 bool ok
= updatePreventIdleSleepList(this, true);
8443 if (ok
&& (changedBits
& kIOPMDriverAssertionPreventSystemIdleSleepBit
)) {
8444 // Cancel idle sleep if there is one in progress
8445 cancelIdlePowerDown(this);
8449 DLOG("PreventIdleSleep driver assertion dropped\n");
8450 updatePreventIdleSleepList(this, false);
8458 //******************************************************************************
8461 //******************************************************************************
8464 IOPMrootDomain::pmStatsRecordEvent(
8466 AbsoluteTime timestamp
)
8468 bool starting
= eventIndex
& kIOPMStatsEventStartFlag
? true:false;
8469 bool stopping
= eventIndex
& kIOPMStatsEventStopFlag
? true:false;
8472 OSData
*publishPMStats
= NULL
;
8474 eventIndex
&= ~(kIOPMStatsEventStartFlag
| kIOPMStatsEventStopFlag
);
8476 absolutetime_to_nanoseconds(timestamp
, &nsec
);
8478 switch (eventIndex
) {
8479 case kIOPMStatsHibernateImageWrite
:
8481 gPMStats
.hibWrite
.start
= nsec
;
8482 } else if (stopping
) {
8483 gPMStats
.hibWrite
.stop
= nsec
;
8487 delta
= gPMStats
.hibWrite
.stop
- gPMStats
.hibWrite
.start
;
8488 IOLog("PMStats: Hibernate write took %qd ms\n", delta
/ NSEC_PER_MSEC
);
8491 case kIOPMStatsHibernateImageRead
:
8493 gPMStats
.hibRead
.start
= nsec
;
8494 } else if (stopping
) {
8495 gPMStats
.hibRead
.stop
= nsec
;
8499 delta
= gPMStats
.hibRead
.stop
- gPMStats
.hibRead
.start
;
8500 IOLog("PMStats: Hibernate read took %qd ms\n", delta
/ NSEC_PER_MSEC
);
8502 publishPMStats
= OSData::withBytes(&gPMStats
, sizeof(gPMStats
));
8503 setProperty(kIOPMSleepStatisticsKey
, publishPMStats
);
8504 publishPMStats
->release();
8505 bzero(&gPMStats
, sizeof(gPMStats
));
8512 * Appends a record of the application response to
8513 * IOPMrootDomain::pmStatsAppResponses
8516 IOPMrootDomain::pmStatsRecordApplicationResponse(
8517 const OSSymbol
*response
,
8523 IOPMPowerStateIndex powerState
)
8525 OSDictionary
*responseDescription
= NULL
;
8526 OSNumber
*delayNum
= NULL
;
8527 OSNumber
*powerCaps
= NULL
;
8528 OSNumber
*pidNum
= NULL
;
8529 OSNumber
*msgNum
= NULL
;
8530 const OSSymbol
*appname
;
8531 const OSSymbol
*sleep
= NULL
, *wake
= NULL
;
8532 IOPMServiceInterestNotifier
*notify
= NULL
;
8534 if (object
&& (notify
= OSDynamicCast(IOPMServiceInterestNotifier
, object
))) {
8535 if (response
->isEqualTo(gIOPMStatsResponseTimedOut
)) {
8536 notify
->ackTimeoutCnt
++;
8538 notify
->ackTimeoutCnt
= 0;
8542 if (response
->isEqualTo(gIOPMStatsResponsePrompt
) ||
8543 (_systemTransitionType
== kSystemTransitionNone
) || (_systemTransitionType
== kSystemTransitionNewCapClient
)) {
8548 if (response
->isEqualTo(gIOPMStatsDriverPSChangeSlow
)) {
8549 kdebugTrace(kPMLogDrvPSChangeDelay
, id
, messageType
, delay_ms
);
8550 } else if (notify
) {
8551 // User space app or kernel capability client
8553 kdebugTrace(kPMLogAppResponseDelay
, id
, notify
->msgType
, delay_ms
);
8555 kdebugTrace(kPMLogDrvResponseDelay
, notify
->uuid0
, messageType
, delay_ms
);
8557 notify
->msgType
= 0;
8560 responseDescription
= OSDictionary::withCapacity(5);
8561 if (responseDescription
) {
8563 responseDescription
->setObject(_statsResponseTypeKey
, response
);
8566 msgNum
= OSNumber::withNumber(messageType
, 32);
8568 responseDescription
->setObject(_statsMessageTypeKey
, msgNum
);
8572 if (!name
&& notify
&& notify
->identifier
) {
8573 name
= notify
->identifier
->getCStringNoCopy();
8576 if (name
&& (strlen(name
) > 0)) {
8577 appname
= OSSymbol::withCString(name
);
8579 responseDescription
->setObject(_statsNameKey
, appname
);
8584 if (!id
&& notify
) {
8588 pidNum
= OSNumber::withNumber(id
, 64);
8590 responseDescription
->setObject(_statsPIDKey
, pidNum
);
8595 delayNum
= OSNumber::withNumber(delay_ms
, 32);
8597 responseDescription
->setObject(_statsTimeMSKey
, delayNum
);
8598 delayNum
->release();
8601 if (response
->isEqualTo(gIOPMStatsDriverPSChangeSlow
)) {
8602 powerCaps
= OSNumber::withNumber(powerState
, 32);
8604 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
8605 IOLog("%s::powerStateChange type(%d) to(%lu) async took %d ms\n",
8607 powerState
, delay_ms
);
8610 powerCaps
= OSNumber::withNumber(_pendingCapability
, 32);
8613 responseDescription
->setObject(_statsPowerCapsKey
, powerCaps
);
8614 powerCaps
->release();
8617 sleep
= OSSymbol::withCString("Sleep");
8618 wake
= OSSymbol::withCString("Wake");
8619 if (_systemTransitionType
== kSystemTransitionSleep
) {
8620 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, sleep
);
8621 } else if (_systemTransitionType
== kSystemTransitionWake
) {
8622 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, wake
);
8623 } else if (_systemTransitionType
== kSystemTransitionCapability
) {
8624 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) {
8625 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, sleep
);
8626 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
8627 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, wake
);
8639 IOLockLock(pmStatsLock
);
8640 if (pmStatsAppResponses
&& pmStatsAppResponses
->getCount() < 50) {
8641 pmStatsAppResponses
->setObject(responseDescription
);
8643 IOLockUnlock(pmStatsLock
);
8645 responseDescription
->release();
8652 // MARK: PMTraceWorker
8654 //******************************************************************************
8655 // TracePoint support
8657 //******************************************************************************
8659 #define kIOPMRegisterNVRAMTracePointHandlerKey \
8660 "IOPMRegisterNVRAMTracePointHandler"
8663 IOPMrootDomain::callPlatformFunction(
8664 const OSSymbol
* functionName
,
8665 bool waitForFunction
,
8666 void * param1
, void * param2
,
8667 void * param3
, void * param4
)
8669 uint32_t bootFailureCode
= 0xffffffff;
8670 if (pmTracer
&& functionName
&&
8671 functionName
->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey
) &&
8672 !pmTracer
->tracePointHandler
&& !pmTracer
->tracePointTarget
) {
8673 uint32_t tracePointPhases
, tracePointPCI
;
8674 uint64_t statusCode
;
8676 pmTracer
->tracePointHandler
= (IOPMTracePointHandler
) param1
;
8677 pmTracer
->tracePointTarget
= (void *) param2
;
8678 tracePointPCI
= (uint32_t)(uintptr_t) param3
;
8679 tracePointPhases
= (uint32_t)(uintptr_t) param4
;
8680 if ((tracePointPhases
& 0xff) == kIOPMTracePointSystemSleep
) {
8681 IORegistryEntry
*node
= IORegistryEntry::fromPath( "/chosen", gIODTPlane
);
8683 OSData
*data
= OSDynamicCast( OSData
, node
->getProperty(kIOEFIBootRomFailureKey
));
8684 if (data
&& data
->getLength() == sizeof(bootFailureCode
)) {
8685 memcpy(&bootFailureCode
, data
->getBytesNoCopy(), sizeof(bootFailureCode
));
8689 // Failure code from EFI/BootRom is a four byte structure
8690 tracePointPCI
= OSSwapBigToHostInt32(bootFailureCode
);
8692 statusCode
= (((uint64_t)tracePointPCI
) << 32) | tracePointPhases
;
8693 if ((tracePointPhases
& 0xff) != kIOPMTracePointSystemUp
) {
8694 MSG("Sleep failure code 0x%08x 0x%08x\n",
8695 tracePointPCI
, tracePointPhases
);
8697 setProperty(kIOPMSleepWakeFailureCodeKey
, statusCode
, 64);
8698 pmTracer
->tracePointHandler( pmTracer
->tracePointTarget
, 0, 0 );
8700 return kIOReturnSuccess
;
8703 else if (functionName
&&
8704 functionName
->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey
)) {
8705 if (gSleepPolicyHandler
) {
8706 return kIOReturnExclusiveAccess
;
8709 return kIOReturnBadArgument
;
8711 gSleepPolicyHandler
= (IOPMSystemSleepPolicyHandler
) param1
;
8712 gSleepPolicyTarget
= (void *) param2
;
8713 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue
);
8714 return kIOReturnSuccess
;
8718 return super::callPlatformFunction(
8719 functionName
, waitForFunction
, param1
, param2
, param3
, param4
);
8723 IOPMrootDomain::kdebugTrace(uint32_t event
, uint64_t id
,
8724 uintptr_t param1
, uintptr_t param2
, uintptr_t param3
)
8726 uint32_t code
= IODBG_POWER(event
);
8727 uint64_t regId
= id
;
8729 regId
= getRegistryEntryID();
8731 IOTimeStampConstant(code
, (uintptr_t) regId
, param1
, param2
, param3
);
8736 IOPMrootDomain::tracePoint( uint8_t point
)
8738 if (systemBooting
) {
8742 if (kIOPMTracePointWakeCapabilityClients
== point
) {
8743 acceptSystemWakeEvents(false);
8746 kdebugTrace(kPMLogSleepWakeTracePoint
, 0, point
, 0);
8747 pmTracer
->tracePoint(point
);
8751 IOPMrootDomain::traceDetail(OSObject
*object
, bool start
)
8753 IOPMServiceInterestNotifier
*notifier
;
8755 if (systemBooting
) {
8759 notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, object
);
8765 pmTracer
->traceDetail( notifier
->uuid0
>> 32 );
8766 kdebugTrace(kPMLogSleepWakeMessage
, pmTracer
->getTracePhase(), notifier
->msgType
, notifier
->uuid0
, notifier
->uuid1
);
8767 if (notifier
->identifier
) {
8768 DLOG("trace point 0x%02x msg 0x%x to %s\n", pmTracer
->getTracePhase(), notifier
->msgType
,
8769 notifier
->identifier
->getCStringNoCopy());
8771 DLOG("trace point 0x%02x msg 0x%x\n", pmTracer
->getTracePhase(), notifier
->msgType
);
8773 notifierThread
= current_thread();
8774 notifierObject
= notifier
;
8777 notifierThread
= NULL
;
8778 notifierObject
= NULL
;
8779 notifier
->release();
8785 IOPMrootDomain::traceAckDelay(OSObject
*object
, uint32_t response
, uint32_t delay_ms
)
8787 IOPMServiceInterestNotifier
*notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, object
);
8789 DLOG("Unknown notifier\n");
8793 if (!systemBooting
) {
8794 kdebugTrace(kPMLogDrvResponseDelay
, notifier
->uuid0
, notifier
->uuid1
, response
, delay_ms
);
8795 if (notifier
->identifier
) {
8796 DLOG("Response from %s took %d ms(response:%d)\n",
8797 notifier
->identifier
->getCStringNoCopy(), delay_ms
, response
);
8799 DLOG("Response from kext UUID %llx-%llx took %d ms(response:%d)\n",
8800 notifier
->uuid0
, notifier
->uuid1
, delay_ms
, response
);
8806 IOPMrootDomain::traceDetail(uint32_t msgType
, uint32_t msgIndex
, uint32_t delay
)
8808 if (!systemBooting
) {
8809 uint32_t detail
= ((msgType
& 0xffff) << 16) | (delay
& 0xffff);
8810 pmTracer
->traceDetail( detail
);
8811 kdebugTrace(kPMLogSleepWakeTracePoint
, pmTracer
->getTracePhase(), msgType
, delay
);
8812 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer
->getTracePhase(), msgType
, delay
);
8818 IOPMrootDomain::configureReportGated(uint64_t channel_id
, uint64_t action
, void *result
)
8821 void **report
= NULL
;
8824 uint32_t *clientCnt
;
8829 if (channel_id
== kAssertDelayChID
) {
8830 report
= &assertOnWakeReport
;
8831 bktCnt
= kAssertDelayBcktCnt
;
8832 bktSize
= kAssertDelayBcktSize
;
8833 clientCnt
= &assertOnWakeClientCnt
;
8834 } else if (channel_id
== kSleepDelaysChID
) {
8835 report
= &sleepDelaysReport
;
8836 bktCnt
= kSleepDelaysBcktCnt
;
8837 bktSize
= kSleepDelaysBcktSize
;
8838 clientCnt
= &sleepDelaysClientCnt
;
8842 case kIOReportEnable
:
8849 reportSize
= HISTREPORT_BUFSIZE(bktCnt
);
8850 *report
= IOMalloc(reportSize
);
8851 if (*report
== NULL
) {
8854 bzero(*report
, reportSize
);
8855 HISTREPORT_INIT(bktCnt
, bktSize
, *report
, reportSize
,
8856 getRegistryEntryID(), channel_id
, kIOReportCategoryPower
);
8858 if (channel_id
== kAssertDelayChID
) {
8859 assertOnWakeSecs
= 0;
8864 case kIOReportDisable
:
8865 if (*clientCnt
== 0) {
8868 if (*clientCnt
== 1) {
8869 IOFree(*report
, HISTREPORT_BUFSIZE(bktCnt
));
8874 if (channel_id
== kAssertDelayChID
) {
8875 assertOnWakeSecs
= -1; // Invalid value to prevent updates
8879 case kIOReportGetDimensions
:
8881 HISTREPORT_UPDATERES(*report
, kIOReportGetDimensions
, result
);
8890 IOPMrootDomain::configureReport(IOReportChannelList
*channelList
,
8891 IOReportConfigureAction action
,
8896 uint64_t configAction
= (uint64_t)action
;
8898 for (cnt
= 0; cnt
< channelList
->nchannels
; cnt
++) {
8899 if ((channelList
->channels
[cnt
].channel_id
== kSleepCntChID
) ||
8900 (channelList
->channels
[cnt
].channel_id
== kDarkWkCntChID
) ||
8901 (channelList
->channels
[cnt
].channel_id
== kUserWkCntChID
)) {
8902 if (action
!= kIOReportGetDimensions
) {
8905 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
8906 } else if ((channelList
->channels
[cnt
].channel_id
== kAssertDelayChID
) ||
8907 (channelList
->channels
[cnt
].channel_id
== kSleepDelaysChID
)) {
8908 gIOPMWorkLoop
->runAction(
8909 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::configureReportGated
),
8910 (OSObject
*)this, (void *)channelList
->channels
[cnt
].channel_id
,
8911 (void *)configAction
, (void *)result
);
8915 return super::configureReport(channelList
, action
, result
, destination
);
8919 IOPMrootDomain::updateReportGated(uint64_t ch_id
, void *result
, IOBufferMemoryDescriptor
*dest
)
8928 if (ch_id
== kAssertDelayChID
) {
8929 report
= &assertOnWakeReport
;
8930 } else if (ch_id
== kSleepDelaysChID
) {
8931 report
= &sleepDelaysReport
;
8934 if (*report
== NULL
) {
8935 return kIOReturnNotOpen
;
8938 HISTREPORT_UPDATEPREP(*report
, data2cpy
, size2cpy
);
8939 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
8940 return kIOReturnOverrun
;
8943 HISTREPORT_UPDATERES(*report
, kIOReportCopyChannelData
, result
);
8944 dest
->appendBytes(data2cpy
, size2cpy
);
8946 return kIOReturnSuccess
;
8950 IOPMrootDomain::updateReport(IOReportChannelList
*channelList
,
8951 IOReportUpdateAction action
,
8957 uint8_t buf
[SIMPLEREPORT_BUFSIZE
];
8958 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
8962 if (action
!= kIOReportCopyChannelData
) {
8966 for (cnt
= 0; cnt
< channelList
->nchannels
; cnt
++) {
8967 ch_id
= channelList
->channels
[cnt
].channel_id
;
8969 if ((ch_id
== kAssertDelayChID
) || (ch_id
== kSleepDelaysChID
)) {
8970 gIOPMWorkLoop
->runAction(
8971 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::updateReportGated
),
8972 (OSObject
*)this, (void *)ch_id
,
8973 (void *)result
, (void *)dest
);
8975 } else if ((ch_id
== kSleepCntChID
) ||
8976 (ch_id
== kDarkWkCntChID
) || (ch_id
== kUserWkCntChID
)) {
8977 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), ch_id
, kIOReportCategoryPower
);
8982 if (ch_id
== kSleepCntChID
) {
8983 SIMPLEREPORT_SETVALUE(buf
, sleepCnt
);
8984 } else if (ch_id
== kDarkWkCntChID
) {
8985 SIMPLEREPORT_SETVALUE(buf
, darkWakeCnt
);
8986 } else if (ch_id
== kUserWkCntChID
) {
8987 SIMPLEREPORT_SETVALUE(buf
, displayWakeCnt
);
8990 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
8991 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
8992 dest
->appendBytes(data2cpy
, size2cpy
);
8996 return super::updateReport(channelList
, action
, result
, destination
);
9000 //******************************************************************************
9001 // PMTraceWorker Class
9003 //******************************************************************************
9006 #define super OSObject
9007 OSDefineMetaClassAndStructors(PMTraceWorker
, OSObject
)
9009 #define kPMBestGuessPCIDevicesCount 25
9010 #define kPMMaxRTCBitfieldSize 32
9012 PMTraceWorker
* PMTraceWorker::tracer(IOPMrootDomain
* owner
)
9016 me
= OSTypeAlloc( PMTraceWorker
);
9017 if (!me
|| !me
->init()) {
9021 DLOG("PMTraceWorker %p\n", OBFUSCATE(me
));
9023 // Note that we cannot instantiate the PCI device -> bit mappings here, since
9024 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
9025 // this dictionary lazily.
9027 me
->pciDeviceBitMappings
= NULL
;
9028 me
->pmTraceWorkerLock
= IOLockAlloc();
9029 me
->tracePhase
= kIOPMTracePointSystemUp
;
9030 me
->traceData32
= 0;
9031 me
->loginWindowData
= 0;
9032 me
->coreDisplayData
= 0;
9033 me
->coreGraphicsData
= 0;
9038 PMTraceWorker::RTC_TRACE(void)
9040 if (tracePointHandler
&& tracePointTarget
) {
9043 IOLockLock(pmTraceWorkerLock
);
9044 wordA
= (loginWindowData
<< 24) | (coreDisplayData
<< 16) |
9045 (coreGraphicsData
<< 8) | tracePhase
;
9046 IOLockUnlock(pmTraceWorkerLock
);
9048 tracePointHandler( tracePointTarget
, traceData32
, wordA
);
9049 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32
, wordA
);
9051 #if DEVELOPMENT || DEBUG
9052 if ((swd_panic_phase
!= 0) && (swd_panic_phase
== tracePhase
)) {
9053 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase
);
9054 IOLock
*l
= IOLockAlloc();
9062 PMTraceWorker::recordTopLevelPCIDevice(IOService
* pciDevice
)
9064 const OSSymbol
* deviceName
;
9067 IOLockLock(pmTraceWorkerLock
);
9069 if (!pciDeviceBitMappings
) {
9070 pciDeviceBitMappings
= OSArray::withCapacity(kPMBestGuessPCIDevicesCount
);
9071 if (!pciDeviceBitMappings
) {
9076 // Check for bitmask overflow.
9077 if (pciDeviceBitMappings
->getCount() >= kPMMaxRTCBitfieldSize
) {
9081 if ((deviceName
= pciDevice
->copyName()) &&
9082 (pciDeviceBitMappings
->getNextIndexOfObject(deviceName
, 0) == (unsigned int)-1) &&
9083 pciDeviceBitMappings
->setObject(deviceName
)) {
9084 index
= pciDeviceBitMappings
->getCount() - 1;
9085 _LOG("PMTrace PCI array: set object %s => %d\n",
9086 deviceName
->getCStringNoCopy(), index
);
9089 deviceName
->release();
9091 if (!addedToRegistry
&& (index
>= 0)) {
9092 addedToRegistry
= owner
->setProperty("PCITopLevel", this);
9096 IOLockUnlock(pmTraceWorkerLock
);
9101 PMTraceWorker::serialize(OSSerialize
*s
) const
9104 if (pciDeviceBitMappings
) {
9105 IOLockLock(pmTraceWorkerLock
);
9106 ok
= pciDeviceBitMappings
->serialize(s
);
9107 IOLockUnlock(pmTraceWorkerLock
);
9113 PMTraceWorker::tracePoint(uint8_t phase
)
9115 // clear trace detail when phase begins
9116 if (tracePhase
!= phase
) {
9122 DLOG("trace point 0x%02x\n", tracePhase
);
9127 PMTraceWorker::traceDetail(uint32_t detail
)
9129 if (detail
== traceData32
) {
9132 traceData32
= detail
;
9137 PMTraceWorker::traceComponentWakeProgress(uint32_t component
, uint32_t data
)
9139 switch (component
) {
9140 case kIOPMLoginWindowProgress
:
9141 loginWindowData
= data
& kIOPMLoginWindowProgressMask
;
9143 case kIOPMCoreDisplayProgress
:
9144 coreDisplayData
= data
& kIOPMCoreDisplayProgressMask
;
9146 case kIOPMCoreGraphicsProgress
:
9147 coreGraphicsData
= data
& kIOPMCoreGraphicsProgressMask
;
9153 DLOG("component trace point 0x%02x data 0x%08x\n", component
, data
);
9158 PMTraceWorker::tracePCIPowerChange(
9159 change_t type
, IOService
*service
, uint32_t changeFlags
, uint32_t bitNum
)
9162 uint32_t expectedFlag
;
9164 // Ignore PCI changes outside of system sleep/wake.
9165 if ((kIOPMTracePointSleepPowerPlaneDrivers
!= tracePhase
) &&
9166 (kIOPMTracePointWakePowerPlaneDrivers
!= tracePhase
)) {
9170 // Only record the WillChange transition when going to sleep,
9171 // and the DidChange on the way up.
9172 changeFlags
&= (kIOPMDomainWillChange
| kIOPMDomainDidChange
);
9173 expectedFlag
= (kIOPMTracePointSleepPowerPlaneDrivers
== tracePhase
) ?
9174 kIOPMDomainWillChange
: kIOPMDomainDidChange
;
9175 if (changeFlags
!= expectedFlag
) {
9179 // Mark this device off in our bitfield
9180 if (bitNum
< kPMMaxRTCBitfieldSize
) {
9181 bitMask
= (1 << bitNum
);
9183 if (kPowerChangeStart
== type
) {
9184 traceData32
|= bitMask
;
9185 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
9186 service
->getName(), bitNum
, bitMask
, traceData32
);
9187 owner
->kdebugTrace(kPMLogPCIDevChangeStart
, service
->getRegistryEntryID(), traceData32
, 0);
9189 traceData32
&= ~bitMask
;
9190 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
9191 service
->getName(), bitNum
, bitMask
, traceData32
);
9192 owner
->kdebugTrace(kPMLogPCIDevChangeDone
, service
->getRegistryEntryID(), traceData32
, 0);
9195 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase
, traceData32
);
9201 PMTraceWorker::getPMStatusCode()
9203 return ((uint64_t)traceData32
<< 32) | ((uint64_t)tracePhase
);
9207 PMTraceWorker::getTracePhase()
9213 PMTraceWorker::getTraceData()
9219 // MARK: PMHaltWorker
9221 //******************************************************************************
9222 // PMHaltWorker Class
9224 //******************************************************************************
9227 PMHaltWorker::worker( void )
9233 me
= OSTypeAlloc( PMHaltWorker
);
9234 if (!me
|| !me
->init()) {
9238 me
->lock
= IOLockAlloc();
9243 DLOG("PMHaltWorker %p\n", OBFUSCATE(me
));
9244 me
->retain(); // thread holds extra retain
9245 if (KERN_SUCCESS
!= kernel_thread_start(&PMHaltWorker::main
, (void *) me
, &thread
)) {
9249 thread_deallocate(thread
);
9260 PMHaltWorker::free( void )
9262 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
9267 return OSObject::free();
9271 PMHaltWorker::main( void * arg
, wait_result_t waitResult
)
9273 PMHaltWorker
* me
= (PMHaltWorker
*) arg
;
9275 IOLockLock( gPMHaltLock
);
9277 me
->depth
= gPMHaltDepth
;
9278 IOLockUnlock( gPMHaltLock
);
9280 while (me
->depth
>= 0) {
9281 PMHaltWorker::work( me
);
9283 IOLockLock( gPMHaltLock
);
9284 if (++gPMHaltIdleCount
>= gPMHaltBusyCount
) {
9285 // This is the last thread to finish work on this level,
9286 // inform everyone to start working on next lower level.
9288 me
->depth
= gPMHaltDepth
;
9289 gPMHaltIdleCount
= 0;
9290 thread_wakeup((event_t
) &gPMHaltIdleCount
);
9292 // One or more threads are still working on this level,
9293 // this thread must wait.
9294 me
->depth
= gPMHaltDepth
- 1;
9296 IOLockSleep(gPMHaltLock
, &gPMHaltIdleCount
, THREAD_UNINT
);
9297 } while (me
->depth
!= gPMHaltDepth
);
9299 IOLockUnlock( gPMHaltLock
);
9302 // No more work to do, terminate thread
9303 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me
), me
->visits
);
9304 thread_wakeup( &gPMHaltDepth
);
9309 PMHaltWorker::work( PMHaltWorker
* me
)
9311 IOService
* service
;
9313 AbsoluteTime startTime
, elapsedTime
;
9321 // Claim an unit of work from the shared pool
9322 IOLockLock( gPMHaltLock
);
9323 inner
= (OSSet
*)gPMHaltArray
->getObject(me
->depth
);
9325 service
= OSDynamicCast(IOService
, inner
->getAnyObject());
9328 inner
->removeObject(service
);
9331 IOLockUnlock( gPMHaltLock
);
9333 break; // no more work at this depth
9335 clock_get_uptime(&startTime
);
9337 if (!service
->isInactive() &&
9338 service
->setProperty(gPMHaltClientAcknowledgeKey
, me
)) {
9339 IOLockLock(me
->lock
);
9340 me
->startTime
= startTime
;
9341 me
->service
= service
;
9342 me
->timeout
= false;
9343 IOLockUnlock(me
->lock
);
9345 service
->systemWillShutdown( gPMHaltMessageType
);
9347 // Wait for driver acknowledgement
9348 IOLockLock(me
->lock
);
9349 while (service
->getProperty(gPMHaltClientAcknowledgeKey
)) {
9350 IOLockSleep(me
->lock
, me
, THREAD_UNINT
);
9353 timeout
= me
->timeout
;
9354 IOLockUnlock(me
->lock
);
9357 deltaTime
= computeDeltaTimeMS(&startTime
, &elapsedTime
);
9358 if ((deltaTime
> kPMHaltTimeoutMS
) || timeout
) {
9359 LOG("%s driver %s (0x%llx) took %u ms\n",
9360 (gPMHaltMessageType
== kIOMessageSystemWillPowerOff
) ?
9361 "PowerOff" : "Restart",
9362 service
->getName(), service
->getRegistryEntryID(),
9363 (uint32_t) deltaTime
);
9364 halt_log_enter("PowerOff/Restart handler completed",
9365 OSMemberFunctionCast(const void *, service
, &IOService::systemWillShutdown
),
9375 PMHaltWorker::checkTimeout( PMHaltWorker
* me
, AbsoluteTime
* now
)
9378 AbsoluteTime startTime
;
9379 AbsoluteTime endTime
;
9383 IOLockLock(me
->lock
);
9384 if (me
->service
&& !me
->timeout
) {
9385 startTime
= me
->startTime
;
9387 if (CMP_ABSOLUTETIME(&endTime
, &startTime
) > 0) {
9388 SUB_ABSOLUTETIME(&endTime
, &startTime
);
9389 absolutetime_to_nanoseconds(endTime
, &nano
);
9391 if (nano
> 3000000000ULL) {
9394 halt_log_enter("PowerOff/Restart still waiting on handler",
9395 OSMemberFunctionCast(const void *, me
->service
, &IOService::systemWillShutdown
),
9397 MSG("%s still waiting on %s\n",
9398 (gPMHaltMessageType
== kIOMessageSystemWillPowerOff
) ? "PowerOff" : "Restart",
9399 me
->service
->getName());
9402 IOLockUnlock(me
->lock
);
9405 //******************************************************************************
9406 // acknowledgeSystemWillShutdown
9408 // Acknowledgement from drivers that they have prepared for shutdown/restart.
9409 //******************************************************************************
9412 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService
* from
)
9414 PMHaltWorker
* worker
;
9421 //DLOG("%s acknowledged\n", from->getName());
9422 prop
= from
->copyProperty( gPMHaltClientAcknowledgeKey
);
9424 worker
= (PMHaltWorker
*) prop
;
9425 IOLockLock(worker
->lock
);
9426 from
->removeProperty( gPMHaltClientAcknowledgeKey
);
9427 thread_wakeup((event_t
) worker
);
9428 IOLockUnlock(worker
->lock
);
9431 DLOG("%s acknowledged without worker property\n",
9437 //******************************************************************************
9438 // notifySystemShutdown
9440 // Notify all objects in PM tree that system will shutdown or restart
9441 //******************************************************************************
9444 notifySystemShutdown( IOService
* root
, uint32_t messageType
)
9446 #define PLACEHOLDER ((OSSet *)gPMHaltArray)
9447 IORegistryIterator
* iter
;
9448 IORegistryEntry
* entry
;
9451 PMHaltWorker
* workers
[kPMHaltMaxWorkers
];
9452 AbsoluteTime deadline
;
9453 unsigned int totalNodes
= 0;
9455 unsigned int rootDepth
;
9456 unsigned int numWorkers
;
9462 DLOG("%s msgType = 0x%x\n", __FUNCTION__
, messageType
);
9464 baseFunc
= OSMemberFunctionCast(void *, root
, &IOService::systemWillShutdown
);
9466 // Iterate the entire PM tree starting from root
9468 rootDepth
= root
->getDepth( gIOPowerPlane
);
9473 // debug - for repeated test runs
9474 while (PMHaltWorker::metaClass
->getInstanceCount()) {
9478 if (!gPMHaltArray
) {
9479 gPMHaltArray
= OSArray::withCapacity(40);
9480 if (!gPMHaltArray
) {
9484 gPMHaltArray
->flushCollection();
9488 gPMHaltLock
= IOLockAlloc();
9494 if (!gPMHaltClientAcknowledgeKey
) {
9495 gPMHaltClientAcknowledgeKey
=
9496 OSSymbol::withCStringNoCopy("PMShutdown");
9497 if (!gPMHaltClientAcknowledgeKey
) {
9502 gPMHaltMessageType
= messageType
;
9504 // Depth-first walk of PM plane
9506 iter
= IORegistryIterator::iterateOver(
9507 root
, gIOPowerPlane
, kIORegistryIterateRecursively
);
9510 while ((entry
= iter
->getNextObject())) {
9511 node
= OSDynamicCast(IOService
, entry
);
9517 OSMemberFunctionCast(void *, node
, &IOService::systemWillShutdown
)) {
9521 depth
= node
->getDepth( gIOPowerPlane
);
9522 if (depth
<= rootDepth
) {
9528 // adjust to zero based depth
9529 depth
-= (rootDepth
+ 1);
9531 // gPMHaltArray is an array of containers, each container
9532 // refers to nodes with the same depth.
9534 count
= gPMHaltArray
->getCount();
9535 while (depth
>= count
) {
9536 // expand array and insert placeholders
9537 gPMHaltArray
->setObject(PLACEHOLDER
);
9540 count
= gPMHaltArray
->getCount();
9541 if (depth
< count
) {
9542 inner
= (OSSet
*)gPMHaltArray
->getObject(depth
);
9543 if (inner
== PLACEHOLDER
) {
9544 inner
= OSSet::withCapacity(40);
9546 gPMHaltArray
->replaceObject(depth
, inner
);
9551 // PM nodes that appear more than once in the tree will have
9552 // the same depth, OSSet will refuse to add the node twice.
9554 ok
= inner
->setObject(node
);
9558 DLOG("Skipped PM node %s\n", node
->getName());
9565 for (int i
= 0; (inner
= (OSSet
*)gPMHaltArray
->getObject(i
)); i
++) {
9567 if (inner
!= PLACEHOLDER
) {
9568 count
= inner
->getCount();
9570 DLOG("Nodes at depth %u = %u\n", i
, count
);
9573 // strip placeholders (not all depths are populated)
9575 for (int i
= 0; (inner
= (OSSet
*)gPMHaltArray
->getObject(i
));) {
9576 if (inner
== PLACEHOLDER
) {
9577 gPMHaltArray
->removeObject(i
);
9580 count
= inner
->getCount();
9581 if (count
> numWorkers
) {
9584 totalNodes
+= count
;
9588 if (gPMHaltArray
->getCount() == 0 || !numWorkers
) {
9592 gPMHaltBusyCount
= 0;
9593 gPMHaltIdleCount
= 0;
9594 gPMHaltDepth
= gPMHaltArray
->getCount() - 1;
9596 // Create multiple workers (and threads)
9598 if (numWorkers
> kPMHaltMaxWorkers
) {
9599 numWorkers
= kPMHaltMaxWorkers
;
9602 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
9603 totalNodes
, gPMHaltArray
->getCount(), numWorkers
);
9605 for (unsigned int i
= 0; i
< numWorkers
; i
++) {
9606 workers
[i
] = PMHaltWorker::worker();
9609 // Wait for workers to exhaust all available work
9611 IOLockLock(gPMHaltLock
);
9612 while (gPMHaltDepth
>= 0) {
9613 clock_interval_to_deadline(1000, kMillisecondScale
, &deadline
);
9615 waitResult
= IOLockSleepDeadline(
9616 gPMHaltLock
, &gPMHaltDepth
, deadline
, THREAD_UNINT
);
9617 if (THREAD_TIMED_OUT
== waitResult
) {
9619 clock_get_uptime(&now
);
9621 IOLockUnlock(gPMHaltLock
);
9622 for (unsigned int i
= 0; i
< numWorkers
; i
++) {
9624 PMHaltWorker::checkTimeout(workers
[i
], &now
);
9627 IOLockLock(gPMHaltLock
);
9630 IOLockUnlock(gPMHaltLock
);
9632 // Release all workers
9634 for (unsigned int i
= 0; i
< numWorkers
; i
++) {
9636 workers
[i
]->release();
9638 // worker also retained by it's own thread
9642 DLOG("%s done\n", __FUNCTION__
);
9647 // MARK: Kernel Assertion
9649 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
9651 IOPMDriverAssertionID
9652 IOPMrootDomain::createPMAssertion(
9653 IOPMDriverAssertionType whichAssertionBits
,
9654 IOPMDriverAssertionLevel assertionLevel
,
9655 IOService
*ownerService
,
9656 const char *ownerDescription
)
9659 IOPMDriverAssertionID newAssertion
;
9661 if (!pmAssertions
) {
9665 ret
= pmAssertions
->createAssertion(whichAssertionBits
, assertionLevel
, ownerService
, ownerDescription
, &newAssertion
);
9667 if (kIOReturnSuccess
== ret
) {
9668 return newAssertion
;
9675 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion
)
9677 if (!pmAssertions
) {
9678 return kIOReturnInternalError
;
9681 return pmAssertions
->releaseAssertion(releaseAssertion
);
9686 IOPMrootDomain::setPMAssertionLevel(
9687 IOPMDriverAssertionID assertionID
,
9688 IOPMDriverAssertionLevel assertionLevel
)
9690 return pmAssertions
->setAssertionLevel(assertionID
, assertionLevel
);
9693 IOPMDriverAssertionLevel
9694 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion
)
9696 IOPMDriverAssertionType sysLevels
;
9698 if (!pmAssertions
|| whichAssertion
== 0) {
9699 return kIOPMDriverAssertionLevelOff
;
9702 sysLevels
= pmAssertions
->getActivatedAssertions();
9704 // Check that every bit set in argument 'whichAssertion' is asserted
9705 // in the aggregate bits.
9706 if ((sysLevels
& whichAssertion
) == whichAssertion
) {
9707 return kIOPMDriverAssertionLevelOn
;
9709 return kIOPMDriverAssertionLevelOff
;
9714 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels
)
9716 if (!pmAssertions
) {
9717 return kIOReturnNotFound
;
9720 return pmAssertions
->setUserAssertionLevels(inLevels
);
9724 IOPMrootDomain::serializeProperties( OSSerialize
* s
) const
9727 pmAssertions
->publishProperties();
9729 return IOService::serializeProperties(s
);
9733 IOPMrootDomain::copyProperty( const char * aKey
) const
9735 OSObject
*obj
= NULL
;
9736 obj
= IOService::copyProperty(aKey
);
9742 if (!strncmp(aKey
, kIOPMSleepWakeWdogRebootKey
,
9743 sizeof(kIOPMSleepWakeWdogRebootKey
))) {
9744 if (swd_flags
& SWD_BOOT_BY_SW_WDOG
) {
9745 return kOSBooleanTrue
;
9747 return kOSBooleanFalse
;
9751 if (!strncmp(aKey
, kIOPMSleepWakeWdogLogsValidKey
,
9752 sizeof(kIOPMSleepWakeWdogLogsValidKey
))) {
9753 if (swd_flags
& SWD_VALID_LOGS
) {
9754 return kOSBooleanTrue
;
9756 return kOSBooleanFalse
;
9761 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey'
9762 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
9763 * issued by DisplayWrangler on darkwake.
9765 if (!strcmp(aKey
, "DesktopMode")) {
9767 return kOSBooleanTrue
;
9769 return kOSBooleanFalse
;
9772 if (!strcmp(aKey
, "DisplayIdleForDemandSleep")) {
9773 if (displayIdleForDemandSleep
) {
9774 return kOSBooleanTrue
;
9776 return kOSBooleanFalse
;
9780 if (!strcmp(aKey
, kIOPMDriverWakeEventsKey
)) {
9781 OSArray
* array
= NULL
;
9783 if (_systemWakeEventsArray
&& _systemWakeEventsArray
->getCount()) {
9784 OSCollection
*collection
= _systemWakeEventsArray
->copyCollection();
9785 if (collection
&& !(array
= OSDynamicCast(OSArray
, collection
))) {
9786 collection
->release();
9793 if (!strcmp(aKey
, kIOPMSleepStatisticsAppsKey
)) {
9794 OSArray
* array
= NULL
;
9795 IOLockLock(pmStatsLock
);
9796 if (pmStatsAppResponses
&& pmStatsAppResponses
->getCount()) {
9797 OSCollection
*collection
= pmStatsAppResponses
->copyCollection();
9798 if (collection
&& !(array
= OSDynamicCast(OSArray
, collection
))) {
9799 collection
->release();
9801 pmStatsAppResponses
->flushCollection();
9803 IOLockUnlock(pmStatsLock
);
9807 if (!strcmp(aKey
, kIOPMIdleSleepPreventersKey
)) {
9808 OSArray
*idleSleepList
= NULL
;
9809 gRootDomain
->copySleepPreventersList(&idleSleepList
, NULL
);
9810 return idleSleepList
;
9813 if (!strcmp(aKey
, kIOPMSystemSleepPreventersKey
)) {
9814 OSArray
*systemSleepList
= NULL
;
9815 gRootDomain
->copySleepPreventersList(NULL
, &systemSleepList
);
9816 return systemSleepList
;
9819 if (!strcmp(aKey
, kIOPMIdleSleepPreventersWithIDKey
)) {
9820 OSArray
*idleSleepList
= NULL
;
9821 gRootDomain
->copySleepPreventersListWithID(&idleSleepList
, NULL
);
9822 return idleSleepList
;
9825 if (!strcmp(aKey
, kIOPMSystemSleepPreventersWithIDKey
)) {
9826 OSArray
*systemSleepList
= NULL
;
9827 gRootDomain
->copySleepPreventersListWithID(NULL
, &systemSleepList
);
9828 return systemSleepList
;
9834 // MARK: Wake Event Reporting
9837 IOPMrootDomain::copyWakeReasonString( char * outBuf
, size_t bufSize
)
9840 strlcpy(outBuf
, gWakeReasonString
, bufSize
);
9844 //******************************************************************************
9845 // acceptSystemWakeEvents
9847 // Private control for the acceptance of driver wake event claims.
9848 //******************************************************************************
9851 IOPMrootDomain::acceptSystemWakeEvents( bool accept
)
9853 bool logWakeReason
= false;
9857 if (!_systemWakeEventsArray
) {
9858 _systemWakeEventsArray
= OSArray::withCapacity(4);
9860 _acceptSystemWakeEvents
= (_systemWakeEventsArray
!= NULL
);
9861 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
9862 if (!(kIOPMWakeEventAOTExitFlags
& _aotPendingFlags
))
9863 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
9865 gWakeReasonString
[0] = '\0';
9866 if (_systemWakeEventsArray
) {
9867 _systemWakeEventsArray
->flushCollection();
9871 _acceptSystemWakeEvents
= false;
9873 logWakeReason
= gWakeReasonSysctlRegistered
;
9875 static int panic_allowed
= -1;
9877 if ((panic_allowed
== -1) &&
9878 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed
, sizeof(panic_allowed
)) == false)) {
9882 if (panic_allowed
) {
9884 // Panic if wake reason is null or empty
9885 for (i
= 0; (i
< strlen(gWakeReasonString
)); i
++) {
9886 if ((gWakeReasonString
[i
] != ' ') && (gWakeReasonString
[i
] != '\t')) {
9890 if (i
>= strlen(gWakeReasonString
)) {
9891 panic("Wake reason is empty\n");
9899 if (logWakeReason
) {
9900 MSG("system wake events:%s\n", gWakeReasonString
);
9904 //******************************************************************************
9905 // claimSystemWakeEvent
9907 // For a driver to claim a device is the source/conduit of a system wake event.
9908 //******************************************************************************
9911 IOPMrootDomain::claimSystemWakeEvent(
9914 const char * reason
,
9915 OSObject
* details
)
9917 const OSSymbol
* deviceName
= NULL
;
9918 OSNumber
* deviceRegId
= NULL
;
9919 OSNumber
* claimTime
= NULL
;
9920 OSData
* flagsData
= NULL
;
9921 OSString
* reasonString
= NULL
;
9922 OSDictionary
* d
= NULL
;
9927 pmEventTimeStamp(×tamp
);
9929 if (!device
|| !reason
) {
9933 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
9934 IOOptionBits aotFlags
= 0;
9935 bool needAOTEvaluate
= FALSE
;
9937 if (kIOPMAOTModeAddEventFlags
& _aotMode
) {
9938 if (!strcmp("hold", reason
)
9939 || !strcmp("help", reason
)
9940 || !strcmp("menu", reason
)
9941 || !strcmp("stockholm", reason
)
9942 || !strcmp("ringer", reason
)
9943 || !strcmp("ringerab", reason
)
9944 || !strcmp("smc0", reason
)
9945 || !strcmp("AOP.RTPWakeupAP", reason
)
9946 || !strcmp("BT.OutboxNotEmpty", reason
)
9947 || !strcmp("WL.OutboxNotEmpty", reason
)) {
9948 flags
|= kIOPMWakeEventAOTExit
;
9952 #if DEVELOPMENT || DEBUG
9953 if (_aotLingerTime
&& !strcmp("rtc", reason
)) {
9954 flags
|= kIOPMWakeEventAOTPossibleExit
;
9956 #endif /* DEVELOPMENT || DEBUG */
9957 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
9959 deviceName
= device
->copyName(gIOServicePlane
);
9960 deviceRegId
= OSNumber::withNumber(device
->getRegistryEntryID(), 64);
9961 claimTime
= OSNumber::withNumber(timestamp
, 64);
9962 flagsData
= OSData::withBytes(&flags
, sizeof(flags
));
9963 reasonString
= OSString::withCString(reason
);
9964 d
= OSDictionary::withCapacity(5 + (details
? 1 : 0));
9965 if (!deviceName
|| !deviceRegId
|| !claimTime
|| !flagsData
|| !reasonString
) {
9969 d
->setObject(gIONameKey
, deviceName
);
9970 d
->setObject(gIORegistryEntryIDKey
, deviceRegId
);
9971 d
->setObject(kIOPMWakeEventTimeKey
, claimTime
);
9972 d
->setObject(kIOPMWakeEventFlagsKey
, flagsData
);
9973 d
->setObject(kIOPMWakeEventReasonKey
, reasonString
);
9975 d
->setObject(kIOPMWakeEventDetailsKey
, details
);
9979 addWakeReason
= _acceptSystemWakeEvents
;
9980 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
9982 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason
, deviceName
->getCStringNoCopy(), (int)flags
, _aotPendingFlags
, _aotReadyToFullWake
);
9984 aotFlags
= (kIOPMWakeEventAOTFlags
& flags
);
9985 aotFlags
= (aotFlags
& ~_aotPendingFlags
);
9986 needAOTEvaluate
= false;
9987 if (_aotNow
&& aotFlags
) {
9988 if (kIOPMWakeEventAOTPossibleExit
& flags
) {
9989 _aotMetrics
->possibleCount
++;
9991 if (kIOPMWakeEventAOTConfirmedPossibleExit
& flags
) {
9992 _aotMetrics
->confirmedPossibleCount
++;
9994 if (kIOPMWakeEventAOTRejectedPossibleExit
& flags
) {
9995 _aotMetrics
->rejectedPossibleCount
++;
9997 if (kIOPMWakeEventAOTExpiredPossibleExit
& flags
) {
9998 _aotMetrics
->expiredPossibleCount
++;
10001 _aotPendingFlags
|= aotFlags
;
10002 addWakeReason
= _aotNow
&& _systemWakeEventsArray
&& ((kIOPMWakeEventAOTExitFlags
& aotFlags
));
10003 needAOTEvaluate
= _aotReadyToFullWake
;
10005 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
10007 if (!gWakeReasonSysctlRegistered
) {
10008 // Lazy registration until the platform driver stops registering
10010 gWakeReasonSysctlRegistered
= true;
10011 #if CONFIG_EMBEDDED
10012 sysctl_register_oid(&sysctl__kern_wakereason
);
10015 if (addWakeReason
) {
10016 ok
= _systemWakeEventsArray
->setObject(d
);
10017 if (gWakeReasonString
[0] != '\0') {
10018 strlcat(gWakeReasonString
, " ", sizeof(gWakeReasonString
));
10020 strlcat(gWakeReasonString
, reason
, sizeof(gWakeReasonString
));
10023 WAKEEVENT_UNLOCK();
10024 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
10025 if (needAOTEvaluate
) {
10028 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
10032 deviceName
->release();
10035 deviceRegId
->release();
10038 claimTime
->release();
10041 flagsData
->release();
10043 if (reasonString
) {
10044 reasonString
->release();
10051 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10054 // MARK: PMSettingHandle
10056 OSDefineMetaClassAndStructors( PMSettingHandle
, OSObject
)
10059 PMSettingHandle::free( void )
10062 pmso
->clientHandleFreed();
10071 // MARK: PMSettingObject
10074 #define super OSObject
10075 OSDefineMetaClassAndFinalStructors( PMSettingObject
, OSObject
)
10078 * Static constructor/initializer for PMSettingObject
10080 PMSettingObject
*PMSettingObject::pmSettingObject(
10081 IOPMrootDomain
* parent_arg
,
10082 IOPMSettingControllerCallback handler_arg
,
10083 OSObject
* target_arg
,
10084 uintptr_t refcon_arg
,
10085 uint32_t supportedPowerSources
,
10086 const OSSymbol
* settings
[],
10087 OSObject
* *handle_obj
)
10089 uint32_t settingCount
= 0;
10090 PMSettingObject
*pmso
= NULL
;
10091 PMSettingHandle
*pmsh
= NULL
;
10093 if (!parent_arg
|| !handler_arg
|| !settings
|| !handle_obj
) {
10097 // count OSSymbol entries in NULL terminated settings array
10098 while (settings
[settingCount
]) {
10101 if (0 == settingCount
) {
10105 pmso
= new PMSettingObject
;
10106 if (!pmso
|| !pmso
->init()) {
10110 pmsh
= new PMSettingHandle
;
10111 if (!pmsh
|| !pmsh
->init()) {
10115 queue_init(&pmso
->calloutQueue
);
10116 pmso
->parent
= parent_arg
;
10117 pmso
->func
= handler_arg
;
10118 pmso
->target
= target_arg
;
10119 pmso
->refcon
= refcon_arg
;
10120 pmso
->settingCount
= settingCount
;
10122 pmso
->retain(); // handle holds a retain on pmso
10126 pmso
->publishedFeatureID
= (uint32_t *)IOMalloc(sizeof(uint32_t) * settingCount
);
10127 if (pmso
->publishedFeatureID
) {
10128 for (unsigned int i
= 0; i
< settingCount
; i
++) {
10129 // Since there is now at least one listener to this setting, publish
10130 // PM root domain support for it.
10131 parent_arg
->publishPMSetting( settings
[i
],
10132 supportedPowerSources
, &pmso
->publishedFeatureID
[i
] );
10136 *handle_obj
= pmsh
;
10150 PMSettingObject::free( void )
10152 if (publishedFeatureID
) {
10153 for (uint32_t i
= 0; i
< settingCount
; i
++) {
10154 if (publishedFeatureID
[i
]) {
10155 parent
->removePublishedFeature( publishedFeatureID
[i
] );
10159 IOFree(publishedFeatureID
, sizeof(uint32_t) * settingCount
);
10166 PMSettingObject::dispatchPMSetting( const OSSymbol
* type
, OSObject
* object
)
10168 (*func
)(target
, type
, object
, refcon
);
10172 PMSettingObject::clientHandleFreed( void )
10174 parent
->deregisterPMSettingObject(this);
10178 // MARK: PMAssertionsTracker
10180 //*********************************************************************************
10181 //*********************************************************************************
10182 //*********************************************************************************
10183 // class PMAssertionsTracker Implementation
10185 #define kAssertUniqueIDStart 500
10187 PMAssertionsTracker
*
10188 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain
*rootDomain
)
10190 PMAssertionsTracker
*myself
;
10192 myself
= new PMAssertionsTracker
;
10196 myself
->owner
= rootDomain
;
10197 myself
->issuingUniqueID
= kAssertUniqueIDStart
;
10198 myself
->assertionsArray
= OSArray::withCapacity(5);
10199 myself
->assertionsKernel
= 0;
10200 myself
->assertionsUser
= 0;
10201 myself
->assertionsCombined
= 0;
10202 myself
->assertionsArrayLock
= IOLockAlloc();
10203 myself
->tabulateProducerCount
= myself
->tabulateConsumerCount
= 0;
10205 if (!myself
->assertionsArray
|| !myself
->assertionsArrayLock
) {
10214 * - Update assertionsKernel to reflect the state of all
10215 * assertions in the kernel.
10216 * - Update assertionsCombined to reflect both kernel & user space.
10219 PMAssertionsTracker::tabulate(void)
10223 PMAssertStruct
*_a
= NULL
;
10226 IOPMDriverAssertionType oldKernel
= assertionsKernel
;
10227 IOPMDriverAssertionType oldCombined
= assertionsCombined
;
10231 assertionsKernel
= 0;
10232 assertionsCombined
= 0;
10234 if (!assertionsArray
) {
10238 if ((count
= assertionsArray
->getCount())) {
10239 for (i
= 0; i
< count
; i
++) {
10240 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
10242 _a
= (PMAssertStruct
*)_d
->getBytesNoCopy();
10243 if (_a
&& (kIOPMDriverAssertionLevelOn
== _a
->level
)) {
10244 assertionsKernel
|= _a
->assertionBits
;
10250 tabulateProducerCount
++;
10251 assertionsCombined
= assertionsKernel
| assertionsUser
;
10253 if ((assertionsKernel
!= oldKernel
) ||
10254 (assertionsCombined
!= oldCombined
)) {
10255 owner
->evaluateAssertions(assertionsCombined
, oldCombined
);
10260 PMAssertionsTracker::publishProperties( void )
10262 OSArray
*assertionsSummary
= NULL
;
10264 if (tabulateConsumerCount
!= tabulateProducerCount
) {
10265 IOLockLock(assertionsArrayLock
);
10267 tabulateConsumerCount
= tabulateProducerCount
;
10269 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
10271 assertionsSummary
= copyAssertionsArray();
10272 if (assertionsSummary
) {
10273 owner
->setProperty(kIOPMAssertionsDriverDetailedKey
, assertionsSummary
);
10274 assertionsSummary
->release();
10276 owner
->removeProperty(kIOPMAssertionsDriverDetailedKey
);
10279 /* Publish the IOPMrootDomain property "DriverPMAssertions"
10281 owner
->setProperty(kIOPMAssertionsDriverKey
, assertionsKernel
, 64);
10283 IOLockUnlock(assertionsArrayLock
);
10287 PMAssertionsTracker::PMAssertStruct
*
10288 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id
, int *index
)
10290 PMAssertStruct
*_a
= NULL
;
10296 if (assertionsArray
10297 && (count
= assertionsArray
->getCount())) {
10298 for (i
= 0; i
< count
; i
++) {
10299 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
10301 _a
= (PMAssertStruct
*)_d
->getBytesNoCopy();
10302 if (_a
&& (_id
== _a
->id
)) {
10320 /* PMAssertionsTracker::handleCreateAssertion
10321 * Perform assertion work on the PM workloop. Do not call directly.
10324 PMAssertionsTracker::handleCreateAssertion(OSData
*newAssertion
)
10328 if (newAssertion
) {
10329 IOLockLock(assertionsArrayLock
);
10330 assertionsArray
->setObject(newAssertion
);
10331 IOLockUnlock(assertionsArrayLock
);
10332 newAssertion
->release();
10336 return kIOReturnSuccess
;
10339 /* PMAssertionsTracker::createAssertion
10340 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
10344 PMAssertionsTracker::createAssertion(
10345 IOPMDriverAssertionType which
,
10346 IOPMDriverAssertionLevel level
,
10347 IOService
*serviceID
,
10348 const char *whoItIs
,
10349 IOPMDriverAssertionID
*outID
)
10351 OSData
*dataStore
= NULL
;
10352 PMAssertStruct track
;
10354 // Warning: trillions and trillions of created assertions may overflow the unique ID.
10355 track
.id
= OSIncrementAtomic64((SInt64
*) &issuingUniqueID
);
10356 track
.level
= level
;
10357 track
.assertionBits
= which
;
10358 track
.ownerString
= whoItIs
? OSSymbol::withCString(whoItIs
):NULL
;
10359 track
.ownerService
= serviceID
;
10360 track
.registryEntryID
= serviceID
? serviceID
->getRegistryEntryID():0;
10361 track
.modifiedTime
= 0;
10362 pmEventTimeStamp(&track
.createdTime
);
10364 dataStore
= OSData::withBytes(&track
, sizeof(PMAssertStruct
));
10366 if (track
.ownerString
) {
10367 track
.ownerString
->release();
10369 return kIOReturnNoMemory
;
10374 if (owner
&& owner
->pmPowerStateQueue
) {
10375 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionCreate
, (void *)dataStore
);
10378 return kIOReturnSuccess
;
10381 /* PMAssertionsTracker::handleReleaseAssertion
10382 * Runs in PM workloop. Do not call directly.
10385 PMAssertionsTracker::handleReleaseAssertion(
10386 IOPMDriverAssertionID _id
)
10391 PMAssertStruct
*assertStruct
= detailsForID(_id
, &index
);
10393 if (!assertStruct
) {
10394 return kIOReturnNotFound
;
10397 IOLockLock(assertionsArrayLock
);
10398 if (assertStruct
->ownerString
) {
10399 assertStruct
->ownerString
->release();
10402 assertionsArray
->removeObject(index
);
10403 IOLockUnlock(assertionsArrayLock
);
10406 return kIOReturnSuccess
;
10409 /* PMAssertionsTracker::releaseAssertion
10410 * Releases an assertion and affects system behavior if appropiate.
10411 * Actual work happens on PM workloop.
10414 PMAssertionsTracker::releaseAssertion(
10415 IOPMDriverAssertionID _id
)
10417 if (owner
&& owner
->pmPowerStateQueue
) {
10418 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionRelease
, NULL
, _id
);
10420 return kIOReturnSuccess
;
10423 /* PMAssertionsTracker::handleSetAssertionLevel
10424 * Runs in PM workloop. Do not call directly.
10427 PMAssertionsTracker::handleSetAssertionLevel(
10428 IOPMDriverAssertionID _id
,
10429 IOPMDriverAssertionLevel _level
)
10431 PMAssertStruct
*assertStruct
= detailsForID(_id
, NULL
);
10435 if (!assertStruct
) {
10436 return kIOReturnNotFound
;
10439 IOLockLock(assertionsArrayLock
);
10440 pmEventTimeStamp(&assertStruct
->modifiedTime
);
10441 assertStruct
->level
= _level
;
10442 IOLockUnlock(assertionsArrayLock
);
10445 return kIOReturnSuccess
;
10448 /* PMAssertionsTracker::setAssertionLevel
10451 PMAssertionsTracker::setAssertionLevel(
10452 IOPMDriverAssertionID _id
,
10453 IOPMDriverAssertionLevel _level
)
10455 if (owner
&& owner
->pmPowerStateQueue
) {
10456 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionSetLevel
,
10457 (void *)(uintptr_t)_level
, _id
);
10460 return kIOReturnSuccess
;
10464 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0
)
10466 IOPMDriverAssertionType new_user_levels
= *(IOPMDriverAssertionType
*) arg0
;
10470 if (new_user_levels
!= assertionsUser
) {
10471 assertionsUser
= new_user_levels
;
10472 DLOG("assertionsUser 0x%llx\n", assertionsUser
);
10476 return kIOReturnSuccess
;
10480 PMAssertionsTracker::setUserAssertionLevels(
10481 IOPMDriverAssertionType new_user_levels
)
10483 if (gIOPMWorkLoop
) {
10484 gIOPMWorkLoop
->runAction(
10485 OSMemberFunctionCast(
10486 IOWorkLoop::Action
,
10488 &PMAssertionsTracker::handleSetUserAssertionLevels
),
10490 (void *) &new_user_levels
, NULL
, NULL
, NULL
);
10493 return kIOReturnSuccess
;
10498 PMAssertionsTracker::copyAssertionsArray(void)
10502 OSArray
*outArray
= NULL
;
10504 if (!assertionsArray
||
10505 (0 == (count
= assertionsArray
->getCount())) ||
10506 (NULL
== (outArray
= OSArray::withCapacity(count
)))) {
10510 for (i
= 0; i
< count
; i
++) {
10511 PMAssertStruct
*_a
= NULL
;
10513 OSDictionary
*details
= NULL
;
10515 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
10516 if (_d
&& (_a
= (PMAssertStruct
*)_d
->getBytesNoCopy())) {
10517 OSNumber
*_n
= NULL
;
10519 details
= OSDictionary::withCapacity(7);
10524 outArray
->setObject(details
);
10525 details
->release();
10527 _n
= OSNumber::withNumber(_a
->id
, 64);
10529 details
->setObject(kIOPMDriverAssertionIDKey
, _n
);
10532 _n
= OSNumber::withNumber(_a
->createdTime
, 64);
10534 details
->setObject(kIOPMDriverAssertionCreatedTimeKey
, _n
);
10537 _n
= OSNumber::withNumber(_a
->modifiedTime
, 64);
10539 details
->setObject(kIOPMDriverAssertionModifiedTimeKey
, _n
);
10542 _n
= OSNumber::withNumber((uintptr_t)_a
->registryEntryID
, 64);
10544 details
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, _n
);
10547 _n
= OSNumber::withNumber(_a
->level
, 64);
10549 details
->setObject(kIOPMDriverAssertionLevelKey
, _n
);
10552 _n
= OSNumber::withNumber(_a
->assertionBits
, 64);
10554 details
->setObject(kIOPMDriverAssertionAssertedKey
, _n
);
10558 if (_a
->ownerString
) {
10559 details
->setObject(kIOPMDriverAssertionOwnerStringKey
, _a
->ownerString
);
10568 IOPMDriverAssertionType
10569 PMAssertionsTracker::getActivatedAssertions(void)
10571 return assertionsCombined
;
10574 IOPMDriverAssertionLevel
10575 PMAssertionsTracker::getAssertionLevel(
10576 IOPMDriverAssertionType type
)
10578 if (type
&& ((type
& assertionsKernel
) == assertionsKernel
)) {
10579 return kIOPMDriverAssertionLevelOn
;
10581 return kIOPMDriverAssertionLevelOff
;
10585 //*********************************************************************************
10586 //*********************************************************************************
10587 //*********************************************************************************
10591 pmEventTimeStamp(uint64_t *recordTS
)
10594 clock_usec_t tusec
;
10600 // We assume tsec fits into 32 bits; 32 bits holds enough
10601 // seconds for 136 years since the epoch in 1970.
10602 clock_get_calendar_microtime(&tsec
, &tusec
);
10605 // Pack the sec & microsec calendar time into a uint64_t, for fun.
10607 *recordTS
|= (uint32_t)tusec
;
10608 *recordTS
|= ((uint64_t)tsec
<< 32);
10614 // MARK: IORootParent
10616 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10618 OSDefineMetaClassAndFinalStructors(IORootParent
, IOService
)
10620 // The reason that root domain needs a root parent is to facilitate demand
10621 // sleep, since a power change from the root parent cannot be vetoed.
10623 // The above statement is no longer true since root domain now performs
10624 // demand sleep using overrides. But root parent remains to avoid changing
10625 // the power tree stacking. Root parent is parked at the max power state.
10628 static IOPMPowerState patriarchPowerStates
[2] =
10630 {1, 0, ON_POWER
, 0, 0, 0, 0, 0, 0, 0, 0, 0},
10631 {1, 0, ON_POWER
, 0, 0, 0, 0, 0, 0, 0, 0, 0},
10635 IORootParent::initialize( void )
10638 gIOPMPSExternalConnectedKey
= OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey
);
10639 gIOPMPSExternalChargeCapableKey
= OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey
);
10640 gIOPMPSBatteryInstalledKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey
);
10641 gIOPMPSIsChargingKey
= OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey
);
10642 gIOPMPSAtWarnLevelKey
= OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey
);
10643 gIOPMPSAtCriticalLevelKey
= OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey
);
10644 gIOPMPSCurrentCapacityKey
= OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey
);
10645 gIOPMPSMaxCapacityKey
= OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey
);
10646 gIOPMPSDesignCapacityKey
= OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey
);
10647 gIOPMPSTimeRemainingKey
= OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey
);
10648 gIOPMPSAmperageKey
= OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey
);
10649 gIOPMPSVoltageKey
= OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey
);
10650 gIOPMPSCycleCountKey
= OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey
);
10651 gIOPMPSMaxErrKey
= OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey
);
10652 gIOPMPSAdapterInfoKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey
);
10653 gIOPMPSLocationKey
= OSSymbol::withCStringNoCopy(kIOPMPSLocationKey
);
10654 gIOPMPSErrorConditionKey
= OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey
);
10655 gIOPMPSManufacturerKey
= OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey
);
10656 gIOPMPSManufactureDateKey
= OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey
);
10657 gIOPMPSModelKey
= OSSymbol::withCStringNoCopy(kIOPMPSModelKey
);
10658 gIOPMPSSerialKey
= OSSymbol::withCStringNoCopy(kIOPMPSSerialKey
);
10659 gIOPMPSLegacyBatteryInfoKey
= OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey
);
10660 gIOPMPSBatteryHealthKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey
);
10661 gIOPMPSHealthConfidenceKey
= OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey
);
10662 gIOPMPSCapacityEstimatedKey
= OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey
);
10663 gIOPMPSBatteryChargeStatusKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey
);
10664 gIOPMPSBatteryTemperatureKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey
);
10665 gIOPMPSAdapterDetailsKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey
);
10666 gIOPMPSChargerConfigurationKey
= OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey
);
10667 gIOPMPSAdapterDetailsIDKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey
);
10668 gIOPMPSAdapterDetailsWattsKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey
);
10669 gIOPMPSAdapterDetailsRevisionKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey
);
10670 gIOPMPSAdapterDetailsSerialNumberKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey
);
10671 gIOPMPSAdapterDetailsFamilyKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey
);
10672 gIOPMPSAdapterDetailsAmperageKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey
);
10673 gIOPMPSAdapterDetailsDescriptionKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey
);
10674 gIOPMPSAdapterDetailsPMUConfigurationKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey
);
10675 gIOPMPSAdapterDetailsSourceIDKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey
);
10676 gIOPMPSAdapterDetailsErrorFlagsKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey
);
10677 gIOPMPSAdapterDetailsSharedSourceKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey
);
10678 gIOPMPSAdapterDetailsCloakedKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey
);
10679 gIOPMPSInvalidWakeSecondsKey
= OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey
);
10680 gIOPMPSPostChargeWaitSecondsKey
= OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey
);
10681 gIOPMPSPostDishargeWaitSecondsKey
= OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey
);
10685 IORootParent::start( IOService
* nub
)
10687 IOService::start(nub
);
10688 attachToParent( getRegistryRoot(), gIOPowerPlane
);
10690 registerPowerDriver(this, patriarchPowerStates
, 2);
10696 IORootParent::shutDownSystem( void )
10701 IORootParent::restartSystem( void )
10706 IORootParent::sleepSystem( void )
10711 IORootParent::dozeSystem( void )
10716 IORootParent::sleepToDoze( void )
10721 IORootParent::wakeSystem( void )
10726 IORootParent::copyProperty( const char * aKey
) const
10728 return IOService::copyProperty(aKey
);
10732 IOPMrootDomain::getWatchdogTimeout()
10734 if (gSwdSleepWakeTimeout
) {
10735 gSwdSleepTimeout
= gSwdWakeTimeout
= gSwdSleepWakeTimeout
;
10737 if ((pmTracer
->getTracePhase() < kIOPMTracePointSystemSleep
) ||
10738 (pmTracer
->getTracePhase() == kIOPMTracePointDarkWakeEntry
)) {
10739 return gSwdSleepTimeout
? gSwdSleepTimeout
: WATCHDOG_SLEEP_TIMEOUT
;
10741 return gSwdWakeTimeout
? gSwdWakeTimeout
: WATCHDOG_WAKE_TIMEOUT
;
10746 #if defined(__i386__) || defined(__x86_64__)
10748 IOPMrootDomain::restartWithStackshot()
10750 takeStackshot(true);
10752 return kIOReturnSuccess
;
10756 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger
)
10758 takeStackshot(wdogTrigger
);
10762 IOPMrootDomain::tracePhase2String(uint32_t tracePhase
, const char **phaseString
, const char **description
)
10764 switch (tracePhase
) {
10765 case kIOPMTracePointSleepStarted
:
10766 *phaseString
= "kIOPMTracePointSleepStarted";
10767 *description
= "starting sleep";
10770 case kIOPMTracePointSleepApplications
:
10771 *phaseString
= "kIOPMTracePointSleepApplications";
10772 *description
= "notifying applications";
10775 case kIOPMTracePointSleepPriorityClients
:
10776 *phaseString
= "kIOPMTracePointSleepPriorityClients";
10777 *description
= "notifying clients about upcoming system capability changes";
10780 case kIOPMTracePointSleepWillChangeInterests
:
10781 *phaseString
= "kIOPMTracePointSleepWillChangeInterests";
10782 *description
= "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
10785 case kIOPMTracePointSleepPowerPlaneDrivers
:
10786 *phaseString
= "kIOPMTracePointSleepPowerPlaneDrivers";
10787 *description
= "calling power state change callbacks";
10790 case kIOPMTracePointSleepDidChangeInterests
:
10791 *phaseString
= "kIOPMTracePointSleepDidChangeInterests";
10792 *description
= "calling rootDomain's clients about rootDomain's state changes";
10795 case kIOPMTracePointSleepCapabilityClients
:
10796 *phaseString
= "kIOPMTracePointSleepCapabilityClients";
10797 *description
= "notifying clients about current system capabilities";
10800 case kIOPMTracePointSleepPlatformActions
:
10801 *phaseString
= "kIOPMTracePointSleepPlatformActions";
10802 *description
= "calling Quiesce/Sleep action callbacks";
10805 case kIOPMTracePointSleepCPUs
:
10807 *phaseString
= "kIOPMTracePointSleepCPUs";
10808 #if defined(__i386__) || defined(__x86_64__)
10810 * We cannot use the getCPUNumber() method to get the cpu number, since
10811 * that cpu number is unrelated to the cpu number we need (we need the cpu
10812 * number as enumerated by the scheduler, NOT the CPU number enumerated
10813 * by ACPIPlatform as the CPUs are enumerated in MADT order).
10814 * Instead, pass the Mach processor pointer associated with the current
10815 * shutdown target so its associated cpu_id can be used in
10816 * processor_to_datastring.
10818 if (currentShutdownTarget
!= NULL
&&
10819 currentShutdownTarget
->getMachProcessor() != NULL
) {
10820 const char *sbuf
= processor_to_datastring("halting all non-boot CPUs",
10821 currentShutdownTarget
->getMachProcessor());
10822 *description
= sbuf
;
10824 *description
= "halting all non-boot CPUs";
10827 *description
= "halting all non-boot CPUs";
10831 case kIOPMTracePointSleepPlatformDriver
:
10832 *phaseString
= "kIOPMTracePointSleepPlatformDriver";
10833 *description
= "executing platform specific code";
10836 case kIOPMTracePointHibernate
:
10837 *phaseString
= "kIOPMTracePointHibernate";
10838 *description
= "writing the hibernation image";
10841 case kIOPMTracePointSystemSleep
:
10842 *phaseString
= "kIOPMTracePointSystemSleep";
10843 *description
= "in EFI/Bootrom after last point of entry to sleep";
10846 case kIOPMTracePointWakePlatformDriver
:
10847 *phaseString
= "kIOPMTracePointWakePlatformDriver";
10848 *description
= "executing platform specific code";
10852 case kIOPMTracePointWakePlatformActions
:
10853 *phaseString
= "kIOPMTracePointWakePlatformActions";
10854 *description
= "calling Wake action callbacks";
10857 case kIOPMTracePointWakeCPUs
:
10858 *phaseString
= "kIOPMTracePointWakeCPUs";
10859 *description
= "starting non-boot CPUs";
10862 case kIOPMTracePointWakeWillPowerOnClients
:
10863 *phaseString
= "kIOPMTracePointWakeWillPowerOnClients";
10864 *description
= "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
10867 case kIOPMTracePointWakeWillChangeInterests
:
10868 *phaseString
= "kIOPMTracePointWakeWillChangeInterests";
10869 *description
= "calling rootDomain's clients about upcoming rootDomain's state changes";
10872 case kIOPMTracePointWakeDidChangeInterests
:
10873 *phaseString
= "kIOPMTracePointWakeDidChangeInterests";
10874 *description
= "calling rootDomain's clients about completed rootDomain's state changes";
10877 case kIOPMTracePointWakePowerPlaneDrivers
:
10878 *phaseString
= "kIOPMTracePointWakePowerPlaneDrivers";
10879 *description
= "calling power state change callbacks";
10882 case kIOPMTracePointWakeCapabilityClients
:
10883 *phaseString
= "kIOPMTracePointWakeCapabilityClients";
10884 *description
= "informing clients about current system capabilities";
10887 case kIOPMTracePointWakeApplications
:
10888 *phaseString
= "kIOPMTracePointWakeApplications";
10889 *description
= "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
10892 case kIOPMTracePointDarkWakeEntry
:
10893 *phaseString
= "kIOPMTracePointDarkWakeEntry";
10894 *description
= "entering darkwake on way to sleep";
10897 case kIOPMTracePointDarkWakeExit
:
10898 *phaseString
= "kIOPMTracePointDarkWakeExit";
10899 *description
= "entering fullwake from darkwake";
10903 *phaseString
= NULL
;
10904 *description
= NULL
;
10909 IOPMrootDomain::saveFailureData2File()
10911 unsigned int len
= 0;
10912 char failureStr
[512];
10915 OSNumber
*statusCode
;
10916 uint64_t pmStatusCode
= 0;
10917 uint32_t phaseData
= 0;
10918 uint32_t phaseDetail
= 0;
10919 bool efiFailure
= false;
10921 statusCode
= OSDynamicCast(OSNumber
, getProperty(kIOPMSleepWakeFailureCodeKey
));
10923 pmStatusCode
= statusCode
->unsigned64BitValue();
10924 phaseData
= pmStatusCode
& 0xFFFFFFFF;
10925 phaseDetail
= (pmStatusCode
>> 32) & 0xFFFFFFFF;
10926 if ((phaseData
& 0xFF) == kIOPMTracePointSystemSleep
) {
10927 LOG("Sleep Wake failure in EFI\n");
10930 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
);
10931 len
= strlen(failureStr
);
10936 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic
, NULL
, &len
)) {
10937 swd_flags
|= SWD_BOOT_BY_SW_WDOG
;
10938 PERemoveNVRAMProperty(kIOSleepWakeFailurePanic
);
10939 // dump panic will handle saving nvram data
10943 /* Keeping this around for capturing data during power
10946 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString
, NULL
, &len
)) {
10947 DLOG("No sleep wake failure string\n");
10951 DLOG("Ignoring zero byte SleepWake failure string\n");
10955 // if PMStatus code is zero, delete stackshot and return
10957 if (((pmStatusCode
& 0xFFFFFFFF) & 0xFF) == 0) {
10958 // there was no sleep wake failure
10959 // this can happen if delete stackshot was called
10960 // before take stackshot completed. Let us delete any
10961 // sleep wake failure data in nvram
10962 DLOG("Deleting stackshot on successful wake\n");
10968 if (len
> sizeof(failureStr
)) {
10969 len
= sizeof(failureStr
);
10972 PEReadNVRAMProperty(kIOSleepWakeFailureString
, failureStr
, &len
);
10974 if (failureStr
[0] != 0) {
10975 error
= sleepWakeDebugSaveFile(kSleepWakeFailureStringFile
, failureStr
, len
);
10977 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error
);
10979 DLOG("Saved SleepWake failure string to file.\n");
10983 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
10988 unsigned int len
= 0;
10990 char nvram_var_name_buffer
[20];
10991 unsigned int concat_len
= 0;
10992 swd_hdr
*hdr
= NULL
;
10995 hdr
= (swd_hdr
*)swd_buffer
;
10996 outbuf
= (char *)hdr
+ hdr
->spindump_offset
;
10998 for (int i
= 0; i
< 8; i
++) {
10999 snprintf(nvram_var_name_buffer
, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, i
+ 1);
11000 if (!PEReadNVRAMProperty(nvram_var_name_buffer
, NULL
, &len
)) {
11001 LOG("No SleepWake blob to read beyond chunk %d\n", i
);
11004 if (PEReadNVRAMProperty(nvram_var_name_buffer
, outbuf
+ concat_len
, &len
) == FALSE
) {
11005 PERemoveNVRAMProperty(nvram_var_name_buffer
);
11006 LOG("Could not read the property :-(\n");
11009 PERemoveNVRAMProperty(nvram_var_name_buffer
);
11012 LOG("Concatenated length for the SWD blob %d\n", concat_len
);
11015 error
= sleepWakeDebugSaveFile(kSleepWakeStacksFilename
, outbuf
, concat_len
);
11017 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error
);
11019 LOG("Saved SleepWake zipped data to file.\n");
11022 // There is a sleep wake failure string but no stackshot
11023 // Write a placeholder stacks file so that swd runs
11024 snprintf(outbuf
, 20, "%s", "No stackshot data\n");
11025 error
= sleepWakeDebugSaveFile(kSleepWakeStacksFilename
, outbuf
, 20);
11027 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error
);
11029 LOG("Saved SleepWake zipped data to file.\n");
11033 LOG("No buffer allocated to save failure stackshot\n");
11037 gRootDomain
->swd_lock
= 0;
11039 PERemoveNVRAMProperty(kIOSleepWakeFailureString
);
11045 IOPMrootDomain::getFailureData(thread_t
*thread
, char *failureStr
, size_t strLen
)
11047 IORegistryIterator
* iter
;
11048 IORegistryEntry
* entry
;
11050 bool nodeFound
= false;
11052 const void * callMethod
= NULL
;
11053 const char * objectName
= NULL
;
11054 uint32_t timeout
= getWatchdogTimeout();
11055 const char * phaseString
= NULL
;
11056 const char * phaseDescription
= NULL
;
11058 IOPMServiceInterestNotifier
*notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, notifierObject
);
11059 uint32_t tracePhase
= pmTracer
->getTracePhase();
11062 if ((tracePhase
< kIOPMTracePointSystemSleep
) || (tracePhase
== kIOPMTracePointDarkWakeEntry
)) {
11063 snprintf(failureStr
, strLen
, "%sSleep transition timed out after %d seconds", failureStr
, timeout
);
11065 snprintf(failureStr
, strLen
, "%sWake transition timed out after %d seconds", failureStr
, timeout
);
11067 tracePhase2String(tracePhase
, &phaseString
, &phaseDescription
);
11069 if (notifierThread
) {
11070 if (notifier
&& (notifier
->identifier
)) {
11071 objectName
= notifier
->identifier
->getCStringNoCopy();
11073 *thread
= notifierThread
;
11075 iter
= IORegistryIterator::iterateOver(
11076 getPMRootDomain(), gIOPowerPlane
, kIORegistryIterateRecursively
);
11079 while ((entry
= iter
->getNextObject())) {
11080 node
= OSDynamicCast(IOService
, entry
);
11084 if (OSDynamicCast(IOPowerConnection
, node
)) {
11088 if (node
->getBlockingDriverCall(thread
, &callMethod
)) {
11096 OSKext
*kext
= OSKext::lookupKextWithAddress((vm_address_t
)callMethod
);
11098 objectName
= kext
->getIdentifierCString();
11103 if (phaseDescription
) {
11104 snprintf(failureStr
, strLen
, "%s while %s.", failureStr
, phaseDescription
);
11107 snprintf(failureStr
, strLen
, "%s Suspected bundle: %s.", failureStr
, objectName
);
11110 snprintf(failureStr
, strLen
, "%s Thread 0x%llx.", failureStr
, thread_tid(*thread
));
11113 DLOG("%s\n", failureStr
);
11116 struct swd_stackshot_compressed_data
{
11117 z_output_func zoutput
;
11119 uint64_t totalbytes
;
11120 uint64_t lastpercent
;
11122 unsigned outremain
;
11127 struct swd_stackshot_compressed_data swd_zip_var
= { };
11130 swd_zs_alloc(void *__unused ref
, u_int items
, u_int size
)
11133 LOG("Alloc in zipping %d items of size %d\n", items
, size
);
11135 result
= (void *)(swd_zs_zmem
+ swd_zs_zoffset
);
11136 swd_zs_zoffset
+= ~31L & (31 + (items
* size
)); // 32b align for vector crc
11137 LOG("Offset %zu\n", swd_zs_zoffset
);
11142 swd_zinput(z_streamp strm
, Bytef
*buf
, unsigned size
)
11146 len
= strm
->avail_in
;
11155 if (strm
->next_in
!= (Bytef
*) strm
) {
11156 memcpy(buf
, strm
->next_in
, len
);
11161 strm
->adler
= z_crc32(strm
->adler
, buf
, len
);
11163 strm
->avail_in
-= len
;
11164 strm
->next_in
+= len
;
11165 strm
->total_in
+= len
;
11171 swd_zoutput(z_streamp strm
, Bytef
*buf
, unsigned len
)
11173 unsigned int i
= 0;
11174 // if outlen > max size don't add to the buffer
11176 if (swd_zip_var
.outlen
+ len
> SWD_COMPRESSED_BUFSIZE
) {
11177 LOG("No space to GZIP... not writing to NVRAM\n");
11181 for (i
= 0; i
< len
; i
++) {
11182 *(swd_zip_var
.outbuf
+ swd_zip_var
.outlen
+ i
) = *(buf
+ i
);
11184 swd_zip_var
.outlen
+= len
;
11188 swd_zs_free(void * __unused ref
, void * __unused ptr
)
11193 swd_compress(char *inPtr
, char *outPtr
, size_t numBytes
)
11198 if (!swd_zs
.zalloc
) {
11199 swd_zs
.zalloc
= swd_zs_alloc
;
11200 swd_zs
.zfree
= swd_zs_free
;
11201 if (deflateInit2(&swd_zs
, Z_BEST_SPEED
, Z_DEFLATED
, wbits
+ 16, memlevel
, Z_DEFAULT_STRATEGY
)) {
11202 // allocation failed
11203 bzero(&swd_zs
, sizeof(swd_zs
));
11204 // swd_zs_zoffset = 0;
11206 LOG("PMRD inited the zlib allocation routines\n");
11212 swd_zip_var
.zipped
= 0;
11213 swd_zip_var
.totalbytes
= 0; // should this be the max that we have?
11214 swd_zip_var
.lastpercent
= 0;
11215 swd_zip_var
.error
= kIOReturnSuccess
;
11216 swd_zip_var
.outremain
= 0;
11217 swd_zip_var
.outlen
= 0;
11218 swd_zip_var
.writes
= 0;
11219 swd_zip_var
.outbuf
= (Bytef
*)outPtr
;
11221 swd_zip_var
.totalbytes
= numBytes
;
11223 swd_zs
.avail_in
= 0;
11224 swd_zs
.next_in
= NULL
;
11225 swd_zs
.avail_out
= 0;
11226 swd_zs
.next_out
= NULL
;
11228 deflateResetWithIO(&swd_zs
, swd_zinput
, swd_zoutput
);
11236 while (swd_zip_var
.error
>= 0) {
11237 if (!zs
->avail_in
) {
11238 zs
->next_in
= (unsigned char *)inPtr
? (Bytef
*)inPtr
: (Bytef
*)zs
; /* zero marker? */
11239 zs
->avail_in
= numBytes
;
11241 if (!zs
->avail_out
) {
11242 zs
->next_out
= (Bytef
*)zs
;
11243 zs
->avail_out
= UINT32_MAX
;
11245 zr
= deflate(zs
, Z_NO_FLUSH
);
11246 if (Z_STREAM_END
== zr
) {
11250 LOG("ZERR %d\n", zr
);
11251 swd_zip_var
.error
= zr
;
11253 if (zs
->total_in
== numBytes
) {
11259 //now flush the stream
11260 while (swd_zip_var
.error
>= 0) {
11261 if (!zs
->avail_out
) {
11262 zs
->next_out
= (Bytef
*)zs
;
11263 zs
->avail_out
= UINT32_MAX
;
11265 zr
= deflate(zs
, Z_FINISH
);
11266 if (Z_STREAM_END
== zr
) {
11270 LOG("ZERR %d\n", zr
);
11271 swd_zip_var
.error
= zr
;
11273 if (zs
->total_in
== numBytes
) {
11274 LOG("Total output size %d\n", swd_zip_var
.outlen
);
11280 return swd_zip_var
.outlen
;
11284 IOPMrootDomain::deleteStackshot()
11286 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11287 // takeStackshot hasn't completed
11290 LOG("Deleting any sleepwake failure data in nvram\n");
11292 PERemoveNVRAMProperty(kIOSleepWakeFailureString
);
11293 char nvram_var_name_buf
[20];
11294 for (int i
= 0; i
< 8; i
++) {
11295 snprintf(nvram_var_name_buf
, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, i
+ 1);
11296 if (PERemoveNVRAMProperty(nvram_var_name_buf
) == false) {
11297 LOG("Removing %s returned false\n", nvram_var_name_buf
);
11300 // force NVRAM sync
11301 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey
, kIONVRAMSyncNowPropertyKey
, strlen(kIONVRAMSyncNowPropertyKey
)) == false) {
11302 DLOG("Failed to force nvram sync\n");
11304 gRootDomain
->swd_lock
= 0;
11307 IOPMrootDomain::takeStackshot(bool wdogTrigger
)
11309 swd_hdr
* hdr
= NULL
;
11313 kern_return_t kr
= KERN_SUCCESS
;
11318 uint32_t bytesRemaining
;
11319 unsigned bytesWritten
= 0;
11321 char failureStr
[512];
11322 thread_t thread
= NULL
;
11323 const char * swfPanic
= "swfPanic";
11329 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11334 if ((kIOSleepWakeWdogOff
& gIOKitDebug
) || systemBooting
|| systemShutdown
|| gWillShutdown
) {
11339 getFailureData(&thread
, failureStr
, sizeof(failureStr
));
11341 if (PEGetCoprocessorVersion() >= kCoprocessorVersion2
) {
11342 goto skip_stackshot
;
11347 clock_get_uptime(&now
);
11348 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
11349 absolutetime_to_nanoseconds(now
, &nsec
);
11350 snprintf(failureStr
, sizeof(failureStr
), "%sPower button pressed during wake transition after %u ms.\n", failureStr
, ((int)((nsec
) / NSEC_PER_MSEC
)));
11353 if (swd_buffer
== NULL
) {
11354 sleepWakeDebugMemAlloc();
11355 if (swd_buffer
== NULL
) {
11359 hdr
= (swd_hdr
*)swd_buffer
;
11360 bufSize
= hdr
->alloc_size
;;
11365 dstAddr
= (char*)hdr
+ hdr
->spindump_offset
;
11366 flags
= STACKSHOT_KCDATA_FORMAT
| STACKSHOT_NO_IO_STATS
| STACKSHOT_SAVE_KEXT_LOADINFO
| STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY
| STACKSHOT_THREAD_WAITINFO
;
11367 /* If not wdogTrigger only take kernel tasks stackshot
11375 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
11376 * If we run out of space, take stackshot with only kernel task
11378 while (success
== 0 && cnt
< max_cnt
) {
11379 bytesRemaining
= bufSize
- hdr
->spindump_offset
;
11381 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining
);
11383 size
= bytesRemaining
;
11384 kr
= stack_snapshot_from_kernel(pid
, dstAddr
, size
, flags
, 0, &bytesWritten
);
11385 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%x bytesWritten: %d\n",
11386 kr
, pid
, size
, flags
, bytesWritten
);
11387 if (kr
== KERN_INSUFFICIENT_BUFFER_SIZE
) {
11391 LOG("Insufficient buffer size for only kernel task\n");
11395 if (kr
== KERN_SUCCESS
) {
11396 if (bytesWritten
== 0) {
11397 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%x\n", kr
, size
, flags
);
11400 bytesRemaining
-= bytesWritten
;
11401 hdr
->spindump_size
= (bufSize
- bytesRemaining
- hdr
->spindump_offset
);
11403 memset(hdr
->reason
, 0x20, sizeof(hdr
->reason
));
11405 // Compress stackshot and save to NVRAM
11407 char *outbuf
= (char *)swd_compressed_buffer
;
11409 int num_chunks
= 0;
11410 int max_chunks
= 0;
11412 char nvram_var_name_buffer
[20];
11414 outlen
= swd_compress((char*)hdr
+ hdr
->spindump_offset
, outbuf
, bytesWritten
);
11417 max_chunks
= outlen
/ (2096 - 200);
11418 leftover
= outlen
% (2096 - 200);
11420 if (max_chunks
< 8) {
11421 for (num_chunks
= 0; num_chunks
< max_chunks
; num_chunks
++) {
11422 snprintf(nvram_var_name_buffer
, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, num_chunks
+ 1);
11423 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer
, (outbuf
+ (num_chunks
* (2096 - 200))), (2096 - 200)) == FALSE
) {
11424 LOG("Failed to update NVRAM %d\n", num_chunks
);
11429 snprintf(nvram_var_name_buffer
, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, num_chunks
+ 1);
11430 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer
, (outbuf
+ (num_chunks
* (2096 - 200))), leftover
) == FALSE
) {
11431 LOG("Failed to update NVRAM with leftovers\n");
11435 LOG("Successfully saved stackshot to NVRAM\n");
11437 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen
);
11441 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen
);
11450 if (failureStr
[0]) {
11451 // append sleep-wake failure code
11452 snprintf(failureStr
, sizeof(failureStr
), "%s\nFailure code:: 0x%08x %08x\n",
11453 failureStr
, pmTracer
->getTraceData(), pmTracer
->getTracePhase());
11454 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString
, failureStr
, strlen(failureStr
)) == false) {
11455 DLOG("Failed to write SleepWake failure string\n");
11459 // force NVRAM sync
11460 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey
, kIONVRAMSyncNowPropertyKey
, strlen(kIONVRAMSyncNowPropertyKey
)) == false) {
11461 DLOG("Failed to force nvram sync\n");
11466 if (PEGetCoprocessorVersion() < kCoprocessorVersion2
) {
11467 if (swd_flags
& SWD_BOOT_BY_SW_WDOG
) {
11468 // If current boot is due to this watch dog trigger restart in previous boot,
11469 // then don't trigger again until at least 1 successful sleep & wake.
11470 if (!(sleepCnt
&& (displayWakeCnt
|| darkWakeCnt
))) {
11471 LOG("Shutting down due to repeated Sleep/Wake failures\n");
11472 if (!tasksSuspended
) {
11473 tasksSuspended
= TRUE
;
11474 updateTasksSuspend();
11476 PEHaltRestart(kPEHaltCPU
);
11480 if (gSwdPanic
== 0) {
11481 LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
11482 if (!tasksSuspended
) {
11483 tasksSuspended
= TRUE
;
11484 updateTasksSuspend();
11486 PEHaltRestart(kPERestartCPU
);
11489 if (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic
, swfPanic
, strlen(swfPanic
)) == false) {
11490 DLOG("Failed to write SleepWake failure panic key\n");
11493 panic_with_thread_context(0, NULL
, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT
, thread
, "%s", failureStr
);
11495 panic_with_options(0, NULL
, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT
, "%s", failureStr
);
11498 gRootDomain
->swd_lock
= 0;
11504 IOPMrootDomain::sleepWakeDebugMemAlloc()
11506 vm_size_t size
= SWD_STACKSHOT_SIZE
+ SWD_COMPRESSED_BUFSIZE
+ SWD_ZLIB_BUFSIZE
;
11508 swd_hdr
*hdr
= NULL
;
11509 void *bufPtr
= NULL
;
11511 IOBufferMemoryDescriptor
*memDesc
= NULL
;
11514 if (kIOSleepWakeWdogOff
& gIOKitDebug
) {
11518 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11522 memDesc
= IOBufferMemoryDescriptor::inTaskWithOptions(
11523 kernel_task
, kIODirectionIn
| kIOMemoryMapperNone
,
11525 if (memDesc
== NULL
) {
11526 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
11530 bufPtr
= memDesc
->getBytesNoCopy();
11532 // Carve out memory for zlib routines
11533 swd_zs_zmem
= (vm_offset_t
)bufPtr
;
11534 bufPtr
= (char *)bufPtr
+ SWD_ZLIB_BUFSIZE
;
11536 // Carve out memory for compressed stackshots
11537 swd_compressed_buffer
= bufPtr
;
11538 bufPtr
= (char *)bufPtr
+ SWD_COMPRESSED_BUFSIZE
;
11540 // Remaining is used for holding stackshot
11541 hdr
= (swd_hdr
*)bufPtr
;
11542 memset(hdr
, 0, sizeof(swd_hdr
));
11544 hdr
->signature
= SWD_HDR_SIGNATURE
;
11545 hdr
->alloc_size
= SWD_STACKSHOT_SIZE
;
11547 hdr
->spindump_offset
= sizeof(swd_hdr
);
11548 swd_buffer
= (void *)hdr
;
11549 swd_memDesc
= memDesc
;
11550 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr
->alloc_size
, hdr
->spindump_offset
);
11553 gRootDomain
->swd_lock
= 0;
11557 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
11559 vm_size_t size
= SWD_SPINDUMP_SIZE
;
11561 swd_hdr
*hdr
= NULL
;
11563 IOBufferMemoryDescriptor
*memDesc
= NULL
;
11565 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11569 memDesc
= IOBufferMemoryDescriptor::inTaskWithOptions(
11570 kernel_task
, kIODirectionIn
| kIOMemoryMapperNone
,
11571 SWD_SPINDUMP_SIZE
);
11573 if (memDesc
== NULL
) {
11574 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
11579 hdr
= (swd_hdr
*)memDesc
->getBytesNoCopy();
11580 memset(hdr
, 0, sizeof(swd_hdr
));
11582 hdr
->signature
= SWD_HDR_SIGNATURE
;
11583 hdr
->alloc_size
= size
;
11585 hdr
->spindump_offset
= sizeof(swd_hdr
);
11586 swd_spindump_buffer
= (void *)hdr
;
11589 gRootDomain
->swd_lock
= 0;
11593 IOPMrootDomain::sleepWakeDebugEnableWdog()
11598 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
11600 return !systemBooting
&& !systemShutdown
&& !gWillShutdown
;
11604 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
11606 swd_hdr
*hdr
= NULL
;
11607 errno_t error
= EIO
;
11609 if (swd_spindump_buffer
&& gSpinDumpBufferFull
) {
11610 hdr
= (swd_hdr
*)swd_spindump_buffer
;
11612 error
= sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
11613 (char*)hdr
+ hdr
->spindump_offset
, hdr
->spindump_size
);
11619 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
11620 (char*)hdr
+ offsetof(swd_hdr
, UUID
),
11621 sizeof(swd_hdr
) - offsetof(swd_hdr
, UUID
));
11623 gSpinDumpBufferFull
= false;
11628 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name
, char *buf
, int len
)
11630 struct vnode
*vp
= NULL
;
11631 vfs_context_t ctx
= vfs_context_create(vfs_context_current());
11632 kauth_cred_t cred
= vfs_context_ucred(ctx
);
11633 struct vnode_attr va
;
11634 errno_t error
= EIO
;
11636 if (vnode_open(name
, (O_CREAT
| FWRITE
| O_NOFOLLOW
),
11637 S_IRUSR
| S_IRGRP
| S_IROTH
, VNODE_LOOKUP_NOFOLLOW
, &vp
, ctx
) != 0) {
11638 LOG("Failed to open the file %s\n", name
);
11639 swd_flags
|= SWD_FILEOP_ERROR
;
11643 VATTR_WANTED(&va
, va_nlink
);
11644 /* Don't dump to non-regular files or files with links. */
11645 if (vp
->v_type
!= VREG
||
11646 vnode_getattr(vp
, &va
, ctx
) || va
.va_nlink
!= 1) {
11647 LOG("Bailing as this is not a regular file\n");
11648 swd_flags
|= SWD_FILEOP_ERROR
;
11652 VATTR_SET(&va
, va_data_size
, 0);
11653 vnode_setattr(vp
, &va
, ctx
);
11657 error
= vn_rdwr(UIO_WRITE
, vp
, buf
, len
, 0,
11658 UIO_SYSSPACE
, IO_NODELOCKED
| IO_UNIT
, cred
, (int *) NULL
, vfs_context_proc(ctx
));
11660 LOG("Failed to save sleep wake log. err 0x%x\n", error
);
11661 swd_flags
|= SWD_FILEOP_ERROR
;
11663 DLOG("Saved %d bytes to file %s\n", len
, name
);
11669 vnode_close(vp
, FWRITE
, ctx
);
11672 vfs_context_rele(ctx
);
11682 IOPMrootDomain::sleepWakeDebugTrig(bool restart
)
11685 if (gSwdPanic
== 0) {
11688 panic("Sleep/Wake hang detected");
11694 IOPMrootDomain::takeStackshot(bool restart
)
11696 #pragma unused(restart)
11699 IOPMrootDomain::deleteStackshot()
11703 IOPMrootDomain::sleepWakeDebugMemAlloc()
11707 IOPMrootDomain::saveFailureData2File()
11712 IOPMrootDomain::sleepWakeDebugEnableWdog()
11717 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
11723 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name
, char *buf
, int len
)