Exemplo n.º 1
0
int
rwsched_tasklet_signal(
    rwsched_tasklet_t *sched_tasklet,
    int signum,
    rwsched_sighandler_t sighandler,
    void* user_data,
    GDestroyNotify dtor)
{
  // 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);

  if (signum < 1 || signum > RWSCHED_MAX_SIGNALS-1) {
    return -1;
  }

  if (!sighandler) {
    sched_tasklet->signal_required &= ~(1<<signum);
    sched_tasklet->signal_handler[signum] = NULL;
    goto done;
  }

  if (!(instance->signal_required & (1<<signum))) {
    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    sa.sa_handler = rwsched_handler;
    if (sigaction(signum, &sa, NULL) == -1) {
      RWSCHED_LOG_EVENT(instance, SchedError, RWLOG_ATTR_SPRINTF("ERROR: rwsched_tasklet_signal(%p signum=%u) FAILED ON sigaction\n", sched_tasklet, signum));
      return -1;
    }
    instance->signal_required |= (1<<signum);
  }
  sched_tasklet->signal_required |= (1<<signum);
  sched_tasklet->signal_handler[signum] = sighandler;
done:
  if (sched_tasklet->signal_dtor[signum]) {
    sched_tasklet->signal_dtor[signum](sched_tasklet->signal_dtor_ud[signum]);
  }
  sched_tasklet->signal_dtor[signum]= dtor;
  sched_tasklet->signal_dtor_ud[signum]= user_data;
  return 0;
}
Exemplo n.º 2
0
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;
  }
}
Exemplo n.º 3
0
void
rwsched_cfsocket_callout_intercept(CFSocketRef s,
				   CFSocketCallBackType type,
				   CFDataRef address,
				   const void *data,
				   void *info)
{
  rwsched_instance_ptr_t instance;
  rwsched_tasklet_ptr_t sched_tasklet;
  rwsched_cfsocket_callback_context_ptr_t callback_context;
  rwsched_CFSocketRef cfsocket = (rwsched_CFSocketRef) info;

  // Validate input parameters
  __CFGenericValidateType_(s, CFSocketGetTypeID(), __PRETTY_FUNCTION__);
  RW_CF_TYPE_VALIDATE(cfsocket, rwsched_CFSocketRef);
  callback_context = &cfsocket->callback_context;
  instance = callback_context->instance;
  RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t);
  sched_tasklet = callback_context->tasklet_info;
  RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t);

  // #1 - Check to see if the cfsocket matches the current blocking source for the tasklet
  // #2 - Otherwise check if the current tasklet is in blocking mode and then relocate the runloop source
  // #3 - Otherwise the current tasklet is not blocking and the event can be processed now
  if (sched_tasklet->blocking_mode.cfsource == callback_context->cfsource) {
    // Abort the runloop that is currently blocking
    CFRunLoopRef rl = CFRunLoopGetCurrent();
    CFRunLoopStop(rl);
  }
  else if (sched_tasklet->blocking_mode.cfsource) {
    // The task is blocking and this event CANNOT be processed yet, so move it to a different runloop mode
    rwsched_cfrunloop_relocate_source(sched_tasklet, callback_context->cfsource);
  }
  else {
    // The current task is not blocking so we can invoke the callback now
    RW_ASSERT(callback_context->cf_callout);
    g_rwresource_track_handle = sched_tasklet->rwresource_track_handle;
    g_tasklet_info = sched_tasklet;


    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;
    }

    (*callback_context->cf_callout)(cfsocket, type, address, data, callback_context->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(callback_context->cf_callout);
  RWSCHED_LOG_EVENT(instance, SchedDebug, RWLOG_ATTR_SPRINTF("rwsched[%d] CF socket/file took %ums ctx %p callback %s", 
                                                             getpid(), cbms, callback_context->cf_context.info, name));
	free(name);
      }
    }

    g_tasklet_info = 0;
    g_rwresource_track_handle = 0;
  }
}