#define _LOG(x...)
+#define DARK_WAKE_DEBUG 1
+#define SUSPEND_PM_NOTIFICATIONS_DEBUG 1
+
#define CHECK_THREAD_CONTEXT
#ifdef CHECK_THREAD_CONTEXT
static IOWorkLoop * gIOPMWorkLoop = 0;
kPowerEventAssertionRelease, // 10
kPowerEventAssertionSetLevel, // 11
kPowerEventQueueSleepWakeUUID, // 12
- kPowerEventPublishSleepWakeUUID // 13
+ kPowerEventPublishSleepWakeUUID, // 13
+ kPowerEventSuspendClient // 14
};
// For evaluatePolicy()
kStimulusDarkWakeActivityTickle, // 5
kStimulusDarkWakeEntry, // 6
kStimulusDarkWakeReentry, // 7
- kStimulusDarkWakeEvaluate // 8
+ kStimulusDarkWakeEvaluate, // 8
+ kStimulusNoIdleSleepPreventers // 9
};
extern "C" {
#define kIOPMRootDomainWakeTypeUser "User"
#define kIOPMRootDomainWakeTypeAlarm "Alarm"
#define kIOPMRootDomainWakeTypeNetwork "Network"
+#define kIOPMRootDomainWakeTypeHIDActivity "HID Activity"
// Special interest that entitles the interested client from receiving
// all system messages. Only used by powerd.
//
#define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest"
+#define kPMSuspendedNotificationClients "PMSuspendedNotificationClients"
+
/*
* Aggressiveness
*/
static UInt32 gPagingOff = 0;
static UInt32 gSleepWakeUUIDIsSet = false;
static uint32_t gAggressivesState = 0;
-static uint32_t gDarkWakeFlags = kDarkWakeFlagHIDTickleNone;
-static bool gRAMDiskImageBoot = false;
+static uint32_t gDarkWakeFlags = kDarkWakeFlagHIDTickleNone | kDarkWakeFlagIgnoreDiskIOAlways;
+static PMStatsStruct gPMStats;
struct timeval gIOLastSleepTime;
struct timeval gIOLastWakeTime;
PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
- IORegistryEntry * chosenEntry = IORegistryEntry::fromPath("/chosen", gIODTPlane);
- if (chosenEntry)
- {
- if (chosenEntry->getProperty("boot-ramdmg-size") &&
- chosenEntry->getProperty("boot-ramdmg-extents"))
- {
- gRAMDiskImageBoot = true;
- }
- chosenEntry->release();
- }
-
queue_init(&aggressivesQueue);
aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
aggressivesData = OSData::withCapacity(
setProperty(kIOSleepSupportedKey, true);
- bzero(&pmStats, sizeof(pmStats));
+ bzero(&gPMStats, sizeof(gPMStats));
pmTracer = PMTraceWorker::tracer(this);
(const OSObject **) &gIOPMSettingSilentRunningKey, 1, 0);
fPMSettingsDict = OSDictionary::withCapacity(5);
+ preventIdleSleepList = OSSet::withCapacity(8);
+ preventSystemSleepList = OSSet::withCapacity(2);
PMinit(); // creates gIOPMWorkLoop
publishFeature("DisplayDims");
}
if(psIterator) {
- psIterator->release();
+ psIterator->release();
}
+
+
+ pmSuspendedCapacity = pmSuspendedSize = 0;
+ pmSuspendedPIDS = NULL;
+
sysctl_register_oid(&sysctl__kern_sleeptime);
sysctl_register_oid(&sysctl__kern_waketime);
return true;
}
+
+
+
+void IOPMrootDomain::handleSuspendPMNotificationClient(uint32_t pid, bool doSuspend)
+{
+ ASSERT_GATED();
+
+ int index = -1;
+ unsigned int i;
+
+ if (!pmSuspendedPIDS) {
+ pmSuspendedCapacity = 8;
+ pmSuspendedSize = pmSuspendedCapacity * sizeof(PMNotifySuspendedStruct);
+ pmSuspendedPIDS = (PMNotifySuspendedStruct *)IOMalloc(pmSuspendedSize);
+ bzero(pmSuspendedPIDS, pmSuspendedSize);
+ }
+
+ /* Find the existing pid in the existing array */
+
+ for (i=0; i < pmSuspendedCapacity; i++) {
+ if (pmSuspendedPIDS[i].pid == pid) {
+ index = i;
+ break;
+ }
+ }
+
+ if (-1 == index)
+ {
+ /* Find an unused slot in the suspended pids table. */
+
+ for (i=0; i < pmSuspendedCapacity; i++) {
+ if (pmSuspendedPIDS[i].refcount == 0) {
+ break;
+ }
+ }
+
+ if (pmSuspendedCapacity == i)
+ {
+ /* GROW if necessary */
+
+ PMNotifySuspendedStruct *newSuspended = NULL;
+ pmSuspendedCapacity *= 2;
+ pmSuspendedSize = pmSuspendedCapacity * sizeof(PMNotifySuspendedStruct);
+ newSuspended = (PMNotifySuspendedStruct *)IOMalloc(pmSuspendedSize);
+
+ bzero(newSuspended, pmSuspendedSize);
+ bcopy(pmSuspendedPIDS, newSuspended, pmSuspendedSize/2);
+ IOFree(pmSuspendedPIDS, pmSuspendedSize/2);
+
+ pmSuspendedPIDS = newSuspended;
+ }
+
+ index = i;
+ pmSuspendedPIDS[index].pid = pid;
+ }
+
+ if (doSuspend) {
+ pmSuspendedPIDS[index].refcount++;
+ } else {
+ pmSuspendedPIDS[index].refcount--;
+ }
+
+ /*
+ * Publish array of suspended pids in IOPMrootDomain
+ */
+ OSArray *publish = OSArray::withCapacity(pmSuspendedCapacity);
+
+ for (i=0; i<pmSuspendedCapacity; i++)
+ {
+ if (pmSuspendedPIDS[i].refcount > 0) {
+ OSDictionary *suspended = OSDictionary::withCapacity(2);
+ OSNumber *n = NULL;
+
+ n = OSNumber::withNumber(pmSuspendedPIDS[i].pid, 32);
+ suspended->setObject("pid", n);
+ n->release();
+
+ n = OSNumber::withNumber(pmSuspendedPIDS[i].refcount, 32);
+ suspended->setObject("refcount", n);
+ n->release();
+
+ publish->setObject(suspended);
+ suspended->release();
+
+ }
+ }
+
+ if (0 != publish->getCount()) {
+ setProperty(kPMSuspendedNotificationClients, publish);
+ } else {
+ removeProperty(kPMSuspendedNotificationClients);
+ }
+
+ publish->release();
+
+ return;
+}
+
+bool IOPMrootDomain::pmNotificationIsSuspended(uint32_t pid)
+{
+ unsigned int index;
+
+ for (index=0; index < pmSuspendedCapacity; index++) {
+ if (pmSuspendedPIDS[index].pid == pid) {
+ return pmSuspendedPIDS[index].refcount > 0;
+ }
+ }
+
+ return false;
+}
+
+
+void IOPMrootDomain::suspendPMNotificationsForPID(uint32_t pid, bool doSuspend)
+{
+ if(pmPowerStateQueue) {
+ pmPowerStateQueue->submitPowerEvent(kPowerEventSuspendClient, (void *)pid, (uint64_t)doSuspend );
+ }
+ return;
+}
+
//******************************************************************************
// setProperties
//
const OSSymbol *hibernatefreeratio_string = OSSymbol::withCString(kIOHibernateFreeRatioKey);
const OSSymbol *hibernatefreetime_string = OSSymbol::withCString(kIOHibernateFreeTimeKey);
#endif
-
+#if SUSPEND_PM_NOTIFICATIONS_DEBUG
+ const OSSymbol *suspendPMClient_string = OSSymbol::withCString(kPMSuspendedNotificationClients);
+#endif
+
if (!dict)
{
return_value = kIOReturnBadArgument;
goto exit;
}
-
+
if ((b = OSDynamicCast(OSBoolean, dict->getObject(publish_simulated_battery_string))))
{
publishResource(publish_simulated_battery_string, kOSBooleanTrue);
{
setProperty(kIOPMDeepSleepDelayKey, n);
}
- if ((b = OSDynamicCast(OSBoolean, dict->getObject(kIOPMDestroyFVKeyOnStandbyKey))))
- {
- setProperty(kIOPMDestroyFVKeyOnStandbyKey, b);
- }
- if ((b = OSDynamicCast(OSBoolean, dict->getObject(kIOPMAutoPowerOffEnabledKey))))
+
+#if SUSPEND_PM_NOTIFICATIONS_DEBUG
+ if ((n = OSDynamicCast(OSNumber, dict->getObject(suspendPMClient_string))))
{
- setProperty(kIOPMAutoPowerOffEnabledKey, b);
+ // Toggle the suspended status for pid n.
+ uint32_t pid_int = n->unsigned32BitValue();
+ suspendPMNotificationsForPID(pid_int, !pmNotificationIsSuspended(pid_int));
}
- if ((n = OSDynamicCast(OSNumber, dict->getObject(kIOPMAutoPowerOffDelayKey))))
+#endif
+
+ if ((b = OSDynamicCast(OSBoolean, dict->getObject(kIOPMDestroyFVKeyOnStandbyKey))))
{
- setProperty(kIOPMAutoPowerOffDelayKey, n);
+ setProperty(kIOPMDestroyFVKeyOnStandbyKey, b);
}
// Relay our allowed PM settings onto our registered PM clients
if(hibernatefile_string) hibernatefile_string->release();
if(hibernatefreeratio_string) hibernatefreeratio_string->release();
if(hibernatefreetime_string) hibernatefreetime_string->release();
+#endif
+#if SUSPEND_PM_NOTIFICATIONS_DEBUG
+ if(suspendPMClient_string) suspendPMClient_string->release();
#endif
return return_value;
}
clock_interval_to_deadline(inSeconds, kSecondScale, &deadline);
thread_call_enter_delayed(extraSleepTimer, deadline);
idleSleepTimerPending = true;
- DLOG("idle timer set for %u seconds\n", inSeconds);
}
+ else
+ {
+ thread_call_enter(extraSleepTimer);
+ }
+ DLOG("idle timer set for %u seconds\n", inSeconds);
}
//******************************************************************************
kIOPMOSSwitchHibernationKey,
kIOPMIdleSleepKey,
kIOPMLowPowerSleepKey,
- kIOPMClamshellSleepKey,
kIOPMThermalEmergencySleepKey,
- kIOPMMaintenanceSleepKey
+ kIOPMMaintenanceSleepKey,
+ kIOPMSleepServiceExitKey,
+ kIOPMDarkWakeThermalEmergencyKey
};
PMEventDetails *details;
return kIOReturnNotPermitted;
}
+ if (kIOPMSleepReasonDarkWakeThermalEmergency == sleepReason)
+ messageClients(kIOPMMessageDarkWakeThermalEmergency);
+
if (timeline)
timeline->setSleepCycleInProgressFlag(true);
if(pmPowerStateQueue) {
pmPowerStateQueue->submitPowerEvent(kPowerEventPublishSleepWakeUUID, (void *)true);
}
-
// Log the beginning of system sleep.
details = PMEventDetails::eventDetails(kIOPMEventTypeSleep, NULL,
logWranglerTickle = true;
sleepTimerMaintenance = false;
wranglerTickleLatched = false;
+ darkWakeThermalAlarm = false;
+ darkWakeThermalEmergency = false;
OSString * wakeType = OSDynamicCast(
OSString, getProperty(kIOPMRootDomainWakeTypeKey));
changePowerStateToPriv(ON_STATE);
} break;
-
- case ON_STATE: {
- bool wasPrevented = childPreventSystemSleep;
-
- details = PMEventDetails::eventDetails(
- kIOPMEventTypeWakeDone,
- NULL,
- 0,
- kIOReturnSuccess);
-
- recordAndReleasePMEvent( details );
- // Update childPreventSystemSleep flag using the capability computed
- // by IOSevice::rebuildChildClampBits().
-
- childPreventSystemSleep =
- ((currentCapability() & kIOPMChildClamp2) != 0);
-
- if (wasPrevented && !childPreventSystemSleep)
+ case ON_STATE: {
+ if (previousPowerState != ON_STATE)
{
- evaluatePolicy( kStimulusDarkWakeEvaluate );
+ details = PMEventDetails::eventDetails(
+ kIOPMEventTypeWakeDone,
+ NULL,
+ 0,
+ kIOReturnSuccess);
+
+ recordAndReleasePMEvent( details );
}
} break;
}
// requestPowerDomainState
//
// Extend implementation in IOService. Running on PM work loop thread.
-//
-// Examine children desires and initiate idle-sleep if all children are idle,
-// prevent idle and system sleep flags are not set.
//******************************************************************************
IOReturn IOPMrootDomain::requestPowerDomainState (
IOPowerConnection * childConnection,
unsigned long specification )
{
- OSIterator *iter;
- OSObject *next;
- IOPowerConnection *connection;
- IOPMPowerFlags mergedChildDesire = 0;
- IOPMPowerFlags editedChildDesire;
- IOPMPowerFlags thisDesire;
- bool sleepASAP = false;
+ // Idle and system sleep prevention flags affects driver desire.
+ // Children desire are irrelevant so they are cleared.
+
+ return super::requestPowerDomainState(0, childConnection, specification);
+}
+
+//******************************************************************************
+// updatePreventIdleSleepList
+//
+// Called by IOService on PM work loop.
+//******************************************************************************
+
+void IOPMrootDomain::updatePreventIdleSleepList(
+ IOService * service, bool addNotRemove )
+{
+ unsigned int oldCount, newCount;
ASSERT_GATED();
- // Disregard disk I/O (anything besides the display wrangler) as a
- // factor in preventing idle sleep - based on a runtime setting.
+ // Disregard disk I/O (anything besides the display wrangler)
+ // as a factor preventing idle sleep,except in the case of legacy disk I/O
if ((gDarkWakeFlags & kDarkWakeFlagIgnoreDiskIOAlways) &&
- (kIOPMPreventIdleSleep & childDesire) &&
- (childConnection != wranglerConnection))
+ addNotRemove && (service != wrangler) && (service != this))
{
- childDesire &= ~kIOPMPreventIdleSleep;
+ return;
}
- // Force the child's input power requirement to 0 unless the prevent
- // idle-sleep flag is set. Nil input power flags maps to our state 0.
- // Our power clamp (deviceDesire) clamps the lowest power state at 2.
-
- editedChildDesire = 0;
- if (childDesire & kIOPMPreventIdleSleep)
- editedChildDesire |= (kIOPMPowerOn | kIOPMPreventIdleSleep);
- if (childDesire & kIOPMPreventSystemSleep)
- editedChildDesire |= (kIOPMPowerOn | kIOPMPreventSystemSleep);
-
- iter = getChildIterator(gIOPowerPlane);
- if ( iter )
+ oldCount = preventIdleSleepList->getCount();
+ if (addNotRemove)
{
- while ( (next = iter->getNextObject()) )
- {
- if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
- {
- // Ignore child that are in the process of joining.
- if (connection->getReadyFlag() == false)
- continue;
+ preventIdleSleepList->setObject(service);
+ DLOG("prevent idle sleep list: %s+ (%u)\n",
+ service->getName(), preventIdleSleepList->getCount());
+ }
+ else if (preventIdleSleepList->member(service))
+ {
+ preventIdleSleepList->removeObject(service);
+ DLOG("prevent idle sleep list: %s- (%u)\n",
+ service->getName(), preventIdleSleepList->getCount());
+ }
+ newCount = preventIdleSleepList->getCount();
+
+ if ((oldCount == 0) && (newCount != 0))
+ {
+ // Driver added to empty prevent list.
+ // Update the driver desire to prevent idle sleep.
+ // Driver desire does not prevent demand sleep.
+
+ changePowerStateTo(ON_STATE);
+ }
+ else if ((oldCount != 0) && (newCount == 0))
+ {
+ // Last driver removed from prevent list.
+ // Drop the driver clamp to allow idle sleep.
- // OR in the child's input power requirements.
- // Is this connection attached to the child that called
- // requestPowerDomainState()?
+ changePowerStateTo(SLEEP_STATE);
+ evaluatePolicy( kStimulusNoIdleSleepPreventers );
+ }
+}
- if (connection == childConnection)
- {
- thisDesire = editedChildDesire;
- }
- else
- {
- thisDesire = 0;
- if (connection->getPreventIdleSleepFlag())
- thisDesire |= (kIOPMPowerOn | kIOPMPreventIdleSleep);
- if (connection->getPreventSystemSleepFlag())
- thisDesire |= (kIOPMPowerOn | kIOPMPreventSystemSleep);
- }
+//******************************************************************************
+// preventSystemSleepListUpdate
+//
+// Called by IOService on PM work loop.
+//******************************************************************************
- mergedChildDesire |= thisDesire;
- if (thisDesire && (kIOLogPMRootDomain & gIOKitDebug))
- {
- IOService * child =
- (IOService *) connection->getChildEntry(gIOPowerPlane);
- LOG("child %p, noIdle %d, noSleep %d - %s\n",
- child,
- ((thisDesire & kIOPMPreventIdleSleep) != 0),
- ((thisDesire & kIOPMPreventSystemSleep) != 0),
- child ? child->getName() : "?");
- }
- }
- }
- iter->release();
- }
+void IOPMrootDomain::updatePreventSystemSleepList(
+ IOService * service, bool addNotRemove )
+{
+ unsigned int oldCount;
- DLOG("mergedChildDesire 0x%lx, extraSleepDelay %ld\n",
- mergedChildDesire, extraSleepDelay);
+ ASSERT_GATED();
+ if (this == service)
+ return;
- if ( !mergedChildDesire && !systemBooting )
+ oldCount = preventSystemSleepList->getCount();
+ if (addNotRemove)
{
- if (!wrangler)
- {
- changePowerStateToPriv(ON_STATE);
- if (idleSeconds)
- {
- // stay awake for at least idleSeconds
- startIdleSleepTimer(idleSeconds);
- }
- }
- else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake)
+ preventSystemSleepList->setObject(service);
+ DLOG("prevent system sleep list: %s+ (%u)\n",
+ service->getName(), preventSystemSleepList->getCount());
+ }
+ else if (preventSystemSleepList->member(service))
+ {
+ preventSystemSleepList->removeObject(service);
+ DLOG("prevent system sleep list: %s- (%u)\n",
+ service->getName(), preventSystemSleepList->getCount());
+
+ if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0))
{
- sleepASAP = true;
+ // Lost all system sleep preventers.
+ // Send stimulus if system sleep was blocked, and is in dark wake.
+ evaluatePolicy( kStimulusDarkWakeEvaluate );
}
}
-
- // Drop our power clamp to SLEEP_STATE when all children became idle,
- // and system sleep and display sleep slider values are equal.
-
- adjustPowerState(sleepASAP);
-
- // If our power clamp has already dropped to SLEEP_STATE, and no child
- // is keeping us at ON_STATE, then the following will trigger idle sleep.
-
- return super::requestPowerDomainState(
- editedChildDesire, childConnection, specification);
}
//******************************************************************************
DLOG("tellNoChangeDown %u->%u\n",
(uint32_t) getPowerState(), (uint32_t) stateNum);
+ // Sleep canceled, clear the sleep trace point.
+ tracePoint(kIOPMTracePointSystemUp);
+
if (idleSeconds && !wrangler)
{
// stay awake for at least idleSeconds
void IOPMrootDomain::tellChangeUp( unsigned long stateNum )
{
- OSData *publishPMStats = NULL;
DLOG("tellChangeUp %u->%u\n",
(uint32_t) getPowerState(), (uint32_t) stateNum);
}
tracePoint( kIOPMTracePointWakeApplications );
- publishPMStats = OSData::withBytes(&pmStats, sizeof(pmStats));
- setProperty(kIOPMSleepStatisticsKey, publishPMStats);
- publishPMStats->release();
- bzero(&pmStats, sizeof(pmStats));
if (pmStatsAppResponses)
{
IOReturn IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
{
- return kIOReturnUnsupported; // ignored
+ DLOG("changePowerStateTo(%lu)\n", ordinal);
+
+ if ((ordinal != ON_STATE) && (ordinal != SLEEP_STATE))
+ return kIOReturnUnsupported;
+
+ return super::changePowerStateTo(ordinal);
}
IOReturn IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
// evaluateSystemSleepPolicy
//******************************************************************************
-#define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
-
-// Sleep flags
-enum {
- kIOPMSleepFlagHibernate = 0x00000001,
- kIOPMSleepFlagSleepTimerEnable = 0x00000002
-};
-
struct IOPMSystemSleepPolicyEntry
{
uint32_t factorMask;
uint32_t factorBits;
uint32_t sleepFlags;
uint32_t wakeEvents;
-} __attribute__((packed));
+};
struct IOPMSystemSleepPolicyTable
{
- uint32_t signature;
+ uint8_t signature[4];
uint16_t version;
uint16_t entryCount;
IOPMSystemSleepPolicyEntry entries[];
-} __attribute__((packed));
+};
+
+enum {
+ kIOPMSleepFactorSleepTimerWake = 0x00000001,
+ kIOPMSleepFactorLidOpen = 0x00000002,
+ kIOPMSleepFactorACPower = 0x00000004,
+ kIOPMSleepFactorLowBattery = 0x00000008,
+ kIOPMSleepFactorDeepSleepNoDelay = 0x00000010,
+ kIOPMSleepFactorDeepSleepDemand = 0x00000020,
+ kIOPMSleepFactorDeepSleepDisable = 0x00000040,
+ kIOPMSleepFactorUSBExternalDevice = 0x00000080,
+ kIOPMSleepFactorBluetoothHIDDevice = 0x00000100,
+ kIOPMSleepFactorExternalMediaMounted = 0x00000200,
+ kIOPMSleepFactorDriverAssertBit5 = 0x00000400, /* Reserved for ThunderBolt */
+ kIOPMSleepFactorDriverAssertBit6 = 0x00000800,
+ kIOPMSleepFactorDriverAssertBit7 = 0x00001000 /* Reserved for legacy I/O */
+};
+
+enum {
+ kSleepPhaseEarly, kSleepPhaseFinal
+};
-bool IOPMrootDomain::evaluateSystemSleepPolicy(
- IOPMSystemSleepParameters * params, int sleepPhase )
+bool IOPMrootDomain::evaluateSystemSleepPolicy( IOPMSystemSleepParameters * p, int sleepPhase )
{
const IOPMSystemSleepPolicyTable * pt;
OSObject * prop = 0;
OSData * policyData;
- uint64_t currentFactors = 0;
- uint32_t standbyDelay;
- uint32_t powerOffDelay;
- uint32_t mismatch;
- bool standbyEnabled;
- bool powerOffEnabled;
- bool found = false;
-
- // Get platform's sleep policy table
- if (!_sleepPolicyHandler)
- {
- prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
- if (!prop) goto done;
- }
-
- // Fetch additional settings
- standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay)
- && (getProperty(kIOPMDeepSleepEnabledKey) == kOSBooleanTrue));
- powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay)
- && (getProperty(kIOPMAutoPowerOffEnabledKey) == kOSBooleanTrue));
- DLOG("standby %d delay %u, powerOff %d delay %u, hibernate %u\n",
- standbyEnabled, standbyDelay, powerOffEnabled, powerOffDelay,
- hibernateMode);
-
- // pmset level overrides
- if ((hibernateMode & kIOHibernateModeOn) == 0)
+ uint32_t currentFactors;
+ uint32_t deepSleepDelay = 0;
+ bool success = false;
+
+ if (getProperty(kIOPMDeepSleepEnabledKey) != kOSBooleanTrue)
+ return false;
+
+ getSleepOption(kIOPMDeepSleepDelayKey, &deepSleepDelay);
+
+ prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
+ if (!prop)
+ return false;
+
+ policyData = OSDynamicCast(OSData, prop);
+ if (!policyData ||
+ (policyData->getLength() < sizeof(IOPMSystemSleepPolicyTable)))
{
- standbyEnabled = false;
- powerOffEnabled = false;
+ goto done;
}
- else if (!(hibernateMode & kIOHibernateModeSleep))
+
+ pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
+ if ((pt->signature[0] != 'S') ||
+ (pt->signature[1] != 'L') ||
+ (pt->signature[2] != 'P') ||
+ (pt->signature[3] != 'T') ||
+ (pt->version != 1) ||
+ (pt->entryCount == 0))
{
- // Force hibernate (i.e. mode 25)
- // If standby is enabled, force standy.
- // If poweroff is enabled, force poweroff.
- if (standbyEnabled)
- currentFactors |= kIOPMSleepFactorStandbyForced;
- else if (powerOffEnabled)
- currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
- else
- currentFactors |= kIOPMSleepFactorHibernateForced;
+ goto done;
}
- // Current factors based on environment and assertions
- if (sleepTimerMaintenance)
- currentFactors |= kIOPMSleepFactorSleepTimerWake;
- if (!clamshellClosed)
- currentFactors |= kIOPMSleepFactorLidOpen;
- if (acAdaptorConnected)
- currentFactors |= kIOPMSleepFactorACPower;
- if (lowBatteryCondition)
- currentFactors |= kIOPMSleepFactorBatteryLow;
- if (!standbyDelay)
- currentFactors |= kIOPMSleepFactorStandbyNoDelay;
- if (!standbyEnabled)
- currentFactors |= kIOPMSleepFactorStandbyDisabled;
+ if ((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
+ (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))
+ {
+ goto done;
+ }
+
+ currentFactors = 0;
if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
kIOPMDriverAssertionLevelOff)
currentFactors |= kIOPMSleepFactorUSBExternalDevice;
if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
kIOPMDriverAssertionLevelOff)
currentFactors |= kIOPMSleepFactorExternalMediaMounted;
- if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
+ if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) != /* AssertionBit5 = Thunderbolt */
kIOPMDriverAssertionLevelOff)
- currentFactors |= kIOPMSleepFactorThunderboltDevice;
- if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit8) !=
+ currentFactors |= kIOPMSleepFactorDriverAssertBit5;
+ if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit7) !=
kIOPMDriverAssertionLevelOff)
- currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
- if (!powerOffEnabled)
- currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
-
- DLOG("sleep factors 0x%llx\n", currentFactors);
-
- // Clear the output params
- bzero(params, sizeof(*params));
-
- if (_sleepPolicyHandler)
- {
- if (!_sleepPolicyVars)
- {
- _sleepPolicyVars = IONew(IOPMSystemSleepPolicyVariables, 1);
- if (!_sleepPolicyVars)
- goto done;
- bzero(_sleepPolicyVars, sizeof(*_sleepPolicyVars));
- }
- _sleepPolicyVars->signature = kIOPMSystemSleepPolicySignature;
- _sleepPolicyVars->version = kIOPMSystemSleepPolicyVersion;
- if (kIOPMSleepPhase1 == sleepPhase)
- {
- _sleepPolicyVars->currentCapability = _currentCapability;
- _sleepPolicyVars->highestCapability = _highestCapability;
- _sleepPolicyVars->sleepReason = lastSleepReason;
- _sleepPolicyVars->hibernateMode = hibernateMode;
- _sleepPolicyVars->standbyDelay = standbyDelay;
- _sleepPolicyVars->poweroffDelay = powerOffDelay;
- }
- _sleepPolicyVars->sleepFactors = currentFactors;
- _sleepPolicyVars->sleepPhase = sleepPhase;
-
- if ((_sleepPolicyHandler(_sleepPolicyTarget, _sleepPolicyVars, params) !=
- kIOReturnSuccess) || (kIOPMSleepTypeInvalid == params->sleepType) ||
- (params->sleepType >= kIOPMSleepTypeLast) ||
- (kIOPMSystemSleepParametersVersion != params->version))
- {
- MSG("sleep policy handler error\n");
- goto done;
- }
-
- DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
- params->version, params->sleepType, params->sleepFlags,
- params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer);
- found = true;
- goto done;
- }
-
- // Policy table is meaningless without standby enabled
- if (!standbyEnabled)
- goto done;
-
- // Validate the sleep policy table
- policyData = OSDynamicCast(OSData, prop);
- if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable)))
- goto done;
-
- pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
- if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
- (pt->version != 1) || (0 == pt->entryCount))
- goto done;
+ currentFactors |= kIOPMSleepFactorDriverAssertBit7;
+ if (0 == deepSleepDelay)
+ currentFactors |= kIOPMSleepFactorDeepSleepNoDelay;
+ if (!clamshellClosed)
+ currentFactors |= kIOPMSleepFactorLidOpen;
+ if (acAdaptorConnected)
+ currentFactors |= kIOPMSleepFactorACPower;
+ if (lowBatteryCondition)
+ currentFactors |= kIOPMSleepFactorLowBattery;
+ if (sleepTimerMaintenance)
+ currentFactors |= kIOPMSleepFactorSleepTimerWake;
- if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
- (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount)))
- goto done;
+ // pmset overrides
+ if ((hibernateMode & kIOHibernateModeOn) == 0)
+ currentFactors |= kIOPMSleepFactorDeepSleepDisable;
+ else if ((hibernateMode & kIOHibernateModeSleep) == 0)
+ currentFactors |= kIOPMSleepFactorDeepSleepDemand;
+
+ DLOG("Sleep policy %u entries, current factors 0x%x\n",
+ pt->entryCount, currentFactors);
for (uint32_t i = 0; i < pt->entryCount; i++)
{
- const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i];
- mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask);
+ const IOPMSystemSleepPolicyEntry * policyEntry = &pt->entries[i];
- DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
- entry->factorMask, entry->factorBits,
- entry->sleepFlags, entry->wakeEvents, mismatch);
- if (mismatch)
- continue;
+ DLOG("factor mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x\n",
+ policyEntry->factorMask, policyEntry->factorBits,
+ policyEntry->sleepFlags, policyEntry->wakeEvents);
- DLOG("^ found match\n");
- found = true;
+ if ((currentFactors ^ policyEntry->factorBits) & policyEntry->factorMask)
+ continue; // mismatch, try next
- params->version = kIOPMSystemSleepParametersVersion;
- params->reserved1 = 1;
- if (entry->sleepFlags & kIOPMSleepFlagHibernate)
- params->sleepType = kIOPMSleepTypeStandby;
- else
- params->sleepType = kIOPMSleepTypeNormalSleep;
+ if (p)
+ {
+ p->version = 1;
+ p->sleepFlags = policyEntry->sleepFlags;
+ p->sleepTimer = 0;
+ p->wakeEvents = policyEntry->wakeEvents;
+ if (p->sleepFlags & kIOPMSleepFlagSleepTimerEnable)
+ {
+ if (kSleepPhaseFinal == sleepPhase)
+ {
+ clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
+
+ if (!_standbyTimerResetSeconds ||
+ (now_secs <= _standbyTimerResetSeconds))
+ {
+ // Reset standby timer adjustment
+ _standbyTimerResetSeconds = now_secs;
+ DLOG("standby delay %u, reset %u\n",
+ deepSleepDelay, (uint32_t) _standbyTimerResetSeconds);
+ }
+ else if (deepSleepDelay)
+ {
+ // Shorten the standby delay timer
+ clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds;
+ if (deepSleepDelay > elapsed)
+ deepSleepDelay -= elapsed;
+ else
+ deepSleepDelay = 1; // must be > 0
+
+ DLOG("standby delay %u, elapsed %u\n",
+ deepSleepDelay, (uint32_t) elapsed);
+ }
+ }
+ p->sleepTimer = deepSleepDelay;
+ }
+ else if (kSleepPhaseFinal == sleepPhase)
+ {
+ // A sleep that does not enable the sleep timer will reset
+ // the standby delay adjustment.
+ _standbyTimerResetSeconds = 0;
+ }
+ }
- params->ecWakeEvents = entry->wakeEvents;
- if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable)
- params->ecWakeTimer = standbyDelay;
+ DLOG("matched policy entry %u\n", i);
+ success = true;
break;
}
if (prop)
prop->release();
- return found;
+ return success;
}
-static IOPMSystemSleepParameters gEarlySystemSleepParams;
-
void IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
{
- // Evaluate early (priority interest phase), before drivers sleep.
+ IOPMSystemSleepParameters params;
+
+ // Evaluate sleep policy before driver sleep phase.
DLOG("%s\n", __FUNCTION__);
removeProperty(kIOPMSystemSleepParametersKey);
+ // Full wake resets the standby timer delay adjustment
+ if (_highestCapability & kIOPMSystemCapabilityGraphics)
+ _standbyTimerResetSeconds = 0;
+
hibernateDisabled = false;
hibernateMode = 0;
getSleepOption(kIOHibernateModeKey, &hibernateMode);
- // Save for late evaluation if sleep is aborted
- bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
-
- if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1))
+ if (!hibernateNoDefeat &&
+ evaluateSystemSleepPolicy(¶ms, kSleepPhaseEarly) &&
+ ((params.sleepFlags & kIOPMSleepFlagHibernate) == 0))
{
- if (!hibernateNoDefeat &&
- (gEarlySystemSleepParams.sleepType == kIOPMSleepTypeNormalSleep))
- {
- // Disable hibernate setup for normal sleep
- hibernateDisabled = true;
- }
+ hibernateDisabled = true;
}
-
- // Publish IOPMSystemSleepType
- uint32_t sleepType = gEarlySystemSleepParams.sleepType;
- if (sleepType == kIOPMSleepTypeInvalid)
- {
- // no sleep policy
- sleepType = kIOPMSleepTypeNormalSleep;
- if (hibernateMode & kIOHibernateModeOn)
- sleepType = (hibernateMode & kIOHibernateModeSleep) ?
- kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
- }
- else if ((sleepType == kIOPMSleepTypeStandby) &&
- (gEarlySystemSleepParams.ecPoweroffTimer))
- {
- // report the lowest possible sleep state
- sleepType = kIOPMSleepTypePowerOff;
- }
-
- setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
}
void IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
IOPMSystemSleepParameters params;
OSData * paramsData;
- // Evaluate sleep policy after sleeping drivers but before platform sleep.
+ // Evaluate sleep policy after drivers but before platform sleep.
DLOG("%s\n", __FUNCTION__);
- if (evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase2))
+ if (evaluateSystemSleepPolicy(¶ms, kSleepPhaseFinal))
{
if ((hibernateDisabled || hibernateAborted) &&
- (params.sleepType != kIOPMSleepTypeNormalSleep))
+ (params.sleepFlags & kIOPMSleepFlagHibernate))
{
- // Final evaluation picked a state requiring hibernation,
- // but hibernate setup was skipped. Retry using the early
- // sleep parameters.
+ // Should hibernate but unable to or aborted.
+ // Arm timer for a short sleep and retry or wake fully.
- bcopy(&gEarlySystemSleepParams, ¶ms, sizeof(params));
- params.sleepType = kIOPMSleepTypeAbortedSleep;
- params.ecWakeTimer = 1;
+ params.sleepFlags &= ~kIOPMSleepFlagHibernate;
+ params.sleepFlags |= kIOPMSleepFlagSleepTimerEnable;
+ params.sleepTimer = 1;
hibernateNoDefeat = true;
DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d\n",
- params.ecWakeTimer, hibernateDisabled, hibernateAborted);
+ params.sleepTimer, hibernateDisabled, hibernateAborted);
}
else
- {
hibernateNoDefeat = false;
- }
paramsData = OSData::withBytes(¶ms, sizeof(params));
if (paramsData)
paramsData->release();
}
- if (params.sleepType >= kIOPMSleepTypeHibernate)
+ if (params.sleepFlags & kIOPMSleepFlagHibernate)
{
- // Disable safe sleep to force the hibernate path
+ // Force hibernate
gIOHibernateMode &= ~kIOHibernateModeSleep;
}
}
}
bool IOPMrootDomain::getHibernateSettings(
- uint32_t * hibernateModePtr,
+ uint32_t * hibernateMode,
uint32_t * hibernateFreeRatio,
uint32_t * hibernateFreeTime )
{
- // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
- // has updated the hibernateDisabled flag.
-
- bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr);
+ bool ok = getSleepOption(kIOHibernateModeKey, hibernateMode);
getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
if (hibernateDisabled)
- *hibernateModePtr = 0;
- DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
+ *hibernateMode = 0;
+ DLOG("hibernateMode 0x%x\n", *hibernateMode);
return ok;
}
if (isDisplayWrangler)
{
wrangler = service;
- wranglerConnection = (IOService *) service->getParentEntry(gIOPowerPlane);
}
#else
isDisplayWrangler = false;
darkWakeToSleepASAP = false;
pciCantSleepValid = false;
rejectWranglerTickle = false;
+ darkWakeSleepService = false;
}
// Entered dark mode.
{
setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
tracePoint( kIOPMTracePointSystemUp, 0 );
+
+ // kIOPMDWOverTemp notification handling was postponed
+ if (darkWakeThermalAlarm)
+ {
+ if (!wranglerTickled && !darkWakeThermalEmergency &&
+ CAP_CURRENT(kIOPMSystemCapabilityCPU) &&
+ !CAP_CURRENT(kIOPMSystemCapabilityGraphics))
+ {
+ darkWakeThermalEmergency = true;
+ privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
+ MSG("DarkWake thermal limits breached. Going to sleep!\n");
+ }
+ darkWakeThermalAlarm = false;
+ }
}
_systemTransitionType = kSystemTransitionNone;
// Activate power limiter.
if ((actions->parameter & kPMActionsFlagIsDisplayWrangler) &&
- ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0))
+ ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
+ (changeFlags & kIOPMSynchronize))
{
actions->parameter |= kPMActionsFlagLimitPower;
}
else if ((actions->parameter & kPMActionsFlagIsAudioDevice) &&
- ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0))
+ ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
+ (changeFlags & kIOPMSynchronize))
{
actions->parameter |= kPMActionsFlagLimitPower;
}
}
}
- if (gRAMDiskImageBoot &&
- (actions->parameter & kPMActionsFlagIsDisplayWrangler))
- {
- // Tag devices subject to power suppression.
- *inOutChangeFlags |= kIOPMPowerSuppressed;
- }
-
if (actions->parameter & kPMActionsFlagLimitPower)
{
uint32_t maxPowerState = (uint32_t)(-1);
maxPowerState = 0;
if ((actions->parameter & kPMActionsFlagIsDisplayWrangler) &&
- (!gRAMDiskImageBoot || (service->getPowerState() > 0)))
+ (service->getPowerState() > 0))
{
// Forces a 3->1 transition sequence
if (changeFlags & kIOPMDomainWillChange)
if (!wranglerTickled &&
((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0))
{
+ setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
DLOG("display wrangler tickled\n");
if (kIOLogPMRootDomain & gIOKitDebug)
OSReportWithBacktrace("Dark wake display tickle");
break; // always sleep on low battery
}
- if (childPreventSystemSleep)
+ if(darkWakeThermalEmergency)
+ {
+ break; // always sleep on dark wake thermal emergencies
+ }
+
+ if (preventSystemSleepList->getCount() != 0)
{
err = 4; // 4. child prevent system sleep clamp
break;
case kPowerEventPublishSleepWakeUUID:
handlePublishSleepWakeUUID((bool)arg0);
break;
+ case kPowerEventSuspendClient:
+ handleSuspendPMNotificationClient((uintptr_t)arg0, (bool)arg1);
+ break;
}
}
privateSleepSystem (kIOPMSleepReasonThermalEmergency);
}
+ if (msg & kIOPMDWOverTemp)
+ {
+ if (!CAP_CURRENT(kIOPMSystemCapabilityCPU) ||
+ (_systemTransitionType == kSystemTransitionSleep) ||
+ (_systemTransitionType == kSystemTransitionWake) ||
+ (_systemTransitionType == kSystemTransitionCapability))
+ {
+ // During early wake or when system capability is changing,
+ // set flag and take action at end of transition.
+ darkWakeThermalAlarm = true;
+ }
+ else if (!wranglerTickled && !darkWakeThermalEmergency &&
+ !CAP_CURRENT(kIOPMSystemCapabilityGraphics))
+ {
+ // System in steady state and in dark wake
+ darkWakeThermalEmergency = true;
+ privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
+ MSG("DarkWake thermal limits breached. Going to sleep!\n");
+ }
+ }
+
/*
* Sleep Now!
*/
// Don't issue a hid tickle when lid is open and polled on wake
if (msg & kIOPMSetValue)
{
+ setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
reportUserInput();
}
// This mirrors the hardware's USB wake event latch, where a latched
// USB wake event followed by an AC attach will trigger a full wake.
latchDisplayWranglerTickle( false );
+
+#if HIBERNATION
+ // AC presence will reset the standy timer delay adjustment.
+ _standbyTimerResetSeconds = 0;
+#endif
}
/*
int displaySleep : 1;
int sleepDelayChanged : 1;
int evaluateDarkWake : 1;
+ int adjustPowerState : 1;
} bit;
uint32_t u32;
} flags;
if ( minutesToIdleSleep > minutesToDisplayDim )
minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
+ else if( minutesToIdleSleep == minutesToDisplayDim )
+ minutesDelta = 1;
if ((sleepSlider == 0) && (minutesToIdleSleep != 0))
flags.bit.idleSleepEnabled = true;
break;
case kStimulusAllowSystemSleepChanged:
- // FIXME: de-compose to change flags.
- adjustPowerState();
+ flags.bit.adjustPowerState = true;
break;
case kStimulusDarkWakeActivityTickle:
#endif
break;
+ case kStimulusNoIdleSleepPreventers:
+ flags.bit.adjustPowerState = true;
+ break;
+
} /* switch(stimulus) */
if (flags.bit.evaluateDarkWake && !wranglerTickled)
// Parked in dark wake, a tickle will return to full wake
rejectWranglerTickle = false;
}
- } else // non-maintenance (network) dark wake
+ }
+ else // non-maintenance (network) dark wake
{
if (checkSystemCanSleep(true))
{
AbsoluteTime now;
uint64_t nanos;
uint32_t minutesSinceDisplaySleep = 0;
- uint32_t sleepDelay;
+ uint32_t sleepDelay = 0;
clock_get_uptime(&now);
if (CMP_ABSOLUTETIME(&now, &wranglerSleepTime) > 0)
{
sleepDelay = extraSleepDelay - minutesSinceDisplaySleep;
}
- else
- {
- sleepDelay = 1; // 1 min
- }
startIdleSleepTimer(sleepDelay * 60);
DLOG("display slept %u min, set idle timer to %u min\n",
restoreUserSpinDownTimeout();
adjustPowerState();
}
+
+ if (flags.bit.adjustPowerState)
+ {
+ bool sleepASAP = false;
+
+ if (!systemBooting && (preventIdleSleepList->getCount() == 0))
+ {
+ if (!wrangler)
+ {
+ changePowerStateToPriv(ON_STATE);
+ if (idleSeconds)
+ {
+ // stay awake for at least idleSeconds
+ startIdleSleepTimer(idleSeconds);
+ }
+ }
+ else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake)
+ {
+ sleepASAP = true;
+ }
+ }
+ if(sleepASAP)
+ {
+ lastSleepReason = kIOPMSleepReasonIdle;
+ setProperty(kRootDomainSleepReasonKey, kIOPMIdleSleepKey);
+ }
+
+ adjustPowerState(sleepASAP);
+ }
}
//******************************************************************************
wrangler->setIgnoreIdleTimer( value );
}
}
+
if (changedBits & kIOPMDriverAssertionCPUBit)
evaluatePolicy(kStimulusDarkWakeEvaluate);
+
+ if (changedBits & kIOPMDriverAssertionReservedBit7) {
+ bool value = (newAssertions & kIOPMDriverAssertionReservedBit7) ? true : false;
+ if (value) {
+ DLOG("Driver assertion ReservedBit7 raised. Legacy IO preventing sleep\n");
+ updatePreventIdleSleepList(this, true);
+ }
+ else {
+ DLOG("Driver assertion ReservedBit7 dropped\n");
+ updatePreventIdleSleepList(this, false);
+ }
+
+ }
}
// MARK: -
bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
uint64_t delta;
uint64_t nsec;
+ OSData *publishPMStats = NULL;
eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
switch (eventIndex) {
case kIOPMStatsHibernateImageWrite:
if (starting)
- pmStats.hibWrite.start = nsec;
+ gPMStats.hibWrite.start = nsec;
else if (stopping)
- pmStats.hibWrite.stop = nsec;
+ gPMStats.hibWrite.stop = nsec;
if (stopping) {
- delta = pmStats.hibWrite.stop - pmStats.hibWrite.start;
+ delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
IOLog("PMStats: Hibernate write took %qd ms\n", delta/1000000ULL);
}
break;
case kIOPMStatsHibernateImageRead:
if (starting)
- pmStats.hibRead.start = nsec;
+ gPMStats.hibRead.start = nsec;
else if (stopping)
- pmStats.hibRead.stop = nsec;
+ gPMStats.hibRead.stop = nsec;
if (stopping) {
- delta = pmStats.hibRead.stop - pmStats.hibRead.start;
+ delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
IOLog("PMStats: Hibernate read took %qd ms\n", delta/1000000ULL);
+
+ publishPMStats = OSData::withBytes(&gPMStats, sizeof(gPMStats));
+ setProperty(kIOPMSleepStatisticsKey, publishPMStats);
+ publishPMStats->release();
+ bzero(&gPMStats, sizeof(gPMStats));
}
break;
}
return kIOReturnSuccess;
}
- else if (functionName &&
- functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey))
- {
- if (_sleepPolicyHandler)
- return kIOReturnExclusiveAccess;
- if (!param1)
- return kIOReturnBadArgument;
- _sleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
- _sleepPolicyTarget = (void *) param2;
- setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
- return kIOReturnSuccess;
- }
return super::callPlatformFunction(
functionName, waitForFunction, param1, param2, param3, param4);
void IOPMrootDomain::tracePoint( uint8_t point )
{
- if (!systemBooting)
- pmTracer->tracePoint(point);
+ if (systemBooting) return;
+
+ pmTracer->tracePoint(point);
+
+#if HIBERNATION
+ if (kIOPMTracePointSleepPowerPlaneDrivers == point) IOHibernateIOKitSleep();
+#endif
}
void IOPMrootDomain::tracePoint( uint8_t point, uint8_t data )
if (!pmAssertions)
return 0;
-
+
ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
if (kIOReturnSuccess == ret)