//------------------------------------------------------------------------------ // IOMIGMachPortCreate //------------------------------------------------------------------------------ IOMIGMachPortRef IOMIGMachPortCreate(CFAllocatorRef allocator, CFIndex maxMessageSize, mach_port_t port) { IOMIGMachPortRef migPort = NULL; void * offset = NULL; uint32_t size; require(maxMessageSize > 0, exit); /* allocate service */ size = sizeof(__IOMIGMachPort) - sizeof(CFRuntimeBase); migPort = ( IOMIGMachPortRef)_CFRuntimeCreateInstance(allocator, IOMIGMachPortGetTypeID(), size, NULL); require(migPort, exit); offset = migPort; bzero(offset + sizeof(CFRuntimeBase), size); CFMachPortContext context = {0, migPort, NULL, NULL, NULL}; migPort->port = (port != MACH_PORT_NULL) ? CFMachPortCreateWithPort(kCFAllocatorDefault, port, __IOMIGMachPortPortCallback, &context, NULL) : CFMachPortCreate(kCFAllocatorDefault, __IOMIGMachPortPortCallback, &context, NULL); require(migPort->port, exit); migPort->maxMessageSize = maxMessageSize; return migPort; exit: if ( migPort ) CFRelease(migPort); return NULL; }
Boolean SetupMIGServer() { Boolean result = true; kern_return_t kern_result = KERN_SUCCESS; CFMachPortRef upsdMachPort = NULL; // must release mach_port_t ups_port = MACH_PORT_NULL; /*if (IOUPSMIGServerIsRunning(&bootstrap_port, NULL)) { result = false; goto finish; }*/ kern_result = task_get_bootstrap_port(mach_task_self(), &bootstrap_port); if (kern_result != KERN_SUCCESS) { result = false; goto finish; } gMainRunLoop = CFRunLoopGetCurrent(); if (!gMainRunLoop) { result = false; goto finish; } kern_result = bootstrap_check_in( bootstrap_port, kIOUPSPlugInServerName, &ups_port); if (BOOTSTRAP_SUCCESS != kern_result) { syslog(LOG_ERR, "ioupsd: bootstrap_check_in \"%s\" error = %d\n", kIOUPSPlugInServerName, kern_result); } else { upsdMachPort = CFMachPortCreateWithPort(kCFAllocatorDefault, ups_port, upsd_mach_port_callback, NULL, NULL); gClientRequestRunLoopSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, upsdMachPort, 0); if (!gClientRequestRunLoopSource) { result = false; goto finish; } CFRunLoopAddSource(gMainRunLoop, gClientRequestRunLoopSource, kCFRunLoopDefaultMode); } finish: if (gClientRequestRunLoopSource) CFRelease(gClientRequestRunLoopSource); if (upsdMachPort) CFRelease(upsdMachPort); return result; }
IOReturn IOFireWireSBP2LibLUN::addIODispatcherToRunLoop( CFRunLoopRef cfRunLoopRef ) { IOReturn status = kIOReturnSuccess; FWLOG(( "IOFireWireSBP2LibLUN : addIODispatcherToRunLoop\n" )); if( !fConnection ) return kIOReturnNoDevice; if( status == kIOReturnSuccess ) { CFMachPortContext context; Boolean shouldFreeInfo; // zzz what's this for? context.version = 1; context.info = this; context.retain = NULL; context.release = NULL; context.copyDescription = NULL; fCFAsyncPort = CFMachPortCreateWithPort( kCFAllocatorDefault, fAsyncPort, (CFMachPortCallBack) IODispatchCalloutFromMessage, &context, &shouldFreeInfo ); if( !fCFAsyncPort ) status = kIOReturnNoMemory; } if( status == kIOReturnSuccess ) { fCFRunLoopSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, fCFAsyncPort, 0 ); if( !fCFRunLoopSource ) status = kIOReturnNoMemory; } if( status == kIOReturnSuccess ) { fCFRunLoop = cfRunLoopRef; CFRunLoopAddSource( fCFRunLoop, fCFRunLoopSource, kCFRunLoopCommonModes ); } if( status == kIOReturnSuccess ) { io_async_ref64_t asyncRef; mach_msg_type_number_t size = 0; asyncRef[kIOAsyncCalloutFuncIndex] = (uint64_t)&IOFireWireSBP2LibLUN::staticMessageCallback; asyncRef[kIOAsyncCalloutRefconIndex] = (uint64_t)this; status = IOConnectCallAsyncScalarMethod( fConnection, kIOFWSBP2UserClientSetMessageCallback, fAsyncPort, asyncRef, kOSAsyncRef64Count, NULL, 0, NULL, &size ); } return status; }
CFRunLoopSourceRef CFUserNotificationCreateRunLoopSource(CFAllocatorRef allocator, CFUserNotificationRef userNotification, CFUserNotificationCallBack callout, CFIndex order) { CHECK_FOR_FORK(); CFRunLoopSourceRef source = NULL; if (userNotification && callout && !userNotification->_machPort && MACH_PORT_NULL != userNotification->_replyPort) { CFMachPortContext context = {0, userNotification, NULL, NULL, NULL}; userNotification->_machPort = CFMachPortCreateWithPort(CFGetAllocator(userNotification), (mach_port_t)userNotification->_replyPort, _CFUserNotificationMachPortCallBack, &context, NULL); } if (userNotification && userNotification->_machPort) { source = CFMachPortCreateRunLoopSource(allocator, userNotification->_machPort, order); userNotification->_callout = callout; } return source; }
static void start_service(mach_port_t service_port) { CFMachPortRef mp; CFRunLoopSourceRef rls; mp = CFMachPortCreateWithPort(NULL, service_port, server_handle_request, NULL, NULL); rls = CFMachPortCreateRunLoopSource(NULL, mp, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); CFRelease(mp); CFRelease(rls); return; }
void cellconnect() { int t1; sc=_CTServerConnectionCreate(kCFAllocatorDefault, callback, NULL); /* port is not currently used, shuld be usable with a runloop. */ port=CFMachPortCreateWithPort(kCFAllocatorDefault, _CTServerConnectionGetPort(sc), NULL, NULL, NULL); _CTServerConnectionCellMonitorStart(&t1,sc); printf("Connected\n"); }
/* * rend_addtorunloop */ static int rend_addtorunloop(dns_service_discovery_ref client) { mach_port_t port=DNSServiceDiscoveryMachPort(client); if(!port) return -1; else { CFMachPortContext context = { 0, 0, NULL, NULL, NULL }; Boolean shouldFreeInfo; CFMachPortRef cfMachPort=CFMachPortCreateWithPort(kCFAllocatorDefault, port, rend_handler, &context, &shouldFreeInfo); CFRunLoopSourceRef rls=CFMachPortCreateRunLoopSource(NULL,cfMachPort,0); CFRunLoopAddSource(CFRunLoopGetCurrent(), rls,kCFRunLoopDefaultMode); CFRelease(rls); return 0; } }
void MonitorStartupItem (StartupContext aStartupContext, CFMutableDictionaryRef anItem) { pid_t aPID = StartupItemGetPID(anItem); if (anItem && aPID > 0) { mach_port_t aPort; kern_return_t aResult; CFMachPortContext aContext; CFMachPortRef aMachPort; CFRunLoopSourceRef aSource; TerminationContext aTerminationContext = (TerminationContext) malloc(sizeof(struct TerminationContextStorage)); aTerminationContext->aStartupContext = aStartupContext; aTerminationContext->anItem = anItem; aContext.version = 0; aContext.info = aTerminationContext; aContext.retain = 0; aContext.release = 0; if ((aResult = task_for_pid(mach_task_self(), aPID, &aPort)) != KERN_SUCCESS) goto out_bad; if (!(aMachPort = CFMachPortCreateWithPort(NULL, aPort, NULL, &aContext, NULL))) goto out_bad; if (!(aSource = CFMachPortCreateRunLoopSource(NULL, aMachPort, 0))) { CFRelease(aMachPort); goto out_bad; } CFMachPortSetInvalidationCallBack(aMachPort, startupItemTerminated); CFRunLoopAddSource(CFRunLoopGetCurrent(), aSource, kCFRunLoopCommonModes); CFRelease(aSource); CFRelease(aMachPort); return; out_bad: /* The assumption is something failed, the task already terminated. */ startupItemTerminated(NULL, aTerminationContext); } }
// This constructor is the general form: // - If inMachPort is MACH_PORT_NULL, the CFMachPort will allocate the port and own the send and // receive rights. Otherwise, the caller owns the rights and is resposible for cleaning them // up. // - If inCallBack is NULL, then received messages will just get swallowed by the CFMachPort. // This is useful if you are only using the CFMachPort to track port death (aka invalidation). // - If inInvalidationCallBack is non-NULL, then it will be installed as the invalidation // callback on the CFMachPort. CACFMachPort::CACFMachPort(mach_port_t inMachPort, CFMachPortCallBack inCallBack, CFMachPortInvalidationCallBack inInvalidationCallBack, void* inUserData) : mMachPort(NULL), mRunLoopSource(NULL), mOwnsPort(false) { CFMachPortContext theContext = { 1, inUserData, NULL, NULL, NULL }; if(inMachPort == MACH_PORT_NULL) { mMachPort = CFMachPortCreate(NULL, inCallBack, &theContext, NULL); ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort: couldn't create the CFMachPort"); mOwnsPort = true; } else { mMachPort = CFMachPortCreateWithPort(NULL, inMachPort, inCallBack, &theContext, NULL); ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort: couldn't create the CFMachPort with a port"); mOwnsPort = false; } mRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mMachPort, 0); if(mRunLoopSource == NULL) { if(mOwnsPort) { CFMachPortInvalidate(mMachPort); } CFRelease(mMachPort); mMachPort = NULL; DebugMessage("CACFMachPort::CACFMachPort: couldn't create the CFRunLoopSource"); throw CAException('what'); } if(inInvalidationCallBack != NULL) { CFMachPortSetInvalidationCallBack(mMachPort, inInvalidationCallBack); } }
CFMessagePortRef CFMessagePortCreateRemote(CFAllocatorRef allocator, CFStringRef name) { CFMessagePortRef memory; CFMachPortRef native; CFMachPortContext ctx; uint8_t *utfname = NULL; CFIndex size; mach_port_t bp, port; kern_return_t ret; name = __CFMessagePortSanitizeStringName(allocator, name, &utfname, NULL); if (NULL == name) { return NULL; } __CFSpinLock(&__CFAllMessagePortsLock); if (NULL != name) { CFMessagePortRef existing; if (NULL != __CFAllRemoteMessagePorts && CFDictionaryGetValueIfPresent(__CFAllRemoteMessagePorts, name, (const void **)&existing)) { __CFSpinUnlock(&__CFAllMessagePortsLock); CFRelease(name); CFAllocatorDeallocate(allocator, utfname); return (CFMessagePortRef)CFRetain(existing); } } size = sizeof(struct __CFMessagePort) - sizeof(CFMessagePortContext) - sizeof(CFRuntimeBase); memory = (CFMessagePortRef)_CFRuntimeCreateInstance(allocator, __kCFMessagePortTypeID, size, NULL); if (NULL == memory) { __CFSpinUnlock(&__CFAllMessagePortsLock); if (NULL != name) { CFRelease(name); } CFAllocatorDeallocate(allocator, utfname); return NULL; } __CFMessagePortUnsetValid(memory); __CFMessagePortSetRemote(memory); memory->_lock = 0; memory->_name = name; memory->_port = NULL; memory->_replies = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL); memory->_convCounter = 0; memory->_replyPort = NULL; memory->_source = NULL; memory->_icallout = NULL; memory->_callout = NULL; ctx.version = 0; ctx.info = memory; ctx.retain = NULL; ctx.release = NULL; ctx.copyDescription = NULL; task_get_bootstrap_port(mach_task_self(), &bp); ret = bootstrap_look_up(bp, utfname, &port); native = (KERN_SUCCESS == ret) ? CFMachPortCreateWithPort(allocator, port, __CFMessagePortDummyCallback, &ctx, NULL) : NULL; CFAllocatorDeallocate(allocator, utfname); if (NULL == native) { __CFSpinUnlock(&__CFAllMessagePortsLock); // name is released by deallocation CFRelease(memory); return NULL; } memory->_port = native; CFMachPortSetInvalidationCallBack(native, __CFMessagePortInvalidationCallBack); __CFMessagePortSetValid(memory); if (NULL != name) { if (NULL == __CFAllRemoteMessagePorts) { __CFAllRemoteMessagePorts = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL); } CFDictionaryAddValue(__CFAllRemoteMessagePorts, name, memory); } __CFSpinUnlock(&__CFAllMessagePortsLock); return (CFMessagePortRef)memory; }
static int ListenUsingCoreFoundation(size_t noteCount, const char **noteNames) // Implements the "listenCF" command. Register for the noteCount // notifications whose names are in the noteNames array. Then wrap the // notification Mach port in a CFMachPort and use CF to read the notification // messages, printing the information about any notifications that arrive // from our CFMachPort callback. { int retVal; uint32_t noteErr; size_t noteIndex; int noteTokens[noteCount]; mach_port_t port = MACH_PORT_NULL; // Register. The first time around this loop fd == -1 and so we don't // specify NOTIFY_REUSE. notify_register_mach_port then allocates // a Mach port and returns it in port. For subsequent iterations // we /do/ specify NOTIFY_REUSE and notify_register_mach_port just // reuses the existing port. noteErr = NOTIFY_STATUS_OK; for (noteIndex = 0; noteIndex < noteCount; noteIndex++) { noteErr = notify_register_mach_port( noteNames[noteIndex], &port, (port == MACH_PORT_NULL) ? 0 : NOTIFY_REUSE, ¬eTokens[noteIndex] ); if (noteErr != NOTIFY_STATUS_OK) { break; } } if (noteErr != NOTIFY_STATUS_OK) { PrintNotifyError("registration failed", noteNames[noteIndex], noteErr); retVal = EXIT_FAILURE; } else { MyCFMachPortCallBackInfo myInfo; CFMachPortContext context = { 0 }; CFMachPortRef cfPort; Boolean shouldFreeInfo; CFRunLoopSourceRef rls; // Set up the context structure for MyCFMachPortCallBack. myInfo.magic = 'CFpI'; myInfo.noteCount = noteCount; myInfo.noteTokens = noteTokens; myInfo.noteNames = noteNames; // Create the CFMachPort. context.info = &myInfo; cfPort = CFMachPortCreateWithPort( NULL, port, MyCFMachPortCallBack, &context, &shouldFreeInfo ); assert(cfPort != NULL); // There can only be one CFMachPort for a given Mach port name. Thus, // if someone had already created a CFMachPort for "port", CFMachPort // would not create a new CFMachPort but, rather, return the existing // CFMachPort with the retain count bumped. In that case it hasn't // taken any 'reference' on the data in context; the context.info // on the /previous/ CFMachPort is still in use, but the context.info // that we supply is now superfluous. In that case it returns // shouldFreeInfo, telling us that we don't need to hold on to this // information. // // In this specific case no one should have already created a CFMachPort // for "port", so shouldFreeInfo should never be true. If it is, it's // time to worry! assert( ! shouldFreeInfo ); // Add it to the run loop. rls = CFMachPortCreateRunLoopSource(NULL, cfPort, 0); assert(rls != NULL); CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); CFRelease(rls); // Run the run loop. fprintf(stdout, "Listening using Core Foundation:\n"); fflush(stdout); CFRunLoopRun(); fprintf(stderr, "CFRunLoopRun returned\n"); retVal = EXIT_FAILURE; } return retVal; }
int wxAddProcessCallbackForPid(wxEndProcessData *proc_data, int pid) { if(pid < 1) return -1; kern_return_t kernResult; mach_port_t taskOfOurProcess; mach_port_t machPortForProcess; taskOfOurProcess = mach_task_self(); if(taskOfOurProcess == MACH_PORT_NULL) { wxLogDebug(wxT("No mach_task_self()")); return -1; } wxLogDebug(wxT("pid=%d"),pid); kernResult = task_for_pid(taskOfOurProcess,pid, &machPortForProcess); if(kernResult != KERN_SUCCESS) { wxLogDebug(wxT("no task_for_pid()")); // try seeing if it is already dead or something // FIXME: a better method would be to call the callback function // from idle time until the process terminates. Of course, how // likely is it that it will take more than 0.1 seconds for the // mach terminate event to make its way to the BSD subsystem? usleep(100); // sleep for 0.1 seconds wxMAC_MachPortEndProcessDetect(NULL, (void*)proc_data); return -1; } CFMachPortContext termcb_contextinfo; termcb_contextinfo.version = 0; termcb_contextinfo.info = (void*)proc_data; termcb_contextinfo.retain = NULL; termcb_contextinfo.release = NULL; termcb_contextinfo.copyDescription = NULL; CFMachPortRef CFMachPortForProcess; Boolean ShouldFreePort; CFMachPortForProcess = CFMachPortCreateWithPort(NULL, machPortForProcess, NULL, &termcb_contextinfo, &ShouldFreePort); if(!CFMachPortForProcess) { wxLogDebug(wxT("No CFMachPortForProcess")); mach_port_deallocate(taskOfOurProcess, machPortForProcess); return -1; } if(ShouldFreePort) { kernResult = mach_port_deallocate(taskOfOurProcess, machPortForProcess); if(kernResult!=KERN_SUCCESS) { wxLogDebug(wxT("Couldn't deallocate mach port")); return -1; } } CFMachPortSetInvalidationCallBack(CFMachPortForProcess, &wxMAC_MachPortEndProcessDetect); CFRunLoopSourceRef runloopsource; runloopsource = CFMachPortCreateRunLoopSource(NULL,CFMachPortForProcess, (CFIndex)0); if(!runloopsource) { wxLogDebug(wxT("Couldn't create runloopsource")); return -1; } CFRelease(CFMachPortForProcess); CFRunLoopAddSource(CFRunLoopGetCurrent(),runloopsource,kCFRunLoopDefaultMode); CFRelease(runloopsource); wxLogDebug(wxT("Successfully added notification to the runloop")); return 0; }
// // Handle dead-port notifications. // Since we don't actually run our own runloop here, we can't well use standard // notifications to our own server port. So we use a CFMachPort facility instead. // void MachRunLoopServer::notifyIfDead(Port port, bool doNotify) const { if (CFMachPortRef cfPort = CFMachPortCreateWithPort(NULL, port, NULL, NULL, NULL)) CFMachPortSetInvalidationCallBack(cfPort, cfInvalidate); }