Loading...
--- xnu/xnu-12377.121.6/iokit/Kernel/IOPMrootDomain.cpp
+++ xnu/xnu-11215.41.3/iokit/Kernel/IOPMrootDomain.cpp
@@ -54,9 +54,8 @@
#include <IOKit/IOCatalogue.h>
#include <IOKit/IOReportMacros.h>
#include <IOKit/IOLib.h>
-#include <IOKit/IOKitKeysPrivate.h>
+#include <IOKit/IOKitKeys.h>
#include <IOKit/IOUserServer.h>
-#include <IOKit/IOBSD.h>
#include "IOKitKernelInternal.h"
#if HIBERNATION
#include <IOKit/IOHibernatePrivate.h>
@@ -69,8 +68,6 @@
#include <sys/vnode_internal.h>
#include <sys/fcntl.h>
#include <os/log.h>
-#include <os/log_private.h>
-#include <pexpert/device_tree.h>
#include <pexpert/protos.h>
#include <AssertMacros.h>
@@ -82,6 +79,7 @@
#include <os/cpp_util.h>
#include <os/atomic_private.h>
#include <libkern/c++/OSBoundedArrayRef.h>
+#include <libkern/coreanalytics/coreanalytics.h>
#if DEVELOPMENT || DEBUG
#include <os/system_event_log.h>
@@ -99,8 +97,6 @@
const char *processor_to_datastring(const char *prefix, processor_t target_processor);
__END_DECLS
#endif
-
-#define ARRAY_LEN(x) (sizeof (x) / sizeof (x[0]))
#define kIOPMrootDomainClass "IOPMrootDomain"
#define LOG_PREFIX "PMRD: "
@@ -193,8 +189,7 @@
kPowerEventPublishSleepWakeUUID, // 13
kPowerEventSetDisplayPowerOn, // 14
kPowerEventPublishWakeType, // 15
- kPowerEventAOTEvaluate, // 16
- kPowerEventRunModeRequest // 17
+ kPowerEventAOTEvaluate // 16
};
// For evaluatePolicy()
@@ -324,11 +319,7 @@
// Minimum time in milliseconds after AP wake that we allow idle timer to expire.
// We impose this minimum to avoid race conditions in the AP wake path where
// userspace clients are not able to acquire power assertions before the idle timer expires.
-#if XNU_TARGET_OS_IOS
-#define kMinimumTimeBeforeIdleSleep 3000
-#else
#define kMinimumTimeBeforeIdleSleep 1000
-#endif
#define DISPLAY_WRANGLER_PRESENT (!NO_KERNEL_HID)
@@ -337,6 +328,15 @@
kWranglerPowerStateSleep = 2,
kWranglerPowerStateDim = 3,
kWranglerPowerStateMax = 4
+};
+
+enum {
+ OFF_STATE = 0,
+ RESTART_STATE = 1,
+ SLEEP_STATE = 2,
+ AOT_STATE = 3,
+ ON_STATE = 4,
+ NUM_POWER_STATES
};
const char *
@@ -620,7 +620,6 @@
static char gWakeReasonString[128];
static char gBootReasonString[80];
static char gShutdownReasonString[80];
-static uint64_t gShutdownTime;
static bool gWakeReasonSysctlRegistered = false;
static bool gBootReasonSysctlRegistered = false;
static bool gShutdownReasonSysctlRegistered = false;
@@ -767,72 +766,6 @@
uint8_t loginWindowData;
uint8_t coreDisplayData;
uint8_t coreGraphicsData;
-};
-
-struct IOPMAssertionLog {
- IOPMAssertionLogData data;
-
- mach_port_t notificationPort;
- uint64_t notificationThreshold;
-
-public:
- IOReturn
- setNotificationThreshold(uint64_t threshold)
- {
- if (threshold > ARRAY_LEN(data.intervals)) {
- return kIOReturnBadArgument;
- }
- notificationThreshold = threshold;
- return kIOReturnSuccess;
- }
-
- IOReturn
- setNotificationPort(mach_port_t port)
- {
- if (port != MACH_PORT_NULL && notificationPort != MACH_PORT_NULL) {
- return kIOReturnExclusiveAccess;
- }
-
- notificationPort = port;
- return kIOReturnSuccess;
- }
-
- void
- notify()
- {
- if (notificationPort == MACH_PORT_NULL) {
- return;
- }
-
- mach_msg_header_t msg;
- msg.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, 0);
- msg.msgh_id = 0;
- msg.msgh_size = sizeof(mach_msg_header_t);
- msg.msgh_local_port = MACH_PORT_NULL;
- msg.msgh_remote_port = notificationPort;
- (void)mach_msg_send_from_kernel_with_options(&msg, msg.msgh_size, MACH64_SEND_TIMEOUT, MACH_MSG_TIMEOUT_NONE);
- }
-
- void
- addInterval(IOPMDriverAssertionID id, uint64_t create_timestamp, uint64_t delete_timestamp)
- {
- IOPMAssertionLogData::Interval& interval = data.intervals[data.intervals_pos++ % ARRAY_LEN(data.intervals)];
- interval.id = id;
- interval.create_timestamp = create_timestamp;
- interval.delete_timestamp = delete_timestamp;
-
- if (notificationPort && notificationThreshold == (data.intervals_pos % ARRAY_LEN(data.intervals))) {
- notify();
- }
- }
-
- void
- addName(IOPMDriverAssertionID id, const char *name)
- {
- IOPMAssertionLogData::Properties& prop = data.props[data.props_pos++ % ARRAY_LEN(data.props)];
- prop.id = id;
- strlcpy(prop.name, name, sizeof(prop.name));
- }
};
/*
@@ -897,10 +830,6 @@
IOPMDriverAssertionType assertionsKernel;
IOPMDriverAssertionType assertionsUser;
IOPMDriverAssertionType assertionsCombined;
-
- IOPMAssertionLog assertionsLog;
-
- friend class IOPMrootDomain;
};
OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
@@ -1446,26 +1375,6 @@
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
NULL, 0, sysctl_shutdownreason, "A", "shutdownreason");
-// This value is meant to represent the last time the device shut down
-// in a unit of the PMU driver's choosing see rdar://138590268 for details
-static int
-sysctl_shutdowntime SYSCTL_HANDLER_ARGS
-{
- uint64_t shutdownTime = 0;
-
- if (gRootDomain && gShutdownReasonSysctlRegistered) {
- gRootDomain->copyShutdownTime(&shutdownTime);
- } else {
- return ENOENT;
- }
-
- return SYSCTL_OUT(req, &shutdownTime, sizeof(shutdownTime));
-}
-
-SYSCTL_PROC(_kern, OID_AUTO, shutdowntime,
- CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
- NULL, 0, sysctl_shutdowntime, "Q", "shutdowntime");
-
static int
sysctl_targettype SYSCTL_HANDLER_ARGS
{
@@ -1487,69 +1396,6 @@
SYSCTL_PROC(_hw, OID_AUTO, targettype,
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
NULL, 0, sysctl_targettype, "A", "targettype");
-
-static SECURITY_READ_ONLY_LATE(char*) jetsam_properties_product_type_string = NULL;
-static SECURITY_READ_ONLY_LATE(size_t) jetsam_properties_product_type_string_len = 0;
-
-/*
- * SecureDTLookupEntry() is only guaranteed to work before PE_init_iokit(),
- * so we load the jetsam_properties_product_type string (if available) in a startup handler.
- */
-__startup_func
-static void
-sysctl_load_jetsam_properties_product_type(void)
-{
- DTEntry node;
- void const *value = NULL;
- unsigned int size = 0;
-
- if (kSuccess != SecureDTLookupEntry(nullptr, "/product", &node)) {
- return;
- }
-
- if (kSuccess != SecureDTGetProperty(node, "jetsam-properties-product-type", (void const **) &value, &size)) {
- return;
- }
-
- if (size == 0) {
- return;
- }
-
- jetsam_properties_product_type_string = (char *) zalloc_permanent(size, ZALIGN_NONE);
- if (jetsam_properties_product_type_string == NULL) {
- return;
- }
-
- memcpy(jetsam_properties_product_type_string, value, size);
- jetsam_properties_product_type_string_len = size;
-}
-STARTUP(SYSCTL, STARTUP_RANK_MIDDLE, sysctl_load_jetsam_properties_product_type);
-
-static int
-sysctl_jetsam_properties_product_type SYSCTL_HANDLER_ARGS
-{
- if (jetsam_properties_product_type_string != NULL) {
- return SYSCTL_OUT(req, jetsam_properties_product_type_string, jetsam_properties_product_type_string_len);
- }
-
- IOService * root;
- OSSharedPtr<OSObject> obj;
- OSData * data;
- char tt[32];
-
- tt[0] = '\0';
- root = IOService::getServiceRoot();
- if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
- if ((data = OSDynamicCast(OSData, obj.get()))) {
- strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
- }
- }
- return sysctl_io_string(req, tt, 0, 0, NULL);
-}
-
-SYSCTL_PROC(_hw, OID_AUTO, jetsam_properties_product_type,
- CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
- NULL, 0, sysctl_jetsam_properties_product_type, "A", "jetsam_properties_product_type");
static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, "");
static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, "");
@@ -1580,8 +1426,6 @@
return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
}
-TUNABLE_DT_WRITEABLE(uint32_t, gAOTMode, "/product/iopm",
- "aot-mode", "aot_mode", 0, TUNABLE_DT_NONE);
static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics,
CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", "");
@@ -1598,8 +1442,8 @@
result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
unsigned int oldCount;
- if (mode && !gRootDomain->_aotMetrics) {
- gRootDomain->_aotMetrics = IOMallocType(IOPMAOTMetrics);
+ if (mode) {
+ gRootDomain->initAOTMetrics();
}
oldCount = gRootDomain->idleSleepPreventersCount();
@@ -1656,15 +1500,6 @@
static SYSCTL_PROC(_kern, OID_AUTO, aotmode,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
NULL, 0, sysctl_aotmode, "I", "");
-
-TUNABLE_DT(uint32_t, gAOTLingerTimeMS, "/product/iopm",
- "aot-linger-time-ms", "aot_linger_time_ms", 800, TUNABLE_DT_NONE);
-
-// Low Power Wake tunables
-TUNABLE_DT_WRITEABLE(uint64_t, gLPWFlags, "/product/iopm",
- "low-power-wake", "low_power_wake", false, TUNABLE_DT_NONE);
-static SYSCTL_QUAD(_kern, OID_AUTO, lowpowerwake, CTLFLAG_RW | CTLFLAG_LOCKED,
- &gLPWFlags, "Low Power Wake");
//******************************************************************************
@@ -1686,7 +1521,7 @@
//
//******************************************************************************
-#define kRootDomainSettingsCount 21
+#define kRootDomainSettingsCount 20
#define kRootDomainNoPublishSettingsCount 4
bool
@@ -1732,7 +1567,6 @@
gIOPMSettingDebugPowerRelativeKey,
OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
- OSSymbol::withCString(kIOPMSettingRestartOnPowerConnectKey),
OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
@@ -1767,10 +1601,6 @@
PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout));
PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic));
PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog));
-
- _aotMode = gAOTMode;
- _aotLingerTime = gAOTLingerTimeMS;
- _aotMetrics = _aotMode ? IOMallocType(IOPMAOTMetrics) : NULL;
// read noidle setting from Device Tree
if (PE_get_default("no-idle", &gNoIdleFlag, sizeof(gNoIdleFlag))) {
@@ -1908,9 +1738,6 @@
PMinit(); // creates gIOPMWorkLoop
gIOPMWorkLoop = getIOPMWorkloop();
- commandGate = IOCommandGate::commandGate(gIOPMWorkLoop);
- gIOPMWorkLoop->addEventSource(commandGate.get());
-
// Create IOPMPowerStateQueue used to queue external power
// events, and to handle those events on the PM work loop.
pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
@@ -1918,6 +1745,7 @@
&IOPMrootDomain::dispatchPowerEvent));
gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
+ _aotMode = 0;
_aotTimerES = IOTimerEventSource::timerEventSource(this,
OSMemberFunctionCast(IOTimerEventSource::Action,
this, &IOPMrootDomain::aotEvaluate));
@@ -2214,79 +2042,6 @@
exit:
return return_value;
-}
-
-#if HIBERNATION
-// MARK: -
-// MARK: setLockdownModeHibernation
-// ***************************************************************************
-void
-IOPMrootDomain::setLockdownModeHibernation(uint32_t status)
-{
- if (!gIOPMWorkLoop->inGate()) {
- gIOPMWorkLoop->runAction(
- OSMemberFunctionCast(IOWorkLoop::Action, this,
- &IOPMrootDomain::setLockdownModeHibernation),
- this, (void *)(uintptr_t) status);
- return;
- }
-
- ldmHibernateDisable = status;
- DLOG("ldmHibernateDisable %d\n", status);
- setProperty("IOPMLDMHibernationDisable", status);
-}
-#endif
-
-IOReturn
-IOPMrootDomain::getAssertionLog(IOPMAssertionLogData *outLog)
-{
- if (!gIOPMWorkLoop->inGate()) {
- return gIOPMWorkLoop->runAction(
- OSMemberFunctionCast(IOWorkLoop::Action, this,
- &IOPMrootDomain::getAssertionLog),
- this, (void *)(uintptr_t) outLog);
- }
-
- if (!pmAssertions) {
- return kIOReturnNotFound;
- }
-
- *outLog = pmAssertions->assertionsLog.data;
- return kIOReturnSuccess;
-}
-
-IOReturn
-IOPMrootDomain::setAssertionLogNotificationPort(mach_port_t port)
-{
- if (!gIOPMWorkLoop->inGate()) {
- return gIOPMWorkLoop->runAction(
- OSMemberFunctionCast(IOWorkLoop::Action, this,
- &IOPMrootDomain::setAssertionLogNotificationPort),
- this, (void *)(uintptr_t) port);
- }
-
- if (!pmAssertions) {
- return kIOReturnNotFound;
- }
-
- return pmAssertions->assertionsLog.setNotificationPort(port);
-}
-
-IOReturn
-IOPMrootDomain::setAssertionLogNotificationThreshold(uint64_t threshold)
-{
- if (!gIOPMWorkLoop->inGate()) {
- return gIOPMWorkLoop->runAction(
- OSMemberFunctionCast(IOWorkLoop::Action, this,
- &IOPMrootDomain::setAssertionLogNotificationThreshold),
- this, (void *)(uintptr_t) threshold);
- }
-
- if (!pmAssertions) {
- return kIOReturnNotFound;
- }
-
- return pmAssertions->assertionsLog.setNotificationThreshold(threshold);
}
// MARK: -
@@ -3069,19 +2824,6 @@
notifierThread = current_thread();
switch (getPowerState()) {
case SLEEP_STATE: {
-#if defined(__arm64__) && HIBERNATION
- if (kIOHibernateStateInactive == gIOHibernateState)
-#endif /* defined(__arm64__) && HIBERNATION */
- {
- if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionForceWakeupBit)) {
- IOLog("accelerate wake for assertion\n");
- setWakeTime(mach_continuous_time());
- }
- if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionForceFullWakeupBit)) {
- // Note: The scheduled RTC wakeup will trigger a full wake.
- scheduleImmediateDebugWake();
- }
- }
if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
secs = 0;
microsecs = 0;
@@ -3150,6 +2892,7 @@
if (!_aotLastWakeTime) {
gIOLastUserSleepTime = gIOLastSleepTime;
}
+
gIOLastWakeTime.tv_sec = 0;
gIOLastWakeTime.tv_usec = 0;
gIOLastSleepAbsTime = now;
@@ -3261,11 +3004,9 @@
if (_aotTestTime) {
if (_aotWakeTimeUTC <= secs) {
- _aotTestTime = mach_continuous_time() + _aotTestInterval;
+ _aotTestTime = _aotTestTime + _aotTestInterval;
}
- if (_aotTestTime < _aotEndTime) {
- _setWakeTime(_aotTestTime);
- }
+ setWakeTime(_aotTestTime);
}
}
@@ -3424,16 +3165,9 @@
// and before the changePowerStateWithTagToPriv() call below.
WAKEEVENT_LOCK();
aotShouldExit(false);
- unsigned long newState = getRUN_STATE();
- if (AOT_STATE == newState) {
- if (gLPWFlags) {
- _aotRunMode = gLPWFlags | _aotWakeEventRunMode;
- }
- IOLog("_aotRunMode = 0x%llx|0x%llx\n", gLPWFlags, _aotWakeEventRunMode);
- }
WAKEEVENT_UNLOCK();
- changePowerStateWithTagToPriv(newState, kCPSReasonWake);
+ changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake);
break;
}
#if !__i386__ && !__x86_64__
@@ -4439,25 +4173,34 @@
}
//******************************************************************************
-// willNotifyInterest
+// willNotifyPowerChildren
//
-// Called after all priority clients have all acknowledged the power change,
-// but before any interested drivers and any power children are informed.
-// Dispatched though a thread call, so it is safe to perform work that might block on a
-// sleeping disk. PM state machine (not thread) will block w/o timeout until this function returns.
+// Called after all interested drivers have all acknowledged the power change,
+// but before any power children is informed. Dispatched though a thread call,
+// so it is safe to perform work that might block on a sleeping disk. PM state
+// machine (not thread) will block w/o timeout until this function returns.
//******************************************************************************
void
-IOPMrootDomain::willNotifyInterested( IOPMPowerStateIndex newPowerState )
+IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
{
if (SLEEP_STATE == newPowerState) {
+ notifierThread = current_thread();
+ if (updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange)) {
+ AbsoluteTime deadline;
+
+ clock_interval_to_deadline(10, kSecondScale, &deadline);
+#if defined(XNU_TARGET_OS_OSX)
+ vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
+#endif /* defined(XNU_TARGET_OS_OSX) */
+ }
+
_aotReadyToFullWake = false;
#if 0
if (_aotLingerTime) {
- uint64_t interval, deadline;
+ uint64_t deadline;
IOLog("aot linger no return\n");
- nanoseconds_to_absolutetime(_aotLingerTime * NSEC_PER_MSEC, &interval);
- clock_absolutetime_interval_to_deadline(interval, &deadline);
+ clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
clock_delay_until(deadline);
}
#endif
@@ -4475,43 +4218,18 @@
_aotLastWakeTime = 0;
bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
if (kIOPMAOTModeCycle & _aotMode) {
- clock_interval_to_absolutetime_interval(10, kSecondScale, &_aotTestInterval);
+ clock_interval_to_absolutetime_interval(60, kSecondScale, &_aotTestInterval);
_aotTestTime = mach_continuous_time() + _aotTestInterval;
- AbsoluteTime endInterval;
- clock_interval_to_absolutetime_interval(60, kSecondScale, &endInterval);
- _aotEndTime = mach_continuous_time() + endInterval;
- _setWakeTime(_aotTestTime);
- }
+ setWakeTime(_aotTestTime);
+ }
+ uint32_t lingerSecs;
+ if (!PE_parse_boot_argn("aotlinger", &lingerSecs, sizeof(lingerSecs))) {
+ lingerSecs = 0;
+ }
+ clock_interval_to_absolutetime_interval(lingerSecs, kSecondScale, &_aotLingerTime);
clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow);
clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow);
}
-
- if (updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange)) {
- IOLog("PMRD: tasks suspend\n");
- AbsoluteTime deadline;
-
- clock_interval_to_deadline(10, kSecondScale, &deadline);
-#if defined(XNU_TARGET_OS_OSX)
- vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
-#endif /* defined(XNU_TARGET_OS_OSX) */
- }
- }
-}
-
-//******************************************************************************
-// willNotifyPowerChildren
-//
-// Called after all interested drivers have all acknowledged the power change,
-// but before any power children are informed.
-// Dispatched though a thread call, so it is safe to perform work that might block on a
-// sleeping disk. PM state machine (not thread) will block w/o timeout until this function returns.
-//******************************************************************************
-
-void
-IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
-{
- if (SLEEP_STATE == newPowerState) {
- notifierThread = current_thread();
#if HIBERNATION
// Adjust watchdog for IOHibernateSystemSleep
@@ -4524,9 +4242,6 @@
IOHibernateIOKitSleep();
#endif
#if defined(__arm64__) && HIBERNATION
- if (gIOHibernateState == kIOHibernateStateInactive) {
- setProperty(kIOPMSystemSleepTypeKey, kIOPMSleepTypeDeepIdle, 32);
- }
// On AS, hibernation cannot be aborted. Resetting RTC to 1s during hibernation upon detecting
// user activity is pointless (we are likely to spend >1s hibernating). It also clears existing
// alarms, which can mess with cycler tools.
@@ -6445,7 +6160,7 @@
#if HIBERNATION && defined(__arm64__)
if (lowBatteryCondition && (desiredPowerState < currentPowerState)) {
- if (!ml_is_secure_hib_supported() || ldmHibernateDisable) {
+ if (!ml_is_secure_hib_supported()) {
// If hibernation is unsupported, reject sleep requests to avoid
// racing with system shutdown.
*inOutChangeFlags |= kIOPMNotDone;
@@ -6527,22 +6242,21 @@
if (changeFlags & kIOPMSynchronize) {
if (newPowerState == ON_STATE) {
if (changeFlags & kIOPMSyncNoChildNotify) {
- setSystemTransitionTypeGated(kSystemTransitionNewCapClient);
+ _systemTransitionType = kSystemTransitionNewCapClient;
} else {
- setSystemTransitionTypeGated(kSystemTransitionCapability);
+ _systemTransitionType = kSystemTransitionCapability;
}
}
}
// 2. Going to sleep (cancellation still possible).
else if (newPowerState < currentPowerState) {
- setSystemTransitionTypeGated(kSystemTransitionSleep);
+ _systemTransitionType = kSystemTransitionSleep;
}
// 3. Woke from (idle or demand) sleep.
else if (!systemBooting &&
(changeFlags & kIOPMSelfInitiated) &&
(newPowerState > currentPowerState)) {
- setSystemTransitionTypeGated(kSystemTransitionWake);
-
+ _systemTransitionType = kSystemTransitionWake;
_desiredCapability = kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityNetwork;
// Early exit from dark wake to full (e.g. LID open)
@@ -6584,7 +6298,7 @@
if ((kSystemTransitionCapability == _systemTransitionType) &&
(_pendingCapability == _currentCapability)) {
// Cancel the PM state change.
- setSystemTransitionTypeGated(kSystemTransitionNone);
+ _systemTransitionType = kSystemTransitionNone;
*inOutChangeFlags |= kIOPMNotDone;
}
if (__builtin_popcount(_pendingCapability) <
@@ -6693,12 +6407,7 @@
// Clear stats about sleep
if (AOT_STATE == newPowerState) {
- // Temporarily increase the capacity of the log subsystem to buffer logs in AOT.
- os_log_adjust_buffering_capacity(LOG_BUFFERING_CAPACITY_MAX);
- _pendingCapability = kIOPMSystemCapabilityAOT;
- } else {
- // Restore the maximum capacity of the log subsystem once waking to full wake.
- os_log_adjust_buffering_capacity(LOG_BUFFERING_CAPACITY_DEFAULT);
+ _pendingCapability = 0;
}
if (AOT_STATE == currentPowerState) {
@@ -6789,38 +6498,6 @@
}
void
-IOPMrootDomain::setSystemTransitionTypeGated(SystemTransitionType type)
-{
- assert(gIOPMWorkLoop->inGate());
- _systemTransitionType = type;
- commandGate->commandWakeup(&_systemTransitionType);
-}
-
-void
-IOPMrootDomain::waitForSystemTransitionToMinPowerState(IOPMRootDomainPowerState state)
-{
- while (true) {
- IOReturn ret = gIOPMWorkLoop->runActionBlock(^{
- // Block until all in progress transitions have completed.
- while (_systemTransitionType != kSystemTransitionNone) {
- commandGate->commandSleep(&_systemTransitionType);
- }
-
- // Check the current power state.
- if (getPowerState() >= state) {
- return kIOReturnSuccess;
- }
-
- return kIOReturnError;
- });
-
- if (ret == kIOReturnSuccess) {
- break;
- }
- }
-}
-
-void
IOPMrootDomain::handleOurPowerChangeDone(
IOService * service,
IOPMActions * actions,
@@ -6829,7 +6506,7 @@
IOPMPowerChangeFlags changeFlags )
{
if (kSystemTransitionNewCapClient == _systemTransitionType) {
- setSystemTransitionTypeGated(kSystemTransitionNone);
+ _systemTransitionType = kSystemTransitionNone;
return;
}
@@ -6994,8 +6671,7 @@
tracePoint( kIOPMTracePointSystemUp );
}
- setSystemTransitionTypeGated(kSystemTransitionNone);
-
+ _systemTransitionType = kSystemTransitionNone;
_systemMessageClientMask = 0;
toldPowerdCapWillChange = false;
@@ -7837,7 +7513,20 @@
break;
#endif
- if (_driverKitMatchingAssertionCount != 0 || _driverKitSyncedAssertionCount != 0) {
+ if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
+ break; // always sleep on low battery or when in thermal warning/emergency state
+ }
+
+ if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
+ break; // always sleep on dark wake thermal emergencies
+ }
+
+ if (preventSystemSleepList->getCount() != 0) {
+ err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
+ break;
+ }
+
+ if (_driverKitMatchingAssertionCount != 0) {
err = kPMCPUAssertion;
break;
}
@@ -7846,33 +7535,17 @@
// this is in flight can cause IOServicePH to timeout.
if (!IOServicePH::checkPMReady()) {
#if !defined(XNU_TARGET_OS_OSX)
- if (!(lowBatteryCondition || thermalWarningState || thermalEmergencyState)) {
- // 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
- // in dark wake for long periods of time, which causes issues as apps were
- // already informed of sleep during the f->9 transition. As a temporary
- // measure, always full wake if we hit this specific condition.
- pmPowerStateQueue->submitPowerEvent(
- kPowerEventPolicyStimulus,
- (void *) kStimulusDarkWakeActivityTickle);
- }
+ // 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
+ // in dark wake for long periods of time, which causes issues as apps were
+ // already informed of sleep during the f->9 transition. As a temporary
+ // measure, always full wake if we hit this specific condition.
+ pmPowerStateQueue->submitPowerEvent(
+ kPowerEventPolicyStimulus,
+ (void *) kStimulusDarkWakeActivityTickle);
#endif
err = kPMDKNotReady;
break;
}
-
- if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
- break; // always sleep on low battery or when in thermal warning/emergency state
- }
-
- if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
- break; // always sleep on dark wake thermal emergencies
- }
-
- if (preventSystemSleepList->getCount() != 0) {
- err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
- break;
- }
-
if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
kIOPMDriverAssertionLevelOn) {
@@ -7963,59 +7636,6 @@
}
//******************************************************************************
-// considerRunMode
-// consider the driver for AOT power on via the runmode mask
-//******************************************************************************
-
-int32_t
-IOPMrootDomain::considerRunMode(IOService * service, uint64_t pmDriverClass)
-{
- int32_t promote;
-
- if ((0 == _aotRunMode) || (service == this)) {
- // neutral
- return 0;
- }
- if (pmDriverClass) {
- IOLog("considerRunMode: %s 0x%llx 0x%llx\n", service->getName(), pmDriverClass, _aotRunMode);
- }
- promote = (0 != (_aotRunMode & pmDriverClass)) ? 1 : -1;
- if (promote > 0) {
- IOLog("IOPMRD: %s 0x%llx runmode to %s\n", service->getName(), pmDriverClass, (promote < 0) ? "OFF" : "ON");
- }
- return promote;
-}
-
-void
-IOPMrootDomain::handleRegisterPowerDriver(IOService * child)
-{
- OSNumber * num;
- IOService * userServer;
- uint64_t driverClassFlags;
- OSSharedPtr<OSObject> prop = child->copyProperty(kIOPMAOTAllowKey);
-
- if (!prop || (NULL == (num = OSDynamicCast(OSNumber, prop.get())))) {
- return;
- }
- driverClassFlags = num->unsigned64BitValue();
-
- userServer = NULL;
- if (child->reserved->uvars && (userServer = child->reserved->uvars->userServer)) {
- WAKEEVENT_LOCK();
- _aotWakeEventRunModeImpliesStorage |= driverClassFlags;
- WAKEEVENT_UNLOCK();
- }
-
- IOLog("addPMDriverClass %s %llx\n", child->getName(), driverClassFlags);
- if (driverClassFlags) {
- child->addPMDriverClass(driverClassFlags);
- if (userServer) {
- userServer->addPMDriverClass(driverClassFlags);
- }
- }
-}
-
-//******************************************************************************
// attemptIdleSleepAbort
//******************************************************************************
@@ -8192,42 +7812,8 @@
return _aotNow;
}
-bool
-IOPMrootDomain::isLPWMode()
-{
- return gLPWFlags && currentOrPendingPowerState(AOT_STATE);
-}
-
-bool
-IOPMIsAOTMode(void)
-{
- return gIOPMRootDomain && gIOPMRootDomain->isAOTMode();
-}
-bool
-IOPMIsLPWMode(void)
-{
- return gIOPMRootDomain && gIOPMRootDomain->isLPWMode();
-}
-
-void
-IOPMNetworkStackFullWake(uint64_t flags, const char * reason)
-{
- assert(kIOPMNetworkStackFullWakeFlag == flags);
- assert(gIOPMRootDomain);
- gIOPMRootDomain->claimSystemWakeEvent(gIOPMRootDomain, kIOPMWakeEventAOTExit, reason, NULL);
-}
-
IOReturn
IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
-{
- if (kIOPMAOTModeCycle & _aotMode) {
- return kIOReturnSuccess;
- }
- return _setWakeTime(wakeContinuousTime);
-}
-
-IOReturn
-IOPMrootDomain::_setWakeTime(uint64_t wakeContinuousTime)
{
clock_sec_t nowsecs, wakesecs;
clock_usec_t nowmicrosecs, wakemicrosecs;
@@ -8318,7 +7904,6 @@
ASSERT_GATED();
_aotNow = false;
- _aotRunMode = 0;
_aotReadyToFullWake = false;
if (_aotTimerScheduled) {
_aotTimerES->cancelTimeout();
@@ -8391,8 +7976,8 @@
void
IOPMrootDomain::adjustPowerState( bool sleepASAP )
{
- DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d, _aotNow %d\n",
- getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled, _aotNow);
+ DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
+ getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
ASSERT_GATED();
@@ -8408,7 +7993,11 @@
&& !_aotTimerScheduled
&& (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
_aotTimerScheduled = true;
- _aotTimerES->setTimeout(_aotLingerTime, kMillisecondScale);
+ if (_aotLingerTime) {
+ _aotTimerES->setTimeout(_aotLingerTime);
+ } else {
+ _aotTimerES->setTimeout(800, kMillisecondScale);
+ }
}
WAKEEVENT_UNLOCK();
if (exitNow) {
@@ -8664,11 +8253,6 @@
aotEvaluate(NULL);
}
break;
- case kPowerEventRunModeRequest:
- DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
- // arg1 == runModeMask
- handleRequestRunMode(arg1);
- break;
}
}
@@ -8865,7 +8449,7 @@
if (msg & kIOPMPowerEmergency) {
DLOG("Received kIOPMPowerEmergency");
#if HIBERNATION && defined(__arm64__)
- if (!ml_is_secure_hib_supported() || ldmHibernateDisable) {
+ if (!ml_is_secure_hib_supported()) {
// Wait for the next low battery notification if the system state is
// in transition.
if ((_systemTransitionType == kSystemTransitionNone) &&
@@ -8875,7 +8459,6 @@
lowBatteryCondition = true;
// Notify userspace to initiate system shutdown
- DLOG("Initiating userspace shutdown ml_is_secure_hib_supported %d lockdownMode %d", ml_is_secure_hib_supported(), ldmHibernateDisable);
messageClients(kIOPMMessageRequestSystemShutdown);
}
} else {
@@ -9425,9 +9008,7 @@
if (!systemBooting && (0 == idleSleepPreventersCount())) {
if (!wrangler) {
- if (kStimulusNoIdleSleepPreventers != stimulus) {
- changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
- }
+ changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
if (idleSleepEnabled) {
#if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
if (!extraSleepDelay && !idleSleepTimerPending && !gNoIdleFlag) {
@@ -11030,12 +10611,6 @@
serviceName, ownerDescription);
}
#endif /* (DEVELOPMENT || DEBUG) */
-
- const bool waitForWakeup = (whichAssertionBits & kIOPMDriverAssertionForceWakeupBit);
- if (waitForWakeup) {
- waitForSystemTransitionToMinPowerState(AOT_STATE);
- }
-
return newAssertion;
} else {
return 0;
@@ -11111,7 +10686,7 @@
_driverKitMatchingAssertionCount++;
return kIOReturnSuccess;
} else {
- if (kSystemTransitionSleep == _systemTransitionType && !idleSleepRevertible) {
+ if (kSystemTransitionSleep == _systemTransitionType) {
// system going to sleep
return kIOReturnBusy;
} else {
@@ -11147,75 +10722,6 @@
});
}
-IOReturn
-IOPMrootDomain::acquireDriverKitSyncedAssertion(IOService * from, IOPMDriverAssertionID * assertionID)
-{
- return gIOPMWorkLoop->runActionBlock(^{
- if (kSystemTransitionSleep == _systemTransitionType && !idleSleepRevertible) {
- // system going to sleep
- return kIOReturnBusy;
- }
- // createPMAssertion is asynchronous.
- // we must also set _driverKitSyncedAssertionCount under the PM workloop lock so that we can cancel sleep immediately
- // only kIOPMDriverAssertionCPUBit is used for "synced" assertion
- *assertionID = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, from->getName());
- if (*assertionID != kIOPMUndefinedDriverAssertionID) {
- _driverKitSyncedAssertionCount++;
- return kIOReturnSuccess;
- } else {
- return kIOReturnBusy;
- }
- });
-}
-
-void
-IOPMrootDomain::releaseDriverKitSyncedAssertion(IOPMDriverAssertionID assertionID)
-{
- gIOPMWorkLoop->runActionBlock(^{
- if (_driverKitSyncedAssertionCount != 0) {
- _driverKitSyncedAssertionCount--;
- releasePMAssertion(assertionID);
- } else {
- panic("Over-release of driverkit synced assertion");
- }
- return kIOReturnSuccess;
- });
-}
-
-
-IOReturn
-IOPMrootDomain::createPMAssertionSafe(
- IOPMDriverAssertionID *assertionID,
- IOPMDriverAssertionType whichAssertionBits,
- IOPMDriverAssertionLevel assertionLevel,
- IOService *ownerService,
- const char *ownerDescription)
-{
- IOReturn ret;
- IOPMDriverAssertionID __block id;
-
- if (!assertionID) {
- return kIOReturnBadArgument;
- }
-
- // Grab workloop to check current transition
- ret = gIOPMWorkLoop->runActionBlock(^{
- if (_systemTransitionType == kSystemTransitionSleep) {
- return kIOReturnBusy;
- }
- id = createPMAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription);
- return id ? kIOReturnSuccess : kIOReturnError;
- });
-
- if (ret == kIOReturnSuccess) {
- *assertionID = id;
- } else if (ret == kIOReturnBusy && (kIOLogPMRootDomain & gIOKitDebug)) {
- DLOG("assertion denied due to ongoing sleep transition (%s)\n", ownerDescription);
- }
-
- return ret;
-}
-
bool
IOPMrootDomain::serializeProperties( OSSerialize * s ) const
{
@@ -11344,14 +10850,6 @@
WAKEEVENT_UNLOCK();
}
-void
-IOPMrootDomain::copyShutdownTime( uint64_t * time )
-{
- WAKEEVENT_LOCK();
- *time = gShutdownTime;
- WAKEEVENT_UNLOCK();
-}
-
//******************************************************************************
// acceptSystemWakeEvents
//
@@ -11377,7 +10875,6 @@
_systemWakeEventsArray->flushCollection();
}
}
- _aotWakeEventRunMode = 0;
// Remove stale WakeType property before system sleep
removeProperty(kIOPMRootDomainWakeTypeKey);
@@ -11467,14 +10964,18 @@
IOOptionBits aotFlags = 0;
bool needAOTEvaluate = FALSE;
- if ((kIOPMAOTModeAddEventFlags & _aotMode) && (!flags || (flags == kIOPMWakeEventSource))) {
- flags |= kIOPMWakeEventAOTExit;
-
+ if (kIOPMAOTModeAddEventFlags & _aotMode) {
// Only allow lingering in AOT_STATE for the two wake reasons used for the wrist raise gesture.
- if (!strcmp("AOP.OutboxNotEmpty", reason) || !strcmp("spu_gesture", reason)) {
- flags &= ~kIOPMWakeEventAOTExit;
- }
- }
+ if (strcmp("AOP.OutboxNotEmpty", reason) && strcmp("spu_gesture", reason)) {
+ flags |= kIOPMWakeEventAOTExit;
+ }
+ }
+
+#if DEVELOPMENT || DEBUG
+ if (_aotLingerTime && !strcmp("rtc", reason)) {
+ flags |= kIOPMWakeEventAOTPossibleExit;
+ }
+#endif /* DEVELOPMENT || DEBUG */
#if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
// Publishing the WakeType is serialized by the PM work loop
@@ -11522,15 +11023,19 @@
if (_aotNow && aotFlags) {
if (kIOPMWakeEventAOTPossibleExit & flags) {
_aotMetrics->possibleCount++;
+ _aotAnalytics->possibleCount++;
}
if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
_aotMetrics->confirmedPossibleCount++;
+ _aotAnalytics->confirmedPossibleCount++;
}
if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
_aotMetrics->rejectedPossibleCount++;
+ _aotAnalytics->rejectedPossibleCount++;
}
if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
_aotMetrics->expiredPossibleCount++;
+ _aotAnalytics->expiredPossibleCount++;
}
_aotPendingFlags |= aotFlags;
@@ -11566,17 +11071,6 @@
strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
}
strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
- }
-
- if (_aotNow && _acceptSystemWakeEvents) {
- uint64_t runModeBits = (kIOPMAOTModeRunModeMask & flags) >> kIOPMAOTModeRunModeShift;
- if (runModeBits) {
- if (_aotWakeEventRunModeImpliesStorage & runModeBits) {
- runModeBits |= kIOPMDriverClassStorage;
- }
- IOLog("AOT wake event %s -> mode 0x%llx\n", reasonString->getCStringNoCopy(), runModeBits);
- _aotWakeEventRunMode |= runModeBits;
- }
}
WAKEEVENT_UNLOCK();
@@ -11638,7 +11132,7 @@
IOService * device,
IOOptionBits flags,
const char * reason,
- OSObject * details )
+ __unused OSObject * details )
{
if (!device || !reason) {
return;
@@ -11661,55 +11155,8 @@
}
strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
- if (details) {
- OSDictionary *dict = OSDynamicCast(OSDictionary, details);
- if (dict) {
- OSSharedPtr<OSString> sharedKey = OSString::withCString(kIOPMRootDomainShutdownTime);
- if (sharedKey) {
- OSNumber *num = OSDynamicCast(OSNumber, dict->getObject(sharedKey.get()));
- if (num) {
- gShutdownTime = (uint64_t)(num->unsigned64BitValue());
- }
- }
- }
- }
-
gShutdownReasonSysctlRegistered = true;
WAKEEVENT_UNLOCK();
-}
-
-//******************************************************************************
-// requestRunMode
-//
-// For clients to request a LPW run mode. Only full wake is supported currently.
-//******************************************************************************
-
-IOReturn
-IOPMrootDomain::requestRunMode(uint64_t runModeMask)
-{
- // We only support requesting full wake at the moment
- if (runModeMask == kIOPMRunModeFullWake) {
- pmPowerStateQueue->submitPowerEvent(kPowerEventRunModeRequest, NULL, runModeMask);
- return kIOReturnSuccess;
- }
- return kIOReturnUnsupported;
-}
-
-IOReturn
-IOPMrootDomain::handleRequestRunMode(uint64_t runModeMask)
-{
- // TODO: Replace with run mode logic when implemented
- IOReturn ret = kIOReturnUnsupported;
-
- // We only support requesting full wake at the moment
- if (runModeMask == kIOPMRunModeFullWake) {
- // A simple CPS should suffice for now
- changePowerStateWithTagToPriv(ON_STATE, kCPSReasonEvaluatePolicy);
- ret = kIOReturnSuccess;
- }
-
- DLOG("%s: mask %llx ret %x\n", __func__, runModeMask, ret);
- return ret;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -11869,7 +11316,6 @@
me->assertionsCombined = 0;
me->assertionsArrayLock = IOLockAlloc();
me->tabulateProducerCount = me->tabulateConsumerCount = 0;
- bzero(&me->assertionsLog, sizeof(me->assertionsLog));
assert(me->assertionsArray);
assert(me->assertionsArrayLock);
@@ -11926,7 +11372,7 @@
void
PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
{
- AbsoluteTime now, elapsed;
+ AbsoluteTime now;
uint64_t nsec;
if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
@@ -11934,11 +11380,9 @@
return;
}
- now = mach_continuous_time();
- assertionsLog.addInterval(assertStruct->id, assertStruct->assertCPUStartTime, now);
-
- elapsed = now - assertStruct->assertCPUStartTime;
- absolutetime_to_nanoseconds(elapsed, &nsec);
+ now = mach_absolute_time();
+ SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
+ absolutetime_to_nanoseconds(now, &nsec);
assertStruct->assertCPUDuration += nsec;
assertStruct->assertCPUStartTime = 0;
@@ -12065,16 +11509,12 @@
ASSERT_GATED();
if (newAssertion) {
+ IOLockLock(assertionsArrayLock);
assertStruct = newAssertion->getMutableBytesNoCopy();
-
if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
(assertStruct->level == kIOPMDriverAssertionLevelOn)) {
- assertStruct->assertCPUStartTime = mach_continuous_time();
- }
-
- assertionsLog.addName(assertStruct->id, assertStruct->ownerString->getCStringNoCopy());
-
- IOLockLock(assertionsArrayLock);
+ assertStruct->assertCPUStartTime = mach_absolute_time();
+ }
assertionsArray->setObject(newAssertion);
IOLockUnlock(assertionsArrayLock);
newAssertion->release();
@@ -12203,7 +11643,7 @@
if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
(assertStruct->level != _level)) {
if (_level == kIOPMDriverAssertionLevelOn) {
- assertStruct->assertCPUStartTime = mach_continuous_time();
+ assertStruct->assertCPUStartTime = mach_absolute_time();
} else {
updateCPUBitAccounting(assertStruct);
}
@@ -12393,8 +11833,8 @@
static IOPMPowerState patriarchPowerStates[2] =
{
- {.version = kIOPMPowerStateVersion1, .outputPowerCharacter = ON_POWER },
- {.version = kIOPMPowerStateVersion1, .outputPowerCharacter = ON_POWER }
+ {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
void
@@ -12508,6 +11948,70 @@
}
}
+static void
+reportAnalyticsTimerExpired(
+ thread_call_param_t us, thread_call_param_t )
+{
+ ((IOPMrootDomain *)us)->reportAnalytics();
+}
+
+void
+IOPMrootDomain::initAOTMetrics()
+{
+ if (!_aotMetrics) {
+ _aotMetrics = IOMallocType(IOPMAOTMetrics);
+ }
+
+ if (!_aotAnalytics) {
+ _aotAnalytics = IOMallocType(IOPMAOTAnalytics);
+ analyticsThreadCall = thread_call_allocate_with_options(reportAnalyticsTimerExpired,
+ (thread_call_param_t)this, THREAD_CALL_PRIORITY_KERNEL, THREAD_CALL_OPTIONS_ONCE);
+ scheduleAnalyticsThreadCall();
+ }
+}
+
+#define ANALYTICS_PERIOD_HOURS 24
+#define ANALYTICS_LEEWAY_MINUTES 5
+
+void
+IOPMrootDomain::scheduleAnalyticsThreadCall()
+{
+ uint64_t leeway, period, leeway_ns, period_ns, deadline;
+
+ period_ns = ANALYTICS_PERIOD_HOURS * 60 * 60 * NSEC_PER_SEC;
+ leeway_ns = ANALYTICS_LEEWAY_MINUTES * 60 * NSEC_PER_SEC;
+
+ nanoseconds_to_absolutetime(period_ns, &period);
+ nanoseconds_to_absolutetime(leeway_ns, &leeway);
+ deadline = mach_continuous_time() + period;
+ thread_call_enter_delayed_with_leeway(analyticsThreadCall, NULL, deadline, leeway, THREAD_CALL_CONTINUOUS);
+}
+
+CA_EVENT(aot_analytics,
+ CA_INT, possible_count,
+ CA_INT, confirmed_possible_count,
+ CA_INT, rejected_possible_count,
+ CA_INT, expired_possible_count);
+
+void
+IOPMrootDomain::reportAnalytics()
+{
+ if (_aotAnalytics) {
+ IOLog("IOPMAOTAnalytics possibleCount: %u, confirmedPossibleCount: %u, rejectedPossibleCount: %u, expiredPossibleCount: %u\n",
+ _aotAnalytics->possibleCount, _aotAnalytics->confirmedPossibleCount, _aotAnalytics->rejectedPossibleCount, _aotAnalytics->expiredPossibleCount);
+
+ ca_event_t event = CA_EVENT_ALLOCATE(aot_analytics);
+ CA_EVENT_TYPE(aot_analytics) * e = (CA_EVENT_TYPE(aot_analytics) *)event->data;
+ e->possible_count = _aotAnalytics->possibleCount;
+ e->confirmed_possible_count = _aotAnalytics->confirmedPossibleCount;
+ e->rejected_possible_count = _aotAnalytics->rejectedPossibleCount;
+ e->expired_possible_count = _aotAnalytics->expiredPossibleCount;
+ CA_EVENT_SEND(event);
+
+ bzero(_aotAnalytics, sizeof(IOPMAOTAnalytics));
+ scheduleAnalyticsThreadCall();
+ }
+}
#if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
IOReturn
@@ -12820,20 +12324,18 @@
const void * callMethod = NULL;
const char * objectName = NULL;
+ uint32_t timeout = getWatchdogTimeout();
const char * phaseString = NULL;
const char * phaseDescription = NULL;
- uint64_t delta;
IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
uint32_t tracePhase = pmTracer->getTracePhase();
*thread = NULL;
-
- delta = get_watchdog_elapsed_time();
if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
- snprintf(failureStr, strLen, "Sleep transition timed out after %qd seconds", delta);
+ snprintf(failureStr, strLen, "Sleep transition timed out after %d seconds", timeout);
} else {
- snprintf(failureStr, strLen, "Wake transition timed out after %qd seconds", delta);
+ snprintf(failureStr, strLen, "Wake transition timed out after %d seconds", timeout);
}
tracePhase2String(tracePhase, &phaseString, &phaseDescription);