int main(int argc, char** argv) { // // From https://developer.apple.com/library/mac/qa/qa1340/_index.html // I have basically no idea how this works :) // // notification port allocated by IORegisterForSystemPower IONotificationPortRef notifyPortRef; // notifier object, used to deregister later io_object_t notifierObject; // this parameter is passed to the callback void* refCon; // register to receive system sleep notifications root_port = IORegisterForSystemPower(refCon, ¬ifyPortRef, SleepCallBack, ¬ifierObject); if (root_port == 0) { printf("IORegisterForSystemPower failed\n"); return 1; } // add the notification port to the application runloop CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes); /* Start the run loop to receive sleep notifications. Don't call CFRunLoopRun if this code is running on the main thread of a Cocoa or Carbon application. Cocoa and Carbon manage the main thread's run loop for you as part of their event handling mechanisms. */ CFRunLoopRun(); //Not reached, CFRunLoopRun doesn't return in this case. return 0; }
void CCocoaPowerSyscall::CreateOSPowerCallBacks(void) { #if !defined(TARGET_DARWIN_IOS) CCocoaAutoPool autopool; // we want sleep/wake notifications, register to receive system power notifications m_root_port = IORegisterForSystemPower(this, &m_notify_port, OSPowerCallBack, &m_notifier_object); if (m_root_port) { // add the notification port to the application runloop CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m_notify_port), kCFRunLoopDefaultMode); } else { CLog::Log(LOGERROR, "%s - IORegisterForSystemPower failed", __FUNCTION__); } // if we have a battery, we want power source change notifications (on AC, on Battery, etc) if (m_HasBattery) { m_power_source = IOPSNotificationCreateRunLoopSource(OSPowerSourceCallBack, this); if (m_power_source) CFRunLoopAddSource(CFRunLoopGetCurrent(), m_power_source, kCFRunLoopDefaultMode); else CLog::Log(LOGERROR, "%s - IOPSNotificationCreateRunLoopSource failed", __FUNCTION__); } #endif }
bool mac_sleep_start() { if (!root_port) { root_port = IORegisterForSystemPower(this, ¬ifyPortRef, callback_static, ¬ifierObject); if (!root_port) return false; CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes); } return true; }
void COSXScreen::watchSystemPowerThread(void*) { io_object_t notifier; IONotificationPortRef notificationPortRef; CFRunLoopSourceRef runloopSourceRef = 0; m_pmRunloop = CFRunLoopGetCurrent(); // install system power change callback m_pmRootPort = IORegisterForSystemPower(this, ¬ificationPortRef, powerChangeCallback, ¬ifier); if (m_pmRootPort == 0) { LOG((CLOG_WARN "IORegisterForSystemPower failed")); } else { runloopSourceRef = IONotificationPortGetRunLoopSource(notificationPortRef); CFRunLoopAddSource(m_pmRunloop, runloopSourceRef, kCFRunLoopCommonModes); } // thread is ready { CLock lock(m_pmMutex); *m_pmThreadReady = true; m_pmThreadReady->signal(); } // if we were unable to initialize then exit. we must do this after // setting m_pmThreadReady to true otherwise the parent thread will // block waiting for it. if (m_pmRootPort == 0) { return; } // start the run loop LOG((CLOG_DEBUG "started watchSystemPowerThread")); CFRunLoopRun(); // cleanup if (notificationPortRef) { CFRunLoopRemoveSource(m_pmRunloop, runloopSourceRef, kCFRunLoopDefaultMode); CFRunLoopSourceInvalidate(runloopSourceRef); CFRelease(runloopSourceRef); } CLock lock(m_pmMutex); IODeregisterForSystemPower(¬ifier); m_pmRootPort = 0; LOG((CLOG_DEBUG "stopped watchSystemPowerThread")); }
int main( int argc, char **argv ) { IONotificationPortRef notifyPortRef; io_object_t notifierObject; void* refCon; root_port = IORegisterForSystemPower( refCon, ¬ifyPortRef, MySleepCallBack, ¬ifierObject ); if ( root_port == 0 ) { printf("IORegisterForSystemPower failed\n"); return 1; } CFRunLoopAddSource( CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes ); CFRunLoopRun(); return (0); }
MacSystemWatch::MacSystemWatch() { // Initialize sleep callback IONotificationPortRef notify; io_object_t anIterator; root_port = IORegisterForSystemPower(this, ¬ify, sleepCallBack, &anIterator); if (!root_port) { printf("IORegisterForSystemPower failed\n"); } else { CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notify), kCFRunLoopCommonModes); } }
static void initializePowerNotifications (void) { static io_connect_t rootPort; /* used by powerCallback() via context pointer */ IONotificationPortRef notificationPort; io_object_t notifier; rootPort = IORegisterForSystemPower(&rootPort, ¬ificationPort, powerCallback, ¬ifier); if (! rootPort) { message (LOG_ERR, "IORegisterForSystemPower failed\n"); exit (1); } CFRunLoopAddSource (CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notificationPort), kCFRunLoopDefaultMode); }
/*! Registers the daemon with the kernel to receive power events * (e.g., sleep/wake notifications). * @return true if the daemon was successfully registered. */ bool iSCSIDRegisterForPowerEvents() { powerPlaneRoot = IORegisterForSystemPower(NULL, &powerNotifyPortRef, iSCSIDHandlePowerEvent, &powerNotifier); if(powerPlaneRoot == 0) return false; CFRunLoopAddSource(CFRunLoopGetMain(), IONotificationPortGetRunLoopSource(powerNotifyPortRef), kCFRunLoopDefaultMode); return true; }
void SystemEventsManager::runLoop() { void* refCon = nullptr; rootPort = IORegisterForSystemPower(refCon, ¬ifyPortRef, systemEventCallback, ¬ifierObject); if (rootPort != 0) { systemEventLoopRunning = true; CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes); CFRunLoopRun(); } }
int main( int argc, char **argv ) { syslog(LOG_LEVEL, "start"); root_port = IORegisterForSystemPower( refCon, ¬ifyPortRef, MySleepCallBack, ¬ifierObject ); if ( root_port == 0 ) { syslog(LOG_ERR,"IORegisterForSystemPower failed\n"); return 1; } CFRunLoopAddSource( CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes ); CFRunLoopRun(); syslog(LOG_LEVEL, "end"); return (0); }
static int pypowerobserver_init(PyPowerObserver *self, PyObject *args, PyObject *kwargs) { if (!PyArg_ParseTuple(args, ":__init__")) return -1; if (self) { io_object_t notifier; self->rootPort = IORegisterForSystemPower(self, &self->notificationPort, powerCallback, ¬ifier); if (!self->rootPort) { PyErr_SetString(PyExc_RuntimeError, "IORegisterForSystemPower failed"); return -1; } } return 0; }
DECLCALLBACK(int) HostPowerServiceDarwin::powerChangeNotificationThread(RTTHREAD /* ThreadSelf */, void *pInstance) { HostPowerServiceDarwin *pPowerObj = static_cast<HostPowerServiceDarwin *>(pInstance); /* We have to initial set the critical state of the battery, cause we want * not the HostPowerService to inform about that state when a VM starts. * See lowPowerHandler for more info. */ pPowerObj->checkBatteryCriticalLevel(); /* Register to receive system sleep notifications */ pPowerObj->mRootPort = IORegisterForSystemPower(pPowerObj, &pPowerObj->mNotifyPort, HostPowerServiceDarwin::powerChangeNotificationHandler, &pPowerObj->mNotifierObject); if (pPowerObj->mRootPort == MACH_PORT_NULL) { LogFlow(("IORegisterForSystemPower failed\n")); return VERR_NOT_SUPPORTED; } pPowerObj->mRunLoop = CFRunLoopGetCurrent(); /* Add the notification port to the application runloop */ CFRunLoopAddSource(pPowerObj->mRunLoop, IONotificationPortGetRunLoopSource(pPowerObj->mNotifyPort), kCFRunLoopCommonModes); /* Register for all battery change events. The handler will check for low * power events itself. */ CFRunLoopSourceRef runLoopSource = IOPSNotificationCreateRunLoopSource(HostPowerServiceDarwin::lowPowerHandler, pPowerObj); CFRunLoopAddSource(pPowerObj->mRunLoop, runLoopSource, kCFRunLoopCommonModes); /* Start the run loop. This blocks. */ CFRunLoopRun(); return VINF_SUCCESS; }
static void iokit_poll_notifications(void *opaque) { int phase = 0; Semaphore *handshake = opaque; IONotificationPortRef notification_port; io_object_t notifier; io_connect_t root_port; CFRunLoopSourceRef notification_run_loop_source; log_debug("Started notification poll thread"); // need to register this PThread with the Objective-C garbage collector, // because CoreFoundation uses Objective-C #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 objc_registerThreadWithCollector(); #endif // register for system sleep/wake notifications root_port = IORegisterForSystemPower(&root_port, ¬ification_port, iokit_handle_notifications, ¬ifier); if (root_port == MACH_PORT_NULL) { log_error("Could not register for root power domain"); goto cleanup; } phase = 1; // get notification run loop source notification_run_loop_source = IONotificationPortGetRunLoopSource(notification_port); if (notification_run_loop_source == NULL) { log_error("Could not get notification run loop source"); goto cleanup; } CFRunLoopAddSource(CFRunLoopGetCurrent(), notification_run_loop_source, kCFRunLoopDefaultMode); phase = 2; // start loop _run_loop = (CFRunLoopRef)CFRetain(CFRunLoopGetCurrent()); _running = true; semaphore_release(handshake); CFRunLoopRun(); log_debug("Stopped notification poll thread"); cleanup: if (!_running) { // need to release the handshake in all cases, otherwise iokit_init // will block forever in semaphore_acquire semaphore_release(handshake); } switch (phase) { // no breaks, all cases fall through intentionally case 2: CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notification_run_loop_source, kCFRunLoopDefaultMode); case 1: IODeregisterForSystemPower(¬ifier); IOServiceClose(root_port); IONotificationPortDestroy(notification_port); default: break; } _running = false; }
/* Main program */ int main (int argc, const char * argv[]) { enum suspend_type {soft, dump, hard}; int vmmib[2] = {CTL_VM, VM_SWAPUSAGE}; int osmib[2] = {CTL_KERN, KERN_OSRELEASE}; int original_mode; int target_mode; int default_mode; int original_profile; int target_profile = -1; void *refCon; struct xsw_usage swap; size_t swlen = sizeof(swap); size_t oslen; char *kernel_version; int major_version = 0; int minor_version = 0; struct stat sleepimage; /* By default, */ int do_sleep = 1; /* send the sleep call, */ int repair = 0; /* do not check the validity of the original hibernation mode, */ int check_hibernation = 1; /* check if the hibernation file is present, */ int check_os = 1; /* check if the operating system is supported, */ enum suspend_type target_suspend = soft; /* send computer to software suspend mode, */ int restore = 1; /* restore the original mode, */ if (argc >= 2) { if (!strcmp(argv[1], "-v")) { /* Display version number if invoked with -v */ printf("deepsleep build %s\n", VERSION); return 0; } else if (!strcmp(argv[1], "-h")) { printf("deepsleep usage: deepsleep [-bdhrvsu] [hard|dump|soft]\n"); printf(" -b : bypass the hibernation file check\n"); printf(" -d : debug mode - be verbose\n"); printf(" -h : display this help screen\n"); printf(" -m : mute - be silent\n"); printf(" -o : do not restore the original hibernation mode\n"); printf(" -r : repair the default hibernation mode if needed\n"); printf(" -s : simulation - do not send the computer to sleep\n"); printf(" -v : display version number\n"); printf(" -u : perform operations even on unsupported OS revisions\n"); printf(" hard : send computer to hardware suspend mode\n"); printf(" dump : send computer to safe hardware suspend mode\n"); printf(" soft : send computer to software suspend mode (by default)\n"); return 0; } else { if (argc >= 3) { if (strstr(argv[1], "b")) /* Do not check the existence of the hibernation file if invoked with -b */ check_hibernation = 0; if (strstr(argv[1], "d")) /* Print debug information if invoked with -d */ debug = 1; if (strstr(argv[1], "o")) /* Do not restore the original hibernation mode if invoked with -o */ restore = 0; if (strstr(argv[1], "r")) /* Check for the validity of the original hibernation mode if invoked with -r*/ repair = 1; if (strstr(argv[1], "s")) /* Do not send the sleep call if invoked with -s */ do_sleep = 0; if (strstr(argv[1], "u")) /* Do not care about OS revision if invoked with -u */ check_os = 0; if (strstr(argv[1], "m")) mute = 1; } if (strstr(argv[argc-1], "hard")) /* Send computer to hardware suspend mode instead of software suspend mode if the hard argument is present */ target_suspend = hard; else if (strstr(argv[argc-1], "dump")) /* Send computer to safe hardware suspend mode instead of software suspend mode if the safe argument is present */ target_suspend = dump; } } if (sysctl(osmib, 2, NULL, &oslen, NULL, 0) == -1) { /* Get the operating system revision length */ printf("Failed to get the operating system revision\n"); /* On failure: quit */ return 1; } else { kernel_version = malloc(oslen * sizeof(char)); sysctl(osmib, 2, kernel_version, &oslen, NULL, 0); /* Get the operating system revision length */ sscanf(kernel_version, "%d.%d", &major_version, &minor_version); free(kernel_version); } if (debug) { printf("OS revision: %d.%d", major_version, minor_version); if (!check_os) printf(" (ignored)"); printf("\n"); } if (check_os && (major_version != 8 || minor_version < 3) && (major_version <= 8)) { /* If needed, check if major version is 8 (Mac OS X 10.4) and minor version is greater or equal than 3. Mac OS X 10.5 is also supported.*/ printf("This operating system is not supported\n"); /* On failure: quit */ return 1; } if (check_hibernation && stat("/private/var/vm/sleepimage", &sleepimage)) { /* If needed, check if the hibernation file (/private/var/vm/sleepimage) exists */ printf("Hibernation file is missing\n"); /* On failure: quit */ return 1; } if (sysctl(vmmib, 2, &swap, &swlen, NULL, 0) == -1) { /* Get the current virtual memory parameters */ printf("Failed to get the virtual memory information\n"); /* On failure: quit */ return 1; } else { default_mode = 3; if (target_suspend == dump) { target_mode = default_mode; /* we will use the regular mode 3 for safe hardware suspsend */ } else /*if (target_suspend == soft)*/ { target_mode = 25; /* or the regular mode 25 for software suspsend */ } if (target_suspend == hard) /* If we only want to perform basic hardware suspend */ target_mode = 0; /* we will sleep with hibernate mode 0 */ if (debug) printf("target mode: %d\n", target_mode); } ps_info = IOPSCopyPowerSourcesInfo(); /* Get the power source information */ if (ps_info) { current_ps = IOPSGetProvidingPowerSourceType(ps_info); /* On success, store the active power source */ } else { printf("Failed to get the power source information\n"); /* On failure: quit */ return 1; } if (debug) printf("target power source: %s\n", CFStringGetCStringPtr(current_ps, kCFStringEncodingMacRoman)); active_prof = IOPMCopyActivePowerProfiles(); /* Get the power profiles */ if (!active_prof) { printf("Failed to get the active profile\n"); CFCleanup(); return 1; } if (CFDictionaryContainsKey(active_prof, current_ps)) { /* Get the active profile corresponding to the current power source */ profile_ref = (CFNumberRef) CFDictionaryGetValue(active_prof, current_ps); profile_type = CFNumberGetType(profile_ref); CFNumberGetValue(profile_ref, profile_type, &original_profile); /* On succes, store its value */ if (debug) printf("original profile: %d\n", original_profile); } else { printf("Failed to get the power management settings\n"); /* On failure: quit */ CFCleanup(); return 1; } ds = SCDynamicStoreCreate(NULL, CFSTR("deepsleep"), NULL, NULL); /* Create a new dynamic store */ live_settings = SCDynamicStoreCopyValue(ds, CFSTR(kIOPMDynamicStoreSettingsKey)); /* Read current settings */ if(!isA_CFDictionary(live_settings)) { /* We did not get the settings: quit */ printf("Failed to get the power management settings\n"); CFCleanup(); return 1; } if (CFDictionaryContainsKey(live_settings, CFSTR("Hibernate Mode"))) { /* Check if the hibernate mode key exists */ hm_ref = (CFNumberRef) CFDictionaryGetValue(live_settings, CFSTR("Hibernate Mode")); /* On success, get its value */ hm_type = CFNumberGetType(hm_ref); CFNumberGetValue(hm_ref, hm_type, &original_mode); if (debug) printf("original mode: %d\n", original_mode); } else { /* On failure, cleanup and quit */ printf("Failed to get the hibernation mode\n"); CFCleanup(); return 1; } if (repair && original_mode == target_mode) { /* If the original mode is the same as the target mode */ original_mode = default_mode; /* A crash has probably happened during hibernation: we will set back the hibernation mode to its default value after wakeup */ if (debug) printf("repair mode to: %d\n", default_mode); } root_power_port = IORegisterForSystemPower(refCon, ¬ifyPortRef, PowerCallBack, ¬ifierObject); /* Register to the Root Power Domain IOService: notifications will be handled by the PowerCallBack functions */ if (!root_power_port) { /* Registering failed: quit */ printf("Failed to register to the Root Power Domain IOService\n"); CFCleanup(); return 1; } CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes); /* Add the notification port to the run loop */ if (SetActiveProfile(target_profile, current_ps, active_prof)) { /* Set the active power profile to custom (-1) */ printf("Failed to set the active profile\n"); PortsCleanup(); CFCleanup(); return 1; } if (SetHibernateMode(target_mode, current_ps)) { /* Set the hibernate mode to target mode */ printf("Failed to set the hibernation mode\n"); SetActiveProfile(original_profile, current_ps, active_prof); PortsCleanup(); CFCleanup(); return 1; } if (do_sleep) { /* If we are not in simulation mode */ sleep(3); /* Wait for 3s to allow settings to settle down */ if (IOPMSleepSystem(root_power_port) == kIOReturnSuccess) /* Request the system to sleep */ CFRunLoopRun(); /* On success, start the run loop */ else perror("Failed to send the sleep request\n"); /* On failure, do not start it */ } /* The run loop has stopped: system has woken up */ if (restore) { /* If we are asked to restore the original hibernate mode */ if (SetHibernateMode(original_mode, current_ps)) { /* Restore the original hibernate mode */ printf("Failed to set the hibernation mode\n"); SetActiveProfile(original_profile, current_ps, active_prof); PortsCleanup(); CFCleanup(); return 1; } if (SetActiveProfile(original_profile, current_ps, active_prof)) { /* Restore the original power profile */ printf("Failed to set the active profile\n"); PortsCleanup(); CFCleanup(); return 1; } } PortsCleanup(); /* Cleanup */ CFCleanup(); return 0; }
static void * /* O - Return status/value */ sysEventThreadEntry(void) { io_object_t powerNotifierObj; /* Power notifier object */ IONotificationPortRef powerNotifierPort; /* Power notifier port */ SCDynamicStoreRef store = NULL;/* System Config dynamic store */ CFRunLoopSourceRef powerRLS = NULL,/* Power runloop source */ storeRLS = NULL;/* System Config runloop source */ CFStringRef key[6], /* System Config keys */ pattern[2]; /* System Config patterns */ CFArrayRef keys = NULL, /* System Config key array*/ patterns = NULL;/* System Config pattern array */ SCDynamicStoreContext storeContext; /* Dynamic store context */ CFRunLoopTimerContext timerContext; /* Timer context */ cupsd_thread_data_t threadData; /* Thread context data for the * * runloop notifiers */ /* * Register for power state change notifications */ bzero(&threadData, sizeof(threadData)); threadData.sysevent.powerKernelPort = IORegisterForSystemPower(&threadData, &powerNotifierPort, sysEventPowerNotifier, &powerNotifierObj); if (threadData.sysevent.powerKernelPort) { powerRLS = IONotificationPortGetRunLoopSource(powerNotifierPort); CFRunLoopAddSource(CFRunLoopGetCurrent(), powerRLS, kCFRunLoopDefaultMode); } else DEBUG_puts("sysEventThreadEntry: error registering for system power " "notifications"); /* * Register for system configuration change notifications */ bzero(&storeContext, sizeof(storeContext)); storeContext.info = &threadData; store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), sysEventConfigurationNotifier, &storeContext); if (!ComputerNameKey) ComputerNameKey = SCDynamicStoreKeyCreateComputerName(kCFAllocatorDefault); if (!BTMMKey) BTMMKey = SCDynamicStoreKeyCreate(kCFAllocatorDefault, CFSTR("Setup:/Network/BackToMyMac")); if (!NetworkGlobalKeyIPv4) NetworkGlobalKeyIPv4 = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetIPv4); if (!NetworkGlobalKeyIPv6) NetworkGlobalKeyIPv6 = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetIPv6); if (!NetworkGlobalKeyDNS) NetworkGlobalKeyDNS = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetDNS); if (!HostNamesKey) HostNamesKey = SCDynamicStoreKeyCreateHostNames(kCFAllocatorDefault); if (!NetworkInterfaceKeyIPv4) NetworkInterfaceKeyIPv4 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); if (!NetworkInterfaceKeyIPv6) NetworkInterfaceKeyIPv6 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6); if (store && ComputerNameKey && HostNamesKey && NetworkGlobalKeyIPv4 && NetworkGlobalKeyIPv6 && NetworkGlobalKeyDNS && NetworkInterfaceKeyIPv4 && NetworkInterfaceKeyIPv6) { key[0] = ComputerNameKey; key[1] = BTMMKey; key[2] = NetworkGlobalKeyIPv4; key[3] = NetworkGlobalKeyIPv6; key[4] = NetworkGlobalKeyDNS; key[5] = HostNamesKey; pattern[0] = NetworkInterfaceKeyIPv4; pattern[1] = NetworkInterfaceKeyIPv6; keys = CFArrayCreate(kCFAllocatorDefault, (const void **)key, sizeof(key) / sizeof(key[0]), &kCFTypeArrayCallBacks); patterns = CFArrayCreate(kCFAllocatorDefault, (const void **)pattern, sizeof(pattern) / sizeof(pattern[0]), &kCFTypeArrayCallBacks); if (keys && patterns && SCDynamicStoreSetNotificationKeys(store, keys, patterns)) { if ((storeRLS = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, store, 0)) != NULL) { CFRunLoopAddSource(CFRunLoopGetCurrent(), storeRLS, kCFRunLoopDefaultMode); } else DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreCreateRunLoopSource " "failed: %s\n", SCErrorString(SCError()))); } else DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreSetNotificationKeys " "failed: %s\n", SCErrorString(SCError()))); } else DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreCreate failed: %s\n", SCErrorString(SCError()))); if (keys) CFRelease(keys); if (patterns) CFRelease(patterns); /* * Set up a timer to delay the wake change notifications. * * The initial time is set a decade or so into the future, we'll adjust * this later. */ bzero(&timerContext, sizeof(timerContext)); timerContext.info = &threadData; threadData.timerRef = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + (86400L * 365L * 10L), 86400L * 365L * 10L, 0, 0, sysEventTimerNotifier, &timerContext); CFRunLoopAddTimer(CFRunLoopGetCurrent(), threadData.timerRef, kCFRunLoopDefaultMode); /* * Store our runloop in a global so the main thread can use it to stop us. */ pthread_mutex_lock(&SysEventThreadMutex); SysEventRunloop = CFRunLoopGetCurrent(); pthread_cond_signal(&SysEventThreadCond); pthread_mutex_unlock(&SysEventThreadMutex); /* * Disappear into the runloop until it's stopped by the main thread. */ CFRunLoopRun(); /* * Clean up before exiting. */ if (threadData.timerRef) { CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), threadData.timerRef, kCFRunLoopDefaultMode); CFRelease(threadData.timerRef); } if (threadData.sysevent.powerKernelPort) { CFRunLoopRemoveSource(CFRunLoopGetCurrent(), powerRLS, kCFRunLoopDefaultMode); IODeregisterForSystemPower(&powerNotifierObj); IOServiceClose(threadData.sysevent.powerKernelPort); IONotificationPortDestroy(powerNotifierPort); } if (storeRLS) { CFRunLoopRemoveSource(CFRunLoopGetCurrent(), storeRLS, kCFRunLoopDefaultMode); CFRunLoopSourceInvalidate(storeRLS); CFRelease(storeRLS); } if (store) CFRelease(store); pthread_exit(NULL); }