/* * Schedule the next rwmain phase. This will run on the scheduler in the * next interation. * * @param rwmain - rwmain instance * @param next - next phase function * @param frequency - times per second to execute timer, 0 to run only once * @param ctx - if defined, context passed to the next phase, otherwise the * rwmain instance is passed. */ static void schedule_next( struct rwmain_gi * rwmain, rwsched_CFRunLoopTimerCallBack next, uint16_t frequency, void * ctx) { rwsched_CFRunLoopTimerRef cftimer; rwsched_CFRunLoopTimerContext cf_context; bzero(&cf_context, sizeof(rwsched_CFRunLoopTimerContext)); cf_context.info = ctx ? ctx : rwmain; cftimer = rwsched_tasklet_CFRunLoopTimerCreate( rwmain->rwvx->rwsched_tasklet, kCFAllocatorDefault, CFAbsoluteTimeGetCurrent(), frequency ? 1.0 / (double)frequency : 0, 0, 0, next, &cf_context); rwsched_tasklet_CFRunLoopAddTimer( rwmain->rwvx->rwsched_tasklet, rwsched_tasklet_CFRunLoopGetCurrent(rwmain->rwvx->rwsched_tasklet), cftimer, rwmain->rwvx->rwsched->main_cfrunloop_mode); }
void rwsched_cfrunloop_relocate_timers_to_main_mode(rwsched_tasklet_ptr_t sched_tasklet) { //unsigned int i, j; unsigned int i; rwsched_CFRunLoopTimerRef rwsched_object; rwsched_instance_ptr_t instance; // Validate input parameters RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t); for (i = 1 ; i < sched_tasklet->cftimer_array->len ; i++) { if ((rwsched_object = g_array_index(sched_tasklet->cftimer_array, rwsched_CFRunLoopTimerRef, i)) != NULL) { RW_CF_TYPE_VALIDATE(rwsched_object, rwsched_CFRunLoopTimerRef); instance = rwsched_object->callback_context.instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); //CFRunLoopRemoveTimer(rwsched_tasklet_CFRunLoopGetCurrent(sched_tasklet), rwsched_object->cf_object, instance->deferred_cfrunloop_mode); if (rwsched_object->onetime_timer_fired_while_blocked) { //(rwsched_object->cf_callout)(rwsched_object, rwsched_object->cf_context.info); RW_ASSERT(rwsched_object->onetime_timer); rwsched_object->cf_object = CFRunLoopTimerCreate(rwsched_object->ott.allocator, CFAbsoluteTimeGetCurrent()+0.000001, 0, rwsched_object->ott.flags, rwsched_object->ott.order, rwsched_cftimer_callout_intercept, &rwsched_object->tmp_context); rwsched_object->onetime_timer_fired_while_blocked = 0; } CFRunLoopAddTimer(rwsched_tasklet_CFRunLoopGetCurrent(sched_tasklet), rwsched_object->cf_object, instance->main_cfrunloop_mode); } } }
uint64_t rwmsg_toyRtimer_add(rwmsg_toytask_t *toy, int ms, toytimer_cb_t cb, void *ud) { rwsched_instance_ptr_t instance; rwmsg_toytask_t *toytask = toy; struct rwmsg_toytimer_s *toytimer; //uint64_t nsec; // Validate input parameters RW_CF_TYPE_VALIDATE(toytask, rwtoytask_tasklet_ptr_t); // Get the rwsched instance from the toytask instance = toytask->toysched->rwsched_instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); // Allocate a toytimer container type and track it toytimer = RW_CF_TYPE_MALLOC0(sizeof(*toytimer), rwmsg_toytimer_ptr_t); RW_CF_TYPE_VALIDATE(toytimer, rwmsg_toytimer_ptr_t); // Create a CF runloop timer CFRunLoopTimerContext cf_context = { 0, NULL, NULL, NULL, NULL }; double timer_interval = ms * .001; rwsched_CFRunLoopRef runloop = rwsched_tasklet_CFRunLoopGetCurrent(toytask->rwsched_tasklet_info); rwsched_CFRunLoopTimerRef cftimer; // Create a CFRunLoopTimer as a runloop source for the toytimer cf_context.info = toytimer; cftimer = rwsched_tasklet_CFRunLoopTimerCreate(toytask->rwsched_tasklet_info, kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + timer_interval, timer_interval, 0, 0, rwmsg_toysched_Rtimer_callback, &cf_context); RW_CF_TYPE_VALIDATE(cftimer, rwsched_CFRunLoopTimerRef); rwsched_tasklet_CFRunLoopAddTimer(toytask->rwsched_tasklet_info, runloop, cftimer, instance->main_cfrunloop_mode); // Fill in the toytimer structure toytimer->id = cftimer->index; toytimer->cb = cb; toytimer->ud = ud; // Fill in the toytimer context structure toytimer->context.toytask = toy; toytimer->context.source.cftimer = cftimer; toytimer->context.u.toytimer.toytimer = toytimer; // Return the callback id return (uint64_t) toytimer->id; }
void rwsched_cfrunloop_relocate_sources_to_main_mode(rwsched_tasklet_ptr_t sched_tasklet) { rwsched_CFRunLoopSourceRef source; rwsched_CFRunLoopRef cfrunloop; //CFStringRef current_mode; // Validate input paraemters RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t); rwsched_instance_ptr_t instance = sched_tasklet->instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); cfrunloop = rwsched_tasklet_CFRunLoopGetCurrent(sched_tasklet); //current_mode = rwsched_tasklet_CFRunLoopCopyCurrentMode(sched_tasklet, cfrunloop); //for (i = sched_tasklet->cfsource_array->len ; i > 1; i--) { while ((source = g_array_index(sched_tasklet->cfsource_array, rwsched_CFRunLoopSourceRef, 1)) != NULL) {; RW_CF_TYPE_VALIDATE(source, rwsched_CFRunLoopSourceRef); g_array_remove_index (sched_tasklet->cfsource_array, 1); rwsched_tasklet_CFRunLoopAddSource(sched_tasklet, cfrunloop, source, instance->main_cfrunloop_mode); } }
static void rwsched_cfrunloop_relocate_source(rwsched_tasklet_ptr_t sched_tasklet, rwsched_CFRunLoopSourceRef source) { rwsched_CFRunLoopRef cfrunloop; //CFStringRef current_mode; // Validate input paraemters RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t); rwsched_instance_ptr_t instance = sched_tasklet->instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); RW_CF_TYPE_VALIDATE(source, rwsched_CFRunLoopSourceRef); //RW_GOBJECT_TYPE_VALIDATE(sched_tasklet->cfsource_array, GArray); cfrunloop = rwsched_tasklet_CFRunLoopGetCurrent(sched_tasklet); //current_mode = rwsched_tasklet_CFRunLoopCopyCurrentMode(sched_tasklet, cfrunloop); // Remove the runloop source from the current runloop mode rwsched_tasklet_CFRunLoopRemoveSource(sched_tasklet, cfrunloop, source, instance->main_cfrunloop_mode); g_array_append_val(sched_tasklet->cfsource_array, source); }
static void setup_inotify_watcher(rwvx_instance_ptr_t rwvx) { RW_ASSERT(rwvx); rwvx->pacemaker_inotify.fd = inotify_init(); RW_ASSERT(rwvx->pacemaker_inotify.fd >= 0); int inotify_wd = inotify_add_watch( rwvx->pacemaker_inotify.fd, "/tmp/corosync", IN_MODIFY); RW_ASSERT(inotify_wd >= 0); CFSocketContext cf_context = { 0, rwvx, NULL, NULL, NULL }; CFOptionFlags cf_callback_flags = kCFSocketReadCallBack; CFOptionFlags cf_option_flags = kCFSocketAutomaticallyReenableReadCallBack; // Release cfsource if (rwvx->pacemaker_inotify.cfsource) { RW_CF_TYPE_VALIDATE(rwvx->pacemaker_inotify.cfsource, rwsched_CFRunLoopSourceRef); rwsched_tasklet_CFSocketReleaseRunLoopSource( rwvx->rwsched_tasklet, rwvx->pacemaker_inotify.cfsource); } // Release the cfsocket if (rwvx->pacemaker_inotify.cfsocket) { RW_CF_TYPE_VALIDATE(rwvx->pacemaker_inotify.cfsocket, rwsched_CFSocketRef); // Invalidate the cfsocket rwsched_tasklet_CFSocketInvalidate( rwvx->rwsched_tasklet, rwvx->pacemaker_inotify.cfsocket); // Release the cfsocket rwsched_tasklet_CFSocketRelease( rwvx->rwsched_tasklet, rwvx->pacemaker_inotify.cfsocket); } rwvx->pacemaker_inotify.cfsocket = rwsched_tasklet_CFSocketCreateWithNative( rwvx->rwsched_tasklet, kCFAllocatorSystemDefault, rwvx->pacemaker_inotify.fd, cf_callback_flags, pacemaker_state_changed, &cf_context); RW_CF_TYPE_VALIDATE(rwvx->pacemaker_inotify.cfsocket, rwsched_CFSocketRef); rwsched_tasklet_CFSocketSetSocketFlags( rwvx->rwsched_tasklet, rwvx->pacemaker_inotify.cfsocket, cf_option_flags); rwvx->pacemaker_inotify.cfsource = rwsched_tasklet_CFSocketCreateRunLoopSource( rwvx->rwsched_tasklet, kCFAllocatorSystemDefault, rwvx->pacemaker_inotify.cfsocket, 0); RW_CF_TYPE_VALIDATE(rwvx->pacemaker_inotify.cfsource, rwsched_CFRunLoopSourceRef); rwsched_tasklet_CFRunLoopAddSource( rwvx->rwsched_tasklet, rwsched_tasklet_CFRunLoopGetCurrent(rwvx->rwsched_tasklet), rwvx->pacemaker_inotify.cfsource, rwvx->rwsched->main_cfrunloop_mode); }
void rwsched_cftimer_callout_intercept(CFRunLoopTimerRef timer, void *info) { rwsched_instance_ptr_t instance; rwsched_CFRunLoopTimerRef rwsched_object = (rwsched_CFRunLoopTimerRef) info; rwsched_tasklet_ptr_t sched_tasklet; // Validate input parameters __CFGenericValidateType_(timer, CFRunLoopTimerGetTypeID(), __PRETTY_FUNCTION__); RW_CF_TYPE_VALIDATE(rwsched_object, rwsched_CFRunLoopTimerRef); sched_tasklet = rwsched_object->callback_context.tasklet_info; RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t); instance = rwsched_object->callback_context.instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); // #1 - Check if the current tasklet is in blocking mode; if a // timer fired while blocking, then dont call the callback // #2 - Otherwise the current tasklet is not blocking and the timer callback // shall be called if (sched_tasklet->blocking_mode.blocked) { /* printf("BLOK timer=%p valid=%d repeat=%d interval=%f next-fire=%f \n", timer, CFRunLoopTimerIsValid(timer), CFRunLoopTimerDoesRepeat(timer), CFRunLoopTimerGetInterval(timer), (CFRunLoopTimerGetNextFireDate(timer) - CFAbsoluteTimeGetCurrent())); */ CFRunLoopRemoveTimer(rwsched_tasklet_CFRunLoopGetCurrent(sched_tasklet), rwsched_object->cf_object, instance->main_cfrunloop_mode); //CFRunLoopAddTimer(rwsched_tasklet_CFRunLoopGetCurrent(sched_tasklet), rwsched_object->cf_object, instance->deferred_cfrunloop_mode); if (rwsched_object->onetime_timer) rwsched_object->onetime_timer_fired_while_blocked = 1; } else { /* printf("MAIN timer=%p valid=%d repeat=%d interval=%f next-fire=%f \n", timer, CFRunLoopTimerIsValid(timer), CFRunLoopTimerDoesRepeat(timer), CFRunLoopTimerGetInterval(timer), (CFRunLoopTimerGetNextFireDate(timer) - CFAbsoluteTimeGetCurrent())); */ g_rwresource_track_handle = sched_tasklet->rwresource_track_handle; g_tasklet_info = sched_tasklet; // The current task is not blocking so we can invoke the callback now struct timeval tv_begin, tv_end, tv_delta; if (sched_tasklet->instance->latency.check_threshold_ms) { gettimeofday(&tv_begin, NULL); } else { tv_begin.tv_sec = 0; } (rwsched_object->cf_callout)(rwsched_object, rwsched_object->cf_context.info); if (tv_begin.tv_sec && sched_tasklet->instance->latency.check_threshold_ms) { gettimeofday(&tv_end, NULL); timersub(&tv_end, &tv_begin, &tv_delta); unsigned int cbms = (tv_delta.tv_sec * 1000 + tv_delta.tv_usec / 1000); if (cbms >= sched_tasklet->instance->latency.check_threshold_ms) { char *name = rw_btrace_get_proc_name(rwsched_object->cf_callout); RWSCHED_LOG_EVENT(instance, SchedDebug, RWLOG_ATTR_SPRINTF("rwsched[%d] CF timer took %ums ctx %p callback %s", getpid(), cbms, rwsched_object->cf_context.info, name)); free(name); } } g_tasklet_info = 0; g_rwresource_track_handle = 0; } }
uint64_t rwmsg_toyfd_add(rwmsg_toytask_t *toy, int fd, int pollbits, toyfd_cb_t cb, void *ud) { rwsched_instance_ptr_t instance; rwmsg_toytask_t *toytask = toy; //rwsched_dispatch_source_t source; struct rwmsg_toyfd_s *toyfd; // Validate input parameters RW_CF_TYPE_VALIDATE(toytask, rwtoytask_tasklet_ptr_t); // Get the rwsched instance from the toytask instance = toytask->toysched->rwsched_instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); // Allocate a toyfd container type and track it toyfd = RW_CF_TYPE_MALLOC0(sizeof(*toyfd), rwmsg_toyfd_ptr_t); RW_CF_TYPE_VALIDATE(toyfd, rwmsg_toyfd_ptr_t); // Example of using CFSocket to manage file descriptors on a runloop using CFStreamCreatePairWithSocket() // http://lists.apple.com/archives/macnetworkprog/2003/Jul/msg00075.html CFSocketContext cf_context = { 0, NULL, NULL, NULL, NULL }; CFOptionFlags cf_callback_flags = 0; CFOptionFlags cf_option_flags = 0; rwsched_CFRunLoopRef runloop = rwsched_tasklet_CFRunLoopGetCurrent(toytask->rwsched_tasklet_info); rwsched_CFSocketRef cfsocket; rwsched_CFRunLoopSourceRef cfsource; // Use the pollbits to determine which socket callback events to register if (pollbits & POLLIN) { cf_callback_flags |= kCFSocketReadCallBack; cf_option_flags |= kCFSocketAutomaticallyReenableReadCallBack; } if (pollbits & POLLOUT) { cf_callback_flags |= kCFSocketWriteCallBack; cf_option_flags |= kCFSocketAutomaticallyReenableWriteCallBack; } // Create a CFSocket as a runloop source for the toyfd file descriptor cf_context.info = toyfd; cfsocket = rwsched_tasklet_CFSocketCreateWithNative(toytask->rwsched_tasklet_info, kCFAllocatorSystemDefault, fd, cf_callback_flags, rwmsg_toysched_io_callback, &cf_context); RW_CF_TYPE_VALIDATE(cfsocket, rwsched_CFSocketRef); rwsched_tasklet_CFSocketSetSocketFlags(toytask->rwsched_tasklet_info, cfsocket, cf_option_flags); cfsource = rwsched_tasklet_CFSocketCreateRunLoopSource(toytask->rwsched_tasklet_info, kCFAllocatorSystemDefault, cfsocket, 0); RW_CF_TYPE_VALIDATE(cfsource, rwsched_CFRunLoopSourceRef); rwsched_tasklet_CFRunLoopAddSource(toytask->rwsched_tasklet_info, runloop, cfsource, instance->main_cfrunloop_mode); // Fill in the toyfd structure toyfd->cf_ref = cfsocket; toyfd->id = cfsocket->index; toyfd->fd = fd; toyfd->cb = cb; toyfd->ud = ud; toyfd->toytask = toytask; // Fill in the read context structure if (pollbits & POLLIN) { toyfd->read_context.source.cfsource = cfsource; } // Fill in the write context structure if (pollbits & POLLOUT) { toyfd->write_context.source.cfsource = cfsource; } // Return the callback id return (uint64_t) toyfd->id; }