Changeset View
Changeset View
Standalone View
Standalone View
head/lib/libc/sys/__vdso_gettimeofday.c
Show All 28 Lines | |||||
#include <sys/elf.h> | #include <sys/elf.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#include <sys/vdso.h> | #include <sys/vdso.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <time.h> | #include <time.h> | ||||
#include <machine/atomic.h> | #include <machine/atomic.h> | ||||
#include "libc_private.h" | #include "libc_private.h" | ||||
static u_int | static int | ||||
tc_delta(const struct vdso_timehands *th) | tc_delta(const struct vdso_timehands *th, u_int *delta) | ||||
{ | { | ||||
int error; | |||||
u_int tc; | |||||
return ((__vdso_gettc(th) - th->th_offset_count) & | error = __vdso_gettc(th, &tc); | ||||
th->th_counter_mask); | if (error == 0) | ||||
*delta = (tc - th->th_offset_count) & th->th_counter_mask; | |||||
return (error); | |||||
} | } | ||||
/* | /* | ||||
* Calculate the absolute or boot-relative time from the | * Calculate the absolute or boot-relative time from the | ||||
* machine-specific fast timecounter and the published timehands | * machine-specific fast timecounter and the published timehands | ||||
* structure read from the shared page. | * structure read from the shared page. | ||||
* | * | ||||
* The lockless reading scheme is similar to the one used to read the | * The lockless reading scheme is similar to the one used to read the | ||||
* in-kernel timehands, see sys/kern/kern_tc.c:binuptime(). This code | * in-kernel timehands, see sys/kern/kern_tc.c:binuptime(). This code | ||||
* is based on the kernel implementation. | * is based on the kernel implementation. | ||||
*/ | */ | ||||
static int | static int | ||||
binuptime(struct bintime *bt, struct vdso_timekeep *tk, int abs) | binuptime(struct bintime *bt, struct vdso_timekeep *tk, int abs) | ||||
{ | { | ||||
struct vdso_timehands *th; | struct vdso_timehands *th; | ||||
uint32_t curr, gen; | uint32_t curr, gen; | ||||
u_int delta; | |||||
int error; | |||||
do { | do { | ||||
if (!tk->tk_enabled) | if (!tk->tk_enabled) | ||||
return (ENOSYS); | return (ENOSYS); | ||||
curr = atomic_load_acq_32(&tk->tk_current); | curr = atomic_load_acq_32(&tk->tk_current); | ||||
th = &tk->tk_th[curr]; | th = &tk->tk_th[curr]; | ||||
if (th->th_algo != VDSO_TH_ALGO_1) | |||||
return (ENOSYS); | |||||
gen = atomic_load_acq_32(&th->th_gen); | gen = atomic_load_acq_32(&th->th_gen); | ||||
*bt = th->th_offset; | *bt = th->th_offset; | ||||
bintime_addx(bt, th->th_scale * tc_delta(th)); | error = tc_delta(th, &delta); | ||||
if (error == EAGAIN) | |||||
continue; | |||||
if (error != 0) | |||||
return (error); | |||||
bintime_addx(bt, th->th_scale * delta); | |||||
if (abs) | if (abs) | ||||
bintime_add(bt, &th->th_boottime); | bintime_add(bt, &th->th_boottime); | ||||
/* | /* | ||||
* Ensure that the load of th_offset is completed | * Ensure that the load of th_offset is completed | ||||
* before the load of th_gen. | * before the load of th_gen. | ||||
*/ | */ | ||||
atomic_thread_fence_acq(); | atomic_thread_fence_acq(); | ||||
▲ Show 20 Lines • Show All 69 Lines • Show Last 20 Lines |