static void on_timer( timer_callback_info *callback, struct timespec *now ) { assert( callback != NULL ); assert( callback->function != NULL ); debug( "Executing a timer event ( function = %p, expires_at = %u.%09u, interval = %u.%09u, user_data = %p ).", callback->function, callback->expires_at.tv_sec, callback->expires_at.tv_nsec, callback->interval.tv_sec, callback->interval.tv_nsec, callback->user_data ); if ( VALID_TIMESPEC( &callback->expires_at ) ) { callback->function( callback->user_data ); if ( VALID_TIMESPEC( &callback->interval ) ) { ADD_TIMESPEC( &callback->expires_at, &callback->interval, &callback->expires_at ); if ( TIMESPEC_LESS_THEN( &callback->expires_at, now ) ) { callback->expires_at.tv_sec = now->tv_sec; callback->expires_at.tv_nsec = now->tv_nsec; } } else { callback->expires_at.tv_sec = 0; callback->expires_at.tv_nsec = 0; callback->function = NULL; } debug( "Set expires_at value to %u.%09u.", callback->expires_at.tv_sec, callback->expires_at.tv_nsec ); } else { error( "Invalid expires_at value." ); } }
static bool _add_timer_event_callback( struct itimerspec *interval, timer_callback callback, void *user_data ) { assert( interval != NULL ); assert( callback != NULL ); timer_read_begin(); struct timer_info *timer = get_timer_info(); timer_read_end(); assert( timer != NULL ); debug( "Adding a timer event callback ( interval = %u.%09u, initial expiration = %u.%09u, callback = %p, user_data = %p ).", interval->it_interval.tv_sec, interval->it_interval.tv_nsec, interval->it_value.tv_sec, interval->it_value.tv_nsec, callback, user_data ); timer_callback_info *cb; struct timespec now; cb = xmalloc( sizeof( timer_callback_info ) ); memset( cb, 0, sizeof( timer_callback_info ) ); cb->function = callback; cb->user_data = user_data; if ( clock_gettime( CLOCK_MONOTONIC, &now ) != 0 ) { error( "Failed to retrieve monotonic time ( %s [%d] ).", strerror( errno ), errno ); xfree( cb ); return false; } cb->interval = interval->it_interval; if ( VALID_TIMESPEC( &interval->it_value ) ) { ADD_TIMESPEC( &now, &interval->it_value, &cb->expires_at ); } else if ( VALID_TIMESPEC( &interval->it_interval ) ) { ADD_TIMESPEC( &now, &interval->it_interval, &cb->expires_at ); } else { error( "Timer must not be zero when a timer event is added." ); xfree( cb ); return false; } debug( "Set an initial expiration time to %u.%09u.", now.tv_sec, now.tv_nsec ); assert( timer->timer_callbacks != NULL ); insert_timer_callback( timer, cb ); return true; }