typedef unsigned int __u32; __extension__ typedef __signed__ long long __s64; __extension__ typedef unsigned long long __u64; typedef __u32 u32; typedef __s64 s64; typedef __u64 u64; typedef long long __kernel_time64_t; typedef _Bool bool; typedef __s64 time64_t; struct __kernel_timespec { __kernel_time64_t tv_sec; long long tv_nsec; }; struct timespec64 { time64_t tv_sec; long tv_nsec; }; extern struct timespec64 ns_to_timespec64(const s64 nsec); int put_timespec64(const struct timespec64 *ts, struct __kernel_timespec *uts); /* [...snip...] */ extern int put_old_timespec32(const struct timespec64 *, void *); /* [...snip...] */ /* [...snip...] */ typedef s64 ktime_t; /* [...snip...] */ extern void ktime_get_real_ts64(struct timespec64 *tv); /* [...snip...] */ enum tk_offsets { TK_OFFS_REAL, TK_OFFS_BOOT, TK_OFFS_TAI, TK_OFFS_MAX, }; extern ktime_t ktime_get(void); extern ktime_t ktime_get_with_offset(enum tk_offsets offs); extern ktime_t ktime_get_coarse_with_offset(enum tk_offsets offs); extern ktime_t ktime_mono_to_any(ktime_t tmono, enum tk_offsets offs); extern ktime_t ktime_get_raw(void); extern u32 ktime_get_resolution_ns(void); static ktime_t ktime_get_real(void) { return ktime_get_with_offset(TK_OFFS_REAL); } /* [...snip...] */ struct socket { /* [...snip...] */ struct sock *sk; /* [...snip...] */ }; /* [...snip...] */ struct sock { /* [...snip...] */ ktime_t sk_stamp; /* [...snip...] */ }; /* [...snip...] */ static ktime_t sock_read_timestamp(struct sock *sk) { return *(const volatile typeof(sk->sk_stamp) *)&(sk->sk_stamp); } static void sock_write_timestamp(struct sock *sk, ktime_t kt) { *(volatile typeof(sk->sk_stamp) *)&(sk->sk_stamp) = kt; } /* [...snip...] */ int sock_gettstamp(struct socket *sock, void *userstamp, bool timeval, bool time32) { struct sock *sk = sock->sk; struct timespec64 ts; /* [...snip...] */ ts = ns_to_timespec64((sock_read_timestamp(sk))); if (ts.tv_sec == -1) return -2; if (ts.tv_sec == 0) { ktime_t kt = ktime_get_real(); sock_write_timestamp(sk, kt); ts = ns_to_timespec64((kt)); } if (timeval) ts.tv_nsec /= 1000; if (time32) return put_old_timespec32(&ts, userstamp); return put_timespec64(&ts, userstamp); }