#include <sys/types.h>
#include <sys/atomic.h>
#include <sys/timetc.h>
#include <time.h>
static inline int
tc_delta(struct timekeep *tk, u_int *delta)
{
u_int tc;
if (_tc_get_timecount(tk, &tc))
return -1;
*delta = (tc - tk->tk_offset_count) & tk->tk_counter_mask;
return 0;
}
static int
binuptime(struct bintime *bt, struct timekeep *tk)
{
u_int gen, delta;
do {
gen = tk->tk_generation;
membar_consumer();
if (tc_delta(tk, &delta))
return -1;
TIMECOUNT_TO_BINTIME(delta, tk->tk_scale, bt);
bintimeadd(bt, &tk->tk_offset, bt);
membar_consumer();
} while (gen == 0 || gen != tk->tk_generation);
return 0;
}
static int
binruntime(struct bintime *bt, struct timekeep *tk)
{
u_int gen, delta;
do {
gen = tk->tk_generation;
membar_consumer();
if (tc_delta(tk, &delta))
return -1;
TIMECOUNT_TO_BINTIME(delta, tk->tk_scale, bt);
bintimeadd(bt, &tk->tk_offset, bt);
bintimesub(bt, &tk->tk_naptime, bt);
membar_consumer();
} while (gen == 0 || gen != tk->tk_generation);
return 0;
}
static int
bintime(struct bintime *bt, struct timekeep *tk)
{
u_int gen, delta;
do {
gen = tk->tk_generation;
membar_consumer();
if (tc_delta(tk, &delta))
return -1;
TIMECOUNT_TO_BINTIME(delta, tk->tk_scale, bt);
bintimeadd(bt, &tk->tk_offset, bt);
bintimeadd(bt, &tk->tk_boottime, bt);
membar_consumer();
} while (gen == 0 || gen != tk->tk_generation);
return 0;
}
int
_microtime(struct timeval *tvp, struct timekeep *tk)
{
struct bintime bt;
if (bintime(&bt, tk))
return -1;
BINTIME_TO_TIMEVAL(&bt, tvp);
return 0;
}
int
_nanotime(struct timespec *tsp, struct timekeep *tk)
{
struct bintime bt;
if (bintime(&bt, tk))
return -1;
BINTIME_TO_TIMESPEC(&bt, tsp);
return 0;
}
int
_nanoruntime(struct timespec *ts, struct timekeep *tk)
{
struct bintime bt;
if (binruntime(&bt, tk))
return -1;
BINTIME_TO_TIMESPEC(&bt, ts);
return 0;
}
int
_nanouptime(struct timespec *tsp, struct timekeep *tk)
{
struct bintime bt;
if (binuptime(&bt, tk))
return -1;
BINTIME_TO_TIMESPEC(&bt, tsp);
return 0;
}