unsigned long hwtimer_arch_now(void) { struct timespec t; DEBUG("hwtimer_arch_now()\n"); _native_syscall_enter(); #ifdef __MACH__ clock_serv_t cclock; mach_timespec_t mts; host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); clock_get_time(cclock, &mts); mach_port_deallocate(mach_task_self(), cclock); t.tv_sec = mts.tv_sec; t.tv_nsec = mts.tv_nsec; #else if (real_clock_gettime(CLOCK_MONOTONIC, &t) == -1) { err(EXIT_FAILURE, "hwtimer_arch_now: clock_gettime"); } #endif _native_syscall_leave(); native_hwtimer_now = ts2ticks(&t) - time_null; struct timeval tv; ticks2tv(native_hwtimer_now, &tv); DEBUG("hwtimer_arch_now(): it is now %lu s %lu us\n", (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec); DEBUG("hwtimer_arch_now(): returning %lu\n", native_hwtimer_now); return native_hwtimer_now; }
/** * set next_timer to the next lowest enabled timer index */ void schedule_timer(void) { /* try to find *an active* timer */ next_timer = -1; for (int i = 0; i < HWTIMER_MAXTIMERS; i++) { if (native_hwtimer_isset[i] == 1) { next_timer = i; break; } } if (next_timer == -1) { DEBUG("schedule_timer(): no valid timer found - nothing to schedule\n"); struct itimerval null_timer; null_timer.it_interval.tv_sec = 0; null_timer.it_interval.tv_usec = 0; null_timer.it_value.tv_sec = 0; null_timer.it_value.tv_usec = 0; if (real_setitimer(ITIMER_REAL, &null_timer, NULL) == -1) { err(EXIT_FAILURE, "schedule_timer: setitimer"); } return; } /* find the next pending timer (next_timer now points to *a* valid pending timer) */ for (int i = 0; i < HWTIMER_MAXTIMERS; i++) { if ( (native_hwtimer_isset[i] == 1) && (tv2ticks(&(native_hwtimer[i].it_value)) < tv2ticks(&(native_hwtimer[next_timer].it_value))) ) { /* timer in slot i is active and the timeout is more recent than next_timer */ next_timer = i; } } /* next pending timer is in slot next_timer */ struct timeval now; hwtimer_arch_now(); // update timer ticks2tv(native_hwtimer_now, &now); struct itimerval result; memset(&result, 0, sizeof(result)); int retval = timeval_subtract(&result.it_value, &native_hwtimer[next_timer].it_value, &now); if (retval || (tv2ticks(&result.it_value) < HWTIMERMINOFFSET)) { DEBUG("\033[31mschedule_timer(): timer is already due (%i), mitigating.\033[0m\n", next_timer); result.it_value.tv_sec = 0; result.it_value.tv_usec = 1; } _native_syscall_enter(); if (real_setitimer(ITIMER_REAL, &result, NULL) == -1) { err(EXIT_FAILURE, "schedule_timer: setitimer"); } else { DEBUG("schedule_timer(): set next timer (%i).\n", next_timer); } _native_syscall_leave(); }
void hwtimer_arch_set_absolute(unsigned long value, short timer) { DEBUG("hwtimer_arch_set_absolute(%lu, %i)\n", value, timer); ticks2tv(value, &(native_hwtimer[timer].it_value)); DEBUG("hwtimer_arch_set_absolute(): that is at %lu s %lu us\n", (unsigned long)native_hwtimer[timer].it_value.tv_sec, (unsigned long)native_hwtimer[timer].it_value.tv_usec); native_hwtimer_isset[timer] = 1; schedule_timer(); return; }
void hwtimer_arch_set(unsigned long offset, short timer) { DEBUG("hwtimer_arch_set(%lu, %i)\n", offset, timer); if (offset < HWTIMERMINOFFSET) { offset = HWTIMERMINOFFSET; DEBUG("hwtimer_arch_set: offset < MIN, set to: %lu\n", offset); } native_hwtimer_irq[timer] = 1; native_hwtimer_isset[timer] = 1; ticks2tv(offset, &(native_hwtimer[timer].it_value)); DEBUG("hwtimer_arch_set(): that is %lu s %lu us from now\n", (unsigned long)native_hwtimer[timer].it_value.tv_sec, (unsigned long)native_hwtimer[timer].it_value.tv_usec); schedule_timer(); return; }