| 211 | */ |
| 212 | |
| 213 | static __inline void |
| 214 | bintime_off(struct bintime *bt, u_int off) |
| 215 | { |
| 216 | struct timehands *th; |
| 217 | struct bintime *btp; |
| 218 | uint64_t scale, x; |
| 219 | u_int delta, gen, large_delta; |
| 220 | |
| 221 | do { |
| 222 | th = timehands; |
| 223 | gen = atomic_load_acq_int(&th->th_generation); |
| 224 | btp = (struct bintime *)((vm_offset_t)th + off); |
| 225 | *bt = *btp; |
| 226 | scale = th->th_scale; |
| 227 | delta = tc_delta(th); |
| 228 | large_delta = th->th_large_delta; |
| 229 | atomic_thread_fence_acq(); |
| 230 | } while (gen == 0 || gen != th->th_generation); |
| 231 | |
| 232 | if (__predict_false(delta >= large_delta)) { |
| 233 | /* Avoid overflow for scale * delta. */ |
| 234 | x = (scale >> 32) * delta; |
| 235 | bt->sec += x >> 32; |
| 236 | bintime_addx(bt, x << 32); |
| 237 | bintime_addx(bt, (scale & 0xffffffff) * delta); |
| 238 | } else { |
| 239 | bintime_addx(bt, scale * delta); |
| 240 | } |
| 241 | } |
| 242 | #define GETTHBINTIME(dst, member) \ |
| 243 | do { \ |
| 244 | bintime_off(dst, __offsetof(struct timehands, member)); \ |
nothing calls this directly
no test coverage detected