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 19
1353 #define kRootDomainNoPublishSettingsCount 3
1356 IOPMrootDomain::start( IOService
* nub
)
1358 OSIterator
*psIterator
;
1359 OSDictionary
*tmpDict
;
1360 IORootParent
* patriarch
;
1365 gIOPMSettingAutoWakeCalendarKey
= OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey
);
1366 gIOPMSettingAutoWakeSecondsKey
= OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey
);
1367 gIOPMSettingAutoPowerCalendarKey
= OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey
);
1368 gIOPMSettingAutoPowerSecondsKey
= OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey
);
1369 gIOPMSettingDebugWakeRelativeKey
= OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey
);
1370 gIOPMSettingDebugPowerRelativeKey
= OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey
);
1371 gIOPMSettingMaintenanceWakeCalendarKey
= OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey
);
1372 gIOPMSettingSleepServiceWakeCalendarKey
= OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey
);
1373 gIOPMSettingSilentRunningKey
= OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey
);
1374 gIOPMUserTriggeredFullWakeKey
= OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey
);
1375 gIOPMUserIsActiveKey
= OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey
);
1377 gIOPMStatsResponseTimedOut
= OSSymbol::withCString(kIOPMStatsResponseTimedOut
);
1378 gIOPMStatsResponseCancel
= OSSymbol::withCString(kIOPMStatsResponseCancel
);
1379 gIOPMStatsResponseSlow
= OSSymbol::withCString(kIOPMStatsResponseSlow
);
1380 gIOPMStatsResponsePrompt
= OSSymbol::withCString(kIOPMStatsResponsePrompt
);
1381 gIOPMStatsDriverPSChangeSlow
= OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow
);
1383 sleepSupportedPEFunction
= OSSymbol::withCString("IOPMSetSleepSupported");
1384 sleepMessagePEFunction
= OSSymbol::withCString("IOPMSystemSleepMessage");
1386 const OSSymbol
*settingsArr
[kRootDomainSettingsCount
] =
1388 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey
),
1389 gIOPMSettingAutoWakeSecondsKey
,
1390 gIOPMSettingAutoPowerSecondsKey
,
1391 gIOPMSettingAutoWakeCalendarKey
,
1392 gIOPMSettingAutoPowerCalendarKey
,
1393 gIOPMSettingDebugWakeRelativeKey
,
1394 gIOPMSettingDebugPowerRelativeKey
,
1395 OSSymbol::withCString(kIOPMSettingWakeOnRingKey
),
1396 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
),
1397 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey
),
1398 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey
),
1399 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey
),
1400 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey
),
1401 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey
),
1402 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey
),
1403 OSSymbol::withCString(kIOPMStateConsoleShutdown
),
1404 OSSymbol::withCString(kIOPMSettingProModeControl
),
1405 OSSymbol::withCString(kIOPMSettingProModeDefer
),
1406 gIOPMSettingSilentRunningKey
,
1409 const OSSymbol
*noPublishSettingsArr
[kRootDomainNoPublishSettingsCount
] =
1411 OSSymbol::withCString(kIOPMSettingProModeControl
),
1412 OSSymbol::withCString(kIOPMSettingProModeDefer
),
1413 gIOPMSettingSilentRunningKey
,
1416 PE_parse_boot_argn("darkwake", &gDarkWakeFlags
, sizeof(gDarkWakeFlags
));
1417 PE_parse_boot_argn("noidle", &gNoIdleFlag
, sizeof(gNoIdleFlag
));
1418 PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout
, sizeof(gSwdSleepTimeout
));
1419 PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout
, sizeof(gSwdWakeTimeout
));
1420 PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout
, sizeof(gSwdSleepWakeTimeout
));
1421 PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic
, sizeof(gHaltTimeMaxPanic
));
1422 PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog
, sizeof(gHaltTimeMaxLog
));
1424 queue_init(&aggressivesQueue
);
1425 aggressivesThreadCall
= thread_call_allocate(handleAggressivesFunction
, this);
1426 aggressivesData
= OSData::withCapacity(
1427 sizeof(AggressivesRecord
) * (kPMLastAggressivenessType
+ 4));
1429 featuresDictLock
= IOLockAlloc();
1430 settingsCtrlLock
= IOLockAlloc();
1431 wakeEventLock
= IOLockAlloc();
1432 gHaltLogLock
= IOLockAlloc();
1433 setPMRootDomain(this);
1435 extraSleepTimer
= thread_call_allocate(
1436 idleSleepTimerExpired
,
1437 (thread_call_param_t
) this);
1439 powerButtonDown
= thread_call_allocate(
1440 powerButtonDownCallout
,
1441 (thread_call_param_t
) this);
1443 powerButtonUp
= thread_call_allocate(
1444 powerButtonUpCallout
,
1445 (thread_call_param_t
) this);
1447 diskSyncCalloutEntry
= thread_call_allocate(
1449 (thread_call_param_t
) this);
1450 updateConsoleUsersEntry
= thread_call_allocate(
1451 &updateConsoleUsersCallout
,
1452 (thread_call_param_t
) this);
1454 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
1455 fullWakeThreadCall
= thread_call_allocate(
1456 OSMemberFunctionCast(thread_call_func_t
, this,
1457 &IOPMrootDomain::fullWakeDelayedWork
),
1458 (thread_call_param_t
) this);
1461 setProperty(kIOSleepSupportedKey
, true);
1463 bzero(&gPMStats
, sizeof(gPMStats
));
1465 pmTracer
= PMTraceWorker::tracer(this);
1467 pmAssertions
= PMAssertionsTracker::pmAssertionsTracker(this);
1469 userDisabledAllSleep
= false;
1470 systemBooting
= true;
1471 idleSleepEnabled
= false;
1473 idleSleepTimerPending
= false;
1475 clamshellClosed
= false;
1476 clamshellExists
= false;
1477 clamshellDisabled
= true;
1478 acAdaptorConnected
= true;
1479 clamshellSleepDisabled
= false;
1480 gWakeReasonString
[0] = '\0';
1482 // Initialize to user active.
1483 // Will never transition to user inactive w/o wrangler.
1484 fullWakeReason
= kFullWakeReasonLocalUser
;
1485 userIsActive
= userWasActive
= true;
1486 clock_get_uptime(&gUserActiveAbsTime
);
1487 setProperty(gIOPMUserIsActiveKey
, kOSBooleanTrue
);
1489 // Set the default system capabilities at boot.
1490 _currentCapability
= kIOPMSystemCapabilityCPU
|
1491 kIOPMSystemCapabilityGraphics
|
1492 kIOPMSystemCapabilityAudio
|
1493 kIOPMSystemCapabilityNetwork
;
1495 _pendingCapability
= _currentCapability
;
1496 _desiredCapability
= _currentCapability
;
1497 _highestCapability
= _currentCapability
;
1498 setProperty(kIOPMSystemCapabilitiesKey
, _currentCapability
, 64);
1500 queuedSleepWakeUUIDString
= NULL
;
1501 initializeBootSessionUUID();
1502 pmStatsAppResponses
= OSArray::withCapacity(5);
1503 _statsNameKey
= OSSymbol::withCString(kIOPMStatsNameKey
);
1504 _statsPIDKey
= OSSymbol::withCString(kIOPMStatsPIDKey
);
1505 _statsTimeMSKey
= OSSymbol::withCString(kIOPMStatsTimeMSKey
);
1506 _statsResponseTypeKey
= OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey
);
1507 _statsMessageTypeKey
= OSSymbol::withCString(kIOPMStatsMessageTypeKey
);
1508 _statsPowerCapsKey
= OSSymbol::withCString(kIOPMStatsPowerCapabilityKey
);
1509 assertOnWakeSecs
= -1;// Invalid value to prevent updates
1511 pmStatsLock
= IOLockAlloc();
1512 idxPMCPUClamshell
= kCPUUnknownIndex
;
1513 idxPMCPULimitedPower
= kCPUUnknownIndex
;
1515 tmpDict
= OSDictionary::withCapacity(1);
1516 setProperty(kRootDomainSupportedFeatures
, tmpDict
);
1519 settingsCallbacks
= OSDictionary::withCapacity(1);
1521 // Create a list of the valid PM settings that we'll relay to
1522 // interested clients in setProperties() => setPMSetting()
1523 allowedPMSettings
= OSArray::withObjects(
1524 (const OSObject
**)settingsArr
,
1525 kRootDomainSettingsCount
,
1528 // List of PM settings that should not automatically publish itself
1529 // as a feature when registered by a listener.
1530 noPublishPMSettings
= OSArray::withObjects(
1531 (const OSObject
**)noPublishSettingsArr
,
1532 kRootDomainNoPublishSettingsCount
,
1535 fPMSettingsDict
= OSDictionary::withCapacity(5);
1536 preventIdleSleepList
= OSSet::withCapacity(8);
1537 preventSystemSleepList
= OSSet::withCapacity(2);
1539 PMinit(); // creates gIOPMWorkLoop
1540 gIOPMWorkLoop
= getIOPMWorkloop();
1542 // Create IOPMPowerStateQueue used to queue external power
1543 // events, and to handle those events on the PM work loop.
1544 pmPowerStateQueue
= IOPMPowerStateQueue::PMPowerStateQueue(
1545 this, OSMemberFunctionCast(IOEventSource::Action
, this,
1546 &IOPMrootDomain::dispatchPowerEvent
));
1547 gIOPMWorkLoop
->addEventSource(pmPowerStateQueue
);
1549 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
1551 _aotTimerES
= IOTimerEventSource::timerEventSource(this,
1552 OSMemberFunctionCast(IOTimerEventSource::Action
,
1553 this, &IOPMrootDomain::aotEvaluate
));
1554 gIOPMWorkLoop
->addEventSource(_aotTimerES
);
1555 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
1557 // create our power parent
1558 patriarch
= new IORootParent
;
1560 patriarch
->attach(this);
1561 patriarch
->start(this);
1562 patriarch
->addPowerChild(this);
1564 registerPowerDriver(this, ourPowerStates
, NUM_POWER_STATES
);
1565 changePowerStateToPriv(ON_STATE
);
1567 // install power change handler
1568 gSysPowerDownNotifier
= registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, NULL
);
1571 // Register for a notification when IODisplayWrangler is published
1572 if ((tmpDict
= serviceMatching("IODisplayWrangler"))) {
1573 _displayWranglerNotifier
= addMatchingNotification(
1574 gIOPublishNotification
, tmpDict
,
1575 (IOServiceMatchingNotificationHandler
) & displayWranglerMatchPublished
,
1581 #if defined(__i386__) || defined(__x86_64__)
1583 wranglerIdleSettings
= NULL
;
1584 OSNumber
* wranglerIdlePeriod
= NULL
;
1585 wranglerIdleSettings
= OSDictionary::withCapacity(1);
1586 wranglerIdlePeriod
= OSNumber::withNumber(kDefaultWranglerIdlePeriod
, 32);
1588 if (wranglerIdleSettings
&& wranglerIdlePeriod
) {
1589 wranglerIdleSettings
->setObject(kIORequestWranglerIdleKey
,
1590 wranglerIdlePeriod
);
1593 if (wranglerIdlePeriod
) {
1594 wranglerIdlePeriod
->release();
1598 const OSSymbol
*ucClassName
= OSSymbol::withCStringNoCopy("RootDomainUserClient");
1599 setProperty(gIOUserClientClassKey
, (OSObject
*) ucClassName
);
1600 ucClassName
->release();
1602 // IOBacklightDisplay can take a long time to load at boot, or it may
1603 // not load at all if you're booting with clamshell closed. We publish
1604 // 'DisplayDims' here redundantly to get it published early and at all.
1605 OSDictionary
* matching
;
1606 matching
= serviceMatching("IOPMPowerSource");
1607 psIterator
= getMatchingServices( matching
);
1609 matching
->release();
1611 if (psIterator
&& psIterator
->getNextObject()) {
1612 // There's at least one battery on the system, so we publish
1613 // 'DisplayDims' support for the LCD.
1614 publishFeature("DisplayDims");
1617 psIterator
->release();
1620 // read swd_panic boot-arg
1621 PE_parse_boot_argn("swd_panic", &gSwdPanic
, sizeof(gSwdPanic
));
1622 sysctl_register_oid(&sysctl__kern_sleeptime
);
1623 sysctl_register_oid(&sysctl__kern_waketime
);
1624 sysctl_register_oid(&sysctl__kern_willshutdown
);
1625 sysctl_register_oid(&sysctl__kern_iokittest
);
1626 sysctl_register_oid(&sysctl__debug_iokit
);
1627 sysctl_register_oid(&sysctl__hw_targettype
);
1629 #if !CONFIG_EMBEDDED
1630 sysctl_register_oid(&sysctl__kern_progressmeterenable
);
1631 sysctl_register_oid(&sysctl__kern_progressmeter
);
1632 sysctl_register_oid(&sysctl__kern_wakereason
);
1633 #endif /* !CONFIG_EMBEDDED */
1634 sysctl_register_oid(&sysctl__kern_consoleoptions
);
1635 sysctl_register_oid(&sysctl__kern_progressoptions
);
1637 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
1638 sysctl_register_oid(&sysctl__kern_aotmode
);
1639 sysctl_register_oid(&sysctl__kern_aotmodebits
);
1640 sysctl_register_oid(&sysctl__kern_aotmetrics
);
1641 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
1644 IOHibernateSystemInit(this);
1647 registerService(); // let clients find us
1652 //******************************************************************************
1655 // Receive a setProperty call
1656 // The "System Boot" property means the system is completely booted.
1657 //******************************************************************************
1660 IOPMrootDomain::setProperties( OSObject
* props_obj
)
1662 IOReturn return_value
= kIOReturnSuccess
;
1663 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, props_obj
);
1666 const OSSymbol
*key
;
1668 OSCollectionIterator
* iter
= NULL
;
1671 return kIOReturnBadArgument
;
1674 bool clientEntitled
= false;
1675 obj
= IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty
);
1676 clientEntitled
= (obj
== kOSBooleanTrue
);
1677 OSSafeReleaseNULL(obj
);
1679 if (!clientEntitled
) {
1680 const char * errorSuffix
= NULL
;
1682 // IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1683 // That API can set 6 possible keys that are checked below.
1684 if ((dict
->getCount() == 1) &&
1685 (dict
->getObject(gIOPMSettingAutoWakeSecondsKey
) ||
1686 dict
->getObject(gIOPMSettingAutoPowerSecondsKey
) ||
1687 dict
->getObject(gIOPMSettingAutoWakeCalendarKey
) ||
1688 dict
->getObject(gIOPMSettingAutoPowerCalendarKey
) ||
1689 dict
->getObject(gIOPMSettingDebugWakeRelativeKey
) ||
1690 dict
->getObject(gIOPMSettingDebugPowerRelativeKey
))) {
1691 return_value
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
1692 if (return_value
!= kIOReturnSuccess
) {
1693 errorSuffix
= "privileged";
1696 return_value
= kIOReturnNotPermitted
;
1697 errorSuffix
= "entitled";
1700 if (return_value
!= kIOReturnSuccess
) {
1701 OSString
* procName
= IOCopyLogNameForPID(proc_selfpid());
1702 DLOG("%s failed, process %s is not %s\n", __func__
,
1703 procName
? procName
->getCStringNoCopy() : "", errorSuffix
);
1704 OSSafeReleaseNULL(procName
);
1705 return return_value
;
1709 const OSSymbol
*publish_simulated_battery_string
= OSSymbol::withCString("SoftwareSimulatedBatteries");
1710 const OSSymbol
*boot_complete_string
= OSSymbol::withCString("System Boot Complete");
1711 const OSSymbol
*sys_shutdown_string
= OSSymbol::withCString("System Shutdown");
1712 const OSSymbol
*stall_halt_string
= OSSymbol::withCString("StallSystemAtHalt");
1713 const OSSymbol
*battery_warning_disabled_string
= OSSymbol::withCString("BatteryWarningsDisabled");
1714 const OSSymbol
*idle_seconds_string
= OSSymbol::withCString("System Idle Seconds");
1715 const OSSymbol
*sleepdisabled_string
= OSSymbol::withCString("SleepDisabled");
1716 const OSSymbol
*ondeck_sleepwake_uuid_string
= OSSymbol::withCString(kIOPMSleepWakeUUIDKey
);
1717 const OSSymbol
*loginwindow_progress_string
= OSSymbol::withCString(kIOPMLoginWindowProgressKey
);
1718 const OSSymbol
*coredisplay_progress_string
= OSSymbol::withCString(kIOPMCoreDisplayProgressKey
);
1719 const OSSymbol
*coregraphics_progress_string
= OSSymbol::withCString(kIOPMCoreGraphicsProgressKey
);
1721 const OSSymbol
*hibernatemode_string
= OSSymbol::withCString(kIOHibernateModeKey
);
1722 const OSSymbol
*hibernatefile_string
= OSSymbol::withCString(kIOHibernateFileKey
);
1723 const OSSymbol
*hibernatefilemin_string
= OSSymbol::withCString(kIOHibernateFileMinSizeKey
);
1724 const OSSymbol
*hibernatefilemax_string
= OSSymbol::withCString(kIOHibernateFileMaxSizeKey
);
1725 const OSSymbol
*hibernatefreeratio_string
= OSSymbol::withCString(kIOHibernateFreeRatioKey
);
1726 const OSSymbol
*hibernatefreetime_string
= OSSymbol::withCString(kIOHibernateFreeTimeKey
);
1729 iter
= OSCollectionIterator::withCollection(dict
);
1731 return_value
= kIOReturnNoMemory
;
1735 while ((key
= (const OSSymbol
*) iter
->getNextObject()) &&
1736 (obj
= dict
->getObject(key
))) {
1737 if (key
->isEqualTo(publish_simulated_battery_string
)) {
1738 if (OSDynamicCast(OSBoolean
, obj
)) {
1739 publishResource(key
, kOSBooleanTrue
);
1741 } else if (key
->isEqualTo(idle_seconds_string
)) {
1742 if ((n
= OSDynamicCast(OSNumber
, obj
))) {
1743 setProperty(key
, n
);
1744 idleSeconds
= n
->unsigned32BitValue();
1746 } else if (key
->isEqualTo(boot_complete_string
)) {
1747 pmPowerStateQueue
->submitPowerEvent(kPowerEventSystemBootCompleted
);
1748 } else if (key
->isEqualTo(sys_shutdown_string
)) {
1749 if ((b
= OSDynamicCast(OSBoolean
, obj
))) {
1750 pmPowerStateQueue
->submitPowerEvent(kPowerEventSystemShutdown
, (void *) b
);
1752 } else if (key
->isEqualTo(battery_warning_disabled_string
)) {
1753 setProperty(key
, obj
);
1756 else if (key
->isEqualTo(hibernatemode_string
) ||
1757 key
->isEqualTo(hibernatefilemin_string
) ||
1758 key
->isEqualTo(hibernatefilemax_string
) ||
1759 key
->isEqualTo(hibernatefreeratio_string
) ||
1760 key
->isEqualTo(hibernatefreetime_string
)) {
1761 if ((n
= OSDynamicCast(OSNumber
, obj
))) {
1762 setProperty(key
, n
);
1764 } else if (key
->isEqualTo(hibernatefile_string
)) {
1765 OSString
* str
= OSDynamicCast(OSString
, obj
);
1767 setProperty(key
, str
);
1771 else if (key
->isEqualTo(sleepdisabled_string
)) {
1772 if ((b
= OSDynamicCast(OSBoolean
, obj
))) {
1773 setProperty(key
, b
);
1774 pmPowerStateQueue
->submitPowerEvent(kPowerEventUserDisabledSleep
, (void *) b
);
1776 } else if (key
->isEqualTo(ondeck_sleepwake_uuid_string
)) {
1778 pmPowerStateQueue
->submitPowerEvent(kPowerEventQueueSleepWakeUUID
, (void *)obj
);
1779 } else if (key
->isEqualTo(loginwindow_progress_string
)) {
1780 if (pmTracer
&& (n
= OSDynamicCast(OSNumber
, obj
))) {
1781 uint32_t data
= n
->unsigned32BitValue();
1782 pmTracer
->traceComponentWakeProgress(kIOPMLoginWindowProgress
, data
);
1783 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMLoginWindowProgress
, data
);
1785 } else if (key
->isEqualTo(coredisplay_progress_string
)) {
1786 if (pmTracer
&& (n
= OSDynamicCast(OSNumber
, obj
))) {
1787 uint32_t data
= n
->unsigned32BitValue();
1788 pmTracer
->traceComponentWakeProgress(kIOPMCoreDisplayProgress
, data
);
1789 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMCoreDisplayProgress
, data
);
1791 } else if (key
->isEqualTo(coregraphics_progress_string
)) {
1792 if (pmTracer
&& (n
= OSDynamicCast(OSNumber
, obj
))) {
1793 uint32_t data
= n
->unsigned32BitValue();
1794 pmTracer
->traceComponentWakeProgress(kIOPMCoreGraphicsProgress
, data
);
1795 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMCoreGraphicsProgress
, data
);
1797 } else if (key
->isEqualTo(kIOPMDeepSleepEnabledKey
) ||
1798 key
->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey
) ||
1799 key
->isEqualTo(kIOPMAutoPowerOffEnabledKey
) ||
1800 key
->isEqualTo(stall_halt_string
)) {
1801 if ((b
= OSDynamicCast(OSBoolean
, obj
))) {
1802 setProperty(key
, b
);
1804 } else if (key
->isEqualTo(kIOPMDeepSleepDelayKey
) ||
1805 key
->isEqualTo(kIOPMDeepSleepTimerKey
) ||
1806 key
->isEqualTo(kIOPMAutoPowerOffDelayKey
) ||
1807 key
->isEqualTo(kIOPMAutoPowerOffTimerKey
)) {
1808 if ((n
= OSDynamicCast(OSNumber
, obj
))) {
1809 setProperty(key
, n
);
1811 } else if (key
->isEqualTo(kIOPMUserWakeAlarmScheduledKey
)) {
1812 if (kOSBooleanTrue
== obj
) {
1813 OSBitOrAtomic(kIOPMAlarmBitCalendarWake
, &_userScheduledAlarm
);
1815 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake
, &_userScheduledAlarm
);
1817 DLOG("_userScheduledAlarm = 0x%x\n", (uint32_t) _userScheduledAlarm
);
1819 // Relay our allowed PM settings onto our registered PM clients
1820 else if ((allowedPMSettings
->getNextIndexOfObject(key
, 0) != (unsigned int) -1)) {
1821 return_value
= setPMSetting(key
, obj
);
1822 if (kIOReturnSuccess
!= return_value
) {
1826 if (gIOPMSettingDebugWakeRelativeKey
== key
) {
1827 if ((n
= OSDynamicCast(OSNumber
, obj
)) &&
1828 (_debugWakeSeconds
= n
->unsigned32BitValue())) {
1829 OSBitOrAtomic(kIOPMAlarmBitDebugWake
, &_scheduledAlarms
);
1831 _debugWakeSeconds
= 0;
1832 OSBitAndAtomic(~kIOPMAlarmBitDebugWake
, &_scheduledAlarms
);
1834 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms
);
1835 } else if (gIOPMSettingAutoWakeCalendarKey
== key
) {
1837 if ((data
= OSDynamicCast(OSData
, obj
)) &&
1838 (data
->getLength() == sizeof(IOPMCalendarStruct
))) {
1839 const IOPMCalendarStruct
* cs
=
1840 (const IOPMCalendarStruct
*) data
->getBytesNoCopy();
1841 IOLog("gIOPMSettingAutoWakeCalendarKey " YMDTF
"\n", YMDT(cs
));
1843 _scheduledAlarmUTC
= IOPMConvertCalendarToSeconds(cs
);
1844 OSBitOrAtomic(kIOPMAlarmBitCalendarWake
, &_scheduledAlarms
);
1846 _scheduledAlarmUTC
= 0;
1847 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake
, &_scheduledAlarms
);
1849 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms
);
1853 DLOG("setProperties(%s) not handled\n", key
->getCStringNoCopy());
1858 if (publish_simulated_battery_string
) {
1859 publish_simulated_battery_string
->release();
1861 if (boot_complete_string
) {
1862 boot_complete_string
->release();
1864 if (sys_shutdown_string
) {
1865 sys_shutdown_string
->release();
1867 if (stall_halt_string
) {
1868 stall_halt_string
->release();
1870 if (battery_warning_disabled_string
) {
1871 battery_warning_disabled_string
->release();
1873 if (idle_seconds_string
) {
1874 idle_seconds_string
->release();
1876 if (sleepdisabled_string
) {
1877 sleepdisabled_string
->release();
1879 if (ondeck_sleepwake_uuid_string
) {
1880 ondeck_sleepwake_uuid_string
->release();
1882 if (loginwindow_progress_string
) {
1883 loginwindow_progress_string
->release();
1885 if (coredisplay_progress_string
) {
1886 coredisplay_progress_string
->release();
1888 if (coregraphics_progress_string
) {
1889 coregraphics_progress_string
->release();
1892 if (hibernatemode_string
) {
1893 hibernatemode_string
->release();
1895 if (hibernatefile_string
) {
1896 hibernatefile_string
->release();
1898 if (hibernatefreeratio_string
) {
1899 hibernatefreeratio_string
->release();
1901 if (hibernatefreetime_string
) {
1902 hibernatefreetime_string
->release();
1908 return return_value
;
1912 // MARK: Aggressiveness
1914 //******************************************************************************
1915 // setAggressiveness
1917 // Override IOService::setAggressiveness()
1918 //******************************************************************************
1921 IOPMrootDomain::setAggressiveness(
1923 unsigned long value
)
1925 return setAggressiveness( type
, value
, 0 );
1929 * Private setAggressiveness() with an internal options argument.
1932 IOPMrootDomain::setAggressiveness(
1934 unsigned long value
,
1935 IOOptionBits options
)
1937 AggressivesRequest
* entry
;
1938 AggressivesRequest
* request
;
1941 if (type
== kPMMinutesToDim
|| type
== kPMMinutesToSleep
) {
1942 DLOG("setAggressiveness(%x) %s = %u\n",
1943 (uint32_t) options
, getAggressivenessTypeString((uint32_t) type
), (uint32_t) value
);
1945 DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
1946 (uint32_t) options
, getAggressivenessTypeString((uint32_t) type
), (uint32_t) value
);
1949 request
= IONew(AggressivesRequest
, 1);
1951 return kIOReturnNoMemory
;
1954 memset(request
, 0, sizeof(*request
));
1955 request
->options
= options
;
1956 request
->dataType
= kAggressivesRequestTypeRecord
;
1957 request
->data
.record
.type
= (uint32_t) type
;
1958 request
->data
.record
.value
= (uint32_t) value
;
1962 // Update disk quick spindown flag used by getAggressiveness().
1963 // Never merge requests with quick spindown flags set.
1965 if (options
& kAggressivesOptionQuickSpindownEnable
) {
1966 gAggressivesState
|= kAggressivesStateQuickSpindown
;
1967 } else if (options
& kAggressivesOptionQuickSpindownDisable
) {
1968 gAggressivesState
&= ~kAggressivesStateQuickSpindown
;
1970 // Coalesce requests with identical aggressives types.
1971 // Deal with callers that calls us too "aggressively".
1973 queue_iterate(&aggressivesQueue
, entry
, AggressivesRequest
*, chain
)
1975 if ((entry
->dataType
== kAggressivesRequestTypeRecord
) &&
1976 (entry
->data
.record
.type
== type
) &&
1977 ((entry
->options
& kAggressivesOptionQuickSpindownMask
) == 0)) {
1978 entry
->data
.record
.value
= value
;
1986 queue_enter(&aggressivesQueue
, request
, AggressivesRequest
*, chain
);
1989 AGGRESSIVES_UNLOCK();
1992 IODelete(request
, AggressivesRequest
, 1);
1995 if (options
& kAggressivesOptionSynchronous
) {
1996 handleAggressivesRequests(); // not truly synchronous
1998 thread_call_enter(aggressivesThreadCall
);
2001 return kIOReturnSuccess
;
2004 //******************************************************************************
2005 // getAggressiveness
2007 // Override IOService::setAggressiveness()
2008 // Fetch the aggressiveness factor with the given type.
2009 //******************************************************************************
2012 IOPMrootDomain::getAggressiveness(
2014 unsigned long * outLevel
)
2020 return kIOReturnBadArgument
;
2025 // Disk quick spindown in effect, report value = 1
2027 if ((gAggressivesState
& kAggressivesStateQuickSpindown
) &&
2028 (type
== kPMMinutesToSpinDown
)) {
2029 value
= kAggressivesMinValue
;
2033 // Consult the pending request queue.
2036 AggressivesRequest
* entry
;
2038 queue_iterate(&aggressivesQueue
, entry
, AggressivesRequest
*, chain
)
2040 if ((entry
->dataType
== kAggressivesRequestTypeRecord
) &&
2041 (entry
->data
.record
.type
== type
) &&
2042 ((entry
->options
& kAggressivesOptionQuickSpindownMask
) == 0)) {
2043 value
= entry
->data
.record
.value
;
2050 // Consult the backend records.
2052 if (!source
&& aggressivesData
) {
2053 AggressivesRecord
* record
;
2056 count
= aggressivesData
->getLength() / sizeof(AggressivesRecord
);
2057 record
= (AggressivesRecord
*) aggressivesData
->getBytesNoCopy();
2059 for (i
= 0; i
< count
; i
++, record
++) {
2060 if (record
->type
== type
) {
2061 value
= record
->value
;
2068 AGGRESSIVES_UNLOCK();
2071 *outLevel
= (unsigned long) value
;
2072 return kIOReturnSuccess
;
2074 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type
);
2075 *outLevel
= 0; // default return = 0, driver may not check for error
2076 return kIOReturnInvalid
;
2080 //******************************************************************************
2081 // joinAggressiveness
2083 // Request from IOService to join future aggressiveness broadcasts.
2084 //******************************************************************************
2087 IOPMrootDomain::joinAggressiveness(
2088 IOService
* service
)
2090 AggressivesRequest
* request
;
2092 if (!service
|| (service
== this)) {
2093 return kIOReturnBadArgument
;
2096 DEBUG_LOG("joinAggressiveness %s %p\n", service
->getName(), OBFUSCATE(service
));
2098 request
= IONew(AggressivesRequest
, 1);
2100 return kIOReturnNoMemory
;
2103 service
->retain(); // released by synchronizeAggressives()
2105 memset(request
, 0, sizeof(*request
));
2106 request
->dataType
= kAggressivesRequestTypeService
;
2107 request
->data
.service
= service
;
2110 queue_enter(&aggressivesQueue
, request
, AggressivesRequest
*, chain
);
2111 AGGRESSIVES_UNLOCK();
2113 thread_call_enter(aggressivesThreadCall
);
2115 return kIOReturnSuccess
;
2118 //******************************************************************************
2119 // handleAggressivesRequests
2121 // Backend thread processes all incoming aggressiveness requests in the queue.
2122 //******************************************************************************
2125 handleAggressivesFunction(
2126 thread_call_param_t param1
,
2127 thread_call_param_t param2
)
2130 ((IOPMrootDomain
*) param1
)->handleAggressivesRequests();
2135 IOPMrootDomain::handleAggressivesRequests( void )
2137 AggressivesRecord
* start
;
2138 AggressivesRecord
* record
;
2139 AggressivesRequest
* request
;
2140 queue_head_t joinedQueue
;
2144 bool pingSelf
= false;
2148 if ((gAggressivesState
& kAggressivesStateBusy
) || !aggressivesData
||
2149 queue_empty(&aggressivesQueue
)) {
2153 gAggressivesState
|= kAggressivesStateBusy
;
2154 count
= aggressivesData
->getLength() / sizeof(AggressivesRecord
);
2155 start
= (AggressivesRecord
*) aggressivesData
->getBytesNoCopy();
2159 queue_init(&joinedQueue
);
2162 // Remove request from the incoming queue in FIFO order.
2163 queue_remove_first(&aggressivesQueue
, request
, AggressivesRequest
*, chain
);
2164 switch (request
->dataType
) {
2165 case kAggressivesRequestTypeRecord
:
2166 // Update existing record if found.
2168 for (i
= 0, record
= start
; i
< count
; i
++, record
++) {
2169 if (record
->type
== request
->data
.record
.type
) {
2172 if (request
->options
& kAggressivesOptionQuickSpindownEnable
) {
2173 if ((record
->flags
& kAggressivesRecordFlagMinValue
) == 0) {
2175 record
->flags
|= (kAggressivesRecordFlagMinValue
|
2176 kAggressivesRecordFlagModified
);
2177 DLOG("disk spindown accelerated, was %u min\n",
2180 } else if (request
->options
& kAggressivesOptionQuickSpindownDisable
) {
2181 if (record
->flags
& kAggressivesRecordFlagMinValue
) {
2183 record
->flags
|= kAggressivesRecordFlagModified
;
2184 record
->flags
&= ~kAggressivesRecordFlagMinValue
;
2185 DLOG("disk spindown restored to %u min\n",
2188 } else if (record
->value
!= request
->data
.record
.value
) {
2189 record
->value
= request
->data
.record
.value
;
2190 if ((record
->flags
& kAggressivesRecordFlagMinValue
) == 0) {
2192 record
->flags
|= kAggressivesRecordFlagModified
;
2199 // No matching record, append a new record.
2201 ((request
->options
& kAggressivesOptionQuickSpindownDisable
) == 0)) {
2202 AggressivesRecord newRecord
;
2204 newRecord
.flags
= kAggressivesRecordFlagModified
;
2205 newRecord
.type
= request
->data
.record
.type
;
2206 newRecord
.value
= request
->data
.record
.value
;
2207 if (request
->options
& kAggressivesOptionQuickSpindownEnable
) {
2208 newRecord
.flags
|= kAggressivesRecordFlagMinValue
;
2209 DLOG("disk spindown accelerated\n");
2212 aggressivesData
->appendBytes(&newRecord
, sizeof(newRecord
));
2214 // OSData may have switched to another (larger) buffer.
2215 count
= aggressivesData
->getLength() / sizeof(AggressivesRecord
);
2216 start
= (AggressivesRecord
*) aggressivesData
->getBytesNoCopy();
2220 // Finished processing the request, release it.
2221 IODelete(request
, AggressivesRequest
, 1);
2224 case kAggressivesRequestTypeService
:
2225 // synchronizeAggressives() will free request.
2226 queue_enter(&joinedQueue
, request
, AggressivesRequest
*, chain
);
2230 panic("bad aggressives request type %x\n", request
->dataType
);
2233 } while (!queue_empty(&aggressivesQueue
));
2235 // Release the lock to perform work, with busy flag set.
2236 if (!queue_empty(&joinedQueue
) || broadcast
) {
2237 AGGRESSIVES_UNLOCK();
2238 if (!queue_empty(&joinedQueue
)) {
2239 synchronizeAggressives(&joinedQueue
, start
, count
);
2242 broadcastAggressives(start
, count
);
2247 // Remove the modified flag from all records.
2248 for (i
= 0, record
= start
; i
< count
; i
++, record
++) {
2249 if ((record
->flags
& kAggressivesRecordFlagModified
) &&
2250 ((record
->type
== kPMMinutesToDim
) ||
2251 (record
->type
== kPMMinutesToSleep
))) {
2255 record
->flags
&= ~kAggressivesRecordFlagModified
;
2258 // Check the incoming queue again since new entries may have been
2259 // added while lock was released above.
2260 } while (!queue_empty(&aggressivesQueue
));
2262 gAggressivesState
&= ~kAggressivesStateBusy
;
2265 AGGRESSIVES_UNLOCK();
2267 // Root domain is interested in system and display sleep slider changes.
2268 // Submit a power event to handle those changes on the PM work loop.
2270 if (pingSelf
&& pmPowerStateQueue
) {
2271 pmPowerStateQueue
->submitPowerEvent(
2272 kPowerEventPolicyStimulus
,
2273 (void *) kStimulusAggressivenessChanged
);
2277 //******************************************************************************
2278 // synchronizeAggressives
2280 // Push all known aggressiveness records to one or more IOService.
2281 //******************************************************************************
2284 IOPMrootDomain::synchronizeAggressives(
2285 queue_head_t
* joinedQueue
,
2286 const AggressivesRecord
* array
,
2289 IOService
* service
;
2290 AggressivesRequest
* request
;
2291 const AggressivesRecord
* record
;
2292 IOPMDriverCallEntry callEntry
;
2296 while (!queue_empty(joinedQueue
)) {
2297 queue_remove_first(joinedQueue
, request
, AggressivesRequest
*, chain
);
2298 if (request
->dataType
== kAggressivesRequestTypeService
) {
2299 service
= request
->data
.service
;
2304 IODelete(request
, AggressivesRequest
, 1);
2308 if (service
->assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetAggressive
)) {
2309 for (i
= 0, record
= array
; i
< count
; i
++, record
++) {
2310 value
= record
->value
;
2311 if (record
->flags
& kAggressivesRecordFlagMinValue
) {
2312 value
= kAggressivesMinValue
;
2315 _LOG("synchronizeAggressives 0x%x = %u to %s\n",
2316 record
->type
, value
, service
->getName());
2317 service
->setAggressiveness(record
->type
, value
);
2319 service
->deassertPMDriverCall(&callEntry
);
2321 service
->release(); // retained by joinAggressiveness()
2326 //******************************************************************************
2327 // broadcastAggressives
2329 // Traverse PM tree and call setAggressiveness() for records that have changed.
2330 //******************************************************************************
2333 IOPMrootDomain::broadcastAggressives(
2334 const AggressivesRecord
* array
,
2337 IORegistryIterator
* iter
;
2338 IORegistryEntry
* entry
;
2339 IOPowerConnection
* connect
;
2340 IOService
* service
;
2341 const AggressivesRecord
* record
;
2342 IOPMDriverCallEntry callEntry
;
2346 iter
= IORegistryIterator::iterateOver(
2347 this, gIOPowerPlane
, kIORegistryIterateRecursively
);
2351 while ((entry
= iter
->getNextObject())) {
2352 connect
= OSDynamicCast(IOPowerConnection
, entry
);
2353 if (!connect
|| !connect
->getReadyFlag()) {
2357 if ((service
= OSDynamicCast(IOService
, connect
->copyChildEntry(gIOPowerPlane
)))) {
2358 if (service
->assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetAggressive
)) {
2359 for (i
= 0, record
= array
; i
< count
; i
++, record
++) {
2360 if (record
->flags
& kAggressivesRecordFlagModified
) {
2361 value
= record
->value
;
2362 if (record
->flags
& kAggressivesRecordFlagMinValue
) {
2363 value
= kAggressivesMinValue
;
2365 _LOG("broadcastAggressives %x = %u to %s\n",
2366 record
->type
, value
, service
->getName());
2367 service
->setAggressiveness(record
->type
, value
);
2370 service
->deassertPMDriverCall(&callEntry
);
2375 }while (!entry
&& !iter
->isValid());
2380 //*****************************************
2381 // stackshot on power button press
2382 // ***************************************
2384 powerButtonDownCallout(thread_call_param_t us
, thread_call_param_t
)
2386 /* Power button pressed during wake
2389 DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2390 ((IOPMrootDomain
*)us
)->takeStackshot(false);
2394 powerButtonUpCallout(thread_call_param_t us
, thread_call_param_t
)
2396 /* Power button released.
2397 * Delete any stackshot data
2399 DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2400 ((IOPMrootDomain
*)us
)->deleteStackshot();
2402 //*************************************************************************
2406 // MARK: System Sleep
2408 //******************************************************************************
2409 // startIdleSleepTimer
2411 //******************************************************************************
2414 IOPMrootDomain::startIdleSleepTimer( uint32_t inSeconds
)
2416 AbsoluteTime deadline
;
2420 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag
);
2424 clock_interval_to_deadline(inSeconds
, kSecondScale
, &deadline
);
2425 thread_call_enter_delayed(extraSleepTimer
, deadline
);
2426 idleSleepTimerPending
= true;
2428 thread_call_enter(extraSleepTimer
);
2430 DLOG("idle timer set for %u seconds\n", inSeconds
);
2433 //******************************************************************************
2434 // cancelIdleSleepTimer
2436 //******************************************************************************
2439 IOPMrootDomain::cancelIdleSleepTimer( void )
2442 if (idleSleepTimerPending
) {
2443 DLOG("idle timer cancelled\n");
2444 thread_call_cancel(extraSleepTimer
);
2445 idleSleepTimerPending
= false;
2447 if (!assertOnWakeSecs
&& gIOLastWakeAbsTime
) {
2449 clock_usec_t microsecs
;
2450 clock_get_uptime(&now
);
2451 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
2452 absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
);
2453 if (assertOnWakeReport
) {
2454 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
);
2455 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
);
2461 //******************************************************************************
2462 // idleSleepTimerExpired
2464 //******************************************************************************
2467 idleSleepTimerExpired(
2468 thread_call_param_t us
, thread_call_param_t
)
2470 ((IOPMrootDomain
*)us
)->handleSleepTimerExpiration();
2473 //******************************************************************************
2474 // handleSleepTimerExpiration
2476 // The time between the sleep idle timeout and the next longest one has elapsed.
2477 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2478 //******************************************************************************
2481 IOPMrootDomain::handleSleepTimerExpiration( void )
2483 if (!gIOPMWorkLoop
->inGate()) {
2484 gIOPMWorkLoop
->runAction(
2485 OSMemberFunctionCast(IOWorkLoop::Action
, this,
2486 &IOPMrootDomain::handleSleepTimerExpiration
),
2493 DLOG("sleep timer expired\n");
2496 idleSleepTimerPending
= false;
2498 clock_get_uptime(&time
);
2499 setQuickSpinDownTimeout();
2500 adjustPowerState(true);
2503 //******************************************************************************
2504 // getTimeToIdleSleep
2506 // Returns number of seconds left before going into idle sleep.
2507 // Caller has to make sure that idle sleep is allowed at the time of calling
2509 //******************************************************************************
2512 IOPMrootDomain::getTimeToIdleSleep( void )
2514 AbsoluteTime now
, lastActivityTime
;
2516 uint32_t minutesSinceUserInactive
= 0;
2517 uint32_t sleepDelay
= 0;
2519 if (!idleSleepEnabled
) {
2523 if (userActivityTime
) {
2524 lastActivityTime
= userActivityTime
;
2526 lastActivityTime
= userBecameInactiveTime
;
2529 clock_get_uptime(&now
);
2530 if (CMP_ABSOLUTETIME(&now
, &lastActivityTime
) > 0) {
2531 SUB_ABSOLUTETIME(&now
, &lastActivityTime
);
2532 absolutetime_to_nanoseconds(now
, &nanos
);
2533 minutesSinceUserInactive
= nanos
/ (60000000000ULL);
2535 if (minutesSinceUserInactive
>= sleepSlider
) {
2538 sleepDelay
= sleepSlider
- minutesSinceUserInactive
;
2541 sleepDelay
= sleepSlider
;
2544 DLOG("user inactive %u min, time to idle sleep %u min\n",
2545 minutesSinceUserInactive
, sleepDelay
);
2547 return sleepDelay
* 60;
2550 //******************************************************************************
2551 // setQuickSpinDownTimeout
2553 //******************************************************************************
2556 IOPMrootDomain::setQuickSpinDownTimeout( void )
2560 kPMMinutesToSpinDown
, 0, kAggressivesOptionQuickSpindownEnable
);
2563 //******************************************************************************
2564 // restoreUserSpinDownTimeout
2566 //******************************************************************************
2569 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2573 kPMMinutesToSpinDown
, 0, kAggressivesOptionQuickSpindownDisable
);
2576 //******************************************************************************
2579 //******************************************************************************
2583 IOPMrootDomain::sleepSystem( void )
2585 return sleepSystemOptions(NULL
);
2590 IOPMrootDomain::sleepSystemOptions( OSDictionary
*options
)
2592 OSObject
*obj
= NULL
;
2593 OSString
*reason
= NULL
;
2594 /* sleepSystem is a public function, and may be called by any kernel driver.
2595 * And that's bad - drivers should sleep the system by calling
2596 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2598 * Note that user space app calls to IOPMSleepSystem() will also travel
2599 * this code path and thus be correctly identified as software sleeps.
2602 if (options
&& options
->getObject("OSSwitch")) {
2603 // Log specific sleep cause for OS Switch hibernation
2604 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate
);
2607 if (options
&& (obj
= options
->getObject("Sleep Reason"))) {
2608 reason
= OSDynamicCast(OSString
, obj
);
2609 if (reason
&& reason
->isEqualTo(kIOPMDarkWakeThermalEmergencyKey
)) {
2610 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency
);
2614 return privateSleepSystem( kIOPMSleepReasonSoftware
);
2619 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason
)
2621 /* Called from both gated and non-gated context */
2623 if (!checkSystemSleepEnabled() || !pmPowerStateQueue
) {
2624 return kIOReturnNotPermitted
;
2627 pmPowerStateQueue
->submitPowerEvent(
2628 kPowerEventPolicyStimulus
,
2629 (void *) kStimulusDemandSystemSleep
,
2632 return kIOReturnSuccess
;
2635 //******************************************************************************
2638 // This overrides powerChangeDone in IOService.
2639 //******************************************************************************
2641 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState
)
2643 #if !__i386__ && !__x86_64__
2644 uint64_t timeSinceReset
= 0;
2647 unsigned long newState
;
2649 clock_usec_t microsecs
;
2650 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
2651 clock_sec_t adjWakeTime
;
2652 IOPMCalendarStruct nowCalendar
;
2653 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
2656 newState
= getPowerState();
2657 DLOG("PowerChangeDone: %s->%s\n",
2658 getPowerStateString((uint32_t) previousPowerState
), getPowerStateString((uint32_t) getPowerState()));
2660 if (previousPowerState
== newState
) {
2664 notifierThread
= current_thread();
2665 switch (getPowerState()) {
2667 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
2668 if (kPMCalendarTypeInvalid
!= _aotWakeTimeCalendar
.selector
) {
2671 PEGetUTCTimeOfDay(&secs
, µsecs
);
2674 if ((kIOPMAOTModeRespectTimers
& _aotMode
) && (_scheduledAlarmUTC
< _aotWakeTimeUTC
)) {
2675 IOLog("use _scheduledAlarmUTC\n");
2676 adjWakeTime
= _scheduledAlarmUTC
;
2677 } else if (_aotExit
|| (kIOPMWakeEventAOTExitFlags
& _aotPendingFlags
)) {
2678 IOLog("accelerate _aotWakeTime for exit\n");
2680 } else if (kIOPMDriverAssertionLevelOn
== getPMAssertionLevel(kIOPMDriverAssertionCPUBit
)) {
2681 IOLog("accelerate _aotWakeTime for assertion\n");
2685 IOPMConvertSecondsToCalendar(adjWakeTime
, &_aotWakeTimeCalendar
);
2688 IOPMConvertSecondsToCalendar(secs
, &nowCalendar
);
2689 IOLog("aotSleep at " YMDTF
" sched: " YMDTF
"\n", YMDT(&nowCalendar
), YMDT(&_aotWakeTimeCalendar
));
2691 IOReturn __unused ret
= setMaintenanceWakeCalendar(&_aotWakeTimeCalendar
);
2692 assert(kIOReturnSuccess
== ret
);
2694 if (_aotLastWakeTime
) {
2695 _aotMetrics
->totalTime
+= mach_absolute_time() - _aotLastWakeTime
;
2696 if (_aotMetrics
->sleepCount
&& (_aotMetrics
->sleepCount
<= kIOPMAOTMetricsKernelWakeCountMax
)) {
2697 strlcpy(&_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
- 1][0],
2699 sizeof(_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
]));
2702 _aotPendingFlags
&= ~kIOPMWakeEventAOTPerCycleFlags
;
2703 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
2704 acceptSystemWakeEvents(true);
2706 // re-enable this timer for next sleep
2707 cancelIdleSleepTimer();
2709 clock_get_calendar_absolute_and_microtime(&secs
, µsecs
, &now
);
2711 gIOLastSleepTime
.tv_sec
= secs
;
2712 gIOLastSleepTime
.tv_usec
= microsecs
;
2713 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
2714 if (!_aotLastWakeTime
) {
2715 gIOLastUserSleepTime
= gIOLastSleepTime
;
2718 gIOLastUserSleepTime
= gIOLastSleepTime
;
2719 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
2721 gIOLastWakeTime
.tv_sec
= 0;
2722 gIOLastWakeTime
.tv_usec
= 0;
2723 gIOLastSleepAbsTime
= now
;
2725 if (wake2DarkwakeDelay
&& sleepDelaysReport
) {
2726 clock_sec_t wake2DarkwakeSecs
, darkwake2SleepSecs
;
2727 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2729 SUB_ABSOLUTETIME(&now
, &ts_sleepStart
);
2730 absolutetime_to_microtime(now
, &darkwake2SleepSecs
, µsecs
);
2731 absolutetime_to_microtime(wake2DarkwakeDelay
, &wake2DarkwakeSecs
, µsecs
);
2732 HISTREPORT_TALLYVALUE(sleepDelaysReport
,
2733 (int64_t)(wake2DarkwakeSecs
+ darkwake2SleepSecs
));
2735 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs
, (unsigned long)darkwake2SleepSecs
);
2736 wake2DarkwakeDelay
= 0;
2739 LOG("System %sSleep\n", gIOHibernateState
? "Safe" : "");
2741 IOHibernateSystemHasSlept();
2743 evaluateSystemSleepPolicyFinal();
2745 LOG("System Sleep\n");
2747 if (thermalWarningState
) {
2748 const OSSymbol
*event
= OSSymbol::withCString(kIOPMThermalLevelWarningKey
);
2750 systemPowerEventOccurred(event
, kIOPMThermalLevelUnknown
);
2754 assertOnWakeSecs
= 0;
2755 lowBatteryCondition
= false;
2757 #if DEVELOPMENT || DEBUG
2758 extern int g_should_log_clock_adjustments
;
2759 if (g_should_log_clock_adjustments
) {
2760 clock_sec_t secs
= 0;
2761 clock_usec_t microsecs
= 0;
2762 uint64_t now_b
= mach_absolute_time();
2766 PEGetUTCTimeOfDay(&secs
, µsecs
);
2768 uint64_t now_a
= mach_absolute_time();
2769 os_log(OS_LOG_DEFAULT
, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
2770 __func__
, (unsigned long)secs
, microsecs
, now_b
, now_a
);
2774 getPlatform()->sleepKernel();
2776 // The CPU(s) are off at this point,
2777 // Code will resume execution here upon wake.
2779 clock_get_uptime(&gIOLastWakeAbsTime
);
2780 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime
);
2781 _highestCapability
= 0;
2784 IOHibernateSystemWake();
2787 // sleep transition complete
2788 gSleepOrShutdownPending
= 0;
2790 // trip the reset of the calendar clock
2791 clock_wakeup_calendar();
2792 clock_get_calendar_microtime(&secs
, µsecs
);
2793 gIOLastWakeTime
.tv_sec
= secs
;
2794 gIOLastWakeTime
.tv_usec
= microsecs
;
2796 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
2798 if (_aotWakeTimeCalendar
.selector
!= kPMCalendarTypeInvalid
) {
2799 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeInvalid
;
2802 PEGetUTCTimeOfDay(&secs
, µsecs
);
2803 IOPMConvertSecondsToCalendar(secs
, &nowCalendar
);
2804 IOLog("aotWake at " YMDTF
" sched: " YMDTF
"\n", YMDT(&nowCalendar
), YMDT(&_aotWakeTimeCalendar
));
2805 _aotMetrics
->sleepCount
++;
2806 _aotLastWakeTime
= gIOLastWakeAbsTime
;
2807 if (_aotMetrics
->sleepCount
<= kIOPMAOTMetricsKernelWakeCountMax
) {
2808 _aotMetrics
->kernelSleepTime
[_aotMetrics
->sleepCount
- 1]
2809 = (((uint64_t) gIOLastSleepTime
.tv_sec
) << 10) + (gIOLastSleepTime
.tv_usec
/ 1000);
2810 _aotMetrics
->kernelWakeTime
[_aotMetrics
->sleepCount
- 1]
2811 = (((uint64_t) gIOLastWakeTime
.tv_sec
) << 10) + (gIOLastWakeTime
.tv_usec
/ 1000);
2815 if (_aotWakeTimeUTC
<= secs
) {
2816 _aotTestTime
= _aotTestTime
+ _aotTestInterval
;
2818 setWakeTime(_aotTestTime
);
2821 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
2824 LOG("System %sWake\n", gIOHibernateState
? "SafeSleep " : "");
2827 lastSleepReason
= 0;
2829 _lastDebugWakeSeconds
= _debugWakeSeconds
;
2830 _debugWakeSeconds
= 0;
2831 _scheduledAlarms
= 0;
2833 #if defined(__i386__) || defined(__x86_64__)
2834 kdebugTrace(kPMLogSystemWake
, 0, 0, 0);
2835 wranglerTickled
= false;
2836 graphicsSuppressed
= false;
2837 darkWakePostTickle
= false;
2838 darkWakeHibernateError
= false;
2839 darkWakeToSleepASAP
= true;
2840 logGraphicsClamp
= true;
2841 sleepTimerMaintenance
= false;
2842 sleepToStandby
= false;
2843 wranglerTickleLatched
= false;
2844 userWasActive
= false;
2845 isRTCAlarmWake
= false;
2846 fullWakeReason
= kFullWakeReasonNone
;
2848 OSString
* wakeType
= OSDynamicCast(
2849 OSString
, getProperty(kIOPMRootDomainWakeTypeKey
));
2850 OSString
* wakeReason
= OSDynamicCast(
2851 OSString
, getProperty(kIOPMRootDomainWakeReasonKey
));
2853 if (wakeReason
&& (wakeReason
->getLength() >= 2) &&
2854 gWakeReasonString
[0] == '\0') {
2855 // Until the platform driver can claim its wake reasons
2856 strlcat(gWakeReasonString
, wakeReason
->getCStringNoCopy(),
2857 sizeof(gWakeReasonString
));
2860 if (wakeType
&& wakeType
->isEqualTo(kIOPMrootDomainWakeTypeLowBattery
)) {
2861 lowBatteryCondition
= true;
2862 darkWakeMaintenance
= true;
2863 } else if ((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) != 0) {
2865 OSNumber
* hibOptions
= OSDynamicCast(
2866 OSNumber
, getProperty(kIOHibernateOptionsKey
));
2867 if (hibernateAborted
|| ((hibOptions
&&
2868 !(hibOptions
->unsigned32BitValue() & kIOHibernateOptionDarkWake
)))) {
2869 // Hibernate aborted, or EFI brought up graphics
2870 wranglerTickled
= true;
2871 if (hibernateAborted
) {
2872 DLOG("Hibernation aborted\n");
2874 DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions
->unsigned32BitValue());
2879 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeUser
) ||
2880 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeAlarm
))) {
2881 // User wake or RTC alarm
2882 wranglerTickled
= true;
2883 if (wakeType
->isEqualTo(kIOPMRootDomainWakeTypeAlarm
)) {
2884 isRTCAlarmWake
= true;
2886 } else if (wakeType
&&
2887 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer
)) {
2888 // SMC standby timer trumps SleepX
2889 darkWakeMaintenance
= true;
2890 sleepTimerMaintenance
= true;
2891 } else if ((_lastDebugWakeSeconds
!= 0) &&
2892 ((gDarkWakeFlags
& kDarkWakeFlagAlarmIsDark
) == 0)) {
2893 // SleepX before maintenance
2894 wranglerTickled
= true;
2895 } else if (wakeType
&&
2896 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeMaintenance
)) {
2897 darkWakeMaintenance
= true;
2898 } else if (wakeType
&&
2899 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepService
)) {
2900 darkWakeMaintenance
= true;
2901 darkWakeSleepService
= true;
2903 if (kIOHibernateStateWakingFromHibernate
== gIOHibernateState
) {
2904 sleepToStandby
= true;
2907 } else if (wakeType
&&
2908 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeHibernateError
)) {
2909 darkWakeMaintenance
= true;
2910 darkWakeHibernateError
= true;
2912 // Unidentified wake source, resume to full wake if debug
2913 // alarm is pending.
2915 if (_lastDebugWakeSeconds
&&
2916 (!wakeReason
|| wakeReason
->isEqualTo(""))) {
2917 wranglerTickled
= true;
2922 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer
)) {
2923 darkWakeMaintenance
= true;
2924 sleepTimerMaintenance
= true;
2925 } else if (hibernateAborted
|| !wakeType
||
2926 !wakeType
->isEqualTo(kIOPMRootDomainWakeTypeMaintenance
) ||
2927 !wakeReason
|| !wakeReason
->isEqualTo("RTC")) {
2928 // Post a HID tickle immediately - except for RTC maintenance wake.
2929 wranglerTickled
= true;
2931 darkWakeMaintenance
= true;
2935 if (wranglerTickled
) {
2936 darkWakeToSleepASAP
= false;
2937 fullWakeReason
= kFullWakeReasonLocalUser
;
2939 } else if (displayPowerOnRequested
&& checkSystemCanSustainFullWake()) {
2940 handleDisplayPowerOn();
2941 } else if (!darkWakeMaintenance
) {
2942 // Early/late tickle for non-maintenance wake.
2943 if (((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) ==
2944 kDarkWakeFlagHIDTickleEarly
) ||
2945 ((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) ==
2946 kDarkWakeFlagHIDTickleLate
)) {
2947 darkWakePostTickle
= true;
2950 #else /* !__i386__ && !__x86_64__ */
2951 timeSinceReset
= ml_get_time_since_reset();
2953 kdebugTrace(kPMLogSystemWake
, 0, timeSinceReset
>> 32, timeSinceReset
);
2954 // stay awake for at least 30 seconds
2955 wranglerTickled
= true;
2956 fullWakeReason
= kFullWakeReasonLocalUser
;
2957 startIdleSleepTimer(30);
2961 thread_call_enter(updateConsoleUsersEntry
);
2963 changePowerStateToPriv(getRUN_STATE());
2966 #if !__i386__ && !__x86_64__
2970 DLOG("Force re-evaluating aggressiveness\n");
2971 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
2972 pmPowerStateQueue
->submitPowerEvent(
2973 kPowerEventPolicyStimulus
,
2974 (void *) kStimulusNoIdleSleepPreventers
);
2976 // After changing to ON_STATE, invalidate any previously queued
2977 // request to change to a state less than ON_STATE. This isn't
2978 // necessary for AOT_STATE or if the device has only one running
2979 // state since the changePowerStateToPriv() issued at the tail
2980 // end of SLEEP_STATE case should take care of that.
2981 if (getPowerState() == ON_STATE
) {
2982 changePowerStateToPriv(ON_STATE
);
2986 #endif /* !__i386__ && !__x86_64__ */
2988 notifierThread
= NULL
;
2991 //******************************************************************************
2992 // requestPowerDomainState
2994 // Extend implementation in IOService. Running on PM work loop thread.
2995 //******************************************************************************
2998 IOPMrootDomain::requestPowerDomainState(
2999 IOPMPowerFlags childDesire
,
3000 IOPowerConnection
* childConnection
,
3001 unsigned long specification
)
3003 // Idle and system sleep prevention flags affects driver desire.
3004 // Children desire are irrelevant so they are cleared.
3006 return super::requestPowerDomainState(0, childConnection
, specification
);
3010 //******************************************************************************
3011 // updatePreventIdleSleepList
3013 // Called by IOService on PM work loop.
3014 // Returns true if PM policy recognized the driver's desire to prevent idle
3015 // sleep and updated the list of idle sleep preventers. Returns false otherwise
3016 //******************************************************************************
3019 IOPMrootDomain::updatePreventIdleSleepList(
3020 IOService
* service
, bool addNotRemove
)
3022 unsigned int oldCount
;
3024 oldCount
= idleSleepPreventersCount();
3025 return updatePreventIdleSleepListInternal(service
, addNotRemove
, oldCount
);
3029 IOPMrootDomain::updatePreventIdleSleepListInternal(
3030 IOService
* service
, bool addNotRemove
, unsigned int oldCount
)
3032 unsigned int newCount
;
3036 #if defined(__i386__) || defined(__x86_64__)
3037 // Disregard disk I/O (besides the display wrangler) as a factor preventing
3038 // idle sleep, except in the case of legacy disk I/O
3039 if (service
&& (service
!= wrangler
) && (service
!= this)) {
3046 preventIdleSleepList
->setObject(service
);
3047 DLOG("prevent idle sleep list: %s+ (%u)\n",
3048 service
->getName(), preventIdleSleepList
->getCount());
3049 } else if (preventIdleSleepList
->member(service
)) {
3050 preventIdleSleepList
->removeObject(service
);
3051 DLOG("prevent idle sleep list: %s- (%u)\n",
3052 service
->getName(), preventIdleSleepList
->getCount());
3055 newCount
= idleSleepPreventersCount();
3057 if ((oldCount
== 0) && (newCount
!= 0)) {
3058 // Driver added to empty prevent list.
3059 // Update the driver desire to prevent idle sleep.
3060 // Driver desire does not prevent demand sleep.
3062 changePowerStateTo(getRUN_STATE());
3063 } else if ((oldCount
!= 0) && (newCount
== 0)) {
3064 // Last driver removed from prevent list.
3065 // Drop the driver clamp to allow idle sleep.
3067 changePowerStateTo(SLEEP_STATE
);
3068 evaluatePolicy( kStimulusNoIdleSleepPreventers
);
3070 messageClient(kIOPMMessageIdleSleepPreventers
, systemCapabilityNotifier
,
3071 &newCount
, sizeof(newCount
));
3073 #if defined(__i386__) || defined(__x86_64__)
3074 if (addNotRemove
&& (service
== wrangler
) && !checkSystemCanSustainFullWake()) {
3075 DLOG("Cannot cancel idle sleep\n");
3076 return false; // do not idle-cancel
3083 //******************************************************************************
3085 //******************************************************************************
3088 IOPMrootDomain::startSpinDump(uint32_t spindumpKind
)
3090 messageClients(kIOPMMessageLaunchBootSpinDump
, (void *)(uintptr_t)spindumpKind
);
3093 //******************************************************************************
3094 // preventSystemSleepListUpdate
3096 // Called by IOService on PM work loop.
3097 //******************************************************************************
3100 IOPMrootDomain::updatePreventSystemSleepList(
3101 IOService
* service
, bool addNotRemove
)
3103 unsigned int oldCount
, newCount
;
3106 if (this == service
) {
3110 oldCount
= preventSystemSleepList
->getCount();
3112 preventSystemSleepList
->setObject(service
);
3113 DLOG("prevent system sleep list: %s+ (%u)\n",
3114 service
->getName(), preventSystemSleepList
->getCount());
3115 if (!assertOnWakeSecs
&& gIOLastWakeAbsTime
) {
3117 clock_usec_t microsecs
;
3118 clock_get_uptime(&now
);
3119 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
3120 absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
);
3121 if (assertOnWakeReport
) {
3122 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
);
3123 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
);
3126 } else if (preventSystemSleepList
->member(service
)) {
3127 preventSystemSleepList
->removeObject(service
);
3128 DLOG("prevent system sleep list: %s- (%u)\n",
3129 service
->getName(), preventSystemSleepList
->getCount());
3131 if ((oldCount
!= 0) && (preventSystemSleepList
->getCount() == 0)) {
3132 // Lost all system sleep preventers.
3133 // Send stimulus if system sleep was blocked, and is in dark wake.
3134 evaluatePolicy( kStimulusDarkWakeEvaluate
);
3137 newCount
= preventSystemSleepList
->getCount();
3138 messageClient(kIOPMMessageSystemSleepPreventers
, systemCapabilityNotifier
,
3139 &newCount
, sizeof(newCount
));
3143 IOPMrootDomain::copySleepPreventersList(OSArray
**idleSleepList
, OSArray
**systemSleepList
)
3145 OSCollectionIterator
*iterator
= NULL
;
3146 OSObject
*object
= NULL
;
3147 OSArray
*array
= NULL
;
3149 if (!gIOPMWorkLoop
->inGate()) {
3150 gIOPMWorkLoop
->runAction(
3151 OSMemberFunctionCast(IOWorkLoop::Action
, this,
3152 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList
),
3153 this, (void *)idleSleepList
, (void *)systemSleepList
);
3157 if (idleSleepList
&& preventIdleSleepList
&& (preventIdleSleepList
->getCount() != 0)) {
3158 iterator
= OSCollectionIterator::withCollection(preventIdleSleepList
);
3159 array
= OSArray::withCapacity(5);
3161 while ((object
= iterator
->getNextObject())) {
3162 IOService
*service
= OSDynamicCast(IOService
, object
);
3164 array
->setObject(OSSymbol::withCString(service
->getName()));
3168 iterator
->release();
3169 *idleSleepList
= array
;
3172 if (systemSleepList
&& preventSystemSleepList
&& (preventSystemSleepList
->getCount() != 0)) {
3173 iterator
= OSCollectionIterator::withCollection(preventSystemSleepList
);
3174 array
= OSArray::withCapacity(5);
3176 while ((object
= iterator
->getNextObject())) {
3177 IOService
*service
= OSDynamicCast(IOService
, object
);
3179 array
->setObject(OSSymbol::withCString(service
->getName()));
3183 iterator
->release();
3184 *systemSleepList
= array
;
3189 IOPMrootDomain::copySleepPreventersListWithID(OSArray
**idleSleepList
, OSArray
**systemSleepList
)
3191 OSCollectionIterator
*iterator
= NULL
;
3192 OSObject
*object
= NULL
;
3193 OSArray
*array
= NULL
;
3195 if (!gIOPMWorkLoop
->inGate()) {
3196 gIOPMWorkLoop
->runAction(
3197 OSMemberFunctionCast(IOWorkLoop::Action
, this,
3198 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID
),
3199 this, (void *)idleSleepList
, (void *)systemSleepList
);
3203 if (idleSleepList
&& preventIdleSleepList
&& (preventIdleSleepList
->getCount() != 0)) {
3204 iterator
= OSCollectionIterator::withCollection(preventIdleSleepList
);
3205 array
= OSArray::withCapacity(5);
3207 while ((object
= iterator
->getNextObject())) {
3208 IOService
*service
= OSDynamicCast(IOService
, object
);
3210 OSDictionary
*dict
= OSDictionary::withCapacity(2);
3212 OSNumber
*id
= OSNumber::withNumber(service
->getRegistryEntryID(), 64);
3213 dict
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, id
);
3214 dict
->setObject(kIOPMDriverAssertionOwnerStringKey
, OSSymbol::withCString(service
->getName()));
3215 array
->setObject(dict
);
3222 iterator
->release();
3223 *idleSleepList
= array
;
3226 if (systemSleepList
&& preventSystemSleepList
&& (preventSystemSleepList
->getCount() != 0)) {
3227 iterator
= OSCollectionIterator::withCollection(preventSystemSleepList
);
3228 array
= OSArray::withCapacity(5);
3230 while ((object
= iterator
->getNextObject())) {
3231 IOService
*service
= OSDynamicCast(IOService
, object
);
3233 OSDictionary
*dict
= OSDictionary::withCapacity(2);
3235 OSNumber
*id
= OSNumber::withNumber(service
->getRegistryEntryID(), 64);
3236 dict
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, id
);
3237 dict
->setObject(kIOPMDriverAssertionOwnerStringKey
, OSSymbol::withCString(service
->getName()));
3238 array
->setObject(dict
);
3245 iterator
->release();
3246 *systemSleepList
= array
;
3250 //******************************************************************************
3253 // Override the superclass implementation to send a different message type.
3254 //******************************************************************************
3257 IOPMrootDomain::tellChangeDown( unsigned long stateNum
)
3259 DLOG("tellChangeDown %s->%s\n",
3260 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3262 if (SLEEP_STATE
== stateNum
) {
3263 // Legacy apps were already told in the full->dark transition
3264 if (!ignoreTellChangeDown
) {
3265 tracePoint( kIOPMTracePointSleepApplications
);
3267 tracePoint( kIOPMTracePointSleepPriorityClients
);
3271 if (!ignoreTellChangeDown
) {
3272 userActivityAtSleep
= userActivityCount
;
3273 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep
);
3275 if (SLEEP_STATE
== stateNum
) {
3276 hibernateAborted
= false;
3278 // Direct callout into OSKext so it can disable kext unloads
3279 // during sleep/wake to prevent deadlocks.
3280 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep
);
3282 IOService::updateConsoleUsers(NULL
, kIOMessageSystemWillSleep
);
3284 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3285 // But tellClientsWithResponse() must be called for both.
3286 ignoreTellChangeDown
= true;
3290 return super::tellClientsWithResponse( kIOMessageSystemWillSleep
);
3293 //******************************************************************************
3296 // Override the superclass implementation to send a different message type.
3297 // This must be idle sleep since we don't ask during any other power change.
3298 //******************************************************************************
3301 IOPMrootDomain::askChangeDown( unsigned long stateNum
)
3303 DLOG("askChangeDown %s->%s\n",
3304 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3306 // Don't log for dark wake entry
3307 if (kSystemTransitionSleep
== _systemTransitionType
) {
3308 tracePoint( kIOPMTracePointSleepApplications
);
3311 return super::tellClientsWithResponse( kIOMessageCanSystemSleep
);
3314 //******************************************************************************
3315 // askChangeDownDone
3317 // An opportunity for root domain to cancel the power transition,
3318 // possibily due to an assertion created by powerd in response to
3319 // kIOMessageCanSystemSleep.
3322 // full -> dark wake transition
3323 // 1. Notify apps and powerd with kIOMessageCanSystemSleep
3324 // 2. askChangeDownDone()
3325 // dark -> sleep transition
3326 // 1. Notify powerd with kIOMessageCanSystemSleep
3327 // 2. askChangeDownDone()
3330 // full -> dark wake transition
3331 // 1. Notify powerd with kIOMessageCanSystemSleep
3332 // 2. askChangeDownDone()
3333 // dark -> sleep transition
3334 // 1. Notify powerd with kIOMessageCanSystemSleep
3335 // 2. askChangeDownDone()
3336 //******************************************************************************
3339 IOPMrootDomain::askChangeDownDone(
3340 IOPMPowerChangeFlags
* inOutChangeFlags
, bool * cancel
)
3342 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3343 *inOutChangeFlags
, *cancel
,
3344 _systemTransitionType
,
3345 _currentCapability
, _pendingCapability
);
3347 if ((false == *cancel
) && (kSystemTransitionSleep
== _systemTransitionType
)) {
3348 // Dark->Sleep transition.
3349 // Check if there are any deny sleep assertions.
3350 // lastSleepReason already set by handleOurPowerChangeStart()
3352 if (!checkSystemCanSleep(lastSleepReason
)) {
3353 // Cancel dark wake to sleep transition.
3354 // Must re-scan assertions upon entering dark wake.
3357 DLOG("cancel dark->sleep\n");
3359 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
3360 if (_aotMode
&& (kPMCalendarTypeInvalid
!= _aotWakeTimeCalendar
.selector
)) {
3361 uint64_t now
= mach_continuous_time();
3362 if (((now
+ _aotWakePreWindow
) >= _aotWakeTimeContinuous
)
3363 && (now
< (_aotWakeTimeContinuous
+ _aotWakePostWindow
))) {
3365 IOLog("AOT wake window cancel: %qd, %qd\n", now
, _aotWakeTimeContinuous
);
3368 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
3372 //******************************************************************************
3373 // systemDidNotSleep
3375 // Work common to both canceled or aborted sleep.
3376 //******************************************************************************
3379 IOPMrootDomain::systemDidNotSleep( void )
3381 // reset console lock state
3382 thread_call_enter(updateConsoleUsersEntry
);
3385 if (idleSleepEnabled
) {
3386 // stay awake for at least idleSeconds
3387 startIdleSleepTimer(idleSeconds
);
3390 if (idleSleepEnabled
&& !userIsActive
) {
3391 // Manually start the idle sleep timer besides waiting for
3392 // the user to become inactive.
3393 startIdleSleepTimer( kIdleSleepRetryInterval
);
3397 preventTransitionToUserActive(false);
3398 IOService::setAdvisoryTickleEnable( true );
3400 // After idle revert and cancel, send a did-change message to powerd
3401 // to balance the previous will-change message. Kernel clients do not
3402 // need this since sleep cannot be canceled once they are notified.
3404 if (toldPowerdCapWillChange
&& systemCapabilityNotifier
&&
3405 (_pendingCapability
!= _currentCapability
) &&
3406 ((_systemMessageClientMask
& kSystemMessageClientPowerd
) != 0)) {
3407 // Differs from a real capability gain change where notifyRef != 0,
3408 // but it is zero here since no response is expected.
3410 IOPMSystemCapabilityChangeParameters params
;
3412 bzero(¶ms
, sizeof(params
));
3413 params
.fromCapabilities
= _pendingCapability
;
3414 params
.toCapabilities
= _currentCapability
;
3415 params
.changeFlags
= kIOPMSystemCapabilityDidChange
;
3417 DLOG("MESG cap %x->%x did change\n",
3418 params
.fromCapabilities
, params
.toCapabilities
);
3419 messageClient(kIOMessageSystemCapabilityChange
, systemCapabilityNotifier
,
3420 ¶ms
, sizeof(params
));
3424 //******************************************************************************
3427 // Notify registered applications and kernel clients that we are not dropping
3430 // We override the superclass implementation so we can send a different message
3431 // type to the client or application being notified.
3433 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3434 //******************************************************************************
3437 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum
)
3439 DLOG("tellNoChangeDown %s->%s\n",
3440 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3442 // Sleep canceled, clear the sleep trace point.
3443 tracePoint(kIOPMTracePointSystemUp
);
3445 systemDidNotSleep();
3446 return tellClients( kIOMessageSystemWillNotSleep
);
3449 //******************************************************************************
3452 // Notify registered applications and kernel clients that we are raising power.
3454 // We override the superclass implementation so we can send a different message
3455 // type to the client or application being notified.
3456 //******************************************************************************
3459 IOPMrootDomain::tellChangeUp( unsigned long stateNum
)
3461 DLOG("tellChangeUp %s->%s\n",
3462 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3464 ignoreTellChangeDown
= false;
3466 if (stateNum
== ON_STATE
) {
3467 // Direct callout into OSKext so it can disable kext unloads
3468 // during sleep/wake to prevent deadlocks.
3469 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn
);
3471 // Notify platform that sleep was cancelled or resumed.
3472 getPlatform()->callPlatformFunction(
3473 sleepMessagePEFunction
, false,
3474 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn
,
3477 if (getPowerState() == ON_STATE
) {
3478 // Sleep was cancelled by idle cancel or revert
3479 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
3480 // rdar://problem/50363791
3481 // If system is in dark wake and sleep is cancelled, do not
3482 // send SystemWillPowerOn/HasPoweredOn messages to kernel
3483 // priority clients. They haven't yet seen a SystemWillSleep
3484 // message before the cancellation. So make sure the kernel
3485 // client bit is cleared in _systemMessageClientMask before
3486 // invoking the tellClients() below. This bit may have been
3487 // set by handleOurPowerChangeStart() anticipating a successful
3488 // sleep and setting the filter mask ahead of time allows the
3489 // SystemWillSleep message to go through.
3490 _systemMessageClientMask
&= ~kSystemMessageClientKernel
;
3493 systemDidNotSleep();
3494 tellClients( kIOMessageSystemWillPowerOn
);
3497 tracePoint( kIOPMTracePointWakeApplications
);
3498 tellClients( kIOMessageSystemHasPoweredOn
);
3502 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3503 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3504 ((params)->fromCapabilities & (flag)) && \
3505 (((params)->toCapabilities & (flag)) == 0))
3507 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3508 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3509 ((params)->toCapabilities & (flag)) && \
3510 (((params)->fromCapabilities & (flag)) == 0))
3512 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3513 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3514 ((params)->fromCapabilities & (flag)) && \
3515 (((params)->toCapabilities & (flag)) == 0))
3517 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3518 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3519 ((params)->toCapabilities & (flag)) && \
3520 (((params)->fromCapabilities & (flag)) == 0))
3522 //******************************************************************************
3523 // sysPowerDownHandler
3525 // Perform a vfs sync before system sleep.
3526 //******************************************************************************
3529 IOPMrootDomain::sysPowerDownHandler(
3530 void * target
, void * refCon
,
3531 UInt32 messageType
, IOService
* service
,
3532 void * messageArgs
, vm_size_t argSize
)
3534 static UInt32 lastSystemMessageType
= 0;
3537 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType
));
3539 // rdar://problem/50363791
3540 // Sanity check to make sure the SystemWill/Has message types are
3541 // received in the expected order for all kernel priority clients.
3542 if (messageType
== kIOMessageSystemWillSleep
||
3543 messageType
== kIOMessageSystemWillPowerOn
||
3544 messageType
== kIOMessageSystemHasPoweredOn
) {
3545 switch (messageType
) {
3546 case kIOMessageSystemWillPowerOn
:
3547 assert(lastSystemMessageType
== kIOMessageSystemWillSleep
);
3549 case kIOMessageSystemHasPoweredOn
:
3550 assert(lastSystemMessageType
== kIOMessageSystemWillPowerOn
);
3554 lastSystemMessageType
= messageType
;
3558 return kIOReturnUnsupported
;
3561 if (messageType
== kIOMessageSystemCapabilityChange
) {
3562 IOPMSystemCapabilityChangeParameters
* params
=
3563 (IOPMSystemCapabilityChangeParameters
*) messageArgs
;
3565 // Interested applications have been notified of an impending power
3566 // change and have acked (when applicable).
3567 // This is our chance to save whatever state we can before powering
3569 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3572 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3573 params
->fromCapabilities
, params
->toCapabilities
,
3574 params
->changeFlags
);
3576 if (CAP_WILL_CHANGE_TO_OFF(params
, kIOPMSystemCapabilityCPU
)) {
3577 // We will ack within 20 seconds
3578 params
->maxWaitForReply
= 20 * 1000 * 1000;
3581 gRootDomain
->evaluateSystemSleepPolicyEarly();
3583 // add in time we could spend freeing pages
3584 if (gRootDomain
->hibernateMode
&& !gRootDomain
->hibernateDisabled
) {
3585 params
->maxWaitForReply
= kCapabilityClientMaxWait
;
3587 DLOG("sysPowerDownHandler max wait %d s\n",
3588 (int) (params
->maxWaitForReply
/ 1000 / 1000));
3591 // Notify platform that sleep has begun, after the early
3592 // sleep policy evaluation.
3593 getPlatform()->callPlatformFunction(
3594 sleepMessagePEFunction
, false,
3595 (void *)(uintptr_t) kIOMessageSystemWillSleep
,
3598 if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
)) {
3599 // Purposely delay the ack and hope that shutdown occurs quickly.
3600 // Another option is not to schedule the thread and wait for
3602 AbsoluteTime deadline
;
3603 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
3604 thread_call_enter1_delayed(
3605 gRootDomain
->diskSyncCalloutEntry
,
3606 (thread_call_param_t
)(uintptr_t) params
->notifyRef
,
3610 gRootDomain
->diskSyncCalloutEntry
,
3611 (thread_call_param_t
)(uintptr_t) params
->notifyRef
);
3615 else if (CAP_DID_CHANGE_TO_ON(params
, kIOPMSystemCapabilityCPU
)) {
3616 // We will ack within 110 seconds
3617 params
->maxWaitForReply
= 110 * 1000 * 1000;
3620 gRootDomain
->diskSyncCalloutEntry
,
3621 (thread_call_param_t
)(uintptr_t) params
->notifyRef
);
3624 ret
= kIOReturnSuccess
;
3630 //******************************************************************************
3631 // handleQueueSleepWakeUUID
3633 // Called from IOPMrootDomain when we're initiating a sleep,
3634 // or indirectly from PM configd when PM decides to clear the UUID.
3635 // PM clears the UUID several minutes after successful wake from sleep,
3636 // so that we might associate App spindumps with the immediately previous
3639 // @param obj has a retain on it. We're responsible for releasing that retain.
3640 //******************************************************************************
3643 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject
*obj
)
3645 OSString
*str
= NULL
;
3647 if (kOSBooleanFalse
== obj
) {
3648 handlePublishSleepWakeUUID(NULL
);
3649 } else if ((str
= OSDynamicCast(OSString
, obj
))) {
3650 // This branch caches the UUID for an upcoming sleep/wake
3651 if (queuedSleepWakeUUIDString
) {
3652 queuedSleepWakeUUIDString
->release();
3653 queuedSleepWakeUUIDString
= NULL
;
3655 queuedSleepWakeUUIDString
= str
;
3656 queuedSleepWakeUUIDString
->retain();
3658 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString
->getCStringNoCopy());
3666 //******************************************************************************
3667 // handlePublishSleepWakeUUID
3669 // Called from IOPMrootDomain when we're initiating a sleep,
3670 // or indirectly from PM configd when PM decides to clear the UUID.
3671 // PM clears the UUID several minutes after successful wake from sleep,
3672 // so that we might associate App spindumps with the immediately previous
3674 //******************************************************************************
3677 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish
)
3682 * Clear the current UUID
3684 if (gSleepWakeUUIDIsSet
) {
3685 DLOG("SleepWake UUID cleared\n");
3687 gSleepWakeUUIDIsSet
= false;
3689 removeProperty(kIOPMSleepWakeUUIDKey
);
3690 messageClients(kIOPMMessageSleepWakeUUIDChange
, kIOPMMessageSleepWakeUUIDCleared
);
3694 * Optionally, publish a new UUID
3696 if (queuedSleepWakeUUIDString
&& shouldPublish
) {
3697 OSString
*publishThisUUID
= NULL
;
3699 publishThisUUID
= queuedSleepWakeUUIDString
;
3700 publishThisUUID
->retain();
3702 if (publishThisUUID
) {
3703 setProperty(kIOPMSleepWakeUUIDKey
, publishThisUUID
);
3704 publishThisUUID
->release();
3707 gSleepWakeUUIDIsSet
= true;
3708 messageClients(kIOPMMessageSleepWakeUUIDChange
, kIOPMMessageSleepWakeUUIDSet
);
3710 queuedSleepWakeUUIDString
->release();
3711 queuedSleepWakeUUIDString
= NULL
;
3715 //******************************************************************************
3716 // IOPMGetSleepWakeUUIDKey
3718 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
3719 // To get the full key -- a C string -- the buffer must large enough for
3720 // the end-of-string character.
3721 // The key is expected to be an UUID string
3722 //******************************************************************************
3725 IOPMCopySleepWakeUUIDKey(char *buffer
, size_t buf_len
)
3727 if (!gSleepWakeUUIDIsSet
) {
3731 if (buffer
!= NULL
) {
3734 string
= (OSString
*)
3735 gRootDomain
->copyProperty(kIOPMSleepWakeUUIDKey
);
3737 if (string
== NULL
) {
3740 strlcpy(buffer
, string
->getCStringNoCopy(), buf_len
);
3749 //******************************************************************************
3750 // initializeBootSessionUUID
3752 // Initialize the boot session uuid at boot up and sets it into registry.
3753 //******************************************************************************
3756 IOPMrootDomain::initializeBootSessionUUID(void)
3759 uuid_string_t new_uuid_string
;
3761 uuid_generate(new_uuid
);
3762 uuid_unparse_upper(new_uuid
, new_uuid_string
);
3763 memcpy(bootsessionuuid_string
, new_uuid_string
, sizeof(uuid_string_t
));
3765 setProperty(kIOPMBootSessionUUIDKey
, new_uuid_string
);
3768 //******************************************************************************
3769 // changePowerStateTo & changePowerStateToPriv
3771 // Override of these methods for logging purposes.
3772 //******************************************************************************
3775 IOPMrootDomain::changePowerStateTo( unsigned long ordinal
)
3777 DLOG("changePowerStateTo(%u)\n", (uint32_t) ordinal
);
3779 if ((ordinal
!= ON_STATE
) && (ordinal
!= AOT_STATE
) && (ordinal
!= SLEEP_STATE
)) {
3780 return kIOReturnUnsupported
;
3783 return super::changePowerStateTo(ordinal
);
3787 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal
)
3789 DLOG("changePowerStateToPriv(%u)\n", (uint32_t) ordinal
);
3791 if ((ordinal
!= ON_STATE
) && (ordinal
!= AOT_STATE
) && (ordinal
!= SLEEP_STATE
)) {
3792 return kIOReturnUnsupported
;
3795 return super::changePowerStateToPriv(ordinal
);
3798 //******************************************************************************
3801 //******************************************************************************
3804 IOPMrootDomain::activitySinceSleep(void)
3806 return userActivityCount
!= userActivityAtSleep
;
3810 IOPMrootDomain::abortHibernation(void)
3812 bool ret
= activitySinceSleep();
3814 if (ret
&& !hibernateAborted
&& checkSystemCanSustainFullWake()) {
3815 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount
, userActivityAtSleep
);
3816 hibernateAborted
= true;
3822 hibernate_should_abort(void)
3825 return gRootDomain
->abortHibernation();
3831 //******************************************************************************
3832 // willNotifyPowerChildren
3834 // Called after all interested drivers have all acknowledged the power change,
3835 // but before any power children is informed. Dispatched though a thread call,
3836 // so it is safe to perform work that might block on a sleeping disk. PM state
3837 // machine (not thread) will block w/o timeout until this function returns.
3838 //******************************************************************************
3841 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState
)
3846 if (SLEEP_STATE
== newPowerState
) {
3847 notifierThread
= current_thread();
3848 if (!tasksSuspended
) {
3849 AbsoluteTime deadline
;
3850 tasksSuspended
= TRUE
;
3851 updateTasksSuspend();
3853 clock_interval_to_deadline(10, kSecondScale
, &deadline
);
3854 #if !CONFIG_EMBEDDED
3855 vm_pageout_wait(AbsoluteTime_to_scalar(&deadline
));
3856 #endif /* !CONFIG_EMBEDDED */
3859 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
3860 _aotReadyToFullWake
= false;
3862 if (_aotLingerTime
) {
3864 IOLog("aot linger no return\n");
3865 clock_absolutetime_interval_to_deadline(_aotLingerTime
, &deadline
);
3866 clock_delay_until(deadline
);
3871 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeInvalid
;
3873 bzero(_aotMetrics
, sizeof(IOPMAOTMetrics
));
3875 } else if (!_aotNow
&& !_debugWakeSeconds
) {
3878 _aotPendingFlags
= 0;
3879 _aotTasksSuspended
= true;
3880 _aotLastWakeTime
= 0;
3881 bzero(_aotMetrics
, sizeof(IOPMAOTMetrics
));
3882 if (kIOPMAOTModeCycle
& _aotMode
) {
3883 clock_interval_to_absolutetime_interval(60, kSecondScale
, &_aotTestInterval
);
3884 _aotTestTime
= mach_continuous_time() + _aotTestInterval
;
3885 setWakeTime(_aotTestTime
);
3887 uint32_t lingerSecs
;
3888 if (!PE_parse_boot_argn("aotlinger", &lingerSecs
, sizeof(lingerSecs
))) {
3891 clock_interval_to_absolutetime_interval(lingerSecs
, kSecondScale
, &_aotLingerTime
);
3892 clock_interval_to_absolutetime_interval(2000, kMillisecondScale
, &_aotWakePreWindow
);
3893 clock_interval_to_absolutetime_interval(1100, kMillisecondScale
, &_aotWakePostWindow
);
3895 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
3898 IOHibernateSystemSleep();
3899 IOHibernateIOKitSleep();
3901 if (gRootDomain
->activitySinceSleep()) {
3902 dict
= OSDictionary::withCapacity(1);
3903 secs
= OSNumber::withNumber(1, 32);
3906 dict
->setObject(gIOPMSettingDebugWakeRelativeKey
, secs
);
3907 gRootDomain
->setProperties(dict
);
3908 MSG("Reverting sleep with relative wake\n");
3918 notifierThread
= NULL
;
3922 //******************************************************************************
3923 // sleepOnClamshellClosed
3925 // contains the logic to determine if the system should sleep when the clamshell
3927 //******************************************************************************
3930 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
3932 if (!clamshellExists
) {
3936 DLOG("clamshell closed %d, disabled %d, desktopMode %d, ac %d sleepDisabled %d\n",
3937 clamshellClosed
, clamshellDisabled
, desktopMode
, acAdaptorConnected
, clamshellSleepDisabled
);
3939 return !clamshellDisabled
&& !(desktopMode
&& acAdaptorConnected
) && !clamshellSleepDisabled
;
3943 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
3945 // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
3946 // closed && battery
3947 if (!clamshellExists
) {
3951 DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d, desktopMode %d, ac %d sleepDisabled %d\n",
3952 clamshellClosed
, clamshellDisabled
, desktopMode
, acAdaptorConnected
, clamshellSleepDisabled
);
3954 return !acAdaptorConnected
&& !clamshellSleepDisabled
;
3958 IOPMrootDomain::sendClientClamshellNotification( void )
3960 /* Only broadcast clamshell alert if clamshell exists. */
3961 if (!clamshellExists
) {
3965 setProperty(kAppleClamshellStateKey
,
3966 clamshellClosed
? kOSBooleanTrue
: kOSBooleanFalse
);
3968 setProperty(kAppleClamshellCausesSleepKey
,
3969 shouldSleepOnClamshellClosed() ? kOSBooleanTrue
: kOSBooleanFalse
);
3971 /* Argument to message is a bitfiel of
3972 * ( kClamshellStateBit | kClamshellSleepBit )
3974 messageClients(kIOPMMessageClamshellStateChange
,
3975 (void *)(uintptr_t) ((clamshellClosed
? kClamshellStateBit
: 0)
3976 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit
: 0)));
3979 //******************************************************************************
3980 // getSleepSupported
3983 //******************************************************************************
3986 IOPMrootDomain::getSleepSupported( void )
3988 return platformSleepSupport
;
3991 //******************************************************************************
3992 // setSleepSupported
3995 //******************************************************************************
3998 IOPMrootDomain::setSleepSupported( IOOptionBits flags
)
4000 DLOG("setSleepSupported(%x)\n", (uint32_t) flags
);
4001 OSBitOrAtomic(flags
, &platformSleepSupport
);
4004 //******************************************************************************
4005 // setDisableClamShellSleep
4007 //******************************************************************************
4010 IOPMrootDomain::setDisableClamShellSleep( bool val
)
4012 if (gIOPMWorkLoop
->inGate() == false) {
4013 gIOPMWorkLoop
->runAction(
4014 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::setDisableClamShellSleep
),
4020 DLOG("setDisableClamShellSleep(%x)\n", (uint32_t) val
);
4021 if (clamshellSleepDisabled
!= val
) {
4022 clamshellSleepDisabled
= val
;
4023 // If clamshellSleepDisabled is reset to 0, reevaluate if
4024 // system need to go to sleep due to clamshell state
4025 if (!clamshellSleepDisabled
&& clamshellClosed
) {
4026 handlePowerNotification(kLocalEvalClamshellCommand
);
4032 //******************************************************************************
4036 //******************************************************************************
4039 IOPMrootDomain::wakeFromDoze( void )
4041 // Preserve symbol for familes (IOUSBFamily and IOGraphics)
4047 //******************************************************************************
4050 // Adds a new feature to the supported features dictionary
4051 //******************************************************************************
4054 IOPMrootDomain::publishFeature( const char * feature
)
4056 publishFeature(feature
, kRD_AllPowerSources
, NULL
);
4059 //******************************************************************************
4060 // publishFeature (with supported power source specified)
4062 // Adds a new feature to the supported features dictionary
4063 //******************************************************************************
4066 IOPMrootDomain::publishFeature(
4067 const char *feature
,
4068 uint32_t supportedWhere
,
4069 uint32_t *uniqueFeatureID
)
4071 static uint16_t next_feature_id
= 500;
4073 OSNumber
*new_feature_data
= NULL
;
4074 OSNumber
*existing_feature
= NULL
;
4075 OSArray
*existing_feature_arr
= NULL
;
4076 OSObject
*osObj
= NULL
;
4077 uint32_t feature_value
= 0;
4079 supportedWhere
&= kRD_AllPowerSources
; // mask off any craziness!
4081 if (!supportedWhere
) {
4082 // Feature isn't supported anywhere!
4086 if (next_feature_id
> 5000) {
4087 // Far, far too many features!
4091 if (featuresDictLock
) {
4092 IOLockLock(featuresDictLock
);
4095 OSDictionary
*features
=
4096 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
4098 // Create new features dict if necessary
4099 if (features
&& OSDynamicCast(OSDictionary
, features
)) {
4100 features
= OSDictionary::withDictionary(features
);
4102 features
= OSDictionary::withCapacity(1);
4105 // Create OSNumber to track new feature
4107 next_feature_id
+= 1;
4108 if (uniqueFeatureID
) {
4109 // We don't really mind if the calling kext didn't give us a place
4110 // to stash their unique id. Many kexts don't plan to unload, and thus
4111 // have no need to remove themselves later.
4112 *uniqueFeatureID
= next_feature_id
;
4115 feature_value
= (uint32_t)next_feature_id
;
4116 feature_value
<<= 16;
4117 feature_value
+= supportedWhere
;
4119 new_feature_data
= OSNumber::withNumber(
4120 (unsigned long long)feature_value
, 32);
4122 // Does features object already exist?
4123 if ((osObj
= features
->getObject(feature
))) {
4124 if ((existing_feature
= OSDynamicCast(OSNumber
, osObj
))) {
4125 // We need to create an OSArray to hold the now 2 elements.
4126 existing_feature_arr
= OSArray::withObjects(
4127 (const OSObject
**)&existing_feature
, 1, 2);
4128 } else if ((existing_feature_arr
= OSDynamicCast(OSArray
, osObj
))) {
4129 // Add object to existing array
4130 existing_feature_arr
= OSArray::withArray(
4131 existing_feature_arr
,
4132 existing_feature_arr
->getCount() + 1);
4135 if (existing_feature_arr
) {
4136 existing_feature_arr
->setObject(new_feature_data
);
4137 features
->setObject(feature
, existing_feature_arr
);
4138 existing_feature_arr
->release();
4139 existing_feature_arr
= NULL
;
4142 // The easy case: no previously existing features listed. We simply
4143 // set the OSNumber at key 'feature' and we're on our way.
4144 features
->setObject(feature
, new_feature_data
);
4147 new_feature_data
->release();
4149 setProperty(kRootDomainSupportedFeatures
, features
);
4151 features
->release();
4153 if (featuresDictLock
) {
4154 IOLockUnlock(featuresDictLock
);
4157 // Notify EnergySaver and all those in user space so they might
4158 // re-populate their feature specific UI
4159 if (pmPowerStateQueue
) {
4160 pmPowerStateQueue
->submitPowerEvent( kPowerEventFeatureChanged
);
4164 //******************************************************************************
4165 // removePublishedFeature
4167 // Removes previously published feature
4168 //******************************************************************************
4171 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID
)
4173 IOReturn ret
= kIOReturnError
;
4174 uint32_t feature_value
= 0;
4175 uint16_t feature_id
= 0;
4176 bool madeAChange
= false;
4178 OSSymbol
*dictKey
= NULL
;
4179 OSCollectionIterator
*dictIterator
= NULL
;
4180 OSArray
*arrayMember
= NULL
;
4181 OSNumber
*numberMember
= NULL
;
4182 OSObject
*osObj
= NULL
;
4183 OSNumber
*osNum
= NULL
;
4184 OSArray
*arrayMemberCopy
;
4186 if (kBadPMFeatureID
== removeFeatureID
) {
4187 return kIOReturnNotFound
;
4190 if (featuresDictLock
) {
4191 IOLockLock(featuresDictLock
);
4194 OSDictionary
*features
=
4195 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
4197 if (features
&& OSDynamicCast(OSDictionary
, features
)) {
4198 // Any modifications to the dictionary are made to the copy to prevent
4199 // races & crashes with userland clients. Dictionary updated
4200 // automically later.
4201 features
= OSDictionary::withDictionary(features
);
4204 ret
= kIOReturnNotFound
;
4208 // We iterate 'features' dictionary looking for an entry tagged
4209 // with 'removeFeatureID'. If found, we remove it from our tracking
4210 // structures and notify the OS via a general interest message.
4212 dictIterator
= OSCollectionIterator::withCollection(features
);
4213 if (!dictIterator
) {
4217 while ((dictKey
= OSDynamicCast(OSSymbol
, dictIterator
->getNextObject()))) {
4218 osObj
= features
->getObject(dictKey
);
4220 // Each Feature is either tracked by an OSNumber
4221 if (osObj
&& (numberMember
= OSDynamicCast(OSNumber
, osObj
))) {
4222 feature_value
= numberMember
->unsigned32BitValue();
4223 feature_id
= (uint16_t)(feature_value
>> 16);
4225 if (feature_id
== (uint16_t)removeFeatureID
) {
4227 features
->removeObject(dictKey
);
4232 // Or tracked by an OSArray of OSNumbers
4233 } else if (osObj
&& (arrayMember
= OSDynamicCast(OSArray
, osObj
))) {
4234 unsigned int arrayCount
= arrayMember
->getCount();
4236 for (unsigned int i
= 0; i
< arrayCount
; i
++) {
4237 osNum
= OSDynamicCast(OSNumber
, arrayMember
->getObject(i
));
4242 feature_value
= osNum
->unsigned32BitValue();
4243 feature_id
= (uint16_t)(feature_value
>> 16);
4245 if (feature_id
== (uint16_t)removeFeatureID
) {
4247 if (1 == arrayCount
) {
4248 // If the array only contains one element, remove
4250 features
->removeObject(dictKey
);
4252 // Otherwise remove the element from a copy of the array.
4253 arrayMemberCopy
= OSArray::withArray(arrayMember
);
4254 if (arrayMemberCopy
) {
4255 arrayMemberCopy
->removeObject(i
);
4256 features
->setObject(dictKey
, arrayMemberCopy
);
4257 arrayMemberCopy
->release();
4268 dictIterator
->release();
4271 ret
= kIOReturnSuccess
;
4273 setProperty(kRootDomainSupportedFeatures
, features
);
4275 // Notify EnergySaver and all those in user space so they might
4276 // re-populate their feature specific UI
4277 if (pmPowerStateQueue
) {
4278 pmPowerStateQueue
->submitPowerEvent( kPowerEventFeatureChanged
);
4281 ret
= kIOReturnNotFound
;
4286 features
->release();
4288 if (featuresDictLock
) {
4289 IOLockUnlock(featuresDictLock
);
4294 //******************************************************************************
4295 // publishPMSetting (private)
4297 // Should only be called by PMSettingObject to publish a PM Setting as a
4298 // supported feature.
4299 //******************************************************************************
4302 IOPMrootDomain::publishPMSetting(
4303 const OSSymbol
* feature
, uint32_t where
, uint32_t * featureID
)
4305 if (noPublishPMSettings
&&
4306 (noPublishPMSettings
->getNextIndexOfObject(feature
, 0) != (unsigned int)-1)) {
4307 // Setting found in noPublishPMSettings array
4308 *featureID
= kBadPMFeatureID
;
4313 feature
->getCStringNoCopy(), where
, featureID
);
4316 //******************************************************************************
4317 // setPMSetting (private)
4319 // Internal helper to relay PM settings changes from user space to individual
4320 // drivers. Should be called only by IOPMrootDomain::setProperties.
4321 //******************************************************************************
4324 IOPMrootDomain::setPMSetting(
4325 const OSSymbol
*type
,
4328 PMSettingCallEntry
*entries
= NULL
;
4329 OSArray
*chosen
= NULL
;
4330 const OSArray
*array
;
4331 PMSettingObject
*pmso
;
4332 thread_t thisThread
;
4333 int i
, j
, count
, capacity
;
4336 return kIOReturnBadArgument
;
4341 // Update settings dict so changes are visible from copyPMSetting().
4342 fPMSettingsDict
->setObject(type
, object
);
4344 // Prep all PMSetting objects with the given 'type' for callout.
4345 array
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(type
));
4346 if (!array
|| ((capacity
= array
->getCount()) == 0)) {
4350 // Array to retain PMSetting objects targeted for callout.
4351 chosen
= OSArray::withCapacity(capacity
);
4353 goto unlock_exit
; // error
4355 entries
= IONew(PMSettingCallEntry
, capacity
);
4357 goto unlock_exit
; // error
4359 memset(entries
, 0, sizeof(PMSettingCallEntry
) * capacity
);
4361 thisThread
= current_thread();
4363 for (i
= 0, j
= 0; i
< capacity
; i
++) {
4364 pmso
= (PMSettingObject
*) array
->getObject(i
);
4365 if (pmso
->disabled
) {
4368 entries
[j
].thread
= thisThread
;
4369 queue_enter(&pmso
->calloutQueue
, &entries
[j
], PMSettingCallEntry
*, link
);
4370 chosen
->setObject(pmso
);
4380 // Call each pmso in the chosen array.
4381 for (i
= 0; i
< count
; i
++) {
4382 pmso
= (PMSettingObject
*) chosen
->getObject(i
);
4383 pmso
->dispatchPMSetting(type
, object
);
4387 for (i
= 0; i
< count
; i
++) {
4388 pmso
= (PMSettingObject
*) chosen
->getObject(i
);
4389 queue_remove(&pmso
->calloutQueue
, &entries
[i
], PMSettingCallEntry
*, link
);
4390 if (pmso
->waitThread
) {
4391 PMSETTING_WAKEUP(pmso
);
4401 IODelete(entries
, PMSettingCallEntry
, capacity
);
4404 return kIOReturnSuccess
;
4407 //******************************************************************************
4408 // copyPMSetting (public)
4410 // Allows kexts to safely read setting values, without being subscribed to
4412 //******************************************************************************
4415 IOPMrootDomain::copyPMSetting(
4416 OSSymbol
*whichSetting
)
4418 OSObject
*obj
= NULL
;
4420 if (!whichSetting
) {
4425 obj
= fPMSettingsDict
->getObject(whichSetting
);
4434 //******************************************************************************
4435 // registerPMSettingController (public)
4437 // direct wrapper to registerPMSettingController with uint32_t power source arg
4438 //******************************************************************************
4441 IOPMrootDomain::registerPMSettingController(
4442 const OSSymbol
* settings
[],
4443 IOPMSettingControllerCallback func
,
4448 return registerPMSettingController(
4450 (kIOPMSupportedOnAC
| kIOPMSupportedOnBatt
| kIOPMSupportedOnUPS
),
4451 func
, target
, refcon
, handle
);
4454 //******************************************************************************
4455 // registerPMSettingController (public)
4457 // Kexts may register for notifications when a particular setting is changed.
4458 // A list of settings is available in IOPM.h.
4460 // * settings - An OSArray containing OSSymbols. Caller should populate this
4461 // array with a list of settings caller wants notifications from.
4462 // * func - A C function callback of the type IOPMSettingControllerCallback
4463 // * target - caller may provide an OSObject *, which PM will pass as an
4464 // target to calls to "func"
4465 // * refcon - caller may provide an void *, which PM will pass as an
4466 // argument to calls to "func"
4467 // * handle - This is a return argument. We will populate this pointer upon
4468 // call success. Hold onto this and pass this argument to
4469 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
4471 // kIOReturnSuccess on success
4472 //******************************************************************************
4475 IOPMrootDomain::registerPMSettingController(
4476 const OSSymbol
* settings
[],
4477 uint32_t supportedPowerSources
,
4478 IOPMSettingControllerCallback func
,
4483 PMSettingObject
*pmso
= NULL
;
4484 OSObject
*pmsh
= NULL
;
4485 OSArray
*list
= NULL
;
4488 if (NULL
== settings
||
4491 return kIOReturnBadArgument
;
4494 pmso
= PMSettingObject::pmSettingObject(
4495 (IOPMrootDomain
*) this, func
, target
,
4496 refcon
, supportedPowerSources
, settings
, &pmsh
);
4500 return kIOReturnInternalError
;
4504 for (i
= 0; settings
[i
]; i
++) {
4505 list
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(settings
[i
]));
4507 // New array of callbacks for this setting
4508 list
= OSArray::withCapacity(1);
4509 settingsCallbacks
->setObject(settings
[i
], list
);
4513 // Add caller to the callback list
4514 list
->setObject(pmso
);
4518 // Return handle to the caller, the setting object is private.
4521 return kIOReturnSuccess
;
4524 //******************************************************************************
4525 // deregisterPMSettingObject (private)
4527 // Only called from PMSettingObject.
4528 //******************************************************************************
4531 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject
* pmso
)
4533 thread_t thisThread
= current_thread();
4534 PMSettingCallEntry
*callEntry
;
4535 OSCollectionIterator
*iter
;
4543 pmso
->disabled
= true;
4545 // Wait for all callout threads to finish.
4548 queue_iterate(&pmso
->calloutQueue
, callEntry
, PMSettingCallEntry
*, link
)
4550 if (callEntry
->thread
!= thisThread
) {
4556 assert(NULL
== pmso
->waitThread
);
4557 pmso
->waitThread
= thisThread
;
4558 PMSETTING_WAIT(pmso
);
4559 pmso
->waitThread
= NULL
;
4563 // Search each PM settings array in the kernel.
4564 iter
= OSCollectionIterator::withCollection(settingsCallbacks
);
4566 while ((sym
= OSDynamicCast(OSSymbol
, iter
->getNextObject()))) {
4567 array
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(sym
));
4568 index
= array
->getNextIndexOfObject(pmso
, 0);
4570 array
->removeObject(index
);
4581 //******************************************************************************
4582 // informCPUStateChange
4584 // Call into PM CPU code so that CPU power savings may dynamically adjust for
4585 // running on battery, with the lid closed, etc.
4587 // informCPUStateChange is a no-op on non x86 systems
4588 // only x86 has explicit support in the IntelCPUPowerManagement kext
4589 //******************************************************************************
4592 IOPMrootDomain::informCPUStateChange(
4596 #if defined(__i386__) || defined(__x86_64__)
4598 pmioctlVariableInfo_t varInfoStruct
;
4600 const char *varNameStr
= NULL
;
4601 int32_t *varIndex
= NULL
;
4603 if (kInformAC
== type
) {
4604 varNameStr
= kIOPMRootDomainBatPowerCString
;
4605 varIndex
= &idxPMCPULimitedPower
;
4606 } else if (kInformLid
== type
) {
4607 varNameStr
= kIOPMRootDomainLidCloseCString
;
4608 varIndex
= &idxPMCPUClamshell
;
4613 // Set the new value!
4614 // pmCPUControl will assign us a new ID if one doesn't exist yet
4615 bzero(&varInfoStruct
, sizeof(pmioctlVariableInfo_t
));
4616 varInfoStruct
.varID
= *varIndex
;
4617 varInfoStruct
.varType
= vBool
;
4618 varInfoStruct
.varInitValue
= value
;
4619 varInfoStruct
.varCurValue
= value
;
4620 strlcpy((char *)varInfoStruct
.varName
,
4621 (const char *)varNameStr
,
4622 sizeof(varInfoStruct
.varName
));
4625 pmCPUret
= pmCPUControl( PMIOCSETVARINFO
, (void *)&varInfoStruct
);
4627 // pmCPU only assigns numerical id's when a new varName is specified
4629 && (*varIndex
== kCPUUnknownIndex
)) {
4630 // pmCPUControl has assigned us a new variable ID.
4631 // Let's re-read the structure we just SET to learn that ID.
4632 pmCPUret
= pmCPUControl( PMIOCGETVARNAMEINFO
, (void *)&varInfoStruct
);
4634 if (0 == pmCPUret
) {
4635 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
4636 *varIndex
= varInfoStruct
.varID
;
4642 #endif /* __i386__ || __x86_64__ */
4646 // MARK: Deep Sleep Policy
4650 //******************************************************************************
4651 // evaluateSystemSleepPolicy
4652 //******************************************************************************
4654 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
4658 kIOPMSleepFlagHibernate
= 0x00000001,
4659 kIOPMSleepFlagSleepTimerEnable
= 0x00000002
4662 struct IOPMSystemSleepPolicyEntry
{
4663 uint32_t factorMask
;
4664 uint32_t factorBits
;
4665 uint32_t sleepFlags
;
4666 uint32_t wakeEvents
;
4667 } __attribute__((packed
));
4669 struct IOPMSystemSleepPolicyTable
{
4672 uint16_t entryCount
;
4673 IOPMSystemSleepPolicyEntry entries
[];
4674 } __attribute__((packed
));
4677 kIOPMSleepAttributeHibernateSetup
= 0x00000001,
4678 kIOPMSleepAttributeHibernateSleep
= 0x00000002
4682 getSleepTypeAttributes( uint32_t sleepType
)
4684 static const uint32_t sleepTypeAttributes
[kIOPMSleepTypeLast
] =
4689 /* safesleep */ kIOPMSleepAttributeHibernateSetup
,
4690 /* hibernate */ kIOPMSleepAttributeHibernateSetup
| kIOPMSleepAttributeHibernateSleep
,
4691 /* standby */ kIOPMSleepAttributeHibernateSetup
| kIOPMSleepAttributeHibernateSleep
,
4692 /* poweroff */ kIOPMSleepAttributeHibernateSetup
| kIOPMSleepAttributeHibernateSleep
,
4696 if (sleepType
>= kIOPMSleepTypeLast
) {
4700 return sleepTypeAttributes
[sleepType
];
4704 IOPMrootDomain::evaluateSystemSleepPolicy(
4705 IOPMSystemSleepParameters
* params
, int sleepPhase
, uint32_t * hibMode
)
4707 const IOPMSystemSleepPolicyTable
* pt
;
4708 OSObject
* prop
= NULL
;
4709 OSData
* policyData
;
4710 uint64_t currentFactors
= 0;
4711 char currentFactorsBuf
[512];
4712 uint32_t standbyDelay
= 0;
4713 uint32_t powerOffDelay
= 0;
4714 uint32_t powerOffTimer
= 0;
4715 uint32_t standbyTimer
= 0;
4717 bool standbyEnabled
;
4718 bool powerOffEnabled
;
4721 // Get platform's sleep policy table
4722 if (!gSleepPolicyHandler
) {
4723 prop
= getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey
);
4729 // Fetch additional settings
4730 standbyEnabled
= (getSleepOption(kIOPMDeepSleepDelayKey
, &standbyDelay
)
4731 && (getProperty(kIOPMDeepSleepEnabledKey
) == kOSBooleanTrue
));
4732 powerOffEnabled
= (getSleepOption(kIOPMAutoPowerOffDelayKey
, &powerOffDelay
)
4733 && (getProperty(kIOPMAutoPowerOffEnabledKey
) == kOSBooleanTrue
));
4734 if (!getSleepOption(kIOPMAutoPowerOffTimerKey
, &powerOffTimer
)) {
4735 powerOffTimer
= powerOffDelay
;
4737 if (!getSleepOption(kIOPMDeepSleepTimerKey
, &standbyTimer
)) {
4738 standbyTimer
= standbyDelay
;
4741 DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
4742 sleepPhase
, standbyEnabled
, standbyDelay
, standbyTimer
,
4743 powerOffEnabled
, powerOffDelay
, powerOffTimer
, *hibMode
);
4745 currentFactorsBuf
[0] = 0;
4746 // pmset level overrides
4747 if ((*hibMode
& kIOHibernateModeOn
) == 0) {
4748 if (!gSleepPolicyHandler
) {
4749 standbyEnabled
= false;
4750 powerOffEnabled
= false;
4752 } else if (!(*hibMode
& kIOHibernateModeSleep
)) {
4753 // Force hibernate (i.e. mode 25)
4754 // If standby is enabled, force standy.
4755 // If poweroff is enabled, force poweroff.
4756 if (standbyEnabled
) {
4757 currentFactors
|= kIOPMSleepFactorStandbyForced
;
4758 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "StandbyForced");
4759 } else if (powerOffEnabled
) {
4760 currentFactors
|= kIOPMSleepFactorAutoPowerOffForced
;
4761 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "AutoPowerOffForced");
4763 currentFactors
|= kIOPMSleepFactorHibernateForced
;
4764 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "HibernateForced");
4768 // Current factors based on environment and assertions
4769 if (sleepTimerMaintenance
) {
4770 currentFactors
|= kIOPMSleepFactorSleepTimerWake
;
4771 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "SleepTimerWake");
4773 if (standbyEnabled
&& sleepToStandby
&& !gSleepPolicyHandler
) {
4774 currentFactors
|= kIOPMSleepFactorSleepTimerWake
;
4775 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "SleepTimerWake");
4777 if (!clamshellClosed
) {
4778 currentFactors
|= kIOPMSleepFactorLidOpen
;
4779 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "LidOpen");
4781 if (acAdaptorConnected
) {
4782 currentFactors
|= kIOPMSleepFactorACPower
;
4783 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ACPower");
4785 if (lowBatteryCondition
) {
4786 currentFactors
|= kIOPMSleepFactorBatteryLow
;
4787 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "BatteryLow");
4789 if (!standbyDelay
|| !standbyTimer
) {
4790 currentFactors
|= kIOPMSleepFactorStandbyNoDelay
;
4791 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "StandbyNoDelay");
4793 if (standbyNixed
|| !standbyEnabled
) {
4794 currentFactors
|= kIOPMSleepFactorStandbyDisabled
;
4795 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "StandbyDisabled");
4798 currentFactors
|= kIOPMSleepFactorLocalUserActivity
;
4799 currentFactors
&= ~kIOPMSleepFactorSleepTimerWake
;
4800 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "LocalUserActivity, !SleepTimerWake");
4802 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit
) !=
4803 kIOPMDriverAssertionLevelOff
) {
4804 currentFactors
|= kIOPMSleepFactorUSBExternalDevice
;
4805 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "USBExternalDevice");
4807 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit
) !=
4808 kIOPMDriverAssertionLevelOff
) {
4809 currentFactors
|= kIOPMSleepFactorBluetoothHIDDevice
;
4810 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "BluetoothHIDDevice");
4812 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit
) !=
4813 kIOPMDriverAssertionLevelOff
) {
4814 currentFactors
|= kIOPMSleepFactorExternalMediaMounted
;
4815 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ExternalMediaMounted");
4817 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5
) !=
4818 kIOPMDriverAssertionLevelOff
) {
4819 currentFactors
|= kIOPMSleepFactorThunderboltDevice
;
4820 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ThunderboltDevice");
4822 if (_scheduledAlarms
!= 0) {
4823 currentFactors
|= kIOPMSleepFactorRTCAlarmScheduled
;
4824 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "RTCAlaramScheduled");
4826 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit
) !=
4827 kIOPMDriverAssertionLevelOff
) {
4828 currentFactors
|= kIOPMSleepFactorMagicPacketWakeEnabled
;
4829 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "MagicPacketWakeEnabled");
4831 #define TCPKEEPALIVE 1
4833 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit
) !=
4834 kIOPMDriverAssertionLevelOff
) {
4835 currentFactors
|= kIOPMSleepFactorNetworkKeepAliveActive
;
4836 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "NetworkKeepAliveActive");
4839 if (!powerOffEnabled
) {
4840 currentFactors
|= kIOPMSleepFactorAutoPowerOffDisabled
;
4841 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "AutoPowerOffDisabled");
4844 currentFactors
|= kIOPMSleepFactorExternalDisplay
;
4845 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ExternalDisplay");
4847 if (userWasActive
) {
4848 currentFactors
|= kIOPMSleepFactorLocalUserActivity
;
4849 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "LocalUserActivity");
4851 if (darkWakeHibernateError
&& !CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
4852 currentFactors
|= kIOPMSleepFactorHibernateFailed
;
4853 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "HibernateFailed");
4855 if (thermalWarningState
) {
4856 currentFactors
|= kIOPMSleepFactorThermalWarning
;
4857 snprintf(currentFactorsBuf
, sizeof(currentFactorsBuf
), "%s, %s", currentFactorsBuf
, "ThermalWarning");
4860 DLOG("sleep factors 0x%llx %s\n", currentFactors
, currentFactorsBuf
);
4862 if (gSleepPolicyHandler
) {
4863 uint32_t savedHibernateMode
;
4866 if (!gSleepPolicyVars
) {
4867 gSleepPolicyVars
= IONew(IOPMSystemSleepPolicyVariables
, 1);
4868 if (!gSleepPolicyVars
) {
4871 bzero(gSleepPolicyVars
, sizeof(*gSleepPolicyVars
));
4873 gSleepPolicyVars
->signature
= kIOPMSystemSleepPolicySignature
;
4874 gSleepPolicyVars
->version
= kIOPMSystemSleepPolicyVersion
;
4875 gSleepPolicyVars
->currentCapability
= _currentCapability
;
4876 gSleepPolicyVars
->highestCapability
= _highestCapability
;
4877 gSleepPolicyVars
->sleepFactors
= currentFactors
;
4878 gSleepPolicyVars
->sleepReason
= lastSleepReason
;
4879 gSleepPolicyVars
->sleepPhase
= sleepPhase
;
4880 gSleepPolicyVars
->standbyDelay
= standbyDelay
;
4881 gSleepPolicyVars
->standbyTimer
= standbyTimer
;
4882 gSleepPolicyVars
->poweroffDelay
= powerOffDelay
;
4883 gSleepPolicyVars
->scheduledAlarms
= _scheduledAlarms
| _userScheduledAlarm
;
4884 gSleepPolicyVars
->poweroffTimer
= powerOffTimer
;
4886 if (kIOPMSleepPhase0
== sleepPhase
) {
4887 // preserve hibernateMode
4888 savedHibernateMode
= gSleepPolicyVars
->hibernateMode
;
4889 gSleepPolicyVars
->hibernateMode
= *hibMode
;
4890 } else if (kIOPMSleepPhase1
== sleepPhase
) {
4891 // use original hibernateMode for phase2
4892 gSleepPolicyVars
->hibernateMode
= *hibMode
;
4895 result
= gSleepPolicyHandler(gSleepPolicyTarget
, gSleepPolicyVars
, params
);
4897 if (kIOPMSleepPhase0
== sleepPhase
) {
4898 // restore hibernateMode
4899 gSleepPolicyVars
->hibernateMode
= savedHibernateMode
;
4902 if ((result
!= kIOReturnSuccess
) ||
4903 (kIOPMSleepTypeInvalid
== params
->sleepType
) ||
4904 (params
->sleepType
>= kIOPMSleepTypeLast
) ||
4905 (kIOPMSystemSleepParametersVersion
!= params
->version
)) {
4906 MSG("sleep policy handler error\n");
4910 if ((getSleepTypeAttributes(params
->sleepType
) &
4911 kIOPMSleepAttributeHibernateSetup
) &&
4912 ((*hibMode
& kIOHibernateModeOn
) == 0)) {
4913 *hibMode
|= (kIOHibernateModeOn
| kIOHibernateModeSleep
);
4916 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
4917 params
->version
, params
->sleepType
, params
->sleepFlags
,
4918 params
->ecWakeEvents
, params
->ecWakeTimer
, params
->ecPoweroffTimer
);
4923 // Policy table is meaningless without standby enabled
4924 if (!standbyEnabled
) {
4928 // Validate the sleep policy table
4929 policyData
= OSDynamicCast(OSData
, prop
);
4930 if (!policyData
|| (policyData
->getLength() <= sizeof(IOPMSystemSleepPolicyTable
))) {
4934 pt
= (const IOPMSystemSleepPolicyTable
*) policyData
->getBytesNoCopy();
4935 if ((pt
->signature
!= kIOPMSystemSleepPolicySignature
) ||
4936 (pt
->version
!= 1) || (0 == pt
->entryCount
)) {
4940 if (((policyData
->getLength() - sizeof(IOPMSystemSleepPolicyTable
)) !=
4941 (sizeof(IOPMSystemSleepPolicyEntry
) * pt
->entryCount
))) {
4945 for (uint32_t i
= 0; i
< pt
->entryCount
; i
++) {
4946 const IOPMSystemSleepPolicyEntry
* entry
= &pt
->entries
[i
];
4947 mismatch
= (((uint32_t)currentFactors
^ entry
->factorBits
) & entry
->factorMask
);
4949 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
4950 entry
->factorMask
, entry
->factorBits
,
4951 entry
->sleepFlags
, entry
->wakeEvents
, mismatch
);
4956 DLOG("^ found match\n");
4959 params
->version
= kIOPMSystemSleepParametersVersion
;
4960 params
->reserved1
= 1;
4961 if (entry
->sleepFlags
& kIOPMSleepFlagHibernate
) {
4962 params
->sleepType
= kIOPMSleepTypeStandby
;
4964 params
->sleepType
= kIOPMSleepTypeNormalSleep
;
4967 params
->ecWakeEvents
= entry
->wakeEvents
;
4968 if (entry
->sleepFlags
& kIOPMSleepFlagSleepTimerEnable
) {
4969 if (kIOPMSleepPhase2
== sleepPhase
) {
4970 clock_sec_t now_secs
= gIOLastSleepTime
.tv_sec
;
4972 if (!_standbyTimerResetSeconds
||
4973 (now_secs
<= _standbyTimerResetSeconds
)) {
4974 // Reset standby timer adjustment
4975 _standbyTimerResetSeconds
= now_secs
;
4976 DLOG("standby delay %u, reset %u\n",
4977 standbyDelay
, (uint32_t) _standbyTimerResetSeconds
);
4978 } else if (standbyDelay
) {
4979 // Shorten the standby delay timer
4980 clock_sec_t elapsed
= now_secs
- _standbyTimerResetSeconds
;
4981 if (standbyDelay
> elapsed
) {
4982 standbyDelay
-= elapsed
;
4984 standbyDelay
= 1; // must be > 0
4986 DLOG("standby delay %u, elapsed %u\n",
4987 standbyDelay
, (uint32_t) elapsed
);
4990 params
->ecWakeTimer
= standbyDelay
;
4991 } else if (kIOPMSleepPhase2
== sleepPhase
) {
4992 // A sleep that does not enable the sleep timer will reset
4993 // the standby delay adjustment.
4994 _standbyTimerResetSeconds
= 0;
5007 static IOPMSystemSleepParameters gEarlySystemSleepParams
;
5010 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5012 // Evaluate early (priority interest phase), before drivers sleep.
5014 DLOG("%s\n", __FUNCTION__
);
5015 removeProperty(kIOPMSystemSleepParametersKey
);
5017 // Full wake resets the standby timer delay adjustment
5018 if (_highestCapability
& kIOPMSystemCapabilityGraphics
) {
5019 _standbyTimerResetSeconds
= 0;
5022 hibernateDisabled
= false;
5024 getSleepOption(kIOHibernateModeKey
, &hibernateMode
);
5026 // Save for late evaluation if sleep is aborted
5027 bzero(&gEarlySystemSleepParams
, sizeof(gEarlySystemSleepParams
));
5029 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams
, kIOPMSleepPhase1
,
5031 if (!hibernateRetry
&&
5032 ((getSleepTypeAttributes(gEarlySystemSleepParams
.sleepType
) &
5033 kIOPMSleepAttributeHibernateSetup
) == 0)) {
5034 // skip hibernate setup
5035 hibernateDisabled
= true;
5039 // Publish IOPMSystemSleepType
5040 uint32_t sleepType
= gEarlySystemSleepParams
.sleepType
;
5041 if (sleepType
== kIOPMSleepTypeInvalid
) {
5043 sleepType
= kIOPMSleepTypeNormalSleep
;
5044 if (hibernateMode
& kIOHibernateModeOn
) {
5045 sleepType
= (hibernateMode
& kIOHibernateModeSleep
) ?
5046 kIOPMSleepTypeSafeSleep
: kIOPMSleepTypeHibernate
;
5048 } else if ((sleepType
== kIOPMSleepTypeStandby
) &&
5049 (gEarlySystemSleepParams
.ecPoweroffTimer
)) {
5050 // report the lowest possible sleep state
5051 sleepType
= kIOPMSleepTypePowerOff
;
5054 setProperty(kIOPMSystemSleepTypeKey
, sleepType
, 32);
5058 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5060 IOPMSystemSleepParameters params
;
5061 OSData
* paramsData
;
5063 // Evaluate sleep policy after sleeping drivers but before platform sleep.
5065 DLOG("%s\n", __FUNCTION__
);
5067 bzero(¶ms
, sizeof(params
));
5069 if (evaluateSystemSleepPolicy(¶ms
, kIOPMSleepPhase2
, &hibernateMode
)) {
5070 if ((kIOPMSleepTypeStandby
== params
.sleepType
)
5071 && gIOHibernateStandbyDisabled
&& gSleepPolicyVars
5072 && (!((kIOPMSleepFactorStandbyForced
| kIOPMSleepFactorAutoPowerOffForced
| kIOPMSleepFactorHibernateForced
)
5073 & gSleepPolicyVars
->sleepFactors
))) {
5074 standbyNixed
= true;
5078 || ((hibernateDisabled
|| hibernateAborted
) &&
5079 (getSleepTypeAttributes(params
.sleepType
) &
5080 kIOPMSleepAttributeHibernateSetup
))) {
5081 // Final evaluation picked a state requiring hibernation,
5082 // but hibernate isn't going to proceed. Arm a short sleep using
5083 // the early non-hibernate sleep parameters.
5084 bcopy(&gEarlySystemSleepParams
, ¶ms
, sizeof(params
));
5085 params
.sleepType
= kIOPMSleepTypeAbortedSleep
;
5086 params
.ecWakeTimer
= 1;
5090 // Set hibernateRetry flag to force hibernate setup on the
5092 hibernateRetry
= true;
5094 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5095 params
.ecWakeTimer
, hibernateDisabled
, hibernateAborted
, standbyNixed
);
5097 hibernateRetry
= false;
5100 if (kIOPMSleepTypeAbortedSleep
!= params
.sleepType
) {
5101 resetTimers
= false;
5104 paramsData
= OSData::withBytes(¶ms
, sizeof(params
));
5106 setProperty(kIOPMSystemSleepParametersKey
, paramsData
);
5107 paramsData
->release();
5110 if (getSleepTypeAttributes(params
.sleepType
) &
5111 kIOPMSleepAttributeHibernateSleep
) {
5112 // Disable sleep to force hibernation
5113 gIOHibernateMode
&= ~kIOHibernateModeSleep
;
5119 IOPMrootDomain::getHibernateSettings(
5120 uint32_t * hibernateModePtr
,
5121 uint32_t * hibernateFreeRatio
,
5122 uint32_t * hibernateFreeTime
)
5124 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5125 // has updated the hibernateDisabled flag.
5127 bool ok
= getSleepOption(kIOHibernateModeKey
, hibernateModePtr
);
5128 getSleepOption(kIOHibernateFreeRatioKey
, hibernateFreeRatio
);
5129 getSleepOption(kIOHibernateFreeTimeKey
, hibernateFreeTime
);
5130 if (hibernateDisabled
) {
5131 *hibernateModePtr
= 0;
5132 } else if (gSleepPolicyHandler
) {
5133 *hibernateModePtr
= hibernateMode
;
5135 DLOG("hibernateMode 0x%x\n", *hibernateModePtr
);
5140 IOPMrootDomain::getSleepOption( const char * key
, uint32_t * option
)
5142 OSObject
* optionsProp
;
5143 OSDictionary
* optionsDict
;
5144 OSObject
* obj
= NULL
;
5148 optionsProp
= copyProperty(kRootDomainSleepOptionsKey
);
5149 optionsDict
= OSDynamicCast(OSDictionary
, optionsProp
);
5152 obj
= optionsDict
->getObject(key
);
5158 obj
= copyProperty(key
);
5161 if ((num
= OSDynamicCast(OSNumber
, obj
))) {
5162 *option
= num
->unsigned32BitValue();
5164 } else if (OSDynamicCast(OSBoolean
, obj
)) {
5165 *option
= (obj
== kOSBooleanTrue
) ? 1 : 0;
5174 optionsProp
->release();
5179 #endif /* HIBERNATION */
5182 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType
, uint32_t * standbyTimer
)
5185 IOPMSystemSleepParameters params
;
5186 uint32_t hibMode
= 0;
5189 if (gIOPMWorkLoop
->inGate() == false) {
5190 IOReturn ret
= gIOPMWorkLoop
->runAction(
5191 OSMemberFunctionCast(IOWorkLoop::Action
, this,
5192 &IOPMrootDomain::getSystemSleepType
),
5194 (void *) sleepType
, (void *) standbyTimer
);
5198 getSleepOption(kIOHibernateModeKey
, &hibMode
);
5199 bzero(¶ms
, sizeof(params
));
5201 ok
= evaluateSystemSleepPolicy(¶ms
, kIOPMSleepPhase0
, &hibMode
);
5203 *sleepType
= params
.sleepType
;
5204 if (!getSleepOption(kIOPMDeepSleepTimerKey
, standbyTimer
) &&
5205 !getSleepOption(kIOPMDeepSleepDelayKey
, standbyTimer
)) {
5206 DLOG("Standby delay is not set\n");
5209 return kIOReturnSuccess
;
5213 return kIOReturnUnsupported
;
5217 // MARK: Shutdown and Restart
5219 //******************************************************************************
5220 // handlePlatformHaltRestart
5222 //******************************************************************************
5224 // Phases while performing shutdown/restart
5227 kNotifyPriorityClients
= 0x10,
5228 kNotifyPowerPlaneDrivers
= 0x20,
5229 kNotifyHaltRestartAction
= 0x30,
5234 struct HaltRestartApplierContext
{
5235 IOPMrootDomain
* RootDomain
;
5236 unsigned long PowerState
;
5237 IOPMPowerFlags PowerFlags
;
5240 const char * LogString
;
5241 shutdownPhase_t phase
;
5243 IOServiceInterestHandler handler
;
5247 shutdownPhase2String(shutdownPhase_t phase
)
5251 return "Notifications completed";
5252 case kNotifyPriorityClients
:
5253 return "Notifying priority clients";
5254 case kNotifyPowerPlaneDrivers
:
5255 return "Notifying power plane drivers";
5256 case kNotifyHaltRestartAction
:
5257 return "Notifying HaltRestart action handlers";
5259 return "Quiescing PM";
5266 platformHaltRestartApplier( OSObject
* object
, void * context
)
5268 IOPowerStateChangeNotification notify
;
5269 HaltRestartApplierContext
* ctx
;
5270 AbsoluteTime startTime
, elapsedTime
;
5273 ctx
= (HaltRestartApplierContext
*) context
;
5275 _IOServiceInterestNotifier
* notifier
;
5276 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
5277 memset(¬ify
, 0, sizeof(notify
));
5278 notify
.powerRef
= (void *)(uintptr_t)ctx
->Counter
;
5279 notify
.returnValue
= 0;
5280 notify
.stateNumber
= ctx
->PowerState
;
5281 notify
.stateFlags
= ctx
->PowerFlags
;
5284 ctx
->handler
= notifier
->handler
;
5287 clock_get_uptime(&startTime
);
5288 ctx
->RootDomain
->messageClient( ctx
->MessageType
, object
, (void *)¬ify
);
5289 deltaTime
= computeDeltaTimeMS(&startTime
, &elapsedTime
);
5291 if ((deltaTime
> kPMHaltTimeoutMS
) && notifier
) {
5292 LOG("%s handler %p took %u ms\n",
5293 ctx
->LogString
, OBFUSCATE(notifier
->handler
), deltaTime
);
5294 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier
->handler
, elapsedTime
);
5297 ctx
->handler
= NULL
;
5302 quiescePowerTreeCallback( void * target
, void * param
)
5304 IOLockLock(gPMHaltLock
);
5306 thread_wakeup(param
);
5307 IOLockUnlock(gPMHaltLock
);
5311 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type
)
5313 AbsoluteTime startTime
, elapsedTime
;
5316 memset(&gHaltRestartCtx
, 0, sizeof(gHaltRestartCtx
));
5317 gHaltRestartCtx
.RootDomain
= this;
5319 clock_get_uptime(&startTime
);
5322 case kPEUPSDelayHaltCPU
:
5323 gHaltRestartCtx
.PowerState
= OFF_STATE
;
5324 gHaltRestartCtx
.MessageType
= kIOMessageSystemWillPowerOff
;
5325 gHaltRestartCtx
.LogString
= "PowerOff";
5329 gHaltRestartCtx
.PowerState
= RESTART_STATE
;
5330 gHaltRestartCtx
.MessageType
= kIOMessageSystemWillRestart
;
5331 gHaltRestartCtx
.LogString
= "Restart";
5335 gHaltRestartCtx
.PowerState
= ON_STATE
;
5336 gHaltRestartCtx
.MessageType
= kIOMessageSystemPagingOff
;
5337 gHaltRestartCtx
.LogString
= "PagingOff";
5338 IOService::updateConsoleUsers(NULL
, kIOMessageSystemPagingOff
);
5340 IOHibernateSystemRestart();
5348 gHaltRestartCtx
.phase
= kNotifyPriorityClients
;
5349 // Notify legacy clients
5350 applyToInterested(gIOPriorityPowerStateInterest
, platformHaltRestartApplier
, &gHaltRestartCtx
);
5352 // For normal shutdown, turn off File Server Mode.
5353 if (kPEHaltCPU
== pe_type
) {
5354 const OSSymbol
* setting
= OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
);
5355 OSNumber
* num
= OSNumber::withNumber((unsigned long long) 0, 32);
5356 if (setting
&& num
) {
5357 setPMSetting(setting
, num
);
5364 if (kPEPagingOff
!= pe_type
) {
5365 gHaltRestartCtx
.phase
= kNotifyPowerPlaneDrivers
;
5366 // Notify in power tree order
5367 notifySystemShutdown(this, gHaltRestartCtx
.MessageType
);
5370 gHaltRestartCtx
.phase
= kNotifyHaltRestartAction
;
5371 #if !CONFIG_EMBEDDED
5372 IOCPURunPlatformHaltRestartActions(pe_type
);
5374 if (kPEPagingOff
!= pe_type
) {
5375 IOCPURunPlatformHaltRestartActions(pe_type
);
5379 // Wait for PM to quiesce
5380 if ((kPEPagingOff
!= pe_type
) && gPMHaltLock
) {
5381 gHaltRestartCtx
.phase
= kQuiescePM
;
5382 AbsoluteTime quiesceTime
= mach_absolute_time();
5384 IOLockLock(gPMHaltLock
);
5385 gPMQuiesced
= false;
5386 if (quiescePowerTree(this, &quiescePowerTreeCallback
, &gPMQuiesced
) ==
5388 while (!gPMQuiesced
) {
5389 IOLockSleep(gPMHaltLock
, &gPMQuiesced
, THREAD_UNINT
);
5392 IOLockUnlock(gPMHaltLock
);
5393 deltaTime
= computeDeltaTimeMS(&quiesceTime
, &elapsedTime
);
5394 DLOG("PM quiesce took %u ms\n", deltaTime
);
5395 halt_log_enter("Quiesce", NULL
, elapsedTime
);
5397 gHaltRestartCtx
.phase
= kNotifyDone
;
5399 deltaTime
= computeDeltaTimeMS(&startTime
, &elapsedTime
);
5400 LOG("%s all drivers took %u ms\n", gHaltRestartCtx
.LogString
, deltaTime
);
5402 halt_log_enter(gHaltRestartCtx
.LogString
, NULL
, elapsedTime
);
5404 deltaTime
= computeDeltaTimeMS(&gHaltStartTime
, &elapsedTime
);
5405 LOG("%s total %u ms\n", gHaltRestartCtx
.LogString
, deltaTime
);
5407 if (gHaltLog
&& gHaltTimeMaxLog
&& (deltaTime
>= gHaltTimeMaxLog
)) {
5408 printf("%s total %d ms:%s\n", gHaltRestartCtx
.LogString
, deltaTime
, gHaltLog
);
5411 checkShutdownTimeout();
5415 IOPMrootDomain::checkShutdownTimeout()
5417 AbsoluteTime elapsedTime
;
5418 uint32_t deltaTime
= computeDeltaTimeMS(&gHaltStartTime
, &elapsedTime
);
5420 if (gHaltTimeMaxPanic
&& (deltaTime
>= gHaltTimeMaxPanic
)) {
5427 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs
)
5430 if ((gHaltRestartCtx
.phase
== kNotifyPriorityClients
) && gHaltRestartCtx
.handler
) {
5431 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx
.handler
, mach_absolute_time() - gHaltStartTime
);
5433 panic("%s timed out in phase '%s'. Total %d ms:%s",
5434 gHaltRestartCtx
.LogString
, shutdownPhase2String(gHaltRestartCtx
.phase
), timeoutInMs
, gHaltLog
);
5436 panic("%s timed out in phase \'%s\'. Total %d ms",
5437 gHaltRestartCtx
.LogString
, shutdownPhase2String(gHaltRestartCtx
.phase
), timeoutInMs
);
5441 //******************************************************************************
5444 //******************************************************************************
5447 IOPMrootDomain::shutdownSystem( void )
5449 return kIOReturnUnsupported
;
5452 //******************************************************************************
5455 //******************************************************************************
5458 IOPMrootDomain::restartSystem( void )
5460 return kIOReturnUnsupported
;
5464 // MARK: System Capability
5466 //******************************************************************************
5467 // tagPowerPlaneService
5469 // Running on PM work loop thread.
5470 //******************************************************************************
5473 IOPMrootDomain::tagPowerPlaneService(
5474 IOService
* service
,
5475 IOPMActions
* actions
)
5478 bool isDisplayWrangler
;
5480 memset(actions
, 0, sizeof(*actions
));
5481 actions
->target
= this;
5483 if (service
== this) {
5484 actions
->actionPowerChangeStart
=
5485 OSMemberFunctionCast(
5486 IOPMActionPowerChangeStart
, this,
5487 &IOPMrootDomain::handleOurPowerChangeStart
);
5489 actions
->actionPowerChangeDone
=
5490 OSMemberFunctionCast(
5491 IOPMActionPowerChangeDone
, this,
5492 &IOPMrootDomain::handleOurPowerChangeDone
);
5494 actions
->actionPowerChangeOverride
=
5495 OSMemberFunctionCast(
5496 IOPMActionPowerChangeOverride
, this,
5497 &IOPMrootDomain::overrideOurPowerChange
);
5502 isDisplayWrangler
= (NULL
!= service
->metaCast("IODisplayWrangler"));
5503 if (isDisplayWrangler
) {
5505 // found the display wrangler, check for any display assertions already created
5506 if (pmAssertions
->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit
) {
5507 DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
5508 wrangler
->setIgnoreIdleTimer( true );
5512 isDisplayWrangler
= false;
5515 #if defined(__i386__) || defined(__x86_64__)
5516 if (isDisplayWrangler
) {
5517 flags
|= kPMActionsFlagIsDisplayWrangler
;
5519 if (service
->getProperty("IOPMStrictTreeOrder")) {
5520 flags
|= kPMActionsFlagIsGraphicsDevice
;
5522 if (service
->getProperty("IOPMUnattendedWakePowerState")) {
5523 flags
|= kPMActionsFlagIsAudioDevice
;
5527 // Find the power connection object that is a child of the PCI host
5528 // bridge, and has a graphics/audio device attached below. Mark the
5529 // power branch for delayed child notifications.
5532 IORegistryEntry
* child
= service
;
5533 IORegistryEntry
* parent
= child
->getParentEntry(gIOPowerPlane
);
5535 while (child
!= this) {
5536 if (child
->getProperty("IOPCITunnelled") == kOSBooleanTrue
) {
5537 // Skip delaying notifications and clamping power on external graphics and audio devices.
5538 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service
->getRegistryEntryID(), flags
);
5542 if ((parent
== pciHostBridgeDriver
) ||
5544 if (OSDynamicCast(IOPowerConnection
, child
)) {
5545 IOPowerConnection
* conn
= (IOPowerConnection
*) child
;
5546 conn
->delayChildNotification
= true;
5547 DLOG("delayChildNotification for 0x%llx\n", conn
->getRegistryEntryID());
5552 parent
= child
->getParentEntry(gIOPowerPlane
);
5557 DLOG("%s tag flags %x\n", service
->getName(), flags
);
5558 actions
->parameter
|= flags
;
5559 actions
->actionPowerChangeOverride
=
5560 OSMemberFunctionCast(
5561 IOPMActionPowerChangeOverride
, this,
5562 &IOPMrootDomain::overridePowerChangeForUIService
);
5564 if (flags
& kPMActionsFlagIsDisplayWrangler
) {
5565 actions
->actionActivityTickle
=
5566 OSMemberFunctionCast(
5567 IOPMActionActivityTickle
, this,
5568 &IOPMrootDomain::handleActivityTickleForDisplayWrangler
);
5570 actions
->actionUpdatePowerClient
=
5571 OSMemberFunctionCast(
5572 IOPMActionUpdatePowerClient
, this,
5573 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler
);
5578 // Locate the first PCI host bridge for PMTrace.
5579 if (!pciHostBridgeDevice
&& service
->metaCast("IOPCIBridge")) {
5580 IOService
* provider
= service
->getProvider();
5581 if (OSDynamicCast(IOPlatformDevice
, provider
) &&
5582 provider
->inPlane(gIODTPlane
)) {
5583 pciHostBridgeDevice
= provider
;
5584 pciHostBridgeDriver
= service
;
5585 DLOG("PMTrace found PCI host bridge %s->%s\n",
5586 provider
->getName(), service
->getName());
5590 // Tag top-level PCI devices. The order of PMinit() call does not
5591 // change across boots and is used as the PCI bit number.
5592 if (pciHostBridgeDevice
&& service
->metaCast("IOPCIDevice")) {
5593 // Would prefer to check built-in property, but tagPowerPlaneService()
5594 // is called before pciDevice->registerService().
5595 IORegistryEntry
* parent
= service
->getParentEntry(gIODTPlane
);
5596 if ((parent
== pciHostBridgeDevice
) && service
->getProperty("acpi-device")) {
5597 int bit
= pmTracer
->recordTopLevelPCIDevice( service
);
5599 // Save the assigned bit for fast lookup.
5600 actions
->parameter
|= (bit
& kPMActionsPCIBitNumberMask
);
5602 actions
->actionPowerChangeStart
=
5603 OSMemberFunctionCast(
5604 IOPMActionPowerChangeStart
, this,
5605 &IOPMrootDomain::handlePowerChangeStartForPCIDevice
);
5607 actions
->actionPowerChangeDone
=
5608 OSMemberFunctionCast(
5609 IOPMActionPowerChangeDone
, this,
5610 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice
);
5616 //******************************************************************************
5617 // PM actions for root domain
5618 //******************************************************************************
5621 IOPMrootDomain::overrideOurPowerChange(
5622 IOService
* service
,
5623 IOPMActions
* actions
,
5624 IOPMPowerStateIndex
* inOutPowerState
,
5625 IOPMPowerChangeFlags
* inOutChangeFlags
,
5626 IOPMRequestTag requestTag
)
5628 uint32_t powerState
= (uint32_t) *inOutPowerState
;
5629 uint32_t changeFlags
= *inOutChangeFlags
;
5630 uint32_t currentPowerState
= (uint32_t) getPowerState();
5632 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
5633 if ((AOT_STATE
== powerState
) && (ON_STATE
== currentPowerState
)) {
5634 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
5635 *inOutChangeFlags
|= kIOPMNotDone
;
5638 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
5640 if (changeFlags
& kIOPMParentInitiated
) {
5641 // Root parent is permanently pegged at max power,
5642 // a parent initiated power change is unexpected.
5643 *inOutChangeFlags
|= kIOPMNotDone
;
5647 if (powerState
< currentPowerState
) {
5648 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
5649 // Root domain is dropping power state ON->SLEEP.
5650 // If system is in full wake, first enter dark wake by
5651 // converting the power drop to a capability change.
5652 // Once in dark wake, transition to sleep state ASAP.
5654 darkWakeToSleepASAP
= true;
5656 // Drop graphics and audio capability
5657 _desiredCapability
&= ~(
5658 kIOPMSystemCapabilityGraphics
|
5659 kIOPMSystemCapabilityAudio
);
5661 // Convert to capability change (ON->ON)
5662 *inOutPowerState
= getRUN_STATE();
5663 *inOutChangeFlags
|= kIOPMSynchronize
;
5665 // Revert device desire from SLEEP to ON
5666 changePowerStateToPriv(getRUN_STATE());
5668 // System is in dark wake, ok to drop power state.
5669 // Broadcast root powering down to entire tree.
5670 *inOutChangeFlags
|= kIOPMRootChangeDown
;
5672 } else if (powerState
> currentPowerState
) {
5673 if ((_currentCapability
& kIOPMSystemCapabilityCPU
) == 0) {
5674 // Broadcast power up when waking from sleep, but not for the
5675 // initial power change at boot by checking for cpu capability.
5676 *inOutChangeFlags
|= kIOPMRootChangeUp
;
5682 IOPMrootDomain::handleOurPowerChangeStart(
5683 IOService
* service
,
5684 IOPMActions
* actions
,
5685 IOPMPowerStateIndex powerState
,
5686 IOPMPowerChangeFlags
* inOutChangeFlags
,
5687 IOPMRequestTag requestTag
)
5689 uint32_t changeFlags
= *inOutChangeFlags
;
5690 uint32_t currentPowerState
= (uint32_t) getPowerState();
5691 uint32_t sleepReason
= requestTag
? requestTag
: kIOPMSleepReasonIdle
;
5692 bool publishSleepReason
= false;
5694 _systemTransitionType
= kSystemTransitionNone
;
5695 _systemMessageClientMask
= 0;
5696 capabilityLoss
= false;
5697 toldPowerdCapWillChange
= false;
5699 if (lowBatteryCondition
) {
5700 // Low battery notification may arrive after the initial sleep request
5701 // has been queued. Override the sleep reason so powerd and others can
5702 // treat this as an emergency sleep.
5703 sleepReason
= kIOPMSleepReasonLowPower
;
5706 // 1. Explicit capability change.
5708 if (changeFlags
& kIOPMSynchronize
) {
5709 if (powerState
== ON_STATE
) {
5710 if (changeFlags
& kIOPMSyncNoChildNotify
) {
5711 _systemTransitionType
= kSystemTransitionNewCapClient
;
5713 _systemTransitionType
= kSystemTransitionCapability
;
5717 // 2. Going to sleep (cancellation still possible).
5718 else if (powerState
< currentPowerState
) {
5719 _systemTransitionType
= kSystemTransitionSleep
;
5721 // 3. Woke from (idle or demand) sleep.
5722 else if (!systemBooting
&&
5723 (changeFlags
& kIOPMSelfInitiated
) &&
5724 (powerState
> currentPowerState
)) {
5725 _systemTransitionType
= kSystemTransitionWake
;
5726 _desiredCapability
= kIOPMSystemCapabilityCPU
|
5727 kIOPMSystemCapabilityNetwork
;
5729 // Early exit from dark wake to full (e.g. LID open)
5730 if (kFullWakeReasonNone
!= fullWakeReason
) {
5731 _desiredCapability
|= (
5732 kIOPMSystemCapabilityGraphics
|
5733 kIOPMSystemCapabilityAudio
);
5736 IOHibernateSetWakeCapabilities(_desiredCapability
);
5740 // Update pending wake capability at the beginning of every
5741 // state transition (including synchronize). This will become
5742 // the current capability at the end of the transition.
5744 if (kSystemTransitionSleep
== _systemTransitionType
) {
5745 _pendingCapability
= 0;
5746 capabilityLoss
= true;
5747 } else if (kSystemTransitionNewCapClient
!= _systemTransitionType
) {
5748 _pendingCapability
= _desiredCapability
|
5749 kIOPMSystemCapabilityCPU
|
5750 kIOPMSystemCapabilityNetwork
;
5752 if (_pendingCapability
& kIOPMSystemCapabilityGraphics
) {
5753 _pendingCapability
|= kIOPMSystemCapabilityAudio
;
5756 if ((kSystemTransitionCapability
== _systemTransitionType
) &&
5757 (_pendingCapability
== _currentCapability
)) {
5758 // Cancel the PM state change.
5759 _systemTransitionType
= kSystemTransitionNone
;
5760 *inOutChangeFlags
|= kIOPMNotDone
;
5762 if (__builtin_popcount(_pendingCapability
) <
5763 __builtin_popcount(_currentCapability
)) {
5764 capabilityLoss
= true;
5768 // 1. Capability change.
5770 if (kSystemTransitionCapability
== _systemTransitionType
) {
5771 // Dark to Full transition.
5772 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
5773 tracePoint( kIOPMTracePointDarkWakeExit
);
5775 willEnterFullWake();
5778 // Full to Dark transition.
5779 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) {
5780 // Clear previous stats
5781 IOLockLock(pmStatsLock
);
5782 if (pmStatsAppResponses
) {
5783 pmStatsAppResponses
->release();
5784 pmStatsAppResponses
= OSArray::withCapacity(5);
5786 IOLockUnlock(pmStatsLock
);
5789 tracePoint( kIOPMTracePointDarkWakeEntry
);
5790 *inOutChangeFlags
|= kIOPMSyncTellPowerDown
;
5791 _systemMessageClientMask
= kSystemMessageClientPowerd
|
5792 kSystemMessageClientLegacyApp
;
5796 // Prevent user active transitions before notifying clients
5797 // that system will sleep.
5798 preventTransitionToUserActive(true);
5800 IOService::setAdvisoryTickleEnable( false );
5802 // Publish the sleep reason for full to dark wake
5803 publishSleepReason
= true;
5804 lastSleepReason
= fullToDarkReason
= sleepReason
;
5806 // Publish a UUID for the Sleep --> Wake cycle
5807 handlePublishSleepWakeUUID(true);
5808 if (sleepDelaysReport
) {
5809 clock_get_uptime(&ts_sleepStart
);
5810 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart
);
5813 wranglerTickled
= false;
5817 else if (kSystemTransitionSleep
== _systemTransitionType
) {
5818 // Beginning of a system sleep transition.
5819 // Cancellation is still possible.
5820 tracePoint( kIOPMTracePointSleepStarted
);
5822 _systemMessageClientMask
= kSystemMessageClientAll
;
5823 if ((_currentCapability
& kIOPMSystemCapabilityGraphics
) == 0) {
5824 _systemMessageClientMask
&= ~kSystemMessageClientLegacyApp
;
5826 if ((_highestCapability
& kIOPMSystemCapabilityGraphics
) == 0) {
5827 // Kernel priority clients are only notified on the initial
5828 // transition to full wake, so don't notify them unless system
5829 // has gained graphics capability since the last system wake.
5830 _systemMessageClientMask
&= ~kSystemMessageClientKernel
;
5833 gIOHibernateState
= 0;
5836 // Record the reason for dark wake back to sleep
5837 // System may not have ever achieved full wake
5839 publishSleepReason
= true;
5840 lastSleepReason
= sleepReason
;
5841 if (sleepDelaysReport
) {
5842 clock_get_uptime(&ts_sleepStart
);
5843 DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart
);
5847 else if (kSystemTransitionWake
== _systemTransitionType
) {
5848 tracePoint( kIOPMTracePointWakeWillPowerOnClients
);
5849 // Clear stats about sleep
5851 if (AOT_STATE
== powerState
) {
5852 _pendingCapability
= 0;
5855 if (_pendingCapability
& kIOPMSystemCapabilityGraphics
) {
5856 willEnterFullWake();
5858 // Message powerd only
5859 _systemMessageClientMask
= kSystemMessageClientPowerd
;
5860 tellClients(kIOMessageSystemWillPowerOn
);
5864 // The only location where the sleep reason is published. At this point
5865 // sleep can still be cancelled, but sleep reason should be published
5866 // early for logging purposes.
5868 if (publishSleepReason
) {
5869 static const char * IOPMSleepReasons
[] =
5871 kIOPMClamshellSleepKey
,
5872 kIOPMPowerButtonSleepKey
,
5873 kIOPMSoftwareSleepKey
,
5874 kIOPMOSSwitchHibernationKey
,
5876 kIOPMLowPowerSleepKey
,
5877 kIOPMThermalEmergencySleepKey
,
5878 kIOPMMaintenanceSleepKey
,
5879 kIOPMSleepServiceExitKey
,
5880 kIOPMDarkWakeThermalEmergencyKey
5883 // Record sleep cause in IORegistry
5884 uint32_t reasonIndex
= sleepReason
- kIOPMSleepReasonClamshell
;
5885 if (reasonIndex
< sizeof(IOPMSleepReasons
) / sizeof(IOPMSleepReasons
[0])) {
5886 DLOG("sleep reason %s\n", IOPMSleepReasons
[reasonIndex
]);
5887 setProperty(kRootDomainSleepReasonKey
, IOPMSleepReasons
[reasonIndex
]);
5891 if ((kSystemTransitionNone
!= _systemTransitionType
) &&
5892 (kSystemTransitionNewCapClient
!= _systemTransitionType
)) {
5893 _systemStateGeneration
++;
5894 systemDarkWake
= false;
5896 DLOG("=== START (%s->%s, 0x%x) type %u, gen %u, msg %x, "
5898 getPowerStateString(currentPowerState
), getPowerStateString((uint32_t) powerState
), *inOutChangeFlags
,
5899 _systemTransitionType
, _systemStateGeneration
,
5900 _systemMessageClientMask
,
5901 _desiredCapability
, _currentCapability
, _pendingCapability
);
5904 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
5905 if ((AOT_STATE
== powerState
) && (SLEEP_STATE
!= currentPowerState
)) {
5906 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState
));
5908 if (_aotNow
&& (ON_STATE
== powerState
)) {
5909 aotShouldExit(false, true);
5912 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
5916 IOPMrootDomain::handleOurPowerChangeDone(
5917 IOService
* service
,
5918 IOPMActions
* actions
,
5919 IOPMPowerStateIndex powerState
,
5920 IOPMPowerChangeFlags changeFlags
,
5921 IOPMRequestTag requestTag __unused
)
5923 if (kSystemTransitionNewCapClient
== _systemTransitionType
) {
5924 _systemTransitionType
= kSystemTransitionNone
;
5928 if (_systemTransitionType
!= kSystemTransitionNone
) {
5929 uint32_t currentPowerState
= (uint32_t) getPowerState();
5931 if (changeFlags
& kIOPMNotDone
) {
5932 // Power down was cancelled or vetoed.
5933 _pendingCapability
= _currentCapability
;
5934 lastSleepReason
= 0;
5936 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
) &&
5937 CAP_CURRENT(kIOPMSystemCapabilityCPU
)) {
5938 #if !CONFIG_EMBEDDED
5939 pmPowerStateQueue
->submitPowerEvent(
5940 kPowerEventPolicyStimulus
,
5941 (void *) kStimulusDarkWakeReentry
,
5942 _systemStateGeneration
);
5944 // On embedded, there are no factors that can prolong a
5945 // "darkWake" when a power down is vetoed. We need to
5946 // promote to "fullWake" at least once so that factors
5947 // that prevent idle sleep can assert themselves if required
5948 pmPowerStateQueue
->submitPowerEvent(
5949 kPowerEventPolicyStimulus
,
5950 (void *) kStimulusDarkWakeActivityTickle
);
5954 // Revert device desire to max.
5955 changePowerStateToPriv(getRUN_STATE());
5957 // Send message on dark wake to full wake promotion.
5958 // tellChangeUp() handles the normal SLEEP->ON case.
5960 if (kSystemTransitionCapability
== _systemTransitionType
) {
5961 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
5962 lastSleepReason
= 0; // stop logging wrangler tickles
5963 tellClients(kIOMessageSystemHasPoweredOn
);
5965 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) {
5966 // Going dark, reset full wake state
5967 // userIsActive will be cleared by wrangler powering down
5968 fullWakeReason
= kFullWakeReasonNone
;
5970 if (ts_sleepStart
) {
5971 clock_get_uptime(&wake2DarkwakeDelay
);
5972 SUB_ABSOLUTETIME(&wake2DarkwakeDelay
, &ts_sleepStart
);
5973 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay
);
5979 // Reset state after exiting from dark wake.
5981 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
) ||
5982 CAP_LOSS(kIOPMSystemCapabilityCPU
)) {
5983 darkWakeMaintenance
= false;
5984 darkWakeToSleepASAP
= false;
5985 pciCantSleepValid
= false;
5986 darkWakeSleepService
= false;
5988 if (CAP_LOSS(kIOPMSystemCapabilityCPU
)) {
5989 // Remove the influence of display power assertion
5990 // before next system wake.
5992 wrangler
->changePowerStateForRootDomain(
5993 kWranglerPowerStateMin
);
5995 removeProperty(gIOPMUserTriggeredFullWakeKey
);
5999 // Entered dark mode.
6001 if (((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0) &&
6002 (_pendingCapability
& kIOPMSystemCapabilityCPU
)) {
6003 // Queue an evaluation of whether to remain in dark wake,
6004 // and for how long. This serves the purpose of draining
6005 // any assertions from the queue.
6007 pmPowerStateQueue
->submitPowerEvent(
6008 kPowerEventPolicyStimulus
,
6009 (void *) kStimulusDarkWakeEntry
,
6010 _systemStateGeneration
);
6014 DLOG("=== FINISH (%s->%s, 0x%x) type %u, gen %u, msg %x, "
6015 "dcp %x:%x:%x, dbgtimer %u\n",
6016 getPowerStateString(currentPowerState
), getPowerStateString((uint32_t) powerState
), changeFlags
,
6017 _systemTransitionType
, _systemStateGeneration
,
6018 _systemMessageClientMask
,
6019 _desiredCapability
, _currentCapability
, _pendingCapability
,
6020 _lastDebugWakeSeconds
);
6022 if (_pendingCapability
& kIOPMSystemCapabilityGraphics
) {
6024 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
6025 if (clamshellExists
&& fullWakeThreadCall
&&
6026 CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
6027 // Not the initial graphics full power, graphics won't
6028 // send a power notification to trigger a lid state
6031 AbsoluteTime deadline
;
6032 clock_interval_to_deadline(45, kSecondScale
, &deadline
);
6033 thread_call_enter_delayed(fullWakeThreadCall
, deadline
);
6036 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU
)) {
6040 // Update current system capability.
6041 if (_currentCapability
!= _pendingCapability
) {
6042 _currentCapability
= _pendingCapability
;
6045 // Update highest system capability.
6047 _highestCapability
|= _currentCapability
;
6049 if (darkWakePostTickle
&&
6050 (kSystemTransitionWake
== _systemTransitionType
) &&
6051 (gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) ==
6052 kDarkWakeFlagHIDTickleLate
) {
6053 darkWakePostTickle
= false;
6055 } else if (wranglerTickled
) {
6056 requestFullWake( kFullWakeReasonLocalUser
);
6059 // Reset tracepoint at completion of capability change,
6060 // completion of wake transition, and aborted sleep transition.
6062 if ((_systemTransitionType
== kSystemTransitionCapability
) ||
6063 (_systemTransitionType
== kSystemTransitionWake
) ||
6064 ((_systemTransitionType
== kSystemTransitionSleep
) &&
6065 (changeFlags
& kIOPMNotDone
))) {
6066 setProperty(kIOPMSystemCapabilitiesKey
, _currentCapability
, 64);
6067 tracePoint( kIOPMTracePointSystemUp
);
6070 _systemTransitionType
= kSystemTransitionNone
;
6071 _systemMessageClientMask
= 0;
6072 toldPowerdCapWillChange
= false;
6074 logGraphicsClamp
= false;
6076 if (lowBatteryCondition
) {
6077 privateSleepSystem(kIOPMSleepReasonLowPower
);
6078 } else if ((fullWakeReason
== kFullWakeReasonDisplayOn
) && (!displayPowerOnRequested
)) {
6079 // Request for full wake is removed while system is waking up to full wake
6080 DLOG("DisplayOn fullwake request is removed\n");
6081 handleDisplayPowerOn();
6084 if (isRTCAlarmWake
) {
6085 pmPowerStateQueue
->submitPowerEvent(
6086 kPowerEventReceivedPowerNotification
, (void *)(uintptr_t) kLocalEvalClamshellCommand
);
6091 //******************************************************************************
6092 // PM actions for graphics and audio.
6093 //******************************************************************************
6096 IOPMrootDomain::overridePowerChangeForUIService(
6097 IOService
* service
,
6098 IOPMActions
* actions
,
6099 IOPMPowerStateIndex
* inOutPowerState
,
6100 IOPMPowerChangeFlags
* inOutChangeFlags
)
6102 uint32_t powerState
= (uint32_t) *inOutPowerState
;
6103 uint32_t changeFlags
= (uint32_t) *inOutChangeFlags
;
6105 if (kSystemTransitionNone
== _systemTransitionType
) {
6106 // Not in midst of a system transition.
6107 // Do not modify power limit enable state.
6108 } else if ((actions
->parameter
& kPMActionsFlagLimitPower
) == 0) {
6109 // Activate power limiter.
6111 if ((actions
->parameter
& kPMActionsFlagIsDisplayWrangler
) &&
6112 ((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0) &&
6113 (changeFlags
& kIOPMSynchronize
)) {
6114 actions
->parameter
|= kPMActionsFlagLimitPower
;
6115 } else if ((actions
->parameter
& kPMActionsFlagIsAudioDevice
) &&
6116 ((gDarkWakeFlags
& kDarkWakeFlagAudioNotSuppressed
) == 0) &&
6117 ((_pendingCapability
& kIOPMSystemCapabilityAudio
) == 0) &&
6118 (changeFlags
& kIOPMSynchronize
)) {
6119 actions
->parameter
|= kPMActionsFlagLimitPower
;
6120 } else if ((actions
->parameter
& kPMActionsFlagIsGraphicsDevice
) &&
6121 (_systemTransitionType
== kSystemTransitionSleep
)) {
6122 // For graphics devices, arm the limiter when entering
6123 // system sleep. Not when dropping to dark wake.
6124 actions
->parameter
|= kPMActionsFlagLimitPower
;
6127 if (actions
->parameter
& kPMActionsFlagLimitPower
) {
6128 DLOG("+ plimit %s %p\n",
6129 service
->getName(), OBFUSCATE(service
));
6132 // Remove power limit.
6134 if ((actions
->parameter
& (
6135 kPMActionsFlagIsDisplayWrangler
|
6136 kPMActionsFlagIsGraphicsDevice
)) &&
6137 (_pendingCapability
& kIOPMSystemCapabilityGraphics
)) {
6138 actions
->parameter
&= ~kPMActionsFlagLimitPower
;
6139 } else if ((actions
->parameter
& kPMActionsFlagIsAudioDevice
) &&
6140 (_pendingCapability
& kIOPMSystemCapabilityAudio
)) {
6141 actions
->parameter
&= ~kPMActionsFlagLimitPower
;
6144 if ((actions
->parameter
& kPMActionsFlagLimitPower
) == 0) {
6145 DLOG("- plimit %s %p\n",
6146 service
->getName(), OBFUSCATE(service
));
6150 if (actions
->parameter
& kPMActionsFlagLimitPower
) {
6151 uint32_t maxPowerState
= (uint32_t)(-1);
6153 if (changeFlags
& (kIOPMDomainDidChange
| kIOPMDomainWillChange
)) {
6154 // Enforce limit for system power/cap transitions.
6157 if ((service
->getPowerState() > maxPowerState
) &&
6158 (actions
->parameter
& kPMActionsFlagIsDisplayWrangler
)) {
6161 // Remove lingering effects of any tickle before entering
6162 // dark wake. It will take a new tickle to return to full
6163 // wake, so the existing tickle state is useless.
6165 if (changeFlags
& kIOPMDomainDidChange
) {
6166 *inOutChangeFlags
|= kIOPMExpireIdleTimer
;
6168 } else if (actions
->parameter
& kPMActionsFlagIsGraphicsDevice
) {
6172 // Deny all self-initiated changes when power is limited.
6173 // Wrangler tickle should never defeat the limiter.
6175 maxPowerState
= service
->getPowerState();
6178 if (powerState
> maxPowerState
) {
6179 DLOG("> plimit %s %p (%u->%u, 0x%x)\n",
6180 service
->getName(), OBFUSCATE(service
), powerState
, maxPowerState
,
6182 *inOutPowerState
= maxPowerState
;
6184 if (darkWakePostTickle
&&
6185 (actions
->parameter
& kPMActionsFlagIsDisplayWrangler
) &&
6186 (changeFlags
& kIOPMDomainWillChange
) &&
6187 ((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) ==
6188 kDarkWakeFlagHIDTickleEarly
)) {
6189 darkWakePostTickle
= false;
6194 if (!graphicsSuppressed
&& (changeFlags
& kIOPMDomainDidChange
)) {
6195 if (logGraphicsClamp
) {
6199 clock_get_uptime(&now
);
6200 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
6201 absolutetime_to_nanoseconds(now
, &nsec
);
6202 if (kIOLogPMRootDomain
& gIOKitDebug
) {
6203 MSG("Graphics suppressed %u ms\n",
6204 ((int)((nsec
) / NSEC_PER_MSEC
)));
6207 graphicsSuppressed
= true;
6213 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
6214 IOService
* service
,
6215 IOPMActions
* actions
)
6218 // Warning: Not running in PM work loop context - don't modify state !!!
6219 // Trap tickle directed to IODisplayWrangler while running with graphics
6220 // capability suppressed.
6222 assert(service
== wrangler
);
6224 clock_get_uptime(&userActivityTime
);
6225 bool aborting
= ((lastSleepReason
== kIOPMSleepReasonIdle
)
6226 || (lastSleepReason
== kIOPMSleepReasonMaintenance
)
6227 || (lastSleepReason
== kIOPMSleepReasonSoftware
));
6229 userActivityCount
++;
6230 DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
6231 userActivityCount
, lastSleepReason
);
6234 if (!wranglerTickled
&&
6235 ((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0)) {
6236 DLOG("display wrangler tickled\n");
6237 if (kIOLogPMRootDomain
& gIOKitDebug
) {
6238 OSReportWithBacktrace("Dark wake display tickle");
6240 if (pmPowerStateQueue
) {
6241 pmPowerStateQueue
->submitPowerEvent(
6242 kPowerEventPolicyStimulus
,
6243 (void *) kStimulusDarkWakeActivityTickle
,
6244 true /* set wake type */ );
6251 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
6252 IOService
* service
,
6253 IOPMActions
* actions
,
6254 const OSSymbol
* powerClient
,
6255 IOPMPowerStateIndex oldPowerState
,
6256 IOPMPowerStateIndex newPowerState
)
6259 assert(service
== wrangler
);
6261 // This function implements half of the user active detection
6262 // by monitoring changes to the display wrangler's device desire.
6264 // User becomes active when either:
6265 // 1. Wrangler's DeviceDesire increases to max, but wrangler is already
6266 // in max power state. This desire change in absence of a power state
6267 // change is detected within. This handles the case when user becomes
6268 // active while the display is already lit by setDisplayPowerOn().
6270 // 2. Power state change to max, and DeviceDesire is also at max.
6271 // Handled by displayWranglerNotification().
6273 // User becomes inactive when DeviceDesire drops to sleep state or below.
6275 DLOG("wrangler %s (ps %u, %u->%u)\n",
6276 powerClient
->getCStringNoCopy(),
6277 (uint32_t) service
->getPowerState(),
6278 (uint32_t) oldPowerState
, (uint32_t) newPowerState
);
6280 if (powerClient
== gIOPMPowerClientDevice
) {
6281 if ((newPowerState
> oldPowerState
) &&
6282 (newPowerState
== kWranglerPowerStateMax
) &&
6283 (service
->getPowerState() == kWranglerPowerStateMax
)) {
6284 evaluatePolicy( kStimulusEnterUserActiveState
);
6285 } else if ((newPowerState
< oldPowerState
) &&
6286 (newPowerState
<= kWranglerPowerStateSleep
)) {
6287 evaluatePolicy( kStimulusLeaveUserActiveState
);
6291 if (newPowerState
<= kWranglerPowerStateSleep
) {
6292 evaluatePolicy( kStimulusDisplayWranglerSleep
);
6293 } else if (newPowerState
== kWranglerPowerStateMax
) {
6294 evaluatePolicy( kStimulusDisplayWranglerWake
);
6299 //******************************************************************************
6300 // User active state management
6301 //******************************************************************************
6304 IOPMrootDomain::preventTransitionToUserActive( bool prevent
)
6307 _preventUserActive
= prevent
;
6308 if (wrangler
&& !_preventUserActive
) {
6309 // Allowing transition to user active, but the wrangler may have
6310 // already powered ON in case of sleep cancel/revert. Poll the
6311 // same conditions checked for in displayWranglerNotification()
6312 // to bring the user active state up to date.
6314 if ((wrangler
->getPowerState() == kWranglerPowerStateMax
) &&
6315 (wrangler
->getPowerStateForClient(gIOPMPowerClientDevice
) ==
6316 kWranglerPowerStateMax
)) {
6317 evaluatePolicy( kStimulusEnterUserActiveState
);
6323 //******************************************************************************
6324 // Approve usage of delayed child notification by PM.
6325 //******************************************************************************
6328 IOPMrootDomain::shouldDelayChildNotification(
6329 IOService
* service
)
6331 if (((gDarkWakeFlags
& kDarkWakeFlagHIDTickleMask
) != 0) &&
6332 (kFullWakeReasonNone
== fullWakeReason
) &&
6333 (kSystemTransitionWake
== _systemTransitionType
)) {
6334 DLOG("%s: delay child notify\n", service
->getName());
6340 //******************************************************************************
6341 // PM actions for PCI device.
6342 //******************************************************************************
6345 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
6346 IOService
* service
,
6347 IOPMActions
* actions
,
6348 IOPMPowerStateIndex powerState
,
6349 IOPMPowerChangeFlags
* inOutChangeFlags
)
6351 pmTracer
->tracePCIPowerChange(
6352 PMTraceWorker::kPowerChangeStart
,
6353 service
, *inOutChangeFlags
,
6354 (actions
->parameter
& kPMActionsPCIBitNumberMask
));
6358 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
6359 IOService
* service
,
6360 IOPMActions
* actions
,
6361 IOPMPowerStateIndex powerState
,
6362 IOPMPowerChangeFlags changeFlags
)
6364 pmTracer
->tracePCIPowerChange(
6365 PMTraceWorker::kPowerChangeCompleted
,
6366 service
, changeFlags
,
6367 (actions
->parameter
& kPMActionsPCIBitNumberMask
));
6370 //******************************************************************************
6373 // Override IOService::registerInterest() to intercept special clients.
6374 //******************************************************************************
6376 class IOPMServiceInterestNotifier
: public _IOServiceInterestNotifier
6378 friend class IOPMrootDomain
;
6379 OSDeclareDefaultStructors(IOPMServiceInterestNotifier
);
6382 uint32_t ackTimeoutCnt
;
6383 uint32_t msgType
;// Message pending ack
6387 const OSSymbol
*identifier
;
6390 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier
, _IOServiceInterestNotifier
)
6392 IONotifier
* IOPMrootDomain::registerInterest(
6393 const OSSymbol
* typeOfInterest
,
6394 IOServiceInterestHandler handler
,
6395 void * target
, void * ref
)
6397 IOPMServiceInterestNotifier
*notifier
= NULL
;
6398 bool isSystemCapabilityClient
;
6399 bool isKernelCapabilityClient
;
6400 IOReturn rc
= kIOReturnError
;;
6402 isSystemCapabilityClient
=
6404 typeOfInterest
->isEqualTo(kIOPMSystemCapabilityInterest
);
6406 isKernelCapabilityClient
=
6408 typeOfInterest
->isEqualTo(gIOPriorityPowerStateInterest
);
6410 if (isSystemCapabilityClient
) {
6411 typeOfInterest
= gIOAppPowerStateInterest
;
6414 notifier
= new IOPMServiceInterestNotifier
;
6419 if (notifier
->init()) {
6420 rc
= super::registerInterestForNotifier(notifier
, typeOfInterest
, handler
, target
, ref
);
6422 if (rc
!= kIOReturnSuccess
) {
6423 notifier
->release();
6428 if (pmPowerStateQueue
) {
6429 notifier
->ackTimeoutCnt
= 0;
6430 if (isSystemCapabilityClient
) {
6432 if (pmPowerStateQueue
->submitPowerEvent(
6433 kPowerEventRegisterSystemCapabilityClient
, notifier
) == false) {
6434 notifier
->release();
6438 if (isKernelCapabilityClient
) {
6440 if (pmPowerStateQueue
->submitPowerEvent(
6441 kPowerEventRegisterKernelCapabilityClient
, notifier
) == false) {
6442 notifier
->release();
6447 OSData
*data
= NULL
;
6448 uint8_t *uuid
= NULL
;
6449 OSKext
*kext
= OSKext::lookupKextWithAddress((vm_address_t
)handler
);
6451 data
= kext
->copyUUID();
6453 if (data
&& (data
->getLength() == sizeof(uuid_t
))) {
6454 uuid
= (uint8_t *)(data
->getBytesNoCopy());
6456 notifier
->uuid0
= ((uint64_t)(uuid
[0]) << 56) | ((uint64_t)(uuid
[1]) << 48) | ((uint64_t)(uuid
[2]) << 40) |
6457 ((uint64_t)(uuid
[3]) << 32) | ((uint64_t)(uuid
[4]) << 24) | ((uint64_t)(uuid
[5]) << 16) |
6458 ((uint64_t)(uuid
[6]) << 8) | (uuid
[7]);
6459 notifier
->uuid1
= ((uint64_t)(uuid
[8]) << 56) | ((uint64_t)(uuid
[9]) << 48) | ((uint64_t)(uuid
[10]) << 40) |
6460 ((uint64_t)(uuid
[11]) << 32) | ((uint64_t)(uuid
[12]) << 24) | ((uint64_t)(uuid
[13]) << 16) |
6461 ((uint64_t)(uuid
[14]) << 8) | (uuid
[15]);
6463 notifier
->identifier
= kext
->getIdentifier();
6475 //******************************************************************************
6476 // systemMessageFilter
6478 //******************************************************************************
6481 IOPMrootDomain::systemMessageFilter(
6482 void * object
, void * arg1
, void * arg2
, void * arg3
)
6484 const IOPMInterestContext
* context
= (const IOPMInterestContext
*) arg1
;
6485 bool isCapMsg
= (context
->messageType
== kIOMessageSystemCapabilityChange
);
6486 bool isCapClient
= false;
6488 IOPMServiceInterestNotifier
*notifier
;
6490 notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, (OSObject
*)object
);
6493 if ((kSystemTransitionNewCapClient
== _systemTransitionType
) &&
6494 (!isCapMsg
|| !_joinedCapabilityClients
||
6495 !_joinedCapabilityClients
->containsObject((OSObject
*) object
))) {
6499 // Capability change message for app and kernel clients.
6502 if ((context
->notifyType
== kNotifyPriority
) ||
6503 (context
->notifyType
== kNotifyCapabilityChangePriority
)) {
6507 if ((context
->notifyType
== kNotifyCapabilityChangeApps
) &&
6508 (object
== (void *) systemCapabilityNotifier
)) {
6514 IOPMSystemCapabilityChangeParameters
* capArgs
=
6515 (IOPMSystemCapabilityChangeParameters
*) arg2
;
6517 if (kSystemTransitionNewCapClient
== _systemTransitionType
) {
6518 capArgs
->fromCapabilities
= 0;
6519 capArgs
->toCapabilities
= _currentCapability
;
6520 capArgs
->changeFlags
= 0;
6522 capArgs
->fromCapabilities
= _currentCapability
;
6523 capArgs
->toCapabilities
= _pendingCapability
;
6525 if (context
->isPreChange
) {
6526 capArgs
->changeFlags
= kIOPMSystemCapabilityWillChange
;
6528 capArgs
->changeFlags
= kIOPMSystemCapabilityDidChange
;
6531 if ((object
== (void *) systemCapabilityNotifier
) &&
6532 context
->isPreChange
) {
6533 toldPowerdCapWillChange
= true;
6537 // Capability change messages only go to the PM configd plugin.
6538 // Wait for response post-change if capabilitiy is increasing.
6539 // Wait for response pre-change if capability is decreasing.
6541 if ((context
->notifyType
== kNotifyCapabilityChangeApps
) && arg3
&&
6542 ((capabilityLoss
&& context
->isPreChange
) ||
6543 (!capabilityLoss
&& !context
->isPreChange
))) {
6544 // app has not replied yet, wait for it
6545 *((OSObject
**) arg3
) = kOSBooleanFalse
;
6552 // Capability client will always see kIOMessageCanSystemSleep,
6553 // even for demand sleep. It will also have a chance to veto
6554 // sleep one last time after all clients have responded to
6555 // kIOMessageSystemWillSleep
6557 if ((kIOMessageCanSystemSleep
== context
->messageType
) ||
6558 (kIOMessageSystemWillNotSleep
== context
->messageType
)) {
6559 if (object
== (OSObject
*) systemCapabilityNotifier
) {
6564 // Not idle sleep, don't ask apps.
6565 if (context
->changeFlags
& kIOPMSkipAskPowerDown
) {
6570 if (kIOPMMessageLastCallBeforeSleep
== context
->messageType
) {
6571 if ((object
== (OSObject
*) systemCapabilityNotifier
) &&
6572 CAP_HIGHEST(kIOPMSystemCapabilityGraphics
) &&
6573 (fullToDarkReason
== kIOPMSleepReasonIdle
)) {
6579 // Reject capability change messages for legacy clients.
6580 // Reject legacy system sleep messages for capability client.
6582 if (isCapMsg
|| (object
== (OSObject
*) systemCapabilityNotifier
)) {
6586 // Filter system sleep messages.
6588 if ((context
->notifyType
== kNotifyApps
) &&
6589 (_systemMessageClientMask
& kSystemMessageClientLegacyApp
)) {
6594 if (notifier
->ackTimeoutCnt
>= 3) {
6595 *((OSObject
**) arg3
) = kOSBooleanFalse
;
6597 *((OSObject
**) arg3
) = kOSBooleanTrue
;
6601 } else if ((context
->notifyType
== kNotifyPriority
) &&
6602 (_systemMessageClientMask
& kSystemMessageClientKernel
)) {
6607 if (allow
&& isCapMsg
&& _joinedCapabilityClients
) {
6608 _joinedCapabilityClients
->removeObject((OSObject
*) object
);
6609 if (_joinedCapabilityClients
->getCount() == 0) {
6610 DLOG("destroyed capability client set %p\n",
6611 OBFUSCATE(_joinedCapabilityClients
));
6612 _joinedCapabilityClients
->release();
6613 _joinedCapabilityClients
= NULL
;
6617 notifier
->msgType
= context
->messageType
;
6623 //******************************************************************************
6624 // setMaintenanceWakeCalendar
6626 //******************************************************************************
6629 IOPMrootDomain::setMaintenanceWakeCalendar(
6630 const IOPMCalendarStruct
* calendar
)
6636 return kIOReturnBadArgument
;
6639 data
= OSData::withBytes((void *) calendar
, sizeof(*calendar
));
6641 return kIOReturnNoMemory
;
6644 if (kPMCalendarTypeMaintenance
== calendar
->selector
) {
6645 ret
= setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey
, data
);
6646 if (kIOReturnSuccess
== ret
) {
6647 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake
, &_scheduledAlarms
);
6649 } else if (kPMCalendarTypeSleepService
== calendar
->selector
) {
6650 ret
= setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey
, data
);
6651 if (kIOReturnSuccess
== ret
) {
6652 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake
, &_scheduledAlarms
);
6655 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms
);
6662 // MARK: Display Wrangler
6664 //******************************************************************************
6665 // displayWranglerNotification
6667 // Handle the notification when the IODisplayWrangler changes power state.
6668 //******************************************************************************
6671 IOPMrootDomain::displayWranglerNotification(
6672 void * target
, void * refCon
,
6673 UInt32 messageType
, IOService
* service
,
6674 void * messageArgument
, vm_size_t argSize
)
6677 int displayPowerState
;
6678 IOPowerStateChangeNotification
* params
=
6679 (IOPowerStateChangeNotification
*) messageArgument
;
6681 if ((messageType
!= kIOMessageDeviceWillPowerOff
) &&
6682 (messageType
!= kIOMessageDeviceHasPoweredOn
)) {
6683 return kIOReturnUnsupported
;
6688 return kIOReturnUnsupported
;
6691 displayPowerState
= params
->stateNumber
;
6692 DLOG("wrangler %s ps %d\n",
6693 getIOMessageString(messageType
), displayPowerState
);
6695 switch (messageType
) {
6696 case kIOMessageDeviceWillPowerOff
:
6697 // Display wrangler has dropped power due to display idle
6698 // or force system sleep.
6700 // 4 Display ON kWranglerPowerStateMax
6701 // 3 Display Dim kWranglerPowerStateDim
6702 // 2 Display Sleep kWranglerPowerStateSleep
6703 // 1 Not visible to user
6704 // 0 Not visible to user kWranglerPowerStateMin
6706 if (displayPowerState
<= kWranglerPowerStateSleep
) {
6707 gRootDomain
->evaluatePolicy( kStimulusDisplayWranglerSleep
);
6711 case kIOMessageDeviceHasPoweredOn
:
6712 // Display wrangler has powered on due to user activity
6713 // or wake from sleep.
6715 if (kWranglerPowerStateMax
== displayPowerState
) {
6716 gRootDomain
->evaluatePolicy( kStimulusDisplayWranglerWake
);
6718 // See comment in handleUpdatePowerClientForDisplayWrangler
6719 if (service
->getPowerStateForClient(gIOPMPowerClientDevice
) ==
6720 kWranglerPowerStateMax
) {
6721 gRootDomain
->evaluatePolicy( kStimulusEnterUserActiveState
);
6727 return kIOReturnUnsupported
;
6730 //******************************************************************************
6731 // displayWranglerMatchPublished
6733 // Receives a notification when the IODisplayWrangler is published.
6734 // When it's published we install a power state change handler.
6735 //******************************************************************************
6738 IOPMrootDomain::displayWranglerMatchPublished(
6741 IOService
* newService
,
6742 IONotifier
* notifier __unused
)
6745 // install a handler
6746 if (!newService
->registerInterest( gIOGeneralInterest
,
6747 &displayWranglerNotification
, target
, NULL
)) {
6754 //******************************************************************************
6757 //******************************************************************************
6760 IOPMrootDomain::reportUserInput( void )
6764 OSDictionary
* matching
;
6767 matching
= serviceMatching("IODisplayWrangler");
6768 iter
= getMatchingServices(matching
);
6770 matching
->release();
6773 wrangler
= OSDynamicCast(IOService
, iter
->getNextObject());
6779 wrangler
->activityTickle(0, 0);
6784 //******************************************************************************
6785 // latchDisplayWranglerTickle
6786 //******************************************************************************
6789 IOPMrootDomain::latchDisplayWranglerTickle( bool latch
)
6793 if (!(_currentCapability
& kIOPMSystemCapabilityGraphics
) &&
6794 !(_pendingCapability
& kIOPMSystemCapabilityGraphics
) &&
6795 !checkSystemCanSustainFullWake()) {
6796 // Currently in dark wake, and not transitioning to full wake.
6797 // Full wake is unsustainable, so latch the tickle to prevent
6798 // the display from lighting up momentarily.
6799 wranglerTickleLatched
= true;
6801 wranglerTickleLatched
= false;
6803 } else if (wranglerTickleLatched
&& checkSystemCanSustainFullWake()) {
6804 wranglerTickleLatched
= false;
6806 pmPowerStateQueue
->submitPowerEvent(
6807 kPowerEventPolicyStimulus
,
6808 (void *) kStimulusDarkWakeActivityTickle
);
6811 return wranglerTickleLatched
;
6817 //******************************************************************************
6818 // setDisplayPowerOn
6820 // For root domain user client
6821 //******************************************************************************
6824 IOPMrootDomain::setDisplayPowerOn( uint32_t options
)
6826 pmPowerStateQueue
->submitPowerEvent( kPowerEventSetDisplayPowerOn
,
6827 (void *) NULL
, options
);
6833 //******************************************************************************
6836 // Notification on battery class IOPowerSource appearance
6837 //******************************************************************************
6840 IOPMrootDomain::batteryPublished(
6843 IOService
* resourceService
,
6844 IONotifier
* notifier __unused
)
6846 // rdar://2936060&4435589
6847 // All laptops have dimmable LCD displays
6848 // All laptops have batteries
6849 // So if this machine has a battery, publish the fact that the backlight
6850 // supports dimming.
6851 ((IOPMrootDomain
*)root_domain
)->publishFeature("DisplayDims");
6857 // MARK: System PM Policy
6859 //******************************************************************************
6860 // checkSystemSleepAllowed
6862 //******************************************************************************
6865 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options
,
6866 uint32_t sleepReason
)
6870 // Conditions that prevent idle and demand system sleep.
6873 if (userDisabledAllSleep
) {
6874 err
= kPMUserDisabledAllSleep
; // 1. user-space sleep kill switch
6878 if (systemBooting
|| systemShutdown
|| gWillShutdown
) {
6879 err
= kPMSystemRestartBootingInProgress
; // 2. restart or shutdown in progress
6887 // Conditions above pegs the system at full wake.
6888 // Conditions below prevent system sleep but does not prevent
6889 // dark wake, and must be called from gated context.
6892 err
= kPMConfigPreventSystemSleep
; // 3. config does not support sleep
6896 if (lowBatteryCondition
|| thermalWarningState
) {
6897 break; // always sleep on low battery or when in thermal warning state
6900 if (sleepReason
== kIOPMSleepReasonDarkWakeThermalEmergency
) {
6901 break; // always sleep on dark wake thermal emergencies
6904 if (preventSystemSleepList
->getCount() != 0) {
6905 err
= kPMChildPreventSystemSleep
; // 4. child prevent system sleep clamp
6909 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit
) ==
6910 kIOPMDriverAssertionLevelOn
) {
6911 err
= kPMCPUAssertion
; // 5. CPU assertion
6915 if (pciCantSleepValid
) {
6916 if (pciCantSleepFlag
) {
6917 err
= kPMPCIUnsupported
; // 6. PCI card does not support PM (cached)
6920 } else if (sleepSupportedPEFunction
&&
6921 CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
6923 OSBitAndAtomic(~kPCICantSleep
, &platformSleepSupport
);
6924 ret
= getPlatform()->callPlatformFunction(
6925 sleepSupportedPEFunction
, false,
6926 NULL
, NULL
, NULL
, NULL
);
6927 pciCantSleepValid
= true;
6928 pciCantSleepFlag
= false;
6929 if ((platformSleepSupport
& kPCICantSleep
) ||
6930 ((ret
!= kIOReturnSuccess
) && (ret
!= kIOReturnUnsupported
))) {
6931 err
= 6; // 6. PCI card does not support PM
6932 pciCantSleepFlag
= true;
6939 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err
));
6946 IOPMrootDomain::checkSystemSleepEnabled( void )
6948 return checkSystemSleepAllowed(0, 0);
6952 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason
)
6955 return checkSystemSleepAllowed(1, sleepReason
);
6958 //******************************************************************************
6959 // checkSystemCanSustainFullWake
6960 //******************************************************************************
6963 IOPMrootDomain::checkSystemCanSustainFullWake( void )
6966 if (lowBatteryCondition
|| thermalWarningState
) {
6967 // Low battery wake, or received a low battery notification
6968 // while system is awake. This condition will persist until
6969 // the following wake.
6973 if (clamshellExists
&& clamshellClosed
&& !clamshellSleepDisabled
) {
6974 // Graphics state is unknown and external display might not be probed.
6975 // Do not incorporate state that requires graphics to be in max power
6976 // such as desktopMode or clamshellDisabled.
6978 if (!acAdaptorConnected
) {
6979 DLOG("full wake check: no AC\n");
6987 //******************************************************************************
6989 //******************************************************************************
6994 IOPMrootDomain::mustHibernate( void )
6996 return lowBatteryCondition
|| thermalWarningState
;
6999 #endif /* HIBERNATION */
7001 //******************************************************************************
7003 //******************************************************************************
7005 // Tables for accumulated days in year by month, latter used for leap years
7007 static const int daysbymonth
[] =
7008 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7010 static const int lydaysbymonth
[] =
7011 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7014 IOPMConvertSecondsToCalendar(long secs
, IOPMCalendarStruct
* dt
)
7016 const int * dbm
= daysbymonth
;
7023 // Calculate seconds, minutes and hours
7025 n
= secs
% (24 * 3600);
7026 dt
->second
= n
% 60;
7028 dt
->minute
= n
% 60;
7031 // Calculate day of week
7033 n
= secs
/ (24 * 3600);
7034 // dt->dayWeek = (n + 4) % 7;
7037 // Rebase from days since Unix epoch (1/1/1970) store in 'n',
7038 // to days since 1/1/1968 to start on 4 year cycle, beginning
7043 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7044 // Valid before 2100, since 2100 is not a leap year.
7046 x
= n
/ 1461; // number of 4 year cycles
7047 y
= n
% 1461; // days into current 4 year cycle
7050 // Add in years in the current 4 year cycle
7053 y
-= 366; // days after the leap year
7054 n
= y
% 365; // days into the current year
7055 z
+= (1 + y
/ 365); // years after the past 4-yr cycle
7058 dbm
= lydaysbymonth
;
7066 // Adjust remaining days value to start at 1
7072 for (x
= 1; n
> dbm
[x
]; x
++) {
7077 // Calculate day of month
7079 dt
->day
= n
- dbm
[x
- 1];
7085 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct
* dt
)
7087 const int * dbm
= daysbymonth
;
7090 if (dt
->year
< 1970) {
7094 // Seconds elapsed in the current day
7096 secs
= dt
->second
+ 60 * dt
->minute
+ 3600 * dt
->hour
;
7098 // Number of days from 1/1/70 to beginning of current year
7099 // Account for extra day every 4 years starting at 1973
7101 y
= dt
->year
- 1970;
7102 days
= (y
* 365) + ((y
+ 1) / 4);
7104 // Change table if current year is a leap year
7106 if ((dt
->year
% 4) == 0) {
7107 dbm
= lydaysbymonth
;
7110 // Add in days elapsed in the current year
7112 days
+= (dt
->day
- 1) + dbm
[dt
->month
- 1];
7114 // Add accumulated days to accumulated seconds
7116 secs
+= 24 * 3600 * days
;
7121 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
7124 IOPMrootDomain::getRUN_STATE(void)
7126 return _aotNow
? AOT_STATE
: ON_STATE
;
7130 IOPMrootDomain::isAOTMode()
7136 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime
)
7138 clock_sec_t nowsecs
, wakesecs
;
7139 clock_usec_t nowmicrosecs
, wakemicrosecs
;
7140 uint64_t nowAbs
, wakeAbs
;
7142 clock_gettimeofday_and_absolute_time(&nowsecs
, &nowmicrosecs
, &nowAbs
);
7143 wakeAbs
= continuoustime_to_absolutetime(wakeContinuousTime
);
7144 if (wakeAbs
< nowAbs
) {
7145 printf(LOG_PREFIX
"wakeAbs %qd < nowAbs %qd\n", wakeAbs
, nowAbs
);
7149 absolutetime_to_microtime(wakeAbs
, &wakesecs
, &wakemicrosecs
);
7151 wakesecs
+= nowsecs
;
7152 wakemicrosecs
+= nowmicrosecs
;
7153 if (wakemicrosecs
>= USEC_PER_SEC
) {
7155 wakemicrosecs
-= USEC_PER_SEC
;
7157 if (wakemicrosecs
>= (USEC_PER_SEC
/ 10)) {
7161 IOPMConvertSecondsToCalendar(wakesecs
, &_aotWakeTimeCalendar
);
7163 if (_aotWakeTimeContinuous
!= wakeContinuousTime
) {
7164 _aotWakeTimeContinuous
= wakeContinuousTime
;
7165 IOLog(LOG_PREFIX
"setWakeTime: " YMDTF
"\n", YMDT(&_aotWakeTimeCalendar
));
7167 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeMaintenance
;
7168 _aotWakeTimeUTC
= wakesecs
;
7170 return kIOReturnSuccess
;
7173 // assumes WAKEEVENT_LOCK
7175 IOPMrootDomain::aotShouldExit(bool checkTimeSet
, bool software
)
7178 const char * reason
= "";
7182 _aotMetrics
->softwareRequestCount
++;
7183 reason
= "software request";
7184 } else if (kIOPMWakeEventAOTExitFlags
& _aotPendingFlags
) {
7186 reason
= gWakeReasonString
;
7187 } else if (checkTimeSet
&& (kPMCalendarTypeInvalid
== _aotWakeTimeCalendar
.selector
)) {
7189 _aotMetrics
->noTimeSetCount
++;
7190 reason
= "flipbook expired";
7191 } else if ((kIOPMAOTModeRespectTimers
& _aotMode
) && _scheduledAlarmUTC
) {
7194 clock_get_calendar_microtime(&sec
, &usec
);
7195 if (_scheduledAlarmUTC
<= sec
) {
7197 _aotMetrics
->rtcAlarmsCount
++;
7198 reason
= "user alarm";
7201 exitNow
= (_aotNow
&& _aotExit
);
7204 IOLog(LOG_PREFIX
"AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7206 _aotMetrics
->sleepCount
,
7207 _aotMetrics
->possibleCount
,
7208 _aotMetrics
->confirmedPossibleCount
,
7209 _aotMetrics
->rejectedPossibleCount
,
7210 _aotMetrics
->expiredPossibleCount
,
7211 _aotMetrics
->noTimeSetCount
,
7212 _aotMetrics
->rtcAlarmsCount
);
7218 IOPMrootDomain::aotExit(bool cps
)
7220 _aotTasksSuspended
= false;
7221 _aotReadyToFullWake
= false;
7222 if (_aotTimerScheduled
) {
7223 _aotTimerES
->cancelTimeout();
7224 _aotTimerScheduled
= false;
7226 updateTasksSuspend();
7228 _aotMetrics
->totalTime
+= mach_absolute_time() - _aotLastWakeTime
;
7229 _aotLastWakeTime
= 0;
7230 if (_aotMetrics
->sleepCount
&& (_aotMetrics
->sleepCount
<= kIOPMAOTMetricsKernelWakeCountMax
)) {
7231 strlcpy(&_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
- 1][0],
7233 sizeof(_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
]));
7236 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeInvalid
;
7238 _systemMessageClientMask
= kSystemMessageClientLegacyApp
;
7239 tellClients(kIOMessageSystemWillPowerOn
);
7242 changePowerStateToPriv(getRUN_STATE());
7247 IOPMrootDomain::aotEvaluate(IOTimerEventSource
* timer
)
7251 IOLog("aotEvaluate(%d) 0x%x\n", (timer
!= NULL
), _aotPendingFlags
);
7254 exitNow
= aotShouldExit(false, false);
7255 if (timer
!= NULL
) {
7256 _aotTimerScheduled
= false;
7263 if (_aotLingerTime
) {
7265 IOLog("aot linger before sleep\n");
7266 clock_absolutetime_interval_to_deadline(_aotLingerTime
, &deadline
);
7267 clock_delay_until(deadline
);
7270 privateSleepSystem(kIOPMSleepReasonSoftware
);
7274 #else /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
7277 IOPMrootDomain::getRUN_STATE(void)
7283 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime
)
7285 return kIOReturnUnsupported
;
7288 #endif /* (defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
7290 //******************************************************************************
7293 // Conditions that affect our wake/sleep decision has changed.
7294 // If conditions dictate that the system must remain awake, clamp power
7295 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7296 // is TRUE, then remove the power clamp and allow the power state to drop
7298 //******************************************************************************
7301 IOPMrootDomain::adjustPowerState( bool sleepASAP
)
7303 DEBUG_LOG("adjustPowerState ps %s, asap %d, idleSleepEnabled %d\n",
7304 getPowerStateString((uint32_t) getPowerState()), sleepASAP
, idleSleepEnabled
);
7308 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
7312 if (AOT_STATE
!= getPowerState()) {
7316 exitNow
= aotShouldExit(true, false);
7318 && !_aotTimerScheduled
7319 && (kIOPMWakeEventAOTPossibleExit
== (kIOPMWakeEventAOTPossibleFlags
& _aotPendingFlags
))) {
7320 _aotTimerScheduled
= true;
7321 if (_aotLingerTime
) {
7322 _aotTimerES
->setTimeout(_aotLingerTime
);
7324 _aotTimerES
->setTimeout(800, kMillisecondScale
);
7331 _aotReadyToFullWake
= true;
7332 if (!_aotTimerScheduled
) {
7333 privateSleepSystem(kIOPMSleepReasonSoftware
);
7338 #endif /* (defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
7340 if ((!idleSleepEnabled
) || !checkSystemSleepEnabled()) {
7341 changePowerStateToPriv(getRUN_STATE());
7342 } else if (sleepASAP
) {
7343 changePowerStateToPriv(SLEEP_STATE
);
7348 IOPMrootDomain::handleDisplayPowerOn()
7353 if (displayPowerOnRequested
) {
7354 if (!checkSystemCanSustainFullWake()) {
7358 // Force wrangler to max power state. If system is in dark wake
7359 // this alone won't raise the wrangler's power state.
7361 wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMax
);
7363 // System in dark wake, always requesting full wake should
7364 // not have any bad side-effects, even if the request fails.
7366 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
7367 setProperty(kIOPMRootDomainWakeTypeKey
, kIOPMRootDomainWakeTypeNotification
);
7368 requestFullWake( kFullWakeReasonDisplayOn
);
7371 // Relenquish desire to power up display.
7372 // Must first transition to state 1 since wrangler doesn't
7373 // power off the displays at state 0. At state 0 the root
7374 // domain is removed from the wrangler's power client list.
7376 wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMin
+ 1);
7377 wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMin
);
7381 //******************************************************************************
7382 // dispatchPowerEvent
7384 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
7385 //******************************************************************************
7388 IOPMrootDomain::dispatchPowerEvent(
7389 uint32_t event
, void * arg0
, uint64_t arg1
)
7394 case kPowerEventFeatureChanged
:
7395 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7396 messageClients(kIOPMMessageFeatureChange
, this);
7399 case kPowerEventReceivedPowerNotification
:
7400 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7401 handlePowerNotification((UInt32
)(uintptr_t) arg0
);
7404 case kPowerEventSystemBootCompleted
:
7405 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7406 if (systemBooting
) {
7407 systemBooting
= false;
7409 // read noidle setting from Device Tree
7410 IORegistryEntry
*defaults
= IORegistryEntry::fromPath("IODeviceTree:/defaults");
7411 if (defaults
!= NULL
) {
7412 OSData
*data
= OSDynamicCast(OSData
, defaults
->getProperty("no-idle"));
7413 if ((data
!= NULL
) && (data
->getLength() == 4)) {
7414 gNoIdleFlag
= *(uint32_t*)data
->getBytesNoCopy();
7415 DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag
);
7417 defaults
->release();
7419 if (lowBatteryCondition
) {
7420 privateSleepSystem(kIOPMSleepReasonLowPower
);
7422 // The rest is unnecessary since the system is expected
7423 // to sleep immediately. The following wake will update
7428 sleepWakeDebugMemAlloc();
7429 saveFailureData2File();
7431 // If lid is closed, re-send lid closed notification
7432 // now that booting is complete.
7433 if (clamshellClosed
) {
7434 handlePowerNotification(kLocalEvalClamshellCommand
);
7436 evaluatePolicy( kStimulusAllowSystemSleepChanged
);
7440 case kPowerEventSystemShutdown
:
7441 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7442 if (kOSBooleanTrue
== (OSBoolean
*) arg0
) {
7443 /* We set systemShutdown = true during shutdown
7444 * to prevent sleep at unexpected times while loginwindow is trying
7445 * to shutdown apps and while the OS is trying to transition to
7446 * complete power of.
7448 * Set to true during shutdown, as soon as loginwindow shows
7449 * the "shutdown countdown dialog", through individual app
7450 * termination, and through black screen kernel shutdown.
7452 systemShutdown
= true;
7455 * A shutdown was initiated, but then the shutdown
7456 * was cancelled, clearing systemShutdown to false here.
7458 systemShutdown
= false;
7462 case kPowerEventUserDisabledSleep
:
7463 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7464 userDisabledAllSleep
= (kOSBooleanTrue
== (OSBoolean
*) arg0
);
7467 case kPowerEventRegisterSystemCapabilityClient
:
7468 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7469 if (systemCapabilityNotifier
) {
7470 systemCapabilityNotifier
->release();
7471 systemCapabilityNotifier
= NULL
;
7474 systemCapabilityNotifier
= (IONotifier
*) arg0
;
7475 systemCapabilityNotifier
->retain();
7477 /* intentional fall-through */
7478 [[clang::fallthrough]];
7480 case kPowerEventRegisterKernelCapabilityClient
:
7481 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7482 if (!_joinedCapabilityClients
) {
7483 _joinedCapabilityClients
= OSSet::withCapacity(8);
7486 IONotifier
* notify
= (IONotifier
*) arg0
;
7487 if (_joinedCapabilityClients
) {
7488 _joinedCapabilityClients
->setObject(notify
);
7489 synchronizePowerTree( kIOPMSyncNoChildNotify
);
7495 case kPowerEventPolicyStimulus
:
7496 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7498 int stimulus
= (uintptr_t) arg0
;
7499 evaluatePolicy( stimulus
, (uint32_t) arg1
);
7503 case kPowerEventAssertionCreate
:
7504 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7506 pmAssertions
->handleCreateAssertion((OSData
*)arg0
);
7511 case kPowerEventAssertionRelease
:
7512 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7514 pmAssertions
->handleReleaseAssertion(arg1
);
7518 case kPowerEventAssertionSetLevel
:
7519 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7521 pmAssertions
->handleSetAssertionLevel(arg1
, (IOPMDriverAssertionLevel
)(uintptr_t)arg0
);
7525 case kPowerEventQueueSleepWakeUUID
:
7526 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7527 handleQueueSleepWakeUUID((OSObject
*)arg0
);
7529 case kPowerEventPublishSleepWakeUUID
:
7530 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7531 handlePublishSleepWakeUUID((bool)arg0
);
7534 case kPowerEventSetDisplayPowerOn
:
7535 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7540 displayPowerOnRequested
= true;
7542 displayPowerOnRequested
= false;
7544 handleDisplayPowerOn();
7549 //******************************************************************************
7550 // systemPowerEventOccurred
7552 // The power controller is notifying us of a hardware-related power management
7553 // event that we must handle.
7555 // systemPowerEventOccurred covers the same functionality that
7556 // receivePowerNotification does; it simply provides a richer API for conveying
7557 // more information.
7558 //******************************************************************************
7561 IOPMrootDomain::systemPowerEventOccurred(
7562 const OSSymbol
*event
,
7565 IOReturn attempt
= kIOReturnSuccess
;
7566 OSNumber
*newNumber
= NULL
;
7569 return kIOReturnBadArgument
;
7572 newNumber
= OSNumber::withNumber(intValue
, 8 * sizeof(intValue
));
7574 return kIOReturnInternalError
;
7577 attempt
= systemPowerEventOccurred(event
, (OSObject
*)newNumber
);
7579 newNumber
->release();
7585 IOPMrootDomain::setThermalState(OSObject
*value
)
7589 if (gIOPMWorkLoop
->inGate() == false) {
7590 gIOPMWorkLoop
->runAction(
7591 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::setThermalState
),
7597 if (value
&& (num
= OSDynamicCast(OSNumber
, value
))) {
7598 thermalWarningState
= ((num
->unsigned32BitValue() == kIOPMThermalLevelWarning
) ||
7599 (num
->unsigned32BitValue() == kIOPMThermalLevelTrap
)) ? 1 : 0;
7604 IOPMrootDomain::systemPowerEventOccurred(
7605 const OSSymbol
*event
,
7608 OSDictionary
*thermalsDict
= NULL
;
7609 bool shouldUpdate
= true;
7611 if (!event
|| !value
) {
7612 return kIOReturnBadArgument
;
7616 // We reuse featuresDict Lock because it already exists and guards
7617 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
7618 // of stepping on that lock.
7619 if (featuresDictLock
) {
7620 IOLockLock(featuresDictLock
);
7623 thermalsDict
= (OSDictionary
*)getProperty(kIOPMRootDomainPowerStatusKey
);
7625 if (thermalsDict
&& OSDynamicCast(OSDictionary
, thermalsDict
)) {
7626 thermalsDict
= OSDictionary::withDictionary(thermalsDict
);
7628 thermalsDict
= OSDictionary::withCapacity(1);
7631 if (!thermalsDict
) {
7632 shouldUpdate
= false;
7636 thermalsDict
->setObject(event
, value
);
7638 setProperty(kIOPMRootDomainPowerStatusKey
, thermalsDict
);
7640 thermalsDict
->release();
7644 if (featuresDictLock
) {
7645 IOLockUnlock(featuresDictLock
);
7650 event
->isEqualTo(kIOPMThermalLevelWarningKey
)) {
7651 setThermalState(value
);
7653 messageClients(kIOPMMessageSystemPowerEventOccurred
, (void *)NULL
);
7656 return kIOReturnSuccess
;
7659 //******************************************************************************
7660 // receivePowerNotification
7662 // The power controller is notifying us of a hardware-related power management
7663 // event that we must handle. This may be a result of an 'environment' interrupt
7664 // from the power mgt micro.
7665 //******************************************************************************
7668 IOPMrootDomain::receivePowerNotification( UInt32 msg
)
7670 if (msg
& kIOPMPowerButton
) {
7671 uint32_t currentPhase
= pmTracer
->getTracePhase();
7672 if (currentPhase
!= kIOPMTracePointSystemUp
&& currentPhase
> kIOPMTracePointSystemSleep
) {
7673 DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase
);
7674 swd_flags
|= SWD_PWR_BTN_STACKSHOT
;
7675 thread_call_enter(powerButtonDown
);
7677 DEBUG_LOG("power button pressed when system is up\n");
7679 } else if (msg
& kIOPMPowerButtonUp
) {
7680 if (swd_flags
& SWD_PWR_BTN_STACKSHOT
) {
7681 swd_flags
&= ~SWD_PWR_BTN_STACKSHOT
;
7682 thread_call_enter(powerButtonUp
);
7685 pmPowerStateQueue
->submitPowerEvent(
7686 kPowerEventReceivedPowerNotification
, (void *)(uintptr_t) msg
);
7688 return kIOReturnSuccess
;
7692 IOPMrootDomain::handlePowerNotification( UInt32 msg
)
7694 bool eval_clamshell
= false;
7695 bool eval_clamshell_alarm
= false;
7700 * Local (IOPMrootDomain only) eval clamshell command
7702 if (msg
& kLocalEvalClamshellCommand
) {
7703 if (isRTCAlarmWake
) {
7704 eval_clamshell_alarm
= true;
7706 // reset isRTCAlarmWake. This evaluation should happen only once
7707 // on RTC/Alarm wake. Any clamshell events after wake should follow
7708 // the regular evaluation
7709 isRTCAlarmWake
= false;
7711 eval_clamshell
= true;
7718 if (msg
& kIOPMOverTemp
) {
7719 MSG("PowerManagement emergency overtemp signal. Going to sleep!");
7720 privateSleepSystem(kIOPMSleepReasonThermalEmergency
);
7724 * Forward DW thermal notification to client, if system is not going to sleep
7726 if ((msg
& kIOPMDWOverTemp
) && (_systemTransitionType
!= kSystemTransitionSleep
)) {
7727 DLOG("DarkWake thermal limits message received!\n");
7729 messageClients(kIOPMMessageDarkWakeThermalEmergency
);
7735 if (msg
& kIOPMSleepNow
) {
7736 privateSleepSystem(kIOPMSleepReasonSoftware
);
7742 if (msg
& kIOPMPowerEmergency
) {
7743 lowBatteryCondition
= true;
7744 privateSleepSystem(kIOPMSleepReasonLowPower
);
7750 if (msg
& kIOPMClamshellOpened
) {
7751 DLOG("Clamshell opened\n");
7752 // Received clamshel open message from clamshell controlling driver
7753 // Update our internal state and tell general interest clients
7754 clamshellClosed
= false;
7755 clamshellExists
= true;
7757 // Don't issue a hid tickle when lid is open and polled on wake
7758 if (msg
& kIOPMSetValue
) {
7759 setProperty(kIOPMRootDomainWakeTypeKey
, "Lid Open");
7764 informCPUStateChange(kInformLid
, 0);
7766 // Tell general interest clients
7767 sendClientClamshellNotification();
7769 bool aborting
= ((lastSleepReason
== kIOPMSleepReasonClamshell
)
7770 || (lastSleepReason
== kIOPMSleepReasonIdle
)
7771 || (lastSleepReason
== kIOPMSleepReasonMaintenance
));
7773 userActivityCount
++;
7775 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount
, lastSleepReason
);
7780 * Send the clamshell interest notification since the lid is closing.
7782 if (msg
& kIOPMClamshellClosed
) {
7783 if (clamshellClosed
&& clamshellExists
) {
7784 DLOG("Ignoring redundant Clamshell close event\n");
7786 DLOG("Clamshell closed\n");
7787 // Received clamshel open message from clamshell controlling driver
7788 // Update our internal state and tell general interest clients
7789 clamshellClosed
= true;
7790 clamshellExists
= true;
7793 informCPUStateChange(kInformLid
, 1);
7795 // Tell general interest clients
7796 sendClientClamshellNotification();
7798 // And set eval_clamshell = so we can attempt
7799 eval_clamshell
= true;
7804 * Set Desktop mode (sent from graphics)
7806 * -> reevaluate lid state
7808 if (msg
& kIOPMSetDesktopMode
) {
7809 DLOG("Desktop mode\n");
7810 desktopMode
= (0 != (msg
& kIOPMSetValue
));
7811 msg
&= ~(kIOPMSetDesktopMode
| kIOPMSetValue
);
7813 sendClientClamshellNotification();
7815 // Re-evaluate the lid state
7816 eval_clamshell
= true;
7820 * AC Adaptor connected
7822 * -> reevaluate lid state
7824 if (msg
& kIOPMSetACAdaptorConnected
) {
7825 acAdaptorConnected
= (0 != (msg
& kIOPMSetValue
));
7826 msg
&= ~(kIOPMSetACAdaptorConnected
| kIOPMSetValue
);
7829 informCPUStateChange(kInformAC
, !acAdaptorConnected
);
7831 // Tell BSD if AC is connected
7832 // 0 == external power source; 1 == on battery
7833 post_sys_powersource(acAdaptorConnected
? 0:1);
7835 sendClientClamshellNotification();
7837 // Re-evaluate the lid state
7838 eval_clamshell
= true;
7840 // Lack of AC may have latched a display wrangler tickle.
7841 // This mirrors the hardware's USB wake event latch, where a latched
7842 // USB wake event followed by an AC attach will trigger a full wake.
7843 latchDisplayWranglerTickle( false );
7846 // AC presence will reset the standy timer delay adjustment.
7847 _standbyTimerResetSeconds
= 0;
7849 if (!userIsActive
) {
7850 // Reset userActivityTime when power supply is changed(rdr 13789330)
7851 clock_get_uptime(&userActivityTime
);
7856 * Enable Clamshell (external display disappear)
7858 * -> reevaluate lid state
7860 if (msg
& kIOPMEnableClamshell
) {
7861 DLOG("Clamshell enabled\n");
7862 // Re-evaluate the lid state
7863 // System should sleep on external display disappearance
7864 // in lid closed operation.
7865 if (true == clamshellDisabled
) {
7866 eval_clamshell
= true;
7869 clamshellDisabled
= false;
7870 sendClientClamshellNotification();
7874 * Disable Clamshell (external display appeared)
7875 * We don't bother re-evaluating clamshell state. If the system is awake,
7876 * the lid is probably open.
7878 if (msg
& kIOPMDisableClamshell
) {
7879 DLOG("Clamshell disabled\n");
7880 clamshellDisabled
= true;
7881 sendClientClamshellNotification();
7885 * Evaluate clamshell and SLEEP if appropiate
7887 if (eval_clamshell_alarm
&& clamshellClosed
) {
7888 if (shouldSleepOnRTCAlarmWake()) {
7889 privateSleepSystem(kIOPMSleepReasonClamshell
);
7891 } else if (eval_clamshell
&& clamshellClosed
) {
7892 if (shouldSleepOnClamshellClosed()) {
7893 privateSleepSystem(kIOPMSleepReasonClamshell
);
7895 evaluatePolicy( kStimulusDarkWakeEvaluate
);
7899 if (msg
& kIOPMProModeEngaged
) {
7901 DLOG("ProModeEngaged\n");
7902 messageClient(kIOPMMessageProModeStateChange
, systemCapabilityNotifier
, &newState
, sizeof(newState
));
7905 if (msg
& kIOPMProModeDisengaged
) {
7907 DLOG("ProModeDisengaged\n");
7908 messageClient(kIOPMMessageProModeStateChange
, systemCapabilityNotifier
, &newState
, sizeof(newState
));
7912 //******************************************************************************
7915 // Evaluate root-domain policy in response to external changes.
7916 //******************************************************************************
7919 IOPMrootDomain::evaluatePolicy( int stimulus
, uint32_t arg
)
7923 int idleSleepEnabled
: 1;
7924 int idleSleepDisabled
: 1;
7925 int displaySleep
: 1;
7926 int sleepDelayChanged
: 1;
7927 int evaluateDarkWake
: 1;
7928 int adjustPowerState
: 1;
7929 int userBecameInactive
: 1;
7939 case kStimulusDisplayWranglerSleep
:
7940 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7941 if (!wranglerAsleep
) {
7942 // first transition to wrangler sleep or lower
7943 flags
.bit
.displaySleep
= true;
7947 case kStimulusDisplayWranglerWake
:
7948 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7949 displayIdleForDemandSleep
= false;
7950 wranglerAsleep
= false;
7953 case kStimulusEnterUserActiveState
:
7954 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7955 if (_preventUserActive
) {
7956 DLOG("user active dropped\n");
7959 if (!userIsActive
) {
7960 userIsActive
= true;
7961 userWasActive
= true;
7962 clock_get_uptime(&gUserActiveAbsTime
);
7964 // Stay awake after dropping demand for display power on
7965 if (kFullWakeReasonDisplayOn
== fullWakeReason
) {
7966 fullWakeReason
= fFullWakeReasonDisplayOnAndLocalUser
;
7967 DLOG("User activity while in notification wake\n");
7968 changePowerStateWithOverrideTo( getRUN_STATE(), 0);
7971 kdebugTrace(kPMLogUserActiveState
, 0, 1, 0);
7972 setProperty(gIOPMUserIsActiveKey
, kOSBooleanTrue
);
7973 messageClients(kIOPMMessageUserIsActiveChanged
);
7975 flags
.bit
.idleSleepDisabled
= true;
7978 case kStimulusLeaveUserActiveState
:
7979 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7981 clock_get_uptime(&gUserInactiveAbsTime
);
7982 userIsActive
= false;
7983 clock_get_uptime(&userBecameInactiveTime
);
7984 flags
.bit
.userBecameInactive
= true;
7986 kdebugTrace(kPMLogUserActiveState
, 0, 0, 0);
7987 setProperty(gIOPMUserIsActiveKey
, kOSBooleanFalse
);
7988 messageClients(kIOPMMessageUserIsActiveChanged
);
7992 case kStimulusAggressivenessChanged
:
7994 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
7995 unsigned long minutesToIdleSleep
= 0;
7996 unsigned long minutesToDisplayDim
= 0;
7997 unsigned long minutesDelta
= 0;
7999 // Fetch latest display and system sleep slider values.
8000 getAggressiveness(kPMMinutesToSleep
, &minutesToIdleSleep
);
8001 getAggressiveness(kPMMinutesToDim
, &minutesToDisplayDim
);
8002 DLOG("aggressiveness changed: system %u->%u, display %u\n",
8003 (uint32_t) sleepSlider
,
8004 (uint32_t) minutesToIdleSleep
,
8005 (uint32_t) minutesToDisplayDim
);
8007 DLOG("idle time -> %ld secs (ena %d)\n",
8008 idleSeconds
, (minutesToIdleSleep
!= 0));
8011 // How long to wait before sleeping the system once
8012 // the displays turns off is indicated by 'extraSleepDelay'.
8014 if (minutesToIdleSleep
> minutesToDisplayDim
) {
8015 minutesDelta
= minutesToIdleSleep
- minutesToDisplayDim
;
8016 } else if (minutesToIdleSleep
== minutesToDisplayDim
) {
8020 if ((!idleSleepEnabled
) && (minutesToIdleSleep
!= 0)) {
8021 idleSleepEnabled
= flags
.bit
.idleSleepEnabled
= true;
8024 if ((idleSleepEnabled
) && (minutesToIdleSleep
== 0)) {
8025 flags
.bit
.idleSleepDisabled
= true;
8026 idleSleepEnabled
= false;
8028 if (0x7fffffff == minutesToIdleSleep
) {
8029 minutesToIdleSleep
= idleSeconds
;
8032 if (((minutesDelta
!= extraSleepDelay
) ||
8033 (userActivityTime
!= userActivityTime_prev
)) &&
8034 !flags
.bit
.idleSleepEnabled
&& !flags
.bit
.idleSleepDisabled
) {
8035 flags
.bit
.sleepDelayChanged
= true;
8038 if (systemDarkWake
&& !darkWakeToSleepASAP
&&
8039 (flags
.bit
.idleSleepEnabled
|| flags
.bit
.idleSleepDisabled
)) {
8040 // Reconsider decision to remain in dark wake
8041 flags
.bit
.evaluateDarkWake
= true;
8044 sleepSlider
= minutesToIdleSleep
;
8045 extraSleepDelay
= minutesDelta
;
8046 userActivityTime_prev
= userActivityTime
;
8049 case kStimulusDemandSystemSleep
:
8050 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8051 displayIdleForDemandSleep
= true;
8052 if (wrangler
&& wranglerIdleSettings
) {
8053 // Request wrangler idle only when demand sleep is triggered
8055 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
8056 wrangler
->setProperties(wranglerIdleSettings
);
8057 DLOG("Requested wrangler idle\n");
8060 // arg = sleepReason
8061 changePowerStateWithOverrideTo( SLEEP_STATE
, arg
);
8064 case kStimulusAllowSystemSleepChanged
:
8065 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8066 flags
.bit
.adjustPowerState
= true;
8069 case kStimulusDarkWakeActivityTickle
:
8070 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8071 // arg == true implies real and not self generated wrangler tickle.
8072 // Update wake type on PM work loop instead of the tickle thread to
8073 // eliminate the possibility of an early tickle clobbering the wake
8074 // type set by the platform driver.
8076 setProperty(kIOPMRootDomainWakeTypeKey
, kIOPMRootDomainWakeTypeHIDActivity
);
8079 if (false == wranglerTickled
) {
8080 if (latchDisplayWranglerTickle(true)) {
8081 DLOG("latched tickle\n");
8085 wranglerTickled
= true;
8086 DLOG("Requesting full wake after dark wake activity tickle\n");
8087 requestFullWake( kFullWakeReasonLocalUser
);
8091 case kStimulusDarkWakeEntry
:
8092 case kStimulusDarkWakeReentry
:
8093 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8094 // Any system transitions since the last dark wake transition
8095 // will invalid the stimulus.
8097 if (arg
== _systemStateGeneration
) {
8098 DLOG("dark wake entry\n");
8099 systemDarkWake
= true;
8101 // Keep wranglerAsleep an invariant when wrangler is absent
8103 wranglerAsleep
= true;
8106 if (kStimulusDarkWakeEntry
== stimulus
) {
8107 clock_get_uptime(&userBecameInactiveTime
);
8108 flags
.bit
.evaluateDarkWake
= true;
8109 if (activitySinceSleep()) {
8110 DLOG("User activity recorded while going to darkwake\n");
8115 // Always accelerate disk spindown while in dark wake,
8116 // even if system does not support/allow sleep.
8118 cancelIdleSleepTimer();
8119 setQuickSpinDownTimeout();
8123 case kStimulusDarkWakeEvaluate
:
8124 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8125 if (systemDarkWake
) {
8126 flags
.bit
.evaluateDarkWake
= true;
8130 case kStimulusNoIdleSleepPreventers
:
8131 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8132 flags
.bit
.adjustPowerState
= true;
8134 } /* switch(stimulus) */
8136 if (flags
.bit
.evaluateDarkWake
&& (kFullWakeReasonNone
== fullWakeReason
)) {
8137 if (darkWakeToSleepASAP
||
8138 (clamshellClosed
&& !(desktopMode
&& acAdaptorConnected
))) {
8139 uint32_t newSleepReason
;
8141 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
8142 // System was previously in full wake. Sleep reason from
8143 // full to dark already recorded in fullToDarkReason.
8145 if (lowBatteryCondition
) {
8146 newSleepReason
= kIOPMSleepReasonLowPower
;
8148 newSleepReason
= fullToDarkReason
;
8151 // In dark wake from system sleep.
8153 if (darkWakeSleepService
) {
8154 newSleepReason
= kIOPMSleepReasonSleepServiceExit
;
8156 newSleepReason
= kIOPMSleepReasonMaintenance
;
8160 if (checkSystemCanSleep(newSleepReason
)) {
8161 privateSleepSystem(newSleepReason
);
8163 } else { // non-maintenance (network) dark wake
8164 if (checkSystemCanSleep(kIOPMSleepReasonIdle
)) {
8165 // Release power clamp, and wait for children idle.
8166 adjustPowerState(true);
8168 changePowerStateToPriv(getRUN_STATE());
8173 if (systemDarkWake
) {
8174 // The rest are irrelevant while system is in dark wake.
8178 if ((flags
.bit
.displaySleep
) &&
8179 (kFullWakeReasonDisplayOn
== fullWakeReason
)) {
8180 // kIOPMSleepReasonMaintenance?
8181 DLOG("Display sleep while in notification wake\n");
8182 changePowerStateWithOverrideTo( SLEEP_STATE
, kIOPMSleepReasonMaintenance
);
8185 if (flags
.bit
.userBecameInactive
|| flags
.bit
.sleepDelayChanged
) {
8186 bool cancelQuickSpindown
= false;
8188 if (flags
.bit
.sleepDelayChanged
) {
8189 // Cancel existing idle sleep timer and quick disk spindown.
8190 // New settings will be applied by the idleSleepEnabled flag
8191 // handler below if idle sleep is enabled.
8193 DLOG("extra sleep timer changed\n");
8194 cancelIdleSleepTimer();
8195 cancelQuickSpindown
= true;
8197 DLOG("user inactive\n");
8200 if (!userIsActive
&& idleSleepEnabled
) {
8201 startIdleSleepTimer(getTimeToIdleSleep());
8204 if (cancelQuickSpindown
) {
8205 restoreUserSpinDownTimeout();
8209 if (flags
.bit
.idleSleepEnabled
) {
8210 DLOG("idle sleep timer enabled\n");
8212 changePowerStateToPriv(getRUN_STATE());
8213 startIdleSleepTimer( idleSeconds
);
8215 // Start idle timer if prefs now allow system sleep
8216 // and user is already inactive. Disk spindown is
8217 // accelerated upon timer expiration.
8219 if (!userIsActive
) {
8220 startIdleSleepTimer(getTimeToIdleSleep());
8225 if (flags
.bit
.idleSleepDisabled
) {
8226 DLOG("idle sleep timer disabled\n");
8227 cancelIdleSleepTimer();
8228 restoreUserSpinDownTimeout();
8232 if (flags
.bit
.adjustPowerState
) {
8233 bool sleepASAP
= false;
8235 if (!systemBooting
&& (0 == idleSleepPreventersCount())) {
8237 changePowerStateToPriv(getRUN_STATE());
8238 if (idleSleepEnabled
) {
8239 // stay awake for at least idleSeconds
8240 startIdleSleepTimer(idleSeconds
);
8242 } else if (!extraSleepDelay
&& !idleSleepTimerPending
&& !systemDarkWake
) {
8247 adjustPowerState(sleepASAP
);
8251 //******************************************************************************
8254 IOPMrootDomain::idleSleepPreventersCount()
8256 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
8258 unsigned int count __block
;
8260 preventIdleSleepList
->iterateObjects(^bool (OSObject
* obj
)
8262 count
+= (NULL
== obj
->metaCast("AppleARMBacklight"));
8267 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
8269 return preventIdleSleepList
->getCount();
8273 //******************************************************************************
8276 // Request transition from dark wake to full wake
8277 //******************************************************************************
8280 IOPMrootDomain::requestFullWake( FullWakeReason reason
)
8282 uint32_t options
= 0;
8283 IOService
* pciRoot
= NULL
;
8284 bool promotion
= false;
8286 // System must be in dark wake and a valid reason for entering full wake
8287 if ((kFullWakeReasonNone
== reason
) ||
8288 (kFullWakeReasonNone
!= fullWakeReason
) ||
8289 (CAP_CURRENT(kIOPMSystemCapabilityGraphics
))) {
8293 // Will clear reason upon exit from full wake
8294 fullWakeReason
= reason
;
8296 _desiredCapability
|= (kIOPMSystemCapabilityGraphics
|
8297 kIOPMSystemCapabilityAudio
);
8299 if ((kSystemTransitionWake
== _systemTransitionType
) &&
8300 !(_pendingCapability
& kIOPMSystemCapabilityGraphics
) &&
8301 !graphicsSuppressed
) {
8302 // Promote to full wake while waking up to dark wake due to tickle.
8303 // PM will hold off notifying the graphics subsystem about system wake
8304 // as late as possible, so if a HID tickle does arrive, graphics can
8305 // power up on this same wake cycle. The latency to power up graphics
8306 // on the next cycle can be huge on some systems. However, once any
8307 // graphics suppression has taken effect, it is too late. All other
8308 // graphics devices must be similarly suppressed. But the delay till
8309 // the following cycle should be short.
8311 _pendingCapability
|= (kIOPMSystemCapabilityGraphics
|
8312 kIOPMSystemCapabilityAudio
);
8314 // Immediately bring up audio and graphics
8315 pciRoot
= pciHostBridgeDriver
;
8316 willEnterFullWake();
8320 // Unsafe to cancel once graphics was powered.
8321 // If system woke from dark wake, the return to sleep can
8322 // be cancelled. "awake -> dark -> sleep" transition
8323 // can be canceled also, during the "dark --> sleep" phase
8324 // *prior* to driver power down.
8325 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics
) ||
8326 _pendingCapability
== 0) {
8327 options
|= kIOPMSyncCancelPowerDown
;
8330 synchronizePowerTree(options
, pciRoot
);
8331 if (kFullWakeReasonLocalUser
== fullWakeReason
) {
8332 // IOGraphics doesn't light the display even though graphics is
8333 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
8334 // So, do an explicit activity tickle
8336 wrangler
->activityTickle(0, 0);
8340 // Log a timestamp for the initial full wake request.
8341 // System may not always honor this full wake request.
8342 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
8346 clock_get_uptime(&now
);
8347 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
8348 absolutetime_to_nanoseconds(now
, &nsec
);
8349 MSG("full wake %s (reason %u) %u ms\n",
8350 promotion
? "promotion" : "request",
8351 fullWakeReason
, ((int)((nsec
) / NSEC_PER_MSEC
)));
8355 //******************************************************************************
8356 // willEnterFullWake
8358 // System will enter full wake from sleep, from dark wake, or from dark
8359 // wake promotion. This function aggregate things that are in common to
8360 // all three full wake transitions.
8362 // Assumptions: fullWakeReason was updated
8363 //******************************************************************************
8366 IOPMrootDomain::willEnterFullWake( void )
8368 hibernateRetry
= false;
8369 sleepToStandby
= false;
8370 standbyNixed
= false;
8371 resetTimers
= false;
8372 sleepTimerMaintenance
= false;
8374 _systemMessageClientMask
= kSystemMessageClientPowerd
|
8375 kSystemMessageClientLegacyApp
;
8377 if ((_highestCapability
& kIOPMSystemCapabilityGraphics
) == 0) {
8378 // Initial graphics full power
8379 _systemMessageClientMask
|= kSystemMessageClientKernel
;
8381 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
8382 setProperty(gIOPMUserTriggeredFullWakeKey
,
8383 (kFullWakeReasonLocalUser
== fullWakeReason
) ?
8384 kOSBooleanTrue
: kOSBooleanFalse
);
8387 IOHibernateSetWakeCapabilities(_pendingCapability
);
8390 IOService::setAdvisoryTickleEnable( true );
8391 tellClients(kIOMessageSystemWillPowerOn
);
8392 preventTransitionToUserActive(false);
8395 //******************************************************************************
8396 // fullWakeDelayedWork
8398 // System has already entered full wake. Invoked by a delayed thread call.
8399 //******************************************************************************
8402 IOPMrootDomain::fullWakeDelayedWork( void )
8404 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
8405 // Not gated, don't modify state
8406 if ((kSystemTransitionNone
== _systemTransitionType
) &&
8407 CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
8408 receivePowerNotification( kLocalEvalClamshellCommand
);
8413 //******************************************************************************
8414 // evaluateAssertions
8416 //******************************************************************************
8418 // Bitmask of all kernel assertions that prevent system idle sleep.
8419 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
8420 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
8421 (kIOPMDriverAssertionReservedBit7 | \
8422 kIOPMDriverAssertionPreventSystemIdleSleepBit)
8425 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions
, IOPMDriverAssertionType oldAssertions
)
8427 IOPMDriverAssertionType changedBits
= newAssertions
^ oldAssertions
;
8429 messageClients(kIOPMMessageDriverAssertionsChanged
);
8431 if (changedBits
& kIOPMDriverAssertionPreventDisplaySleepBit
) {
8433 bool value
= (newAssertions
& kIOPMDriverAssertionPreventDisplaySleepBit
) ? true : false;
8435 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value
);
8436 wrangler
->setIgnoreIdleTimer( value
);
8440 if (changedBits
& kIOPMDriverAssertionCPUBit
) {
8441 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
8443 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit
& newAssertions
)));
8445 evaluatePolicy(_aotNow
? kStimulusNoIdleSleepPreventers
: kStimulusDarkWakeEvaluate
);
8447 evaluatePolicy(kStimulusDarkWakeEvaluate
);
8449 if (!assertOnWakeSecs
&& gIOLastWakeAbsTime
) {
8451 clock_usec_t microsecs
;
8452 clock_get_uptime(&now
);
8453 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
8454 absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
);
8455 if (assertOnWakeReport
) {
8456 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
);
8457 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
);
8462 if (changedBits
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) {
8463 if ((newAssertions
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) != 0) {
8464 if ((oldAssertions
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) == 0) {
8465 DLOG("PreventIdleSleep driver assertion raised\n");
8466 bool ok
= updatePreventIdleSleepList(this, true);
8467 if (ok
&& (changedBits
& kIOPMDriverAssertionPreventSystemIdleSleepBit
)) {
8468 // Cancel idle sleep if there is one in progress
8469 cancelIdlePowerDown(this);
8473 DLOG("PreventIdleSleep driver assertion dropped\n");
8474 updatePreventIdleSleepList(this, false);
8482 //******************************************************************************
8485 //******************************************************************************
8488 IOPMrootDomain::pmStatsRecordEvent(
8490 AbsoluteTime timestamp
)
8492 bool starting
= eventIndex
& kIOPMStatsEventStartFlag
? true:false;
8493 bool stopping
= eventIndex
& kIOPMStatsEventStopFlag
? true:false;
8496 OSData
*publishPMStats
= NULL
;
8498 eventIndex
&= ~(kIOPMStatsEventStartFlag
| kIOPMStatsEventStopFlag
);
8500 absolutetime_to_nanoseconds(timestamp
, &nsec
);
8502 switch (eventIndex
) {
8503 case kIOPMStatsHibernateImageWrite
:
8505 gPMStats
.hibWrite
.start
= nsec
;
8506 } else if (stopping
) {
8507 gPMStats
.hibWrite
.stop
= nsec
;
8511 delta
= gPMStats
.hibWrite
.stop
- gPMStats
.hibWrite
.start
;
8512 IOLog("PMStats: Hibernate write took %qd ms\n", delta
/ NSEC_PER_MSEC
);
8515 case kIOPMStatsHibernateImageRead
:
8517 gPMStats
.hibRead
.start
= nsec
;
8518 } else if (stopping
) {
8519 gPMStats
.hibRead
.stop
= nsec
;
8523 delta
= gPMStats
.hibRead
.stop
- gPMStats
.hibRead
.start
;
8524 IOLog("PMStats: Hibernate read took %qd ms\n", delta
/ NSEC_PER_MSEC
);
8526 publishPMStats
= OSData::withBytes(&gPMStats
, sizeof(gPMStats
));
8527 setProperty(kIOPMSleepStatisticsKey
, publishPMStats
);
8528 publishPMStats
->release();
8529 bzero(&gPMStats
, sizeof(gPMStats
));
8536 * Appends a record of the application response to
8537 * IOPMrootDomain::pmStatsAppResponses
8540 IOPMrootDomain::pmStatsRecordApplicationResponse(
8541 const OSSymbol
*response
,
8547 IOPMPowerStateIndex powerState
)
8549 OSDictionary
*responseDescription
= NULL
;
8550 OSNumber
*delayNum
= NULL
;
8551 OSNumber
*powerCaps
= NULL
;
8552 OSNumber
*pidNum
= NULL
;
8553 OSNumber
*msgNum
= NULL
;
8554 const OSSymbol
*appname
;
8555 const OSSymbol
*sleep
= NULL
, *wake
= NULL
;
8556 IOPMServiceInterestNotifier
*notify
= NULL
;
8558 if (object
&& (notify
= OSDynamicCast(IOPMServiceInterestNotifier
, object
))) {
8559 if (response
->isEqualTo(gIOPMStatsResponseTimedOut
)) {
8560 notify
->ackTimeoutCnt
++;
8562 notify
->ackTimeoutCnt
= 0;
8566 if (response
->isEqualTo(gIOPMStatsResponsePrompt
) ||
8567 (_systemTransitionType
== kSystemTransitionNone
) || (_systemTransitionType
== kSystemTransitionNewCapClient
)) {
8572 if (response
->isEqualTo(gIOPMStatsDriverPSChangeSlow
)) {
8573 kdebugTrace(kPMLogDrvPSChangeDelay
, id
, messageType
, delay_ms
);
8574 } else if (notify
) {
8575 // User space app or kernel capability client
8577 kdebugTrace(kPMLogAppResponseDelay
, id
, notify
->msgType
, delay_ms
);
8579 kdebugTrace(kPMLogDrvResponseDelay
, notify
->uuid0
, messageType
, delay_ms
);
8581 notify
->msgType
= 0;
8584 responseDescription
= OSDictionary::withCapacity(5);
8585 if (responseDescription
) {
8587 responseDescription
->setObject(_statsResponseTypeKey
, response
);
8590 msgNum
= OSNumber::withNumber(messageType
, 32);
8592 responseDescription
->setObject(_statsMessageTypeKey
, msgNum
);
8596 if (!name
&& notify
&& notify
->identifier
) {
8597 name
= notify
->identifier
->getCStringNoCopy();
8600 if (name
&& (strlen(name
) > 0)) {
8601 appname
= OSSymbol::withCString(name
);
8603 responseDescription
->setObject(_statsNameKey
, appname
);
8608 if (!id
&& notify
) {
8612 pidNum
= OSNumber::withNumber(id
, 64);
8614 responseDescription
->setObject(_statsPIDKey
, pidNum
);
8619 delayNum
= OSNumber::withNumber(delay_ms
, 32);
8621 responseDescription
->setObject(_statsTimeMSKey
, delayNum
);
8622 delayNum
->release();
8625 if (response
->isEqualTo(gIOPMStatsDriverPSChangeSlow
)) {
8626 powerCaps
= OSNumber::withNumber(powerState
, 32);
8628 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
8629 IOLog("%s::powerStateChange type(%d) to(%lu) async took %d ms\n",
8631 powerState
, delay_ms
);
8634 powerCaps
= OSNumber::withNumber(_pendingCapability
, 32);
8637 responseDescription
->setObject(_statsPowerCapsKey
, powerCaps
);
8638 powerCaps
->release();
8641 sleep
= OSSymbol::withCString("Sleep");
8642 wake
= OSSymbol::withCString("Wake");
8643 if (_systemTransitionType
== kSystemTransitionSleep
) {
8644 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, sleep
);
8645 } else if (_systemTransitionType
== kSystemTransitionWake
) {
8646 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, wake
);
8647 } else if (_systemTransitionType
== kSystemTransitionCapability
) {
8648 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) {
8649 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, sleep
);
8650 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
8651 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, wake
);
8663 IOLockLock(pmStatsLock
);
8664 if (pmStatsAppResponses
&& pmStatsAppResponses
->getCount() < 50) {
8665 pmStatsAppResponses
->setObject(responseDescription
);
8667 IOLockUnlock(pmStatsLock
);
8669 responseDescription
->release();
8676 // MARK: PMTraceWorker
8678 //******************************************************************************
8679 // TracePoint support
8681 //******************************************************************************
8683 #define kIOPMRegisterNVRAMTracePointHandlerKey \
8684 "IOPMRegisterNVRAMTracePointHandler"
8687 IOPMrootDomain::callPlatformFunction(
8688 const OSSymbol
* functionName
,
8689 bool waitForFunction
,
8690 void * param1
, void * param2
,
8691 void * param3
, void * param4
)
8693 uint32_t bootFailureCode
= 0xffffffff;
8694 if (pmTracer
&& functionName
&&
8695 functionName
->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey
) &&
8696 !pmTracer
->tracePointHandler
&& !pmTracer
->tracePointTarget
) {
8697 uint32_t tracePointPhases
, tracePointPCI
;
8698 uint64_t statusCode
;
8700 pmTracer
->tracePointHandler
= (IOPMTracePointHandler
) param1
;
8701 pmTracer
->tracePointTarget
= (void *) param2
;
8702 tracePointPCI
= (uint32_t)(uintptr_t) param3
;
8703 tracePointPhases
= (uint32_t)(uintptr_t) param4
;
8704 if ((tracePointPhases
& 0xff) == kIOPMTracePointSystemSleep
) {
8705 IORegistryEntry
*node
= IORegistryEntry::fromPath( "/chosen", gIODTPlane
);
8707 OSData
*data
= OSDynamicCast( OSData
, node
->getProperty(kIOEFIBootRomFailureKey
));
8708 if (data
&& data
->getLength() == sizeof(bootFailureCode
)) {
8709 memcpy(&bootFailureCode
, data
->getBytesNoCopy(), sizeof(bootFailureCode
));
8713 // Failure code from EFI/BootRom is a four byte structure
8714 tracePointPCI
= OSSwapBigToHostInt32(bootFailureCode
);
8716 statusCode
= (((uint64_t)tracePointPCI
) << 32) | tracePointPhases
;
8717 if ((tracePointPhases
& 0xff) != kIOPMTracePointSystemUp
) {
8718 MSG("Sleep failure code 0x%08x 0x%08x\n",
8719 tracePointPCI
, tracePointPhases
);
8721 setProperty(kIOPMSleepWakeFailureCodeKey
, statusCode
, 64);
8722 pmTracer
->tracePointHandler( pmTracer
->tracePointTarget
, 0, 0 );
8724 return kIOReturnSuccess
;
8727 else if (functionName
&&
8728 functionName
->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey
)) {
8729 if (gSleepPolicyHandler
) {
8730 return kIOReturnExclusiveAccess
;
8733 return kIOReturnBadArgument
;
8735 gSleepPolicyHandler
= (IOPMSystemSleepPolicyHandler
) param1
;
8736 gSleepPolicyTarget
= (void *) param2
;
8737 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue
);
8738 return kIOReturnSuccess
;
8742 return super::callPlatformFunction(
8743 functionName
, waitForFunction
, param1
, param2
, param3
, param4
);
8747 IOPMrootDomain::kdebugTrace(uint32_t event
, uint64_t id
,
8748 uintptr_t param1
, uintptr_t param2
, uintptr_t param3
)
8750 uint32_t code
= IODBG_POWER(event
);
8751 uint64_t regId
= id
;
8753 regId
= getRegistryEntryID();
8755 IOTimeStampConstant(code
, (uintptr_t) regId
, param1
, param2
, param3
);
8760 IOPMrootDomain::tracePoint( uint8_t point
)
8762 if (systemBooting
) {
8766 if (kIOPMTracePointWakeCapabilityClients
== point
) {
8767 acceptSystemWakeEvents(false);
8770 kdebugTrace(kPMLogSleepWakeTracePoint
, 0, point
, 0);
8771 pmTracer
->tracePoint(point
);
8775 IOPMrootDomain::traceDetail(OSObject
*object
, bool start
)
8777 IOPMServiceInterestNotifier
*notifier
;
8779 if (systemBooting
) {
8783 notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, object
);
8789 pmTracer
->traceDetail( notifier
->uuid0
>> 32 );
8790 kdebugTrace(kPMLogSleepWakeMessage
, pmTracer
->getTracePhase(), notifier
->msgType
, notifier
->uuid0
, notifier
->uuid1
);
8791 if (notifier
->identifier
) {
8792 DLOG("trace point 0x%02x msg 0x%x to %s\n", pmTracer
->getTracePhase(), notifier
->msgType
,
8793 notifier
->identifier
->getCStringNoCopy());
8795 DLOG("trace point 0x%02x msg 0x%x\n", pmTracer
->getTracePhase(), notifier
->msgType
);
8797 notifierThread
= current_thread();
8798 notifierObject
= notifier
;
8801 notifierThread
= NULL
;
8802 notifierObject
= NULL
;
8803 notifier
->release();
8809 IOPMrootDomain::traceAckDelay(OSObject
*object
, uint32_t response
, uint32_t delay_ms
)
8811 IOPMServiceInterestNotifier
*notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, object
);
8813 DLOG("Unknown notifier\n");
8817 if (!systemBooting
) {
8818 kdebugTrace(kPMLogDrvResponseDelay
, notifier
->uuid0
, notifier
->uuid1
, response
, delay_ms
);
8819 if (notifier
->identifier
) {
8820 DLOG("Response from %s took %d ms(response:%d)\n",
8821 notifier
->identifier
->getCStringNoCopy(), delay_ms
, response
);
8823 DLOG("Response from kext UUID %llx-%llx took %d ms(response:%d)\n",
8824 notifier
->uuid0
, notifier
->uuid1
, delay_ms
, response
);
8830 IOPMrootDomain::traceDetail(uint32_t msgType
, uint32_t msgIndex
, uint32_t delay
)
8832 if (!systemBooting
) {
8833 uint32_t detail
= ((msgType
& 0xffff) << 16) | (delay
& 0xffff);
8834 pmTracer
->traceDetail( detail
);
8835 kdebugTrace(kPMLogSleepWakeTracePoint
, pmTracer
->getTracePhase(), msgType
, delay
);
8836 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer
->getTracePhase(), msgType
, delay
);
8842 IOPMrootDomain::configureReportGated(uint64_t channel_id
, uint64_t action
, void *result
)
8845 void **report
= NULL
;
8848 uint32_t *clientCnt
;
8853 if (channel_id
== kAssertDelayChID
) {
8854 report
= &assertOnWakeReport
;
8855 bktCnt
= kAssertDelayBcktCnt
;
8856 bktSize
= kAssertDelayBcktSize
;
8857 clientCnt
= &assertOnWakeClientCnt
;
8858 } else if (channel_id
== kSleepDelaysChID
) {
8859 report
= &sleepDelaysReport
;
8860 bktCnt
= kSleepDelaysBcktCnt
;
8861 bktSize
= kSleepDelaysBcktSize
;
8862 clientCnt
= &sleepDelaysClientCnt
;
8866 case kIOReportEnable
:
8873 reportSize
= HISTREPORT_BUFSIZE(bktCnt
);
8874 *report
= IOMalloc(reportSize
);
8875 if (*report
== NULL
) {
8878 bzero(*report
, reportSize
);
8879 HISTREPORT_INIT(bktCnt
, bktSize
, *report
, reportSize
,
8880 getRegistryEntryID(), channel_id
, kIOReportCategoryPower
);
8882 if (channel_id
== kAssertDelayChID
) {
8883 assertOnWakeSecs
= 0;
8888 case kIOReportDisable
:
8889 if (*clientCnt
== 0) {
8892 if (*clientCnt
== 1) {
8893 IOFree(*report
, HISTREPORT_BUFSIZE(bktCnt
));
8898 if (channel_id
== kAssertDelayChID
) {
8899 assertOnWakeSecs
= -1; // Invalid value to prevent updates
8903 case kIOReportGetDimensions
:
8905 HISTREPORT_UPDATERES(*report
, kIOReportGetDimensions
, result
);
8914 IOPMrootDomain::configureReport(IOReportChannelList
*channelList
,
8915 IOReportConfigureAction action
,
8920 uint64_t configAction
= (uint64_t)action
;
8922 for (cnt
= 0; cnt
< channelList
->nchannels
; cnt
++) {
8923 if ((channelList
->channels
[cnt
].channel_id
== kSleepCntChID
) ||
8924 (channelList
->channels
[cnt
].channel_id
== kDarkWkCntChID
) ||
8925 (channelList
->channels
[cnt
].channel_id
== kUserWkCntChID
)) {
8926 if (action
!= kIOReportGetDimensions
) {
8929 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
8930 } else if ((channelList
->channels
[cnt
].channel_id
== kAssertDelayChID
) ||
8931 (channelList
->channels
[cnt
].channel_id
== kSleepDelaysChID
)) {
8932 gIOPMWorkLoop
->runAction(
8933 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::configureReportGated
),
8934 (OSObject
*)this, (void *)channelList
->channels
[cnt
].channel_id
,
8935 (void *)configAction
, (void *)result
);
8939 return super::configureReport(channelList
, action
, result
, destination
);
8943 IOPMrootDomain::updateReportGated(uint64_t ch_id
, void *result
, IOBufferMemoryDescriptor
*dest
)
8952 if (ch_id
== kAssertDelayChID
) {
8953 report
= &assertOnWakeReport
;
8954 } else if (ch_id
== kSleepDelaysChID
) {
8955 report
= &sleepDelaysReport
;
8958 if (*report
== NULL
) {
8959 return kIOReturnNotOpen
;
8962 HISTREPORT_UPDATEPREP(*report
, data2cpy
, size2cpy
);
8963 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
8964 return kIOReturnOverrun
;
8967 HISTREPORT_UPDATERES(*report
, kIOReportCopyChannelData
, result
);
8968 dest
->appendBytes(data2cpy
, size2cpy
);
8970 return kIOReturnSuccess
;
8974 IOPMrootDomain::updateReport(IOReportChannelList
*channelList
,
8975 IOReportUpdateAction action
,
8981 uint8_t buf
[SIMPLEREPORT_BUFSIZE
];
8982 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
8986 if (action
!= kIOReportCopyChannelData
) {
8990 for (cnt
= 0; cnt
< channelList
->nchannels
; cnt
++) {
8991 ch_id
= channelList
->channels
[cnt
].channel_id
;
8993 if ((ch_id
== kAssertDelayChID
) || (ch_id
== kSleepDelaysChID
)) {
8994 gIOPMWorkLoop
->runAction(
8995 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::updateReportGated
),
8996 (OSObject
*)this, (void *)ch_id
,
8997 (void *)result
, (void *)dest
);
8999 } else if ((ch_id
== kSleepCntChID
) ||
9000 (ch_id
== kDarkWkCntChID
) || (ch_id
== kUserWkCntChID
)) {
9001 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), ch_id
, kIOReportCategoryPower
);
9006 if (ch_id
== kSleepCntChID
) {
9007 SIMPLEREPORT_SETVALUE(buf
, sleepCnt
);
9008 } else if (ch_id
== kDarkWkCntChID
) {
9009 SIMPLEREPORT_SETVALUE(buf
, darkWakeCnt
);
9010 } else if (ch_id
== kUserWkCntChID
) {
9011 SIMPLEREPORT_SETVALUE(buf
, displayWakeCnt
);
9014 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
9015 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
9016 dest
->appendBytes(data2cpy
, size2cpy
);
9020 return super::updateReport(channelList
, action
, result
, destination
);
9024 //******************************************************************************
9025 // PMTraceWorker Class
9027 //******************************************************************************
9030 #define super OSObject
9031 OSDefineMetaClassAndStructors(PMTraceWorker
, OSObject
)
9033 #define kPMBestGuessPCIDevicesCount 25
9034 #define kPMMaxRTCBitfieldSize 32
9036 PMTraceWorker
* PMTraceWorker::tracer(IOPMrootDomain
* owner
)
9040 me
= OSTypeAlloc( PMTraceWorker
);
9041 if (!me
|| !me
->init()) {
9045 DLOG("PMTraceWorker %p\n", OBFUSCATE(me
));
9047 // Note that we cannot instantiate the PCI device -> bit mappings here, since
9048 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
9049 // this dictionary lazily.
9051 me
->pciDeviceBitMappings
= NULL
;
9052 me
->pmTraceWorkerLock
= IOLockAlloc();
9053 me
->tracePhase
= kIOPMTracePointSystemUp
;
9054 me
->traceData32
= 0;
9055 me
->loginWindowData
= 0;
9056 me
->coreDisplayData
= 0;
9057 me
->coreGraphicsData
= 0;
9062 PMTraceWorker::RTC_TRACE(void)
9064 if (tracePointHandler
&& tracePointTarget
) {
9067 IOLockLock(pmTraceWorkerLock
);
9068 wordA
= (loginWindowData
<< 24) | (coreDisplayData
<< 16) |
9069 (coreGraphicsData
<< 8) | tracePhase
;
9070 IOLockUnlock(pmTraceWorkerLock
);
9072 tracePointHandler( tracePointTarget
, traceData32
, wordA
);
9073 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32
, wordA
);
9075 #if DEVELOPMENT || DEBUG
9076 if ((swd_panic_phase
!= 0) && (swd_panic_phase
== tracePhase
)) {
9077 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase
);
9078 IOLock
*l
= IOLockAlloc();
9086 PMTraceWorker::recordTopLevelPCIDevice(IOService
* pciDevice
)
9088 const OSSymbol
* deviceName
;
9091 IOLockLock(pmTraceWorkerLock
);
9093 if (!pciDeviceBitMappings
) {
9094 pciDeviceBitMappings
= OSArray::withCapacity(kPMBestGuessPCIDevicesCount
);
9095 if (!pciDeviceBitMappings
) {
9100 // Check for bitmask overflow.
9101 if (pciDeviceBitMappings
->getCount() >= kPMMaxRTCBitfieldSize
) {
9105 if ((deviceName
= pciDevice
->copyName()) &&
9106 (pciDeviceBitMappings
->getNextIndexOfObject(deviceName
, 0) == (unsigned int)-1) &&
9107 pciDeviceBitMappings
->setObject(deviceName
)) {
9108 index
= pciDeviceBitMappings
->getCount() - 1;
9109 _LOG("PMTrace PCI array: set object %s => %d\n",
9110 deviceName
->getCStringNoCopy(), index
);
9113 deviceName
->release();
9115 if (!addedToRegistry
&& (index
>= 0)) {
9116 addedToRegistry
= owner
->setProperty("PCITopLevel", this);
9120 IOLockUnlock(pmTraceWorkerLock
);
9125 PMTraceWorker::serialize(OSSerialize
*s
) const
9128 if (pciDeviceBitMappings
) {
9129 IOLockLock(pmTraceWorkerLock
);
9130 ok
= pciDeviceBitMappings
->serialize(s
);
9131 IOLockUnlock(pmTraceWorkerLock
);
9137 PMTraceWorker::tracePoint(uint8_t phase
)
9139 // clear trace detail when phase begins
9140 if (tracePhase
!= phase
) {
9146 DLOG("trace point 0x%02x\n", tracePhase
);
9151 PMTraceWorker::traceDetail(uint32_t detail
)
9153 if (detail
== traceData32
) {
9156 traceData32
= detail
;
9161 PMTraceWorker::traceComponentWakeProgress(uint32_t component
, uint32_t data
)
9163 switch (component
) {
9164 case kIOPMLoginWindowProgress
:
9165 loginWindowData
= data
& kIOPMLoginWindowProgressMask
;
9167 case kIOPMCoreDisplayProgress
:
9168 coreDisplayData
= data
& kIOPMCoreDisplayProgressMask
;
9170 case kIOPMCoreGraphicsProgress
:
9171 coreGraphicsData
= data
& kIOPMCoreGraphicsProgressMask
;
9177 DLOG("component trace point 0x%02x data 0x%08x\n", component
, data
);
9182 PMTraceWorker::tracePCIPowerChange(
9183 change_t type
, IOService
*service
, uint32_t changeFlags
, uint32_t bitNum
)
9186 uint32_t expectedFlag
;
9188 // Ignore PCI changes outside of system sleep/wake.
9189 if ((kIOPMTracePointSleepPowerPlaneDrivers
!= tracePhase
) &&
9190 (kIOPMTracePointWakePowerPlaneDrivers
!= tracePhase
)) {
9194 // Only record the WillChange transition when going to sleep,
9195 // and the DidChange on the way up.
9196 changeFlags
&= (kIOPMDomainWillChange
| kIOPMDomainDidChange
);
9197 expectedFlag
= (kIOPMTracePointSleepPowerPlaneDrivers
== tracePhase
) ?
9198 kIOPMDomainWillChange
: kIOPMDomainDidChange
;
9199 if (changeFlags
!= expectedFlag
) {
9203 // Mark this device off in our bitfield
9204 if (bitNum
< kPMMaxRTCBitfieldSize
) {
9205 bitMask
= (1 << bitNum
);
9207 if (kPowerChangeStart
== type
) {
9208 traceData32
|= bitMask
;
9209 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
9210 service
->getName(), bitNum
, bitMask
, traceData32
);
9211 owner
->kdebugTrace(kPMLogPCIDevChangeStart
, service
->getRegistryEntryID(), traceData32
, 0);
9213 traceData32
&= ~bitMask
;
9214 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
9215 service
->getName(), bitNum
, bitMask
, traceData32
);
9216 owner
->kdebugTrace(kPMLogPCIDevChangeDone
, service
->getRegistryEntryID(), traceData32
, 0);
9219 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase
, traceData32
);
9225 PMTraceWorker::getPMStatusCode()
9227 return ((uint64_t)traceData32
<< 32) | ((uint64_t)tracePhase
);
9231 PMTraceWorker::getTracePhase()
9237 PMTraceWorker::getTraceData()
9243 // MARK: PMHaltWorker
9245 //******************************************************************************
9246 // PMHaltWorker Class
9248 //******************************************************************************
9251 PMHaltWorker::worker( void )
9257 me
= OSTypeAlloc( PMHaltWorker
);
9258 if (!me
|| !me
->init()) {
9262 me
->lock
= IOLockAlloc();
9267 DLOG("PMHaltWorker %p\n", OBFUSCATE(me
));
9268 me
->retain(); // thread holds extra retain
9269 if (KERN_SUCCESS
!= kernel_thread_start(&PMHaltWorker::main
, (void *) me
, &thread
)) {
9273 thread_deallocate(thread
);
9284 PMHaltWorker::free( void )
9286 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
9291 return OSObject::free();
9295 PMHaltWorker::main( void * arg
, wait_result_t waitResult
)
9297 PMHaltWorker
* me
= (PMHaltWorker
*) arg
;
9299 IOLockLock( gPMHaltLock
);
9301 me
->depth
= gPMHaltDepth
;
9302 IOLockUnlock( gPMHaltLock
);
9304 while (me
->depth
>= 0) {
9305 PMHaltWorker::work( me
);
9307 IOLockLock( gPMHaltLock
);
9308 if (++gPMHaltIdleCount
>= gPMHaltBusyCount
) {
9309 // This is the last thread to finish work on this level,
9310 // inform everyone to start working on next lower level.
9312 me
->depth
= gPMHaltDepth
;
9313 gPMHaltIdleCount
= 0;
9314 thread_wakeup((event_t
) &gPMHaltIdleCount
);
9316 // One or more threads are still working on this level,
9317 // this thread must wait.
9318 me
->depth
= gPMHaltDepth
- 1;
9320 IOLockSleep(gPMHaltLock
, &gPMHaltIdleCount
, THREAD_UNINT
);
9321 } while (me
->depth
!= gPMHaltDepth
);
9323 IOLockUnlock( gPMHaltLock
);
9326 // No more work to do, terminate thread
9327 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me
), me
->visits
);
9328 thread_wakeup( &gPMHaltDepth
);
9333 PMHaltWorker::work( PMHaltWorker
* me
)
9335 IOService
* service
;
9337 AbsoluteTime startTime
, elapsedTime
;
9345 // Claim an unit of work from the shared pool
9346 IOLockLock( gPMHaltLock
);
9347 inner
= (OSSet
*)gPMHaltArray
->getObject(me
->depth
);
9349 service
= OSDynamicCast(IOService
, inner
->getAnyObject());
9352 inner
->removeObject(service
);
9355 IOLockUnlock( gPMHaltLock
);
9357 break; // no more work at this depth
9359 clock_get_uptime(&startTime
);
9361 if (!service
->isInactive() &&
9362 service
->setProperty(gPMHaltClientAcknowledgeKey
, me
)) {
9363 IOLockLock(me
->lock
);
9364 me
->startTime
= startTime
;
9365 me
->service
= service
;
9366 me
->timeout
= false;
9367 IOLockUnlock(me
->lock
);
9369 service
->systemWillShutdown( gPMHaltMessageType
);
9371 // Wait for driver acknowledgement
9372 IOLockLock(me
->lock
);
9373 while (service
->getProperty(gPMHaltClientAcknowledgeKey
)) {
9374 IOLockSleep(me
->lock
, me
, THREAD_UNINT
);
9377 timeout
= me
->timeout
;
9378 IOLockUnlock(me
->lock
);
9381 deltaTime
= computeDeltaTimeMS(&startTime
, &elapsedTime
);
9382 if ((deltaTime
> kPMHaltTimeoutMS
) || timeout
) {
9383 LOG("%s driver %s (0x%llx) took %u ms\n",
9384 (gPMHaltMessageType
== kIOMessageSystemWillPowerOff
) ?
9385 "PowerOff" : "Restart",
9386 service
->getName(), service
->getRegistryEntryID(),
9387 (uint32_t) deltaTime
);
9388 halt_log_enter("PowerOff/Restart handler completed",
9389 OSMemberFunctionCast(const void *, service
, &IOService::systemWillShutdown
),
9399 PMHaltWorker::checkTimeout( PMHaltWorker
* me
, AbsoluteTime
* now
)
9402 AbsoluteTime startTime
;
9403 AbsoluteTime endTime
;
9407 IOLockLock(me
->lock
);
9408 if (me
->service
&& !me
->timeout
) {
9409 startTime
= me
->startTime
;
9411 if (CMP_ABSOLUTETIME(&endTime
, &startTime
) > 0) {
9412 SUB_ABSOLUTETIME(&endTime
, &startTime
);
9413 absolutetime_to_nanoseconds(endTime
, &nano
);
9415 if (nano
> 3000000000ULL) {
9418 halt_log_enter("PowerOff/Restart still waiting on handler",
9419 OSMemberFunctionCast(const void *, me
->service
, &IOService::systemWillShutdown
),
9421 MSG("%s still waiting on %s\n",
9422 (gPMHaltMessageType
== kIOMessageSystemWillPowerOff
) ? "PowerOff" : "Restart",
9423 me
->service
->getName());
9426 IOLockUnlock(me
->lock
);
9429 //******************************************************************************
9430 // acknowledgeSystemWillShutdown
9432 // Acknowledgement from drivers that they have prepared for shutdown/restart.
9433 //******************************************************************************
9436 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService
* from
)
9438 PMHaltWorker
* worker
;
9445 //DLOG("%s acknowledged\n", from->getName());
9446 prop
= from
->copyProperty( gPMHaltClientAcknowledgeKey
);
9448 worker
= (PMHaltWorker
*) prop
;
9449 IOLockLock(worker
->lock
);
9450 from
->removeProperty( gPMHaltClientAcknowledgeKey
);
9451 thread_wakeup((event_t
) worker
);
9452 IOLockUnlock(worker
->lock
);
9455 DLOG("%s acknowledged without worker property\n",
9461 //******************************************************************************
9462 // notifySystemShutdown
9464 // Notify all objects in PM tree that system will shutdown or restart
9465 //******************************************************************************
9468 notifySystemShutdown( IOService
* root
, uint32_t messageType
)
9470 #define PLACEHOLDER ((OSSet *)gPMHaltArray)
9471 IORegistryIterator
* iter
;
9472 IORegistryEntry
* entry
;
9475 PMHaltWorker
* workers
[kPMHaltMaxWorkers
];
9476 AbsoluteTime deadline
;
9477 unsigned int totalNodes
= 0;
9479 unsigned int rootDepth
;
9480 unsigned int numWorkers
;
9486 DLOG("%s msgType = 0x%x\n", __FUNCTION__
, messageType
);
9488 baseFunc
= OSMemberFunctionCast(void *, root
, &IOService::systemWillShutdown
);
9490 // Iterate the entire PM tree starting from root
9492 rootDepth
= root
->getDepth( gIOPowerPlane
);
9497 // debug - for repeated test runs
9498 while (PMHaltWorker::metaClass
->getInstanceCount()) {
9502 if (!gPMHaltArray
) {
9503 gPMHaltArray
= OSArray::withCapacity(40);
9504 if (!gPMHaltArray
) {
9508 gPMHaltArray
->flushCollection();
9512 gPMHaltLock
= IOLockAlloc();
9518 if (!gPMHaltClientAcknowledgeKey
) {
9519 gPMHaltClientAcknowledgeKey
=
9520 OSSymbol::withCStringNoCopy("PMShutdown");
9521 if (!gPMHaltClientAcknowledgeKey
) {
9526 gPMHaltMessageType
= messageType
;
9528 // Depth-first walk of PM plane
9530 iter
= IORegistryIterator::iterateOver(
9531 root
, gIOPowerPlane
, kIORegistryIterateRecursively
);
9534 while ((entry
= iter
->getNextObject())) {
9535 node
= OSDynamicCast(IOService
, entry
);
9541 OSMemberFunctionCast(void *, node
, &IOService::systemWillShutdown
)) {
9545 depth
= node
->getDepth( gIOPowerPlane
);
9546 if (depth
<= rootDepth
) {
9552 // adjust to zero based depth
9553 depth
-= (rootDepth
+ 1);
9555 // gPMHaltArray is an array of containers, each container
9556 // refers to nodes with the same depth.
9558 count
= gPMHaltArray
->getCount();
9559 while (depth
>= count
) {
9560 // expand array and insert placeholders
9561 gPMHaltArray
->setObject(PLACEHOLDER
);
9564 count
= gPMHaltArray
->getCount();
9565 if (depth
< count
) {
9566 inner
= (OSSet
*)gPMHaltArray
->getObject(depth
);
9567 if (inner
== PLACEHOLDER
) {
9568 inner
= OSSet::withCapacity(40);
9570 gPMHaltArray
->replaceObject(depth
, inner
);
9575 // PM nodes that appear more than once in the tree will have
9576 // the same depth, OSSet will refuse to add the node twice.
9578 ok
= inner
->setObject(node
);
9582 DLOG("Skipped PM node %s\n", node
->getName());
9589 for (int i
= 0; (inner
= (OSSet
*)gPMHaltArray
->getObject(i
)); i
++) {
9591 if (inner
!= PLACEHOLDER
) {
9592 count
= inner
->getCount();
9594 DLOG("Nodes at depth %u = %u\n", i
, count
);
9597 // strip placeholders (not all depths are populated)
9599 for (int i
= 0; (inner
= (OSSet
*)gPMHaltArray
->getObject(i
));) {
9600 if (inner
== PLACEHOLDER
) {
9601 gPMHaltArray
->removeObject(i
);
9604 count
= inner
->getCount();
9605 if (count
> numWorkers
) {
9608 totalNodes
+= count
;
9612 if (gPMHaltArray
->getCount() == 0 || !numWorkers
) {
9616 gPMHaltBusyCount
= 0;
9617 gPMHaltIdleCount
= 0;
9618 gPMHaltDepth
= gPMHaltArray
->getCount() - 1;
9620 // Create multiple workers (and threads)
9622 if (numWorkers
> kPMHaltMaxWorkers
) {
9623 numWorkers
= kPMHaltMaxWorkers
;
9626 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
9627 totalNodes
, gPMHaltArray
->getCount(), numWorkers
);
9629 for (unsigned int i
= 0; i
< numWorkers
; i
++) {
9630 workers
[i
] = PMHaltWorker::worker();
9633 // Wait for workers to exhaust all available work
9635 IOLockLock(gPMHaltLock
);
9636 while (gPMHaltDepth
>= 0) {
9637 clock_interval_to_deadline(1000, kMillisecondScale
, &deadline
);
9639 waitResult
= IOLockSleepDeadline(
9640 gPMHaltLock
, &gPMHaltDepth
, deadline
, THREAD_UNINT
);
9641 if (THREAD_TIMED_OUT
== waitResult
) {
9643 clock_get_uptime(&now
);
9645 IOLockUnlock(gPMHaltLock
);
9646 for (unsigned int i
= 0; i
< numWorkers
; i
++) {
9648 PMHaltWorker::checkTimeout(workers
[i
], &now
);
9651 IOLockLock(gPMHaltLock
);
9654 IOLockUnlock(gPMHaltLock
);
9656 // Release all workers
9658 for (unsigned int i
= 0; i
< numWorkers
; i
++) {
9660 workers
[i
]->release();
9662 // worker also retained by it's own thread
9666 DLOG("%s done\n", __FUNCTION__
);
9671 // MARK: Kernel Assertion
9673 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
9675 IOPMDriverAssertionID
9676 IOPMrootDomain::createPMAssertion(
9677 IOPMDriverAssertionType whichAssertionBits
,
9678 IOPMDriverAssertionLevel assertionLevel
,
9679 IOService
*ownerService
,
9680 const char *ownerDescription
)
9683 IOPMDriverAssertionID newAssertion
;
9685 if (!pmAssertions
) {
9689 ret
= pmAssertions
->createAssertion(whichAssertionBits
, assertionLevel
, ownerService
, ownerDescription
, &newAssertion
);
9691 if (kIOReturnSuccess
== ret
) {
9692 return newAssertion
;
9699 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion
)
9701 if (!pmAssertions
) {
9702 return kIOReturnInternalError
;
9705 return pmAssertions
->releaseAssertion(releaseAssertion
);
9710 IOPMrootDomain::setPMAssertionLevel(
9711 IOPMDriverAssertionID assertionID
,
9712 IOPMDriverAssertionLevel assertionLevel
)
9714 return pmAssertions
->setAssertionLevel(assertionID
, assertionLevel
);
9717 IOPMDriverAssertionLevel
9718 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion
)
9720 IOPMDriverAssertionType sysLevels
;
9722 if (!pmAssertions
|| whichAssertion
== 0) {
9723 return kIOPMDriverAssertionLevelOff
;
9726 sysLevels
= pmAssertions
->getActivatedAssertions();
9728 // Check that every bit set in argument 'whichAssertion' is asserted
9729 // in the aggregate bits.
9730 if ((sysLevels
& whichAssertion
) == whichAssertion
) {
9731 return kIOPMDriverAssertionLevelOn
;
9733 return kIOPMDriverAssertionLevelOff
;
9738 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels
)
9740 if (!pmAssertions
) {
9741 return kIOReturnNotFound
;
9744 return pmAssertions
->setUserAssertionLevels(inLevels
);
9748 IOPMrootDomain::serializeProperties( OSSerialize
* s
) const
9751 pmAssertions
->publishProperties();
9753 return IOService::serializeProperties(s
);
9757 IOPMrootDomain::copyProperty( const char * aKey
) const
9759 OSObject
*obj
= NULL
;
9760 obj
= IOService::copyProperty(aKey
);
9766 if (!strncmp(aKey
, kIOPMSleepWakeWdogRebootKey
,
9767 sizeof(kIOPMSleepWakeWdogRebootKey
))) {
9768 if (swd_flags
& SWD_BOOT_BY_SW_WDOG
) {
9769 return kOSBooleanTrue
;
9771 return kOSBooleanFalse
;
9775 if (!strncmp(aKey
, kIOPMSleepWakeWdogLogsValidKey
,
9776 sizeof(kIOPMSleepWakeWdogLogsValidKey
))) {
9777 if (swd_flags
& SWD_VALID_LOGS
) {
9778 return kOSBooleanTrue
;
9780 return kOSBooleanFalse
;
9785 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey'
9786 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
9787 * issued by DisplayWrangler on darkwake.
9789 if (!strcmp(aKey
, "DesktopMode")) {
9791 return kOSBooleanTrue
;
9793 return kOSBooleanFalse
;
9796 if (!strcmp(aKey
, "DisplayIdleForDemandSleep")) {
9797 if (displayIdleForDemandSleep
) {
9798 return kOSBooleanTrue
;
9800 return kOSBooleanFalse
;
9804 if (!strcmp(aKey
, kIOPMDriverWakeEventsKey
)) {
9805 OSArray
* array
= NULL
;
9807 if (_systemWakeEventsArray
&& _systemWakeEventsArray
->getCount()) {
9808 OSCollection
*collection
= _systemWakeEventsArray
->copyCollection();
9809 if (collection
&& !(array
= OSDynamicCast(OSArray
, collection
))) {
9810 collection
->release();
9817 if (!strcmp(aKey
, kIOPMSleepStatisticsAppsKey
)) {
9818 OSArray
* array
= NULL
;
9819 IOLockLock(pmStatsLock
);
9820 if (pmStatsAppResponses
&& pmStatsAppResponses
->getCount()) {
9821 OSCollection
*collection
= pmStatsAppResponses
->copyCollection();
9822 if (collection
&& !(array
= OSDynamicCast(OSArray
, collection
))) {
9823 collection
->release();
9825 pmStatsAppResponses
->flushCollection();
9827 IOLockUnlock(pmStatsLock
);
9831 if (!strcmp(aKey
, kIOPMIdleSleepPreventersKey
)) {
9832 OSArray
*idleSleepList
= NULL
;
9833 gRootDomain
->copySleepPreventersList(&idleSleepList
, NULL
);
9834 return idleSleepList
;
9837 if (!strcmp(aKey
, kIOPMSystemSleepPreventersKey
)) {
9838 OSArray
*systemSleepList
= NULL
;
9839 gRootDomain
->copySleepPreventersList(NULL
, &systemSleepList
);
9840 return systemSleepList
;
9843 if (!strcmp(aKey
, kIOPMIdleSleepPreventersWithIDKey
)) {
9844 OSArray
*idleSleepList
= NULL
;
9845 gRootDomain
->copySleepPreventersListWithID(&idleSleepList
, NULL
);
9846 return idleSleepList
;
9849 if (!strcmp(aKey
, kIOPMSystemSleepPreventersWithIDKey
)) {
9850 OSArray
*systemSleepList
= NULL
;
9851 gRootDomain
->copySleepPreventersListWithID(NULL
, &systemSleepList
);
9852 return systemSleepList
;
9858 // MARK: Wake Event Reporting
9861 IOPMrootDomain::copyWakeReasonString( char * outBuf
, size_t bufSize
)
9864 strlcpy(outBuf
, gWakeReasonString
, bufSize
);
9868 //******************************************************************************
9869 // acceptSystemWakeEvents
9871 // Private control for the acceptance of driver wake event claims.
9872 //******************************************************************************
9875 IOPMrootDomain::acceptSystemWakeEvents( bool accept
)
9877 bool logWakeReason
= false;
9881 if (!_systemWakeEventsArray
) {
9882 _systemWakeEventsArray
= OSArray::withCapacity(4);
9884 _acceptSystemWakeEvents
= (_systemWakeEventsArray
!= NULL
);
9885 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
9886 if (!(_aotNow
&& (kIOPMWakeEventAOTExitFlags
& _aotPendingFlags
)))
9887 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
9889 gWakeReasonString
[0] = '\0';
9890 if (_systemWakeEventsArray
) {
9891 _systemWakeEventsArray
->flushCollection();
9895 _acceptSystemWakeEvents
= false;
9897 logWakeReason
= gWakeReasonSysctlRegistered
;
9899 static int panic_allowed
= -1;
9901 if ((panic_allowed
== -1) &&
9902 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed
, sizeof(panic_allowed
)) == false)) {
9906 if (panic_allowed
) {
9908 // Panic if wake reason is null or empty
9909 for (i
= 0; (i
< strlen(gWakeReasonString
)); i
++) {
9910 if ((gWakeReasonString
[i
] != ' ') && (gWakeReasonString
[i
] != '\t')) {
9914 if (i
>= strlen(gWakeReasonString
)) {
9915 panic("Wake reason is empty\n");
9923 if (logWakeReason
) {
9924 MSG("system wake events:%s\n", gWakeReasonString
);
9928 //******************************************************************************
9929 // claimSystemWakeEvent
9931 // For a driver to claim a device is the source/conduit of a system wake event.
9932 //******************************************************************************
9935 IOPMrootDomain::claimSystemWakeEvent(
9938 const char * reason
,
9939 OSObject
* details
)
9941 const OSSymbol
* deviceName
= NULL
;
9942 OSNumber
* deviceRegId
= NULL
;
9943 OSNumber
* claimTime
= NULL
;
9944 OSData
* flagsData
= NULL
;
9945 OSString
* reasonString
= NULL
;
9946 OSDictionary
* d
= NULL
;
9951 pmEventTimeStamp(×tamp
);
9953 if (!device
|| !reason
) {
9957 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
9958 IOOptionBits aotFlags
= 0;
9959 bool needAOTEvaluate
= FALSE
;
9961 if (kIOPMAOTModeAddEventFlags
& _aotMode
) {
9962 if (!strcmp("hold", reason
)
9963 || !strcmp("help", reason
)
9964 || !strcmp("menu", reason
)
9965 || !strcmp("stockholm", reason
)
9966 || !strcmp("ringer", reason
)
9967 || !strcmp("ringerab", reason
)
9968 || !strcmp("smc0", reason
)
9969 || !strcmp("AOP.RTPWakeupAP", reason
)
9970 || !strcmp("BT.OutboxNotEmpty", reason
)
9971 || !strcmp("WL.OutboxNotEmpty", reason
)) {
9972 flags
|= kIOPMWakeEventAOTExit
;
9976 #if DEVELOPMENT || DEBUG
9977 if (_aotLingerTime
&& !strcmp("rtc", reason
)) {
9978 flags
|= kIOPMWakeEventAOTPossibleExit
;
9980 #endif /* DEVELOPMENT || DEBUG */
9981 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
9983 deviceName
= device
->copyName(gIOServicePlane
);
9984 deviceRegId
= OSNumber::withNumber(device
->getRegistryEntryID(), 64);
9985 claimTime
= OSNumber::withNumber(timestamp
, 64);
9986 flagsData
= OSData::withBytes(&flags
, sizeof(flags
));
9987 reasonString
= OSString::withCString(reason
);
9988 d
= OSDictionary::withCapacity(5 + (details
? 1 : 0));
9989 if (!deviceName
|| !deviceRegId
|| !claimTime
|| !flagsData
|| !reasonString
) {
9993 d
->setObject(gIONameKey
, deviceName
);
9994 d
->setObject(gIORegistryEntryIDKey
, deviceRegId
);
9995 d
->setObject(kIOPMWakeEventTimeKey
, claimTime
);
9996 d
->setObject(kIOPMWakeEventFlagsKey
, flagsData
);
9997 d
->setObject(kIOPMWakeEventReasonKey
, reasonString
);
9999 d
->setObject(kIOPMWakeEventDetailsKey
, details
);
10003 addWakeReason
= _acceptSystemWakeEvents
;
10004 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
10006 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason
, deviceName
->getCStringNoCopy(), (int)flags
, _aotPendingFlags
, _aotReadyToFullWake
);
10008 aotFlags
= (kIOPMWakeEventAOTFlags
& flags
);
10009 aotFlags
= (aotFlags
& ~_aotPendingFlags
);
10010 needAOTEvaluate
= false;
10011 if (_aotNow
&& aotFlags
) {
10012 if (kIOPMWakeEventAOTPossibleExit
& flags
) {
10013 _aotMetrics
->possibleCount
++;
10015 if (kIOPMWakeEventAOTConfirmedPossibleExit
& flags
) {
10016 _aotMetrics
->confirmedPossibleCount
++;
10018 if (kIOPMWakeEventAOTRejectedPossibleExit
& flags
) {
10019 _aotMetrics
->rejectedPossibleCount
++;
10021 if (kIOPMWakeEventAOTExpiredPossibleExit
& flags
) {
10022 _aotMetrics
->expiredPossibleCount
++;
10025 _aotPendingFlags
|= aotFlags
;
10026 addWakeReason
= _aotNow
&& _systemWakeEventsArray
&& ((kIOPMWakeEventAOTExitFlags
& aotFlags
));
10027 needAOTEvaluate
= _aotReadyToFullWake
;
10029 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
10031 if (!gWakeReasonSysctlRegistered
) {
10032 // Lazy registration until the platform driver stops registering
10034 gWakeReasonSysctlRegistered
= true;
10035 #if CONFIG_EMBEDDED
10036 sysctl_register_oid(&sysctl__kern_wakereason
);
10039 if (addWakeReason
) {
10040 ok
= _systemWakeEventsArray
->setObject(d
);
10041 if (gWakeReasonString
[0] != '\0') {
10042 strlcat(gWakeReasonString
, " ", sizeof(gWakeReasonString
));
10044 strlcat(gWakeReasonString
, reason
, sizeof(gWakeReasonString
));
10047 WAKEEVENT_UNLOCK();
10048 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
10049 if (needAOTEvaluate
) {
10052 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
10056 deviceName
->release();
10059 deviceRegId
->release();
10062 claimTime
->release();
10065 flagsData
->release();
10067 if (reasonString
) {
10068 reasonString
->release();
10075 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10078 // MARK: PMSettingHandle
10080 OSDefineMetaClassAndStructors( PMSettingHandle
, OSObject
)
10083 PMSettingHandle::free( void )
10086 pmso
->clientHandleFreed();
10095 // MARK: PMSettingObject
10098 #define super OSObject
10099 OSDefineMetaClassAndFinalStructors( PMSettingObject
, OSObject
)
10102 * Static constructor/initializer for PMSettingObject
10104 PMSettingObject
*PMSettingObject::pmSettingObject(
10105 IOPMrootDomain
* parent_arg
,
10106 IOPMSettingControllerCallback handler_arg
,
10107 OSObject
* target_arg
,
10108 uintptr_t refcon_arg
,
10109 uint32_t supportedPowerSources
,
10110 const OSSymbol
* settings
[],
10111 OSObject
* *handle_obj
)
10113 uint32_t settingCount
= 0;
10114 PMSettingObject
*pmso
= NULL
;
10115 PMSettingHandle
*pmsh
= NULL
;
10117 if (!parent_arg
|| !handler_arg
|| !settings
|| !handle_obj
) {
10121 // count OSSymbol entries in NULL terminated settings array
10122 while (settings
[settingCount
]) {
10125 if (0 == settingCount
) {
10129 pmso
= new PMSettingObject
;
10130 if (!pmso
|| !pmso
->init()) {
10134 pmsh
= new PMSettingHandle
;
10135 if (!pmsh
|| !pmsh
->init()) {
10139 queue_init(&pmso
->calloutQueue
);
10140 pmso
->parent
= parent_arg
;
10141 pmso
->func
= handler_arg
;
10142 pmso
->target
= target_arg
;
10143 pmso
->refcon
= refcon_arg
;
10144 pmso
->settingCount
= settingCount
;
10146 pmso
->retain(); // handle holds a retain on pmso
10150 pmso
->publishedFeatureID
= (uint32_t *)IOMalloc(sizeof(uint32_t) * settingCount
);
10151 if (pmso
->publishedFeatureID
) {
10152 for (unsigned int i
= 0; i
< settingCount
; i
++) {
10153 // Since there is now at least one listener to this setting, publish
10154 // PM root domain support for it.
10155 parent_arg
->publishPMSetting( settings
[i
],
10156 supportedPowerSources
, &pmso
->publishedFeatureID
[i
] );
10160 *handle_obj
= pmsh
;
10174 PMSettingObject::free( void )
10176 if (publishedFeatureID
) {
10177 for (uint32_t i
= 0; i
< settingCount
; i
++) {
10178 if (publishedFeatureID
[i
]) {
10179 parent
->removePublishedFeature( publishedFeatureID
[i
] );
10183 IOFree(publishedFeatureID
, sizeof(uint32_t) * settingCount
);
10190 PMSettingObject::dispatchPMSetting( const OSSymbol
* type
, OSObject
* object
)
10192 (*func
)(target
, type
, object
, refcon
);
10196 PMSettingObject::clientHandleFreed( void )
10198 parent
->deregisterPMSettingObject(this);
10202 // MARK: PMAssertionsTracker
10204 //*********************************************************************************
10205 //*********************************************************************************
10206 //*********************************************************************************
10207 // class PMAssertionsTracker Implementation
10209 #define kAssertUniqueIDStart 500
10211 PMAssertionsTracker
*
10212 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain
*rootDomain
)
10214 PMAssertionsTracker
*myself
;
10216 myself
= new PMAssertionsTracker
;
10220 myself
->owner
= rootDomain
;
10221 myself
->issuingUniqueID
= kAssertUniqueIDStart
;
10222 myself
->assertionsArray
= OSArray::withCapacity(5);
10223 myself
->assertionsKernel
= 0;
10224 myself
->assertionsUser
= 0;
10225 myself
->assertionsCombined
= 0;
10226 myself
->assertionsArrayLock
= IOLockAlloc();
10227 myself
->tabulateProducerCount
= myself
->tabulateConsumerCount
= 0;
10229 if (!myself
->assertionsArray
|| !myself
->assertionsArrayLock
) {
10238 * - Update assertionsKernel to reflect the state of all
10239 * assertions in the kernel.
10240 * - Update assertionsCombined to reflect both kernel & user space.
10243 PMAssertionsTracker::tabulate(void)
10247 PMAssertStruct
*_a
= NULL
;
10250 IOPMDriverAssertionType oldKernel
= assertionsKernel
;
10251 IOPMDriverAssertionType oldCombined
= assertionsCombined
;
10255 assertionsKernel
= 0;
10256 assertionsCombined
= 0;
10258 if (!assertionsArray
) {
10262 if ((count
= assertionsArray
->getCount())) {
10263 for (i
= 0; i
< count
; i
++) {
10264 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
10266 _a
= (PMAssertStruct
*)_d
->getBytesNoCopy();
10267 if (_a
&& (kIOPMDriverAssertionLevelOn
== _a
->level
)) {
10268 assertionsKernel
|= _a
->assertionBits
;
10274 tabulateProducerCount
++;
10275 assertionsCombined
= assertionsKernel
| assertionsUser
;
10277 if ((assertionsKernel
!= oldKernel
) ||
10278 (assertionsCombined
!= oldCombined
)) {
10279 owner
->evaluateAssertions(assertionsCombined
, oldCombined
);
10284 PMAssertionsTracker::publishProperties( void )
10286 OSArray
*assertionsSummary
= NULL
;
10288 if (tabulateConsumerCount
!= tabulateProducerCount
) {
10289 IOLockLock(assertionsArrayLock
);
10291 tabulateConsumerCount
= tabulateProducerCount
;
10293 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
10295 assertionsSummary
= copyAssertionsArray();
10296 if (assertionsSummary
) {
10297 owner
->setProperty(kIOPMAssertionsDriverDetailedKey
, assertionsSummary
);
10298 assertionsSummary
->release();
10300 owner
->removeProperty(kIOPMAssertionsDriverDetailedKey
);
10303 /* Publish the IOPMrootDomain property "DriverPMAssertions"
10305 owner
->setProperty(kIOPMAssertionsDriverKey
, assertionsKernel
, 64);
10307 IOLockUnlock(assertionsArrayLock
);
10311 PMAssertionsTracker::PMAssertStruct
*
10312 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id
, int *index
)
10314 PMAssertStruct
*_a
= NULL
;
10320 if (assertionsArray
10321 && (count
= assertionsArray
->getCount())) {
10322 for (i
= 0; i
< count
; i
++) {
10323 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
10325 _a
= (PMAssertStruct
*)_d
->getBytesNoCopy();
10326 if (_a
&& (_id
== _a
->id
)) {
10344 /* PMAssertionsTracker::handleCreateAssertion
10345 * Perform assertion work on the PM workloop. Do not call directly.
10348 PMAssertionsTracker::handleCreateAssertion(OSData
*newAssertion
)
10352 if (newAssertion
) {
10353 IOLockLock(assertionsArrayLock
);
10354 assertionsArray
->setObject(newAssertion
);
10355 IOLockUnlock(assertionsArrayLock
);
10356 newAssertion
->release();
10360 return kIOReturnSuccess
;
10363 /* PMAssertionsTracker::createAssertion
10364 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
10368 PMAssertionsTracker::createAssertion(
10369 IOPMDriverAssertionType which
,
10370 IOPMDriverAssertionLevel level
,
10371 IOService
*serviceID
,
10372 const char *whoItIs
,
10373 IOPMDriverAssertionID
*outID
)
10375 OSData
*dataStore
= NULL
;
10376 PMAssertStruct track
;
10378 // Warning: trillions and trillions of created assertions may overflow the unique ID.
10379 track
.id
= OSIncrementAtomic64((SInt64
*) &issuingUniqueID
);
10380 track
.level
= level
;
10381 track
.assertionBits
= which
;
10382 track
.ownerString
= whoItIs
? OSSymbol::withCString(whoItIs
):NULL
;
10383 track
.ownerService
= serviceID
;
10384 track
.registryEntryID
= serviceID
? serviceID
->getRegistryEntryID():0;
10385 track
.modifiedTime
= 0;
10386 pmEventTimeStamp(&track
.createdTime
);
10388 dataStore
= OSData::withBytes(&track
, sizeof(PMAssertStruct
));
10390 if (track
.ownerString
) {
10391 track
.ownerString
->release();
10393 return kIOReturnNoMemory
;
10398 if (owner
&& owner
->pmPowerStateQueue
) {
10399 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionCreate
, (void *)dataStore
);
10402 return kIOReturnSuccess
;
10405 /* PMAssertionsTracker::handleReleaseAssertion
10406 * Runs in PM workloop. Do not call directly.
10409 PMAssertionsTracker::handleReleaseAssertion(
10410 IOPMDriverAssertionID _id
)
10415 PMAssertStruct
*assertStruct
= detailsForID(_id
, &index
);
10417 if (!assertStruct
) {
10418 return kIOReturnNotFound
;
10421 IOLockLock(assertionsArrayLock
);
10422 if (assertStruct
->ownerString
) {
10423 assertStruct
->ownerString
->release();
10426 assertionsArray
->removeObject(index
);
10427 IOLockUnlock(assertionsArrayLock
);
10430 return kIOReturnSuccess
;
10433 /* PMAssertionsTracker::releaseAssertion
10434 * Releases an assertion and affects system behavior if appropiate.
10435 * Actual work happens on PM workloop.
10438 PMAssertionsTracker::releaseAssertion(
10439 IOPMDriverAssertionID _id
)
10441 if (owner
&& owner
->pmPowerStateQueue
) {
10442 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionRelease
, NULL
, _id
);
10444 return kIOReturnSuccess
;
10447 /* PMAssertionsTracker::handleSetAssertionLevel
10448 * Runs in PM workloop. Do not call directly.
10451 PMAssertionsTracker::handleSetAssertionLevel(
10452 IOPMDriverAssertionID _id
,
10453 IOPMDriverAssertionLevel _level
)
10455 PMAssertStruct
*assertStruct
= detailsForID(_id
, NULL
);
10459 if (!assertStruct
) {
10460 return kIOReturnNotFound
;
10463 IOLockLock(assertionsArrayLock
);
10464 pmEventTimeStamp(&assertStruct
->modifiedTime
);
10465 assertStruct
->level
= _level
;
10466 IOLockUnlock(assertionsArrayLock
);
10469 return kIOReturnSuccess
;
10472 /* PMAssertionsTracker::setAssertionLevel
10475 PMAssertionsTracker::setAssertionLevel(
10476 IOPMDriverAssertionID _id
,
10477 IOPMDriverAssertionLevel _level
)
10479 if (owner
&& owner
->pmPowerStateQueue
) {
10480 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionSetLevel
,
10481 (void *)(uintptr_t)_level
, _id
);
10484 return kIOReturnSuccess
;
10488 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0
)
10490 IOPMDriverAssertionType new_user_levels
= *(IOPMDriverAssertionType
*) arg0
;
10494 if (new_user_levels
!= assertionsUser
) {
10495 assertionsUser
= new_user_levels
;
10496 DLOG("assertionsUser 0x%llx\n", assertionsUser
);
10500 return kIOReturnSuccess
;
10504 PMAssertionsTracker::setUserAssertionLevels(
10505 IOPMDriverAssertionType new_user_levels
)
10507 if (gIOPMWorkLoop
) {
10508 gIOPMWorkLoop
->runAction(
10509 OSMemberFunctionCast(
10510 IOWorkLoop::Action
,
10512 &PMAssertionsTracker::handleSetUserAssertionLevels
),
10514 (void *) &new_user_levels
, NULL
, NULL
, NULL
);
10517 return kIOReturnSuccess
;
10522 PMAssertionsTracker::copyAssertionsArray(void)
10526 OSArray
*outArray
= NULL
;
10528 if (!assertionsArray
||
10529 (0 == (count
= assertionsArray
->getCount())) ||
10530 (NULL
== (outArray
= OSArray::withCapacity(count
)))) {
10534 for (i
= 0; i
< count
; i
++) {
10535 PMAssertStruct
*_a
= NULL
;
10537 OSDictionary
*details
= NULL
;
10539 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
10540 if (_d
&& (_a
= (PMAssertStruct
*)_d
->getBytesNoCopy())) {
10541 OSNumber
*_n
= NULL
;
10543 details
= OSDictionary::withCapacity(7);
10548 outArray
->setObject(details
);
10549 details
->release();
10551 _n
= OSNumber::withNumber(_a
->id
, 64);
10553 details
->setObject(kIOPMDriverAssertionIDKey
, _n
);
10556 _n
= OSNumber::withNumber(_a
->createdTime
, 64);
10558 details
->setObject(kIOPMDriverAssertionCreatedTimeKey
, _n
);
10561 _n
= OSNumber::withNumber(_a
->modifiedTime
, 64);
10563 details
->setObject(kIOPMDriverAssertionModifiedTimeKey
, _n
);
10566 _n
= OSNumber::withNumber((uintptr_t)_a
->registryEntryID
, 64);
10568 details
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, _n
);
10571 _n
= OSNumber::withNumber(_a
->level
, 64);
10573 details
->setObject(kIOPMDriverAssertionLevelKey
, _n
);
10576 _n
= OSNumber::withNumber(_a
->assertionBits
, 64);
10578 details
->setObject(kIOPMDriverAssertionAssertedKey
, _n
);
10582 if (_a
->ownerString
) {
10583 details
->setObject(kIOPMDriverAssertionOwnerStringKey
, _a
->ownerString
);
10592 IOPMDriverAssertionType
10593 PMAssertionsTracker::getActivatedAssertions(void)
10595 return assertionsCombined
;
10598 IOPMDriverAssertionLevel
10599 PMAssertionsTracker::getAssertionLevel(
10600 IOPMDriverAssertionType type
)
10602 if (type
&& ((type
& assertionsKernel
) == assertionsKernel
)) {
10603 return kIOPMDriverAssertionLevelOn
;
10605 return kIOPMDriverAssertionLevelOff
;
10609 //*********************************************************************************
10610 //*********************************************************************************
10611 //*********************************************************************************
10615 pmEventTimeStamp(uint64_t *recordTS
)
10618 clock_usec_t tusec
;
10624 // We assume tsec fits into 32 bits; 32 bits holds enough
10625 // seconds for 136 years since the epoch in 1970.
10626 clock_get_calendar_microtime(&tsec
, &tusec
);
10629 // Pack the sec & microsec calendar time into a uint64_t, for fun.
10631 *recordTS
|= (uint32_t)tusec
;
10632 *recordTS
|= ((uint64_t)tsec
<< 32);
10638 // MARK: IORootParent
10640 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10642 OSDefineMetaClassAndFinalStructors(IORootParent
, IOService
)
10644 // The reason that root domain needs a root parent is to facilitate demand
10645 // sleep, since a power change from the root parent cannot be vetoed.
10647 // The above statement is no longer true since root domain now performs
10648 // demand sleep using overrides. But root parent remains to avoid changing
10649 // the power tree stacking. Root parent is parked at the max power state.
10652 static IOPMPowerState patriarchPowerStates
[2] =
10654 {1, 0, ON_POWER
, 0, 0, 0, 0, 0, 0, 0, 0, 0},
10655 {1, 0, ON_POWER
, 0, 0, 0, 0, 0, 0, 0, 0, 0},
10659 IORootParent::initialize( void )
10662 gIOPMPSExternalConnectedKey
= OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey
);
10663 gIOPMPSExternalChargeCapableKey
= OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey
);
10664 gIOPMPSBatteryInstalledKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey
);
10665 gIOPMPSIsChargingKey
= OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey
);
10666 gIOPMPSAtWarnLevelKey
= OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey
);
10667 gIOPMPSAtCriticalLevelKey
= OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey
);
10668 gIOPMPSCurrentCapacityKey
= OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey
);
10669 gIOPMPSMaxCapacityKey
= OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey
);
10670 gIOPMPSDesignCapacityKey
= OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey
);
10671 gIOPMPSTimeRemainingKey
= OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey
);
10672 gIOPMPSAmperageKey
= OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey
);
10673 gIOPMPSVoltageKey
= OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey
);
10674 gIOPMPSCycleCountKey
= OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey
);
10675 gIOPMPSMaxErrKey
= OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey
);
10676 gIOPMPSAdapterInfoKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey
);
10677 gIOPMPSLocationKey
= OSSymbol::withCStringNoCopy(kIOPMPSLocationKey
);
10678 gIOPMPSErrorConditionKey
= OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey
);
10679 gIOPMPSManufacturerKey
= OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey
);
10680 gIOPMPSManufactureDateKey
= OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey
);
10681 gIOPMPSModelKey
= OSSymbol::withCStringNoCopy(kIOPMPSModelKey
);
10682 gIOPMPSSerialKey
= OSSymbol::withCStringNoCopy(kIOPMPSSerialKey
);
10683 gIOPMPSLegacyBatteryInfoKey
= OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey
);
10684 gIOPMPSBatteryHealthKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey
);
10685 gIOPMPSHealthConfidenceKey
= OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey
);
10686 gIOPMPSCapacityEstimatedKey
= OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey
);
10687 gIOPMPSBatteryChargeStatusKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey
);
10688 gIOPMPSBatteryTemperatureKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey
);
10689 gIOPMPSAdapterDetailsKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey
);
10690 gIOPMPSChargerConfigurationKey
= OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey
);
10691 gIOPMPSAdapterDetailsIDKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey
);
10692 gIOPMPSAdapterDetailsWattsKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey
);
10693 gIOPMPSAdapterDetailsRevisionKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey
);
10694 gIOPMPSAdapterDetailsSerialNumberKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey
);
10695 gIOPMPSAdapterDetailsFamilyKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey
);
10696 gIOPMPSAdapterDetailsAmperageKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey
);
10697 gIOPMPSAdapterDetailsDescriptionKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey
);
10698 gIOPMPSAdapterDetailsPMUConfigurationKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey
);
10699 gIOPMPSAdapterDetailsSourceIDKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey
);
10700 gIOPMPSAdapterDetailsErrorFlagsKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey
);
10701 gIOPMPSAdapterDetailsSharedSourceKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey
);
10702 gIOPMPSAdapterDetailsCloakedKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey
);
10703 gIOPMPSInvalidWakeSecondsKey
= OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey
);
10704 gIOPMPSPostChargeWaitSecondsKey
= OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey
);
10705 gIOPMPSPostDishargeWaitSecondsKey
= OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey
);
10709 IORootParent::start( IOService
* nub
)
10711 IOService::start(nub
);
10712 attachToParent( getRegistryRoot(), gIOPowerPlane
);
10714 registerPowerDriver(this, patriarchPowerStates
, 2);
10720 IORootParent::shutDownSystem( void )
10725 IORootParent::restartSystem( void )
10730 IORootParent::sleepSystem( void )
10735 IORootParent::dozeSystem( void )
10740 IORootParent::sleepToDoze( void )
10745 IORootParent::wakeSystem( void )
10750 IORootParent::copyProperty( const char * aKey
) const
10752 return IOService::copyProperty(aKey
);
10756 IOPMrootDomain::getWatchdogTimeout()
10758 if (gSwdSleepWakeTimeout
) {
10759 gSwdSleepTimeout
= gSwdWakeTimeout
= gSwdSleepWakeTimeout
;
10761 if ((pmTracer
->getTracePhase() < kIOPMTracePointSystemSleep
) ||
10762 (pmTracer
->getTracePhase() == kIOPMTracePointDarkWakeEntry
)) {
10763 return gSwdSleepTimeout
? gSwdSleepTimeout
: WATCHDOG_SLEEP_TIMEOUT
;
10765 return gSwdWakeTimeout
? gSwdWakeTimeout
: WATCHDOG_WAKE_TIMEOUT
;
10770 #if defined(__i386__) || defined(__x86_64__)
10772 IOPMrootDomain::restartWithStackshot()
10774 takeStackshot(true);
10776 return kIOReturnSuccess
;
10780 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger
)
10782 takeStackshot(wdogTrigger
);
10786 IOPMrootDomain::tracePhase2String(uint32_t tracePhase
, const char **phaseString
, const char **description
)
10788 switch (tracePhase
) {
10789 case kIOPMTracePointSleepStarted
:
10790 *phaseString
= "kIOPMTracePointSleepStarted";
10791 *description
= "starting sleep";
10794 case kIOPMTracePointSleepApplications
:
10795 *phaseString
= "kIOPMTracePointSleepApplications";
10796 *description
= "notifying applications";
10799 case kIOPMTracePointSleepPriorityClients
:
10800 *phaseString
= "kIOPMTracePointSleepPriorityClients";
10801 *description
= "notifying clients about upcoming system capability changes";
10804 case kIOPMTracePointSleepWillChangeInterests
:
10805 *phaseString
= "kIOPMTracePointSleepWillChangeInterests";
10806 *description
= "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
10809 case kIOPMTracePointSleepPowerPlaneDrivers
:
10810 *phaseString
= "kIOPMTracePointSleepPowerPlaneDrivers";
10811 *description
= "calling power state change callbacks";
10814 case kIOPMTracePointSleepDidChangeInterests
:
10815 *phaseString
= "kIOPMTracePointSleepDidChangeInterests";
10816 *description
= "calling rootDomain's clients about rootDomain's state changes";
10819 case kIOPMTracePointSleepCapabilityClients
:
10820 *phaseString
= "kIOPMTracePointSleepCapabilityClients";
10821 *description
= "notifying clients about current system capabilities";
10824 case kIOPMTracePointSleepPlatformActions
:
10825 *phaseString
= "kIOPMTracePointSleepPlatformActions";
10826 *description
= "calling Quiesce/Sleep action callbacks";
10829 case kIOPMTracePointSleepCPUs
:
10831 *phaseString
= "kIOPMTracePointSleepCPUs";
10832 #if defined(__i386__) || defined(__x86_64__)
10834 * We cannot use the getCPUNumber() method to get the cpu number, since
10835 * that cpu number is unrelated to the cpu number we need (we need the cpu
10836 * number as enumerated by the scheduler, NOT the CPU number enumerated
10837 * by ACPIPlatform as the CPUs are enumerated in MADT order).
10838 * Instead, pass the Mach processor pointer associated with the current
10839 * shutdown target so its associated cpu_id can be used in
10840 * processor_to_datastring.
10842 if (currentShutdownTarget
!= NULL
&&
10843 currentShutdownTarget
->getMachProcessor() != NULL
) {
10844 const char *sbuf
= processor_to_datastring("halting all non-boot CPUs",
10845 currentShutdownTarget
->getMachProcessor());
10846 *description
= sbuf
;
10848 *description
= "halting all non-boot CPUs";
10851 *description
= "halting all non-boot CPUs";
10855 case kIOPMTracePointSleepPlatformDriver
:
10856 *phaseString
= "kIOPMTracePointSleepPlatformDriver";
10857 *description
= "executing platform specific code";
10860 case kIOPMTracePointHibernate
:
10861 *phaseString
= "kIOPMTracePointHibernate";
10862 *description
= "writing the hibernation image";
10865 case kIOPMTracePointSystemSleep
:
10866 *phaseString
= "kIOPMTracePointSystemSleep";
10867 *description
= "in EFI/Bootrom after last point of entry to sleep";
10870 case kIOPMTracePointWakePlatformDriver
:
10871 *phaseString
= "kIOPMTracePointWakePlatformDriver";
10872 *description
= "executing platform specific code";
10876 case kIOPMTracePointWakePlatformActions
:
10877 *phaseString
= "kIOPMTracePointWakePlatformActions";
10878 *description
= "calling Wake action callbacks";
10881 case kIOPMTracePointWakeCPUs
:
10882 *phaseString
= "kIOPMTracePointWakeCPUs";
10883 *description
= "starting non-boot CPUs";
10886 case kIOPMTracePointWakeWillPowerOnClients
:
10887 *phaseString
= "kIOPMTracePointWakeWillPowerOnClients";
10888 *description
= "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
10891 case kIOPMTracePointWakeWillChangeInterests
:
10892 *phaseString
= "kIOPMTracePointWakeWillChangeInterests";
10893 *description
= "calling rootDomain's clients about upcoming rootDomain's state changes";
10896 case kIOPMTracePointWakeDidChangeInterests
:
10897 *phaseString
= "kIOPMTracePointWakeDidChangeInterests";
10898 *description
= "calling rootDomain's clients about completed rootDomain's state changes";
10901 case kIOPMTracePointWakePowerPlaneDrivers
:
10902 *phaseString
= "kIOPMTracePointWakePowerPlaneDrivers";
10903 *description
= "calling power state change callbacks";
10906 case kIOPMTracePointWakeCapabilityClients
:
10907 *phaseString
= "kIOPMTracePointWakeCapabilityClients";
10908 *description
= "informing clients about current system capabilities";
10911 case kIOPMTracePointWakeApplications
:
10912 *phaseString
= "kIOPMTracePointWakeApplications";
10913 *description
= "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
10916 case kIOPMTracePointDarkWakeEntry
:
10917 *phaseString
= "kIOPMTracePointDarkWakeEntry";
10918 *description
= "entering darkwake on way to sleep";
10921 case kIOPMTracePointDarkWakeExit
:
10922 *phaseString
= "kIOPMTracePointDarkWakeExit";
10923 *description
= "entering fullwake from darkwake";
10927 *phaseString
= NULL
;
10928 *description
= NULL
;
10933 IOPMrootDomain::saveFailureData2File()
10935 unsigned int len
= 0;
10936 char failureStr
[512];
10939 OSNumber
*statusCode
;
10940 uint64_t pmStatusCode
= 0;
10941 uint32_t phaseData
= 0;
10942 uint32_t phaseDetail
= 0;
10943 bool efiFailure
= false;
10945 statusCode
= OSDynamicCast(OSNumber
, getProperty(kIOPMSleepWakeFailureCodeKey
));
10947 pmStatusCode
= statusCode
->unsigned64BitValue();
10948 phaseData
= pmStatusCode
& 0xFFFFFFFF;
10949 phaseDetail
= (pmStatusCode
>> 32) & 0xFFFFFFFF;
10950 if ((phaseData
& 0xFF) == kIOPMTracePointSystemSleep
) {
10951 LOG("Sleep Wake failure in EFI\n");
10954 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
);
10955 len
= strlen(failureStr
);
10960 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic
, NULL
, &len
)) {
10961 swd_flags
|= SWD_BOOT_BY_SW_WDOG
;
10962 PERemoveNVRAMProperty(kIOSleepWakeFailurePanic
);
10963 // dump panic will handle saving nvram data
10967 /* Keeping this around for capturing data during power
10970 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString
, NULL
, &len
)) {
10971 DLOG("No sleep wake failure string\n");
10975 DLOG("Ignoring zero byte SleepWake failure string\n");
10979 // if PMStatus code is zero, delete stackshot and return
10981 if (((pmStatusCode
& 0xFFFFFFFF) & 0xFF) == 0) {
10982 // there was no sleep wake failure
10983 // this can happen if delete stackshot was called
10984 // before take stackshot completed. Let us delete any
10985 // sleep wake failure data in nvram
10986 DLOG("Deleting stackshot on successful wake\n");
10992 if (len
> sizeof(failureStr
)) {
10993 len
= sizeof(failureStr
);
10996 PEReadNVRAMProperty(kIOSleepWakeFailureString
, failureStr
, &len
);
10998 if (failureStr
[0] != 0) {
10999 error
= sleepWakeDebugSaveFile(kSleepWakeFailureStringFile
, failureStr
, len
);
11001 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error
);
11003 DLOG("Saved SleepWake failure string to file.\n");
11007 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11012 unsigned int len
= 0;
11014 char nvram_var_name_buffer
[20];
11015 unsigned int concat_len
= 0;
11016 swd_hdr
*hdr
= NULL
;
11019 hdr
= (swd_hdr
*)swd_buffer
;
11020 outbuf
= (char *)hdr
+ hdr
->spindump_offset
;
11022 for (int i
= 0; i
< 8; i
++) {
11023 snprintf(nvram_var_name_buffer
, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, i
+ 1);
11024 if (!PEReadNVRAMProperty(nvram_var_name_buffer
, NULL
, &len
)) {
11025 LOG("No SleepWake blob to read beyond chunk %d\n", i
);
11028 if (PEReadNVRAMProperty(nvram_var_name_buffer
, outbuf
+ concat_len
, &len
) == FALSE
) {
11029 PERemoveNVRAMProperty(nvram_var_name_buffer
);
11030 LOG("Could not read the property :-(\n");
11033 PERemoveNVRAMProperty(nvram_var_name_buffer
);
11036 LOG("Concatenated length for the SWD blob %d\n", concat_len
);
11039 error
= sleepWakeDebugSaveFile(kSleepWakeStacksFilename
, outbuf
, concat_len
);
11041 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error
);
11043 LOG("Saved SleepWake zipped data to file.\n");
11046 // There is a sleep wake failure string but no stackshot
11047 // Write a placeholder stacks file so that swd runs
11048 snprintf(outbuf
, 20, "%s", "No stackshot data\n");
11049 error
= sleepWakeDebugSaveFile(kSleepWakeStacksFilename
, outbuf
, 20);
11051 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error
);
11053 LOG("Saved SleepWake zipped data to file.\n");
11057 LOG("No buffer allocated to save failure stackshot\n");
11061 gRootDomain
->swd_lock
= 0;
11063 PERemoveNVRAMProperty(kIOSleepWakeFailureString
);
11069 IOPMrootDomain::getFailureData(thread_t
*thread
, char *failureStr
, size_t strLen
)
11071 IORegistryIterator
* iter
;
11072 IORegistryEntry
* entry
;
11074 bool nodeFound
= false;
11076 const void * callMethod
= NULL
;
11077 const char * objectName
= NULL
;
11078 uint32_t timeout
= getWatchdogTimeout();
11079 const char * phaseString
= NULL
;
11080 const char * phaseDescription
= NULL
;
11082 IOPMServiceInterestNotifier
*notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, notifierObject
);
11083 uint32_t tracePhase
= pmTracer
->getTracePhase();
11086 if ((tracePhase
< kIOPMTracePointSystemSleep
) || (tracePhase
== kIOPMTracePointDarkWakeEntry
)) {
11087 snprintf(failureStr
, strLen
, "%sSleep transition timed out after %d seconds", failureStr
, timeout
);
11089 snprintf(failureStr
, strLen
, "%sWake transition timed out after %d seconds", failureStr
, timeout
);
11091 tracePhase2String(tracePhase
, &phaseString
, &phaseDescription
);
11093 if (notifierThread
) {
11094 if (notifier
&& (notifier
->identifier
)) {
11095 objectName
= notifier
->identifier
->getCStringNoCopy();
11097 *thread
= notifierThread
;
11099 iter
= IORegistryIterator::iterateOver(
11100 getPMRootDomain(), gIOPowerPlane
, kIORegistryIterateRecursively
);
11103 while ((entry
= iter
->getNextObject())) {
11104 node
= OSDynamicCast(IOService
, entry
);
11108 if (OSDynamicCast(IOPowerConnection
, node
)) {
11112 if (node
->getBlockingDriverCall(thread
, &callMethod
)) {
11120 OSKext
*kext
= OSKext::lookupKextWithAddress((vm_address_t
)callMethod
);
11122 objectName
= kext
->getIdentifierCString();
11127 if (phaseDescription
) {
11128 snprintf(failureStr
, strLen
, "%s while %s.", failureStr
, phaseDescription
);
11131 snprintf(failureStr
, strLen
, "%s Suspected bundle: %s.", failureStr
, objectName
);
11134 snprintf(failureStr
, strLen
, "%s Thread 0x%llx.", failureStr
, thread_tid(*thread
));
11137 DLOG("%s\n", failureStr
);
11140 struct swd_stackshot_compressed_data
{
11141 z_output_func zoutput
;
11143 uint64_t totalbytes
;
11144 uint64_t lastpercent
;
11146 unsigned outremain
;
11151 struct swd_stackshot_compressed_data swd_zip_var
= { };
11154 swd_zs_alloc(void *__unused ref
, u_int items
, u_int size
)
11157 LOG("Alloc in zipping %d items of size %d\n", items
, size
);
11159 result
= (void *)(swd_zs_zmem
+ swd_zs_zoffset
);
11160 swd_zs_zoffset
+= ~31L & (31 + (items
* size
)); // 32b align for vector crc
11161 LOG("Offset %zu\n", swd_zs_zoffset
);
11166 swd_zinput(z_streamp strm
, Bytef
*buf
, unsigned size
)
11170 len
= strm
->avail_in
;
11179 if (strm
->next_in
!= (Bytef
*) strm
) {
11180 memcpy(buf
, strm
->next_in
, len
);
11185 strm
->adler
= z_crc32(strm
->adler
, buf
, len
);
11187 strm
->avail_in
-= len
;
11188 strm
->next_in
+= len
;
11189 strm
->total_in
+= len
;
11195 swd_zoutput(z_streamp strm
, Bytef
*buf
, unsigned len
)
11197 unsigned int i
= 0;
11198 // if outlen > max size don't add to the buffer
11200 if (swd_zip_var
.outlen
+ len
> SWD_COMPRESSED_BUFSIZE
) {
11201 LOG("No space to GZIP... not writing to NVRAM\n");
11205 for (i
= 0; i
< len
; i
++) {
11206 *(swd_zip_var
.outbuf
+ swd_zip_var
.outlen
+ i
) = *(buf
+ i
);
11208 swd_zip_var
.outlen
+= len
;
11212 swd_zs_free(void * __unused ref
, void * __unused ptr
)
11217 swd_compress(char *inPtr
, char *outPtr
, size_t numBytes
)
11222 if (!swd_zs
.zalloc
) {
11223 swd_zs
.zalloc
= swd_zs_alloc
;
11224 swd_zs
.zfree
= swd_zs_free
;
11225 if (deflateInit2(&swd_zs
, Z_BEST_SPEED
, Z_DEFLATED
, wbits
+ 16, memlevel
, Z_DEFAULT_STRATEGY
)) {
11226 // allocation failed
11227 bzero(&swd_zs
, sizeof(swd_zs
));
11228 // swd_zs_zoffset = 0;
11230 LOG("PMRD inited the zlib allocation routines\n");
11236 swd_zip_var
.zipped
= 0;
11237 swd_zip_var
.totalbytes
= 0; // should this be the max that we have?
11238 swd_zip_var
.lastpercent
= 0;
11239 swd_zip_var
.error
= kIOReturnSuccess
;
11240 swd_zip_var
.outremain
= 0;
11241 swd_zip_var
.outlen
= 0;
11242 swd_zip_var
.writes
= 0;
11243 swd_zip_var
.outbuf
= (Bytef
*)outPtr
;
11245 swd_zip_var
.totalbytes
= numBytes
;
11247 swd_zs
.avail_in
= 0;
11248 swd_zs
.next_in
= NULL
;
11249 swd_zs
.avail_out
= 0;
11250 swd_zs
.next_out
= NULL
;
11252 deflateResetWithIO(&swd_zs
, swd_zinput
, swd_zoutput
);
11260 while (swd_zip_var
.error
>= 0) {
11261 if (!zs
->avail_in
) {
11262 zs
->next_in
= (unsigned char *)inPtr
? (Bytef
*)inPtr
: (Bytef
*)zs
; /* zero marker? */
11263 zs
->avail_in
= numBytes
;
11265 if (!zs
->avail_out
) {
11266 zs
->next_out
= (Bytef
*)zs
;
11267 zs
->avail_out
= UINT32_MAX
;
11269 zr
= deflate(zs
, Z_NO_FLUSH
);
11270 if (Z_STREAM_END
== zr
) {
11274 LOG("ZERR %d\n", zr
);
11275 swd_zip_var
.error
= zr
;
11277 if (zs
->total_in
== numBytes
) {
11283 //now flush the stream
11284 while (swd_zip_var
.error
>= 0) {
11285 if (!zs
->avail_out
) {
11286 zs
->next_out
= (Bytef
*)zs
;
11287 zs
->avail_out
= UINT32_MAX
;
11289 zr
= deflate(zs
, Z_FINISH
);
11290 if (Z_STREAM_END
== zr
) {
11294 LOG("ZERR %d\n", zr
);
11295 swd_zip_var
.error
= zr
;
11297 if (zs
->total_in
== numBytes
) {
11298 LOG("Total output size %d\n", swd_zip_var
.outlen
);
11304 return swd_zip_var
.outlen
;
11308 IOPMrootDomain::deleteStackshot()
11310 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11311 // takeStackshot hasn't completed
11314 LOG("Deleting any sleepwake failure data in nvram\n");
11316 PERemoveNVRAMProperty(kIOSleepWakeFailureString
);
11317 char nvram_var_name_buf
[20];
11318 for (int i
= 0; i
< 8; i
++) {
11319 snprintf(nvram_var_name_buf
, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, i
+ 1);
11320 if (PERemoveNVRAMProperty(nvram_var_name_buf
) == false) {
11321 LOG("Removing %s returned false\n", nvram_var_name_buf
);
11324 // force NVRAM sync
11325 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey
, kIONVRAMSyncNowPropertyKey
, strlen(kIONVRAMSyncNowPropertyKey
)) == false) {
11326 DLOG("Failed to force nvram sync\n");
11328 gRootDomain
->swd_lock
= 0;
11331 IOPMrootDomain::takeStackshot(bool wdogTrigger
)
11333 swd_hdr
* hdr
= NULL
;
11337 kern_return_t kr
= KERN_SUCCESS
;
11342 uint32_t bytesRemaining
;
11343 unsigned bytesWritten
= 0;
11345 char failureStr
[512];
11346 thread_t thread
= NULL
;
11347 const char * swfPanic
= "swfPanic";
11353 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11358 if ((kIOSleepWakeWdogOff
& gIOKitDebug
) || systemBooting
|| systemShutdown
|| gWillShutdown
) {
11363 getFailureData(&thread
, failureStr
, sizeof(failureStr
));
11365 if (PEGetCoprocessorVersion() >= kCoprocessorVersion2
) {
11366 goto skip_stackshot
;
11371 clock_get_uptime(&now
);
11372 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
11373 absolutetime_to_nanoseconds(now
, &nsec
);
11374 snprintf(failureStr
, sizeof(failureStr
), "%sPower button pressed during wake transition after %u ms.\n", failureStr
, ((int)((nsec
) / NSEC_PER_MSEC
)));
11377 if (swd_buffer
== NULL
) {
11378 sleepWakeDebugMemAlloc();
11379 if (swd_buffer
== NULL
) {
11383 hdr
= (swd_hdr
*)swd_buffer
;
11384 bufSize
= hdr
->alloc_size
;;
11389 dstAddr
= (char*)hdr
+ hdr
->spindump_offset
;
11390 flags
= STACKSHOT_KCDATA_FORMAT
| STACKSHOT_NO_IO_STATS
| STACKSHOT_SAVE_KEXT_LOADINFO
| STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY
| STACKSHOT_THREAD_WAITINFO
;
11391 /* If not wdogTrigger only take kernel tasks stackshot
11399 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
11400 * If we run out of space, take stackshot with only kernel task
11402 while (success
== 0 && cnt
< max_cnt
) {
11403 bytesRemaining
= bufSize
- hdr
->spindump_offset
;
11405 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining
);
11407 size
= bytesRemaining
;
11408 kr
= stack_snapshot_from_kernel(pid
, dstAddr
, size
, flags
, 0, &bytesWritten
);
11409 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%x bytesWritten: %d\n",
11410 kr
, pid
, size
, flags
, bytesWritten
);
11411 if (kr
== KERN_INSUFFICIENT_BUFFER_SIZE
) {
11415 LOG("Insufficient buffer size for only kernel task\n");
11419 if (kr
== KERN_SUCCESS
) {
11420 if (bytesWritten
== 0) {
11421 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%x\n", kr
, size
, flags
);
11424 bytesRemaining
-= bytesWritten
;
11425 hdr
->spindump_size
= (bufSize
- bytesRemaining
- hdr
->spindump_offset
);
11427 memset(hdr
->reason
, 0x20, sizeof(hdr
->reason
));
11429 // Compress stackshot and save to NVRAM
11431 char *outbuf
= (char *)swd_compressed_buffer
;
11433 int num_chunks
= 0;
11434 int max_chunks
= 0;
11436 char nvram_var_name_buffer
[20];
11438 outlen
= swd_compress((char*)hdr
+ hdr
->spindump_offset
, outbuf
, bytesWritten
);
11441 max_chunks
= outlen
/ (2096 - 200);
11442 leftover
= outlen
% (2096 - 200);
11444 if (max_chunks
< 8) {
11445 for (num_chunks
= 0; num_chunks
< max_chunks
; num_chunks
++) {
11446 snprintf(nvram_var_name_buffer
, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, num_chunks
+ 1);
11447 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer
, (outbuf
+ (num_chunks
* (2096 - 200))), (2096 - 200)) == FALSE
) {
11448 LOG("Failed to update NVRAM %d\n", num_chunks
);
11453 snprintf(nvram_var_name_buffer
, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, num_chunks
+ 1);
11454 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer
, (outbuf
+ (num_chunks
* (2096 - 200))), leftover
) == FALSE
) {
11455 LOG("Failed to update NVRAM with leftovers\n");
11459 LOG("Successfully saved stackshot to NVRAM\n");
11461 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen
);
11465 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen
);
11474 if (failureStr
[0]) {
11475 // append sleep-wake failure code
11476 snprintf(failureStr
, sizeof(failureStr
), "%s\nFailure code:: 0x%08x %08x\n",
11477 failureStr
, pmTracer
->getTraceData(), pmTracer
->getTracePhase());
11478 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString
, failureStr
, strlen(failureStr
)) == false) {
11479 DLOG("Failed to write SleepWake failure string\n");
11483 // force NVRAM sync
11484 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey
, kIONVRAMSyncNowPropertyKey
, strlen(kIONVRAMSyncNowPropertyKey
)) == false) {
11485 DLOG("Failed to force nvram sync\n");
11490 if (PEGetCoprocessorVersion() < kCoprocessorVersion2
) {
11491 if (swd_flags
& SWD_BOOT_BY_SW_WDOG
) {
11492 // If current boot is due to this watch dog trigger restart in previous boot,
11493 // then don't trigger again until at least 1 successful sleep & wake.
11494 if (!(sleepCnt
&& (displayWakeCnt
|| darkWakeCnt
))) {
11495 LOG("Shutting down due to repeated Sleep/Wake failures\n");
11496 if (!tasksSuspended
) {
11497 tasksSuspended
= TRUE
;
11498 updateTasksSuspend();
11500 PEHaltRestart(kPEHaltCPU
);
11504 if (gSwdPanic
== 0) {
11505 LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
11506 if (!tasksSuspended
) {
11507 tasksSuspended
= TRUE
;
11508 updateTasksSuspend();
11510 PEHaltRestart(kPERestartCPU
);
11513 if (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic
, swfPanic
, strlen(swfPanic
)) == false) {
11514 DLOG("Failed to write SleepWake failure panic key\n");
11517 panic_with_thread_context(0, NULL
, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT
, thread
, "%s", failureStr
);
11519 panic_with_options(0, NULL
, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT
, "%s", failureStr
);
11522 gRootDomain
->swd_lock
= 0;
11528 IOPMrootDomain::sleepWakeDebugMemAlloc()
11530 vm_size_t size
= SWD_STACKSHOT_SIZE
+ SWD_COMPRESSED_BUFSIZE
+ SWD_ZLIB_BUFSIZE
;
11532 swd_hdr
*hdr
= NULL
;
11533 void *bufPtr
= NULL
;
11535 IOBufferMemoryDescriptor
*memDesc
= NULL
;
11538 if (kIOSleepWakeWdogOff
& gIOKitDebug
) {
11542 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11546 memDesc
= IOBufferMemoryDescriptor::inTaskWithOptions(
11547 kernel_task
, kIODirectionIn
| kIOMemoryMapperNone
,
11549 if (memDesc
== NULL
) {
11550 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
11554 bufPtr
= memDesc
->getBytesNoCopy();
11556 // Carve out memory for zlib routines
11557 swd_zs_zmem
= (vm_offset_t
)bufPtr
;
11558 bufPtr
= (char *)bufPtr
+ SWD_ZLIB_BUFSIZE
;
11560 // Carve out memory for compressed stackshots
11561 swd_compressed_buffer
= bufPtr
;
11562 bufPtr
= (char *)bufPtr
+ SWD_COMPRESSED_BUFSIZE
;
11564 // Remaining is used for holding stackshot
11565 hdr
= (swd_hdr
*)bufPtr
;
11566 memset(hdr
, 0, sizeof(swd_hdr
));
11568 hdr
->signature
= SWD_HDR_SIGNATURE
;
11569 hdr
->alloc_size
= SWD_STACKSHOT_SIZE
;
11571 hdr
->spindump_offset
= sizeof(swd_hdr
);
11572 swd_buffer
= (void *)hdr
;
11573 swd_memDesc
= memDesc
;
11574 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr
->alloc_size
, hdr
->spindump_offset
);
11577 gRootDomain
->swd_lock
= 0;
11581 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
11583 vm_size_t size
= SWD_SPINDUMP_SIZE
;
11585 swd_hdr
*hdr
= NULL
;
11587 IOBufferMemoryDescriptor
*memDesc
= NULL
;
11589 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11593 memDesc
= IOBufferMemoryDescriptor::inTaskWithOptions(
11594 kernel_task
, kIODirectionIn
| kIOMemoryMapperNone
,
11595 SWD_SPINDUMP_SIZE
);
11597 if (memDesc
== NULL
) {
11598 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
11603 hdr
= (swd_hdr
*)memDesc
->getBytesNoCopy();
11604 memset(hdr
, 0, sizeof(swd_hdr
));
11606 hdr
->signature
= SWD_HDR_SIGNATURE
;
11607 hdr
->alloc_size
= size
;
11609 hdr
->spindump_offset
= sizeof(swd_hdr
);
11610 swd_spindump_buffer
= (void *)hdr
;
11613 gRootDomain
->swd_lock
= 0;
11617 IOPMrootDomain::sleepWakeDebugEnableWdog()
11622 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
11624 return !systemBooting
&& !systemShutdown
&& !gWillShutdown
;
11628 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
11630 swd_hdr
*hdr
= NULL
;
11631 errno_t error
= EIO
;
11633 if (swd_spindump_buffer
&& gSpinDumpBufferFull
) {
11634 hdr
= (swd_hdr
*)swd_spindump_buffer
;
11636 error
= sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
11637 (char*)hdr
+ hdr
->spindump_offset
, hdr
->spindump_size
);
11643 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
11644 (char*)hdr
+ offsetof(swd_hdr
, UUID
),
11645 sizeof(swd_hdr
) - offsetof(swd_hdr
, UUID
));
11647 gSpinDumpBufferFull
= false;
11652 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name
, char *buf
, int len
)
11654 struct vnode
*vp
= NULL
;
11655 vfs_context_t ctx
= vfs_context_create(vfs_context_current());
11656 kauth_cred_t cred
= vfs_context_ucred(ctx
);
11657 struct vnode_attr va
;
11658 errno_t error
= EIO
;
11660 if (vnode_open(name
, (O_CREAT
| FWRITE
| O_NOFOLLOW
),
11661 S_IRUSR
| S_IRGRP
| S_IROTH
, VNODE_LOOKUP_NOFOLLOW
, &vp
, ctx
) != 0) {
11662 LOG("Failed to open the file %s\n", name
);
11663 swd_flags
|= SWD_FILEOP_ERROR
;
11667 VATTR_WANTED(&va
, va_nlink
);
11668 /* Don't dump to non-regular files or files with links. */
11669 if (vp
->v_type
!= VREG
||
11670 vnode_getattr(vp
, &va
, ctx
) || va
.va_nlink
!= 1) {
11671 LOG("Bailing as this is not a regular file\n");
11672 swd_flags
|= SWD_FILEOP_ERROR
;
11676 VATTR_SET(&va
, va_data_size
, 0);
11677 vnode_setattr(vp
, &va
, ctx
);
11681 error
= vn_rdwr(UIO_WRITE
, vp
, buf
, len
, 0,
11682 UIO_SYSSPACE
, IO_NODELOCKED
| IO_UNIT
, cred
, (int *) NULL
, vfs_context_proc(ctx
));
11684 LOG("Failed to save sleep wake log. err 0x%x\n", error
);
11685 swd_flags
|= SWD_FILEOP_ERROR
;
11687 DLOG("Saved %d bytes to file %s\n", len
, name
);
11693 vnode_close(vp
, FWRITE
, ctx
);
11696 vfs_context_rele(ctx
);
11706 IOPMrootDomain::sleepWakeDebugTrig(bool restart
)
11709 if (gSwdPanic
== 0) {
11712 panic("Sleep/Wake hang detected");
11718 IOPMrootDomain::takeStackshot(bool restart
)
11720 #pragma unused(restart)
11723 IOPMrootDomain::deleteStackshot()
11727 IOPMrootDomain::sleepWakeDebugMemAlloc()
11731 IOPMrootDomain::saveFailureData2File()
11736 IOPMrootDomain::sleepWakeDebugEnableWdog()
11741 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
11747 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name
, char *buf
, int len
)