-{
- parent->deregisterPMSettingObject(this);
-}
-
-// MARK: -
-// MARK: IOPMTimeline
-
-#undef super
-#define super OSObject
-
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-IOPMTimeline *IOPMTimeline::timeline(IOPMrootDomain *root_domain)
-{
- IOPMTimeline *myself;
-
- if (!root_domain)
- return NULL;
-
- myself = new IOPMTimeline;
-
- if (myself) {
- myself->owner = root_domain;
- myself->init();
- }
-
- return myself;
-}
-
-bool IOPMTimeline::init(void)
-{
- if (!super::init()) {
- return false;
- }
-
- logLock = IOLockAlloc();
-
- // Fresh timeline, no events logged yet
- this->numEventsLoggedThisPeriod = 0;
- this->sleepCycleInProgress = false;
-
- //this->setEventsRecordingLevel(1); // TODO
- this->setEventsTrackedCount(kIOPMDefaultSystemEventsTracked);
-
- return true;
-}
-
-void IOPMTimeline::free(void)
-{
- if (pmTraceMemoryDescriptor) {
- pmTraceMemoryDescriptor->release();
- pmTraceMemoryDescriptor = NULL;
- }
-
- IOLockFree(logLock);
-
- super::free();
-}
-
-IOMemoryDescriptor *IOPMTimeline::getPMTraceMemoryDescriptor()
-{
- return pmTraceMemoryDescriptor;
-}
-
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-bool IOPMTimeline::setProperties(OSDictionary *d)
-{
- OSNumber *n = NULL;
- OSBoolean *b = NULL;
- bool changed = false;
-
- /* Changes size of detailed events buffer */
- n = (OSNumber *)d->getObject(kIOPMTimelineSystemNumberTrackedKey);
- if (OSDynamicCast(OSNumber, n))
- {
- changed = true;
- this->setEventsTrackedCount(n->unsigned32BitValue());
- }
-
-
- /* enables or disables system events */
- b = (OSBoolean *)d->getObject(kIOPMTimelineEnabledKey);
- if (b)
- {
- changed = true;
- this->setEventsRecordingLevel((int)(kOSBooleanTrue == b));
- }
-
- return changed;
-}
-
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-OSDictionary *IOPMTimeline::copyInfoDictionary(void)
-{
- OSDictionary *out = OSDictionary::withCapacity(3);
- OSNumber *n = NULL;
-
- if (!out || !hdr)
- return NULL;
-
- n = OSNumber::withNumber(hdr->sizeEntries, 32);
- out->setObject(kIOPMTimelineSystemNumberTrackedKey, n);
- n->release();
-
- n = OSNumber::withNumber(hdr->sizeBytes, 32);
- out->setObject(kIOPMTimelineSystemBufferSizeKey, n);
- n->release();
-
- // bool
- out->setObject(kIOPMTimelineEnabledKey, eventsRecordingLevel ? kOSBooleanTrue : kOSBooleanFalse);
-
- return out;
-}
-
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-/* IOPMTimeline::recordSystemPowerEvent()
- *
- * Expected "type" arguments are listed in IOPMPrivate.h under enum "SystemEventTypes"
- * Type arguments include "system events", and "Intermediate events"
- *
- * - System Events have paired "start" and "stop" events.
- * - A start event shall be followed by a stop event.
- * - Any number of Intermediate Events may fall between the
- * start and stop events.
- * - Intermediate events are meaningless outside the bounds of a system event's
- * start & stoup routines.
- * - It's invalid to record a Start event without a following Stop event; e.g. two
- * Start events without an intervenining Stop event is invalid.
- *
- * Buffer invariants
- * - The first recorded system event shall be preceded by an entry with type == 0
- * - IOPMTimeline may choose not to record intermediate events while there's not
- * a system event in process.
- */
-IOReturn IOPMTimeline::recordSystemPowerEvent( PMEventDetails *details )
-{
- static bool wakeDonePending = true;
- IOPMSystemEventRecord *record_to = NULL;
- OSString *swUUIDKey = NULL;
- uint32_t useIndex = 0;
-
- if (!details)
- return kIOReturnBadArgument;
-
- if (!traceBuffer)
- return kIOReturnNotReady;
-
- if (details->eventType == kIOPMEventTypeWakeDone)
- {
- if(!wakeDonePending)
- return kIOReturnBadArgument;
- }
-
- IOLockLock(logLock);
-
- if (details->eventType == kIOPMEventTypeWake) {
- wakeDonePending = true;
- } else if (details->eventType == kIOPMEventTypeWakeDone) {
- wakeDonePending = false;
- }
-
- systemState = details->eventType;
-
- useIndex = _atomicIndexIncrement(&hdr->index, hdr->sizeEntries);
-
- // The entry immediately after the latest entry (and thus
- // immediately before the first entry) shall have a type 0.
- if (useIndex + 1 >= hdr->sizeEntries) {
- traceBuffer[useIndex + 1].eventType = 0;
- } else {
- traceBuffer[0].eventType = 0;
- }
-
- record_to = &traceBuffer[useIndex];
- bzero(record_to, sizeof(IOPMSystemEventRecord));
-
- /*****/
- record_to->eventType = details->eventType;
- record_to->eventReason = details->reason;
- record_to->eventResult = details->result;
- pmEventTimeStamp(&record_to->timestamp);
-
- // If caller doesn't provide a UUID, we'll use the UUID that's posted
- // on IOPMrootDomain under key kIOPMSleepWakeUUIDKey
- if (!details->uuid) {
- swUUIDKey = OSDynamicCast(OSString, owner->copyProperty(kIOPMSleepWakeUUIDKey));
-
- if (swUUIDKey)
- details->uuid = swUUIDKey->getCStringNoCopy();
- }
-
- if (details->uuid)
- strncpy(record_to->uuid, details->uuid, kMaxPMStringLength);
-
- if (swUUIDKey)
- swUUIDKey->release();
-
- numEventsLoggedThisPeriod++;
- /*****/
-
- IOLockUnlock(logLock);
-
- return kIOReturnSuccess;
-
-}
-
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-IOReturn IOPMTimeline::recordDetailedPowerEvent( PMEventDetails *details )
-{
- IOPMSystemEventRecord *record_to = NULL;
- uint32_t useIndex;
-
- if (!details->eventType || !details->ownerName)
- return kIOReturnBadArgument;
-
- IOLockLock(logLock);
-
- useIndex = _atomicIndexIncrement(&hdr->index, hdr->sizeEntries);
-
- record_to = (IOPMSystemEventRecord *)&traceBuffer[useIndex];
- bzero(record_to, sizeof(IOPMSystemEventRecord));
-
- /*****/
- record_to->eventType = details->eventType;
- if (details->ownerName && (strlen(details->ownerName) > 1)) {
- strlcpy( record_to->ownerName,
- details->ownerName,
- sizeof(record_to->ownerName));
- }
-
- record_to->ownerDisambiguateID = details->ownerUnique;
-
- if (details->interestName && (strlen(details->interestName) > 1)) {
- strlcpy(record_to->interestName,
- details->interestName,
- sizeof(record_to->interestName));
- }
-
- record_to->oldState = details->oldState;
- record_to->newState = details->newState;
- record_to->eventResult = details->result;
- record_to->elapsedTimeUS = details->elapsedTimeUS;
- pmEventTimeStamp(&record_to->timestamp);
-
- numEventsLoggedThisPeriod++;
- /*****/
-
- IOLockUnlock(logLock);
- return kIOReturnSuccess;
-}
-
-uint32_t IOPMTimeline::getNumEventsLoggedThisPeriod() {
- return this->numEventsLoggedThisPeriod;
-}
-
-void IOPMTimeline::setNumEventsLoggedThisPeriod(uint32_t newCount) {
- this->numEventsLoggedThisPeriod = newCount;
-}
-
-bool IOPMTimeline::isSleepCycleInProgress() {
- return this->sleepCycleInProgress;
-}
-
-void IOPMTimeline::setSleepCycleInProgressFlag(bool flag) {
- this->sleepCycleInProgress = flag;
-}
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-void IOPMTimeline::setEventsTrackedCount(uint32_t newTracked)
-{
- size_t make_buf_size = 0;
-
- make_buf_size = sizeof(IOPMTraceBufferHeader) + (newTracked * sizeof(IOPMSystemEventRecord));
-
- IOLockLock(logLock);
-
- if (pmTraceMemoryDescriptor) {
- pmTraceMemoryDescriptor->release();
- pmTraceMemoryDescriptor = NULL;
- }
-
- hdr = NULL;
- traceBuffer = NULL;
-
- if (0 == newTracked)
- {
- IOLog("IOPMrootDomain -> erased buffer.\n");
- goto exit;
- }
-
- pmTraceMemoryDescriptor = IOBufferMemoryDescriptor::withOptions(
- kIOMemoryKernelUserShared | kIODirectionIn | kIOMemoryMapperNone,
- make_buf_size);
-
- if (!pmTraceMemoryDescriptor)
- {
- IOLog("IOPMRootDomain -> IOBufferMemoryDescriptor(%d) returns NULL\n", (int)make_buf_size);
- goto exit;
- }
-
- pmTraceMemoryDescriptor->prepare(kIODirectionIn);
-
- // Header occupies the first sizeof(IOPMTraceBufferHeader) bytes
- hdr = (IOPMTraceBufferHeader *)pmTraceMemoryDescriptor->getBytesNoCopy();
-
- // Recorded events occupy the remaining bulk of the buffer
- traceBuffer = (IOPMSystemEventRecord *)((uint8_t *)hdr + sizeof(IOPMTraceBufferHeader));
-
- bzero(hdr, make_buf_size);
-
- hdr->sizeBytes = make_buf_size;
- hdr->sizeEntries = newTracked;
-
- IOLog("IOPMRootDomain -> IOBufferMemoryDescriptor(%d) returns bufferMB with address 0x%08x\n", (int)make_buf_size, (unsigned int)(uintptr_t)traceBuffer);
-
-exit:
- IOLockUnlock(logLock);
-}
-
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-void IOPMTimeline::setEventsRecordingLevel(uint32_t eventsTrackedBits)
-{
-
- // TODO
-
- return;
-
-}
-
-/* static helper to IOPMTimeline
- */
-uint32_t IOPMTimeline::_atomicIndexIncrement(uint32_t *index, uint32_t limit)
-{
- uint32_t was_index;
- uint32_t inc_index;
-
- if(!index)
- return NULL;
-
- do {
- was_index = *index;
- inc_index = (was_index+1)%limit;
- } while (!OSCompareAndSwap(was_index, inc_index, index));
-
- return inc_index;