Exemple #1
0
/*
 * 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);
    }
  }
}
Exemple #3
0
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);
}
Exemple #6
0
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;
  }
}
Exemple #8
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;
}