1/*
2 This file is part of Mtproto-proxy Library.
3
4 Mtproto-proxy Library is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 Mtproto-proxy Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
16
17 Copyright 2014 Telegram Messenger Inc
18 2014 Anton Maydell
19*/
20#include <assert.h>
21#include <sys/time.h>
22#include <time.h>
23/* unistd.h defines _POSIX_TIMERS */
24#include <unistd.h>
25
26#include "precise-time.h"
27
28__thread int now;
29__thread double precise_now;
30__thread long long precise_now_rdtsc;
31long long precise_time;
32long long precise_time_rdtsc;
33
34double get_utime_monotonic (void) __attribute__ ((weak));
35double get_utime_monotonic (void) {
36 struct timespec T;
37#if _POSIX_TIMERS
38 assert (clock_gettime (CLOCK_MONOTONIC, &T) >= 0);
39 precise_now_rdtsc = rdtsc ();
40 return precise_now = T.tv_sec + (double) T.tv_nsec * 1e-9;
41#else
42#error "No high-precision clock"
43 return precise_now = time ();
44#endif
45}
46
47double get_double_time (void) {
48 static double last_double_time = -1;
49 static long long next_rdtsc;
50 long long cur_rdtsc = rdtsc ();
51 if (cur_rdtsc > next_rdtsc) {
52 struct timeval tv;
53 gettimeofday (&tv, NULL);
54 next_rdtsc = cur_rdtsc + 1000000;
55 return (last_double_time = tv.tv_sec + 1e-6 * tv.tv_usec);
56 } else {
57 return last_double_time;
58 }
59}
60
61double get_utime (int clock_id) {
62 struct timespec T;
63#if _POSIX_TIMERS
64 assert (clock_gettime (clock_id, &T) >= 0);
65 double res = T.tv_sec + (double) T.tv_nsec * 1e-9;
66#else
67#error "No high-precision clock"
68 double res = time ();
69#endif
70 if (clock_id == CLOCK_REALTIME) {
71 precise_time = (long long) (res * (1LL << 32));
72 precise_time_rdtsc = rdtsc ();
73 }
74 return res;
75}
76
77long long get_precise_time (unsigned precision) {
78 unsigned long long diff = rdtsc() - precise_time_rdtsc;
79 if (diff > precision) {
80 get_utime (CLOCK_REALTIME);
81 }
82 return precise_time;
83}
84