oceanbase

Форк
0
/
easy_time.c 
219 строк · 5.1 Кб
1
#include "util/easy_time.h"
2
#include <sys/time.h>
3
#if defined(__x86_64__)
4
#include <cpuid.h>
5
#endif
6

7
/**
8
 * localtime删除tzset,一起调用一次tzset
9
 */
10
int easy_localtime(const time_t *t, struct tm *tp)
11
{
12
    static const unsigned short int mon_yday[2][13] = {
13
        /* Normal years.  */
14
        { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
15
        /* Leap years.  */
16
        { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
17
    };
18

19
#define SECS_PER_HOUR   (60 * 60)
20
#define SECS_PER_DAY    (SECS_PER_HOUR * 24)
21
#define ISLEAP(year)    ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
22
#define DIV(a, b)       ((a) / (b) - ((a) % (b) < 0))
23
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
24

25
    long int                days, rem, y;
26
    const unsigned short int *ip;
27

28
    days = *t / SECS_PER_DAY;
29
    rem = *t % SECS_PER_DAY;
30
    rem -= timezone;
31

32
    while (rem < 0) {
33
        rem += SECS_PER_DAY;
34
        --days;
35
    }
36

37
    while (rem >= SECS_PER_DAY) {
38
        rem -= SECS_PER_DAY;
39
        ++days;
40
    }
41

42
    tp->tm_hour = rem / SECS_PER_HOUR;
43
    rem %= SECS_PER_HOUR;
44
    tp->tm_min = rem / 60;
45
    tp->tm_sec = rem % 60;
46
    /* January 1, 1970 was a Thursday.  */
47
    tp->tm_wday = (4 + days) % 7;
48

49
    if (tp->tm_wday < 0)
50
        tp->tm_wday += 7;
51

52
    y = 1970;
53

54
    while (days < 0 || days >= (ISLEAP(y) ? 366 : 365)) {
55
        /* Guess a corrected year, assuming 365 days per year.  */
56
        long int                yg = y + days / 365 - (days % 365 < 0);
57

58
        /* Adjust DAYS and Y to match the guessed year.  */
59
        days -= ((yg - y) * 365
60
                 + LEAPS_THRU_END_OF(yg - 1)
61
                 - LEAPS_THRU_END_OF(y - 1));
62
        y = yg;
63
    }
64

65
    tp->tm_year = y - 1900;
66

67
    if (tp->tm_year != y - 1900) {
68
        return 0;
69
    }
70

71
    tp->tm_yday = days;
72
    ip = mon_yday[ISLEAP(y)];
73

74
    for (y = 11; days < (long int) ip[y]; --y)
75
        continue;
76

77
    days -= ip[y];
78
    tp->tm_mon = y;
79
    tp->tm_mday = days + 1;
80
    return 1;
81
}
82

83
void __attribute__((constructor)) easy_time_start_()
84
{
85
    tzset();
86
}
87

88
int64_t easy_time_now()
89
{
90
    struct timeval          tv;
91
    gettimeofday(&tv, 0);
92
    return __INT64_C(1000000) * tv.tv_sec + tv.tv_usec;
93
}
94

95
// 判断是否支持invariant tsc, 入口在CPUID.80000007H:EDX[8].
96
int is_support_invariant_tsc()
97
{
98
    int ret = 0;
99

100
#if defined(__x86_64__)
101
    unsigned int cpu_info[4];
102
    cpu_info[3] = 0;
103
    __get_cpuid(0x80000007, cpu_info, cpu_info + 1, cpu_info + 2, cpu_info + 3);
104
    if (cpu_info[3] & 0x100) {
105
        ret = 1;
106
    }
107
#else
108
    ret = 1;
109
#endif
110

111
    return ret;
112
}
113

114
typedef struct ObTscTimestampStruct {
115
    int64_t start_us;
116
    uint64_t tsc_count;
117
    uint64_t scale;
118
    int use_tsc;
119
    int is_inited;
120
} ObTscTimestamp;
121

122
__thread ObTscTimestamp tsc_obj;
123

124
#if defined(__x86_64__)
125
static __inline__ uint64_t rdtsc()
126
{
127
    uint64_t rax, rdx;
128
    __asm__ __volatile__("rdtsc" : "=a"(rax), "=d"(rdx) :: "%rcx");
129
    return (rdx << 32) + rax;
130
}
131

132
static __inline__ uint64_t rdtscp()
133
{
134
    uint64_t rax, rdx;
135
    __asm__ __volatile__("rdtscp" : "=a"(rax), "=d"(rdx) :: "%rcx");
136
    return (rdx << 32) + rax;
137
}
138
#else
139
static __inline__ uint64_t rdtscp()
140
{
141
    int64_t virtual_timer_value;
142
    asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
143
    return virtual_timer_value;
144
}
145
static __inline__ uint64_t rdtsc()
146
{
147
    return rdtscp();
148
}
149

150
#endif
151

152
#if defined(__x86_64__)
153
// 读取cpu频率
154
uint64_t get_cpufreq_khz()
155
{
156
    char line[256];
157
    FILE *stream = NULL;
158
    double freq_mhz = 0.0;
159
    uint64_t freq_khz = 0;
160

161
    stream = fopen("/proc/cpuinfo", "r");
162
    if (NULL == stream) {
163
    } else {
164
        while (fgets(line, sizeof(line), stream)) {
165
            if (sscanf(line, "cpu MHz\t: %lf", &freq_mhz) == 1) {
166
                freq_khz = (uint64_t)(freq_mhz * 1000UL);
167
                break;
168
            }
169
        }
170
        fclose(stream);
171
    }
172

173
    return freq_khz;
174
}
175
#else
176
uint64_t get_cpufreq_khz(void)
177
{
178
    uint64_t timer_frequency;
179
    asm volatile("mrs %0, cntfrq_el0":"=r"(timer_frequency));
180
    return timer_frequency / 1000;
181
}
182
#endif
183

184
// 初始化tsc时钟
185
void build_tsc_timestamp()
186
{
187
    if (!tsc_obj.is_inited) {
188
        if (is_support_invariant_tsc()) {
189
            int64_t cpu_freq_khz = get_cpufreq_khz();
190
            struct timeval tv;
191
            gettimeofday(&tv, NULL);
192
            tsc_obj.start_us = tv.tv_sec * 1000000 + tv.tv_usec;
193
            tsc_obj.tsc_count = rdtscp();
194
            if (tsc_obj.tsc_count > 0 && cpu_freq_khz > 0) {
195
                tsc_obj.scale = (1000 << 20) / cpu_freq_khz;
196
                tsc_obj.use_tsc = 1;
197
            }
198
        }
199
        // printf("build_tsc_timestamp: use_tsc=%d scale=%ld\n", tsc_obj.use_tsc, tsc_obj.scale);
200
        tsc_obj.is_inited = 1;
201
    }
202
}
203

204
#define LIKELY(x) __builtin_expect(!!(x),!!1)
205

206
int64_t fast_current_time()
207
{
208
    if (LIKELY(tsc_obj.use_tsc)) {
209
        uint64_t current_tsc = rdtsc();
210
        return ((current_tsc - tsc_obj.tsc_count) * tsc_obj.scale >> 20) + tsc_obj.start_us;
211
    } else {
212
        if (!tsc_obj.is_inited) {
213
            build_tsc_timestamp();
214
        }
215
        struct timeval tv;
216
        gettimeofday(&tv, NULL);
217
        return tv.tv_sec * 1000000 + tv.tv_usec;
218
    }
219
}
220

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.