static int hp_timing_getres (struct timespec *res) { if (__glibc_unlikely (nsec == 0)) { hp_timing_t freq; /* This can only happen if we haven't initialized the `nsec' variable yet. Do this now. We don't have to protect this code against multiple execution since all of them should lead to the same result. */ freq = __get_clockfreq (); if (__glibc_unlikely (freq == 0)) /* Something went wrong. */ return -1; nsec = MAX (UINT64_C (1000000000) / freq, 1); } /* Fill in the values. The seconds are always zero (unless we have a 1Hz machine). */ res->tv_sec = 0; res->tv_nsec = nsec; return 0; }
static int hp_timing_settime (clockid_t clock_id, const struct timespec *tp) { hp_timing_t tsc; hp_timing_t usertime; /* First thing is to get the current time. */ HP_TIMING_NOW (tsc); if (__builtin_expect (freq == 0, 0)) { /* This can only happen if we haven't initialized the `freq' variable yet. Do this now. We don't have to protect this code against multiple execution since all of them should lead to the same result. */ freq = __get_clockfreq (); if (__builtin_expect (freq == 0, 0)) /* Something went wrong. */ return -1; } /* Convert the user-provided time into CPU ticks. */ usertime = tp->tv_sec * freq + (tp->tv_nsec * freq) / 1000000000ull; /* Determine the offset and use it as the new base value. */ if (clock_id == CLOCK_PROCESS_CPUTIME_ID || __pthread_clock_settime == NULL) GL(dl_cpuclock_offset) = tsc - usertime; else __pthread_clock_settime (clock_id, tsc - usertime); return 0; }
static int hp_timing_gettime (clockid_t clock_id, struct timespec *tp) { hp_timing_t tsc; if (__builtin_expect (freq == 0, 0)) { /* This can only happen if we haven't initialized the `freq' variable yet. Do this now. We don't have to protect this code against multiple execution since all of them should lead to the same result. */ freq = __get_clockfreq (); if (__builtin_expect (freq == 0, 0)) /* Something went wrong. */ return -1; } if (clock_id != CLOCK_PROCESS_CPUTIME_ID && __pthread_clock_gettime != NULL) return __pthread_clock_gettime (clock_id, freq, tp); /* Get the current counter. */ HP_TIMING_NOW (tsc); /* Compute the offset since the start time of the process. */ tsc -= GL(dl_cpuclock_offset); /* Compute the seconds. */ tp->tv_sec = tsc / freq; /* And the nanoseconds. This computation should be stable until we get machines with about 16GHz frequency. */ tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq; return 0; }
static int clock_test (clockid_t cl) { struct timespec old_ts; struct timespec ts; struct timespec waitit; int result = 0; hp_timing_t freq; int i; memset (&ts, '\0', sizeof ts); waitit.tv_sec = 0; waitit.tv_nsec = 500000000; /* This can only happen if we haven't initialized the `freq' variable yet. Do this now. We don't have to protect this code against multiple execution since all of them should lead to the same result. */ freq = __get_clockfreq (); /* Get and print resolution of the clock. */ printf ("clockfrequency: %d\n", freq); if (clock_getres (cl, &ts) == 0) { if (ts.tv_nsec < 0 || ts.tv_nsec >= 1000000000) { printf ("clock %d: nanosecond value of resolution (%ld) wrong\n", cl, ts.tv_nsec); result = 1; } else printf ("clock %d: resolution = %ld.%09ld secs\n", cl, ts.tv_sec, ts.tv_nsec); } else { printf ("clock %d: cannot get resolution\n", cl); result = 1; } memset (&ts, '\0', sizeof ts); memset (&old_ts, '\0', sizeof old_ts); /* Next get the current time value a few times. */ for (i = 0; i < 10; ++i) { if (clock_gettime (cl, &ts) == 0) { if (ts.tv_nsec < 0 || ts.tv_nsec >= 1000000000) { printf ("clock %d: nanosecond value of time wrong (try %d)\n", cl, i); result = 1; } else { printf ("clock %d: time = %ld.%09ld secs\n", cl, ts.tv_sec, ts.tv_nsec); if (memcmp (&ts, &old_ts, sizeof ts) == 0) { printf ("clock %d: time hasn't changed (try %d)\n", cl, i); result = 1; old_ts = ts; } } } else { printf ("clock %d: cannot get time (try %d)\n", cl, i); result = 1; } /* Wait a bit before the next iteration. */ nanosleep (&waitit, NULL); } return result; }
uint64_t __get_timebase_freq (void) { return (uint64_t) __get_clockfreq (); }
/* Set CLOCK to value TP. */ int clock_settime (clockid_t clock_id, const struct timespec *tp) { struct timeval tv; int retval; /* Make sure the time cvalue is OK. */ if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000) { __set_errno (EINVAL); return -1; } switch (clock_id) { case CLOCK_REALTIME: TIMESPEC_TO_TIMEVAL (&tv, tp); retval = settimeofday (&tv, NULL); break; #if HP_TIMING_AVAIL case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID: { hp_timing_t tsc; hp_timing_t usertime; /* First thing is to get the current time. */ HP_TIMING_NOW (tsc); if (__builtin_expect (freq == 0, 0)) { /* This can only happen if we haven't initialized the `freq' variable yet. Do this now. We don't have to protect this code against multiple execution since all of them should lead to the same result. */ freq = __get_clockfreq (); if (__builtin_expect (freq == 0, 0)) { /* Something went wrong. */ retval = -1; break; } } /* Convert the user-provided time into CPU ticks. */ usertime = tp->tv_sec * freq + (tp->tv_nsec * freq) / 1000000000ull; /* Determine the offset and use it as the new base value. */ if (clock_id != CLOCK_THREAD_CPUTIME_ID || __pthread_clock_settime == NULL) ;// GL(dl_cpuclock_offset) = tsc - usertime; else __pthread_clock_settime (tsc - usertime); retval = 0; } break; #endif default: __set_errno (EINVAL); retval = -1; break; } return retval; }
/* Get current value of CLOCK and store it in TP. */ int clock_gettime (clockid_t clock_id, struct timespec *tp) { struct timeval tv; int retval = -1; switch (clock_id) { case CLOCK_REALTIME: retval = gettimeofday (&tv, NULL); if (retval == 0) /* Convert into `timespec'. */ TIMEVAL_TO_TIMESPEC (&tv, tp); break; #if HP_TIMING_AVAIL case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID: { hp_timing_t tsc; if (__builtin_expect (freq == 0, 0)) { /* This can only happen if we haven't initialized the `freq' variable yet. Do this now. We don't have to protect this code against multiple execution since all of them should lead to the same result. */ freq = __get_clockfreq (); if (__builtin_expect (freq == 0, 0)) /* Something went wrong. */ break; } if (clock_id == CLOCK_THREAD_CPUTIME_ID && __pthread_clock_gettime != NULL) { retval = __pthread_clock_gettime (freq, tp); break; } /* Get the current counter. */ HP_TIMING_NOW (tsc); /* Compute the offset since the start time of the process. */ tsc -= _dl_cpuclock_offset; /* Compute the seconds. */ tp->tv_sec = tsc / freq; /* And the nanoseconds. This computation should be stable until we get machines with about 16GHz frequency. */ tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq; retval = 0; } break; #endif default: __set_errno (EINVAL); break; } return retval; }
/* Get resolution of clock. */ int clock_getres (clockid_t clock_id, struct timespec *res) { int retval = -1; switch (clock_id) { case CLOCK_REALTIME: { long int clk_tck = sysconf (_SC_CLK_TCK); if (__builtin_expect (clk_tck != -1, 1)) { /* This implementation assumes that the realtime clock has a resolution higher than 1 second. This is the case for any reasonable implementation. */ res->tv_sec = 0; res->tv_nsec = 1000000000 / clk_tck; retval = 0; } } break; #if HP_TIMING_AVAIL case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID: { if (__builtin_expect (nsec == 0, 0)) { hp_timing_t freq; /* This can only happen if we haven't initialized the `freq' variable yet. Do this now. We don't have to protect this code against multiple execution since all of them should lead to the same result. */ freq = __get_clockfreq (); if (__builtin_expect (freq == 0, 0)) /* Something went wrong. */ break; nsec = MAX (UINT64_C (1000000000) / freq, 1); } /* File in the values. The seconds are always zero (unless we have a 1Hz machine). */ res->tv_sec = 0; res->tv_nsec = nsec; retval = 0; } break; #endif default: __set_errno (EINVAL); break; } return retval; }
/* Get current value of CLOCK and store it in TP. */ int clock_gettime (clockid_t clock_id, struct timespec *tp) { int retval = -1; switch (clock_id) { #define HANDLE_REALTIME \ do { \ struct timeval tv; \ retval = gettimeofday (&tv, NULL); \ if (retval == 0) \ /* Convert into `timespec'. */ \ TIMEVAL_TO_TIMESPEC (&tv, tp); \ } while (0) #ifdef SYSDEP_GETTIME SYSDEP_GETTIME; #endif #ifndef HANDLED_REALTIME case CLOCK_REALTIME: HANDLE_REALTIME; break; #endif default: #if HP_TIMING_AVAIL if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1)) != CLOCK_THREAD_CPUTIME_ID) #endif { __set_errno (EINVAL); break; } #if HP_TIMING_AVAIL /* FALLTHROUGH. */ case CLOCK_PROCESS_CPUTIME_ID: { hp_timing_t tsc; if (__builtin_expect (freq == 0, 0)) { /* This can only happen if we haven't initialized the `freq' variable yet. Do this now. We don't have to protect this code against multiple execution since all of them should lead to the same result. */ freq = __get_clockfreq (); if (__builtin_expect (freq == 0, 0)) /* Something went wrong. */ break; } if (clock_id != CLOCK_PROCESS_CPUTIME_ID && __pthread_clock_gettime != NULL) { retval = __pthread_clock_gettime (clock_id, freq, tp); break; } /* Get the current counter. */ HP_TIMING_NOW (tsc); /* Compute the offset since the start time of the process. */ tsc -= GL(dl_cpuclock_offset); /* Compute the seconds. */ tp->tv_sec = tsc / freq; /* And the nanoseconds. This computation should be stable until we get machines with about 16GHz frequency. */ tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq; retval = 0; } break; #endif } return retval; }