time_t time(time_t *t) { struct timespec ts; __clock_gettime(CLOCK_REALTIME, &ts); if (t) *t = ts.tv_sec; return ts.tv_sec; }
int __timedwait(volatile int *addr, int val, clockid_t clk, const struct timespec *at, void (*cleanup)(void *), void *arg, int priv) { int r, cs; struct timespec to, *top=0; if (priv) priv = 128; if (at) { if (at->tv_nsec >= 1000000000UL) return EINVAL; if (__clock_gettime(clk, &to)) return EINVAL; to.tv_sec = at->tv_sec - to.tv_sec; if ((to.tv_nsec = at->tv_nsec - to.tv_nsec) < 0) { to.tv_sec--; to.tv_nsec += 1000000000; } if (to.tv_sec < 0) return ETIMEDOUT; top = &to; } if (!cleanup) __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); pthread_cleanup_push(cleanup, arg); r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT|priv, val, top); if (r == ENOSYS) r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT, val, top); if (r != EINTR && r != ETIMEDOUT) r = 0; pthread_cleanup_pop(0); if (!cleanup) __pthread_setcancelstate(cs, 0); return r; }
clock_t clock() { struct timespec ts; struct tms tms; if (!__clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts)) return ts.tv_sec*1000000 + ts.tv_nsec/1000; __syscall(SYS_times, &tms); return (tms.tms_utime + tms.tms_stime)*100; }
/* Set TS to calendar time based in time base BASE. */ int timespec_get (struct timespec *ts, int base) { switch (base) { case TIME_UTC: if (__clock_gettime (CLOCK_REALTIME, ts) < 0) return 0; break; default: return 0; } return base; }
clock_t clock (void) { struct timespec ts; _Static_assert (CLOCKS_PER_SEC == 1000000, "CLOCKS_PER_SEC should be 1000000"); /* clock_gettime shouldn't fail here since CLOCK_PROCESS_CPUTIME_ID is supported since 2.6.12. Check the return value anyway in case the kernel barfs on us for some reason. */ if (__glibc_unlikely (__clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts) != 0)) return (clock_t) -1; return (ts.tv_sec * CLOCKS_PER_SEC + ts.tv_nsec / (1000000000 / CLOCKS_PER_SEC)); }
thread_func (void *arg) { struct thread_node *self = arg; /* Register cleanup handler, in case rogue application terminates this thread. (This cannot happen to __timer_signal_thread, which doesn't invoke application callbacks). */ pthread_cleanup_push (thread_cleanup, self); pthread_mutex_lock (&__timer_mutex); while (1) { struct list_head *first; struct timer_node *timer = NULL; /* While the timer queue is not empty, inspect the first node. */ first = list_first (&self->timer_queue); if (first != list_null (&self->timer_queue)) { struct timespec now; timer = timer_links2ptr (first); /* This assumes that the elements of the list of one thread are all for the same clock. */ __clock_gettime (timer->clock, &now); while (1) { /* If the timer is due or overdue, remove it from the queue. If it's a periodic timer, re-compute its new time and requeue it. Either way, perform the timer expiry. */ if (timespec_compare (&now, &timer->expirytime) < 0) break; list_unlink_ip (first); if (__builtin_expect (timer->value.it_interval.tv_sec, 0) != 0 || timer->value.it_interval.tv_nsec != 0) { timer->overrun_count = 0; timespec_add (&timer->expirytime, &timer->expirytime, &timer->value.it_interval); while (timespec_compare (&timer->expirytime, &now) < 0) { timespec_add (&timer->expirytime, &timer->expirytime, &timer->value.it_interval); if (timer->overrun_count < DELAYTIMER_MAX) ++timer->overrun_count; } __timer_thread_queue_timer (self, timer); } thread_expire_timer (self, timer); first = list_first (&self->timer_queue); if (first == list_null (&self->timer_queue)) break; timer = timer_links2ptr (first); } } /* If the queue is not empty, wait until the expiry time of the first node. Otherwise wait indefinitely. Insertions at the head of the queue must wake up the thread by broadcasting this condition variable. */ if (timer != NULL) pthread_cond_timedwait (&self->cond, &__timer_mutex, &timer->expirytime); else pthread_cond_wait (&self->cond, &__timer_mutex); } /* This macro will never be executed since the while loop loops forever - but we have to add it for proper nesting. */ pthread_cleanup_pop (1); }
int clock_gettime(clockid_t clk_id, struct timespec *tp) { return __clock_gettime(clk_id, tp); }