• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #3798

31 Mar 2025 10:39AM UTC coverage: 9.424% (-20.9%) from 30.372%
#3798

push

travis-ci

happyguoxy
test:add test cases

21549 of 307601 branches covered (7.01%)

Branch coverage included in aggregate %.

36084 of 303967 relevant lines covered (11.87%)

58620.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

62.9
/source/os/src/osTimer.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#define ALLOW_FORBID_FUNC
17
#define _DEFAULT_SOURCE
18
#include "os.h"
19

20
#ifdef WINDOWS
21
#include <Mmsystem.h>
22
#include <Windows.h>
23
#include <stdint.h>
24
#include <stdio.h>
25

26
#pragma warning(disable : 4244)
27

28
typedef void (*win_timer_f)(int signo);
29

30
void WINAPI taosWinOnTimer(UINT wTimerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dwl, DWORD_PTR dw2) {
31
  win_timer_f callback = *((win_timer_f *)&dwUser);
32
  if (callback != NULL) {
33
    callback(0);
34
  }
35
}
36

37
static MMRESULT timerId;
38

39
#elif defined(_TD_DARWIN_64)
40

41
#include <sys/event.h>
42
#include <sys/syscall.h>
43
#include <unistd.h>
44

45
static void (*timer_callback)(int);
46
static int          timer_ms = 0;
47
static TdThread     timer_thread;
48
static int          timer_kq = -1;
49
static volatile int timer_stop = 0;
50

51
static void* timer_routine(void* arg) {
52
  (void)arg;
53
  setThreadName("timer");
54

55
  int             r = 0;
56
  struct timespec to = {0};
57
  to.tv_sec = timer_ms / 1000;
58
  to.tv_nsec = (timer_ms % 1000) * 1000000;
59
  while (!timer_stop) {
60
    struct kevent64_s kev[10] = {0};
61
    r = kevent64(timer_kq, NULL, 0, kev, sizeof(kev) / sizeof(kev[0]), 0, &to);
62
    if (r != 0) {
63
      fprintf(stderr, "==%s[%d]%s()==kevent64 failed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__);
64
      abort();
65
    }
66
    timer_callback(SIGALRM);  // just mock
67
  }
68

69
  return NULL;
70
}
71

72
void taos_block_sigalrm(void) {
73
  // we don't know if there's any specific API for SIGALRM to deliver to specific thread
74
  // this implementation relies on kqueue rather than SIGALRM
75
}
76

77
#else
78
#ifndef TD_ASTRA
79
#include <sys/syscall.h>
80
#endif
81
#include <unistd.h>
82

83
static void taosDeleteTimer(void *tharg) {
×
84
  timer_t *pTimer = tharg;
×
85
  TAOS_SKIP_ERROR(timer_delete(*pTimer));
×
86
}
×
87

88
static TdThread      timerThread;
89
static timer_t       timerId;
90
static volatile bool stopTimer = false;
91

92
#pragma GCC diagnostic push
93
#pragma GCC diagnostic ignored "-Wstringop-overflow"
94
static void *taosProcessAlarmSignal(void *tharg) {
20✔
95
  // Block the signal
96
  sigset_t sigset;
97
  (void)sigemptyset(&sigset);
20✔
98
  (void)sigaddset(&sigset, SIGALRM);
20✔
99
  (void)sigprocmask(SIG_BLOCK, &sigset, NULL);
20✔
100
  void (*callback)(int) = tharg;
20✔
101

102
  struct sigevent sevent = {{0}};
20✔
103

104
  setThreadName("tmr");
20✔
105

106
#ifdef _ALPINE
107
  sevent.sigev_notify = SIGEV_THREAD_ID;
108
  sevent.sigev_notify_thread_id = syscall(__NR_gettid);
109
#elif defined(TD_ASTRA) // TD_ASTRA_TODO
110
  sevent.sigev_notify = SIGEV_THREAD;
111
#else
112
  sevent.sigev_notify = SIGEV_THREAD_ID;
20✔
113
  sevent._sigev_un._tid = syscall(__NR_gettid);
20✔
114
#endif
115

116
  sevent.sigev_signo = SIGALRM;
20✔
117

118
  if (timer_create(CLOCK_REALTIME, &sevent, &timerId) == -1) {
20!
119
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
120
    return NULL;
×
121
  }
122

123
  taosThreadCleanupPush(taosDeleteTimer, &timerId);
20!
124

125
  do {
126
    struct itimerspec ts;
127
    ts.it_value.tv_sec = 0;
20✔
128
    ts.it_value.tv_nsec = 1000000 * MSECONDS_PER_TICK;
20✔
129
    ts.it_interval.tv_sec = 0;
20✔
130
    ts.it_interval.tv_nsec = 1000000 * MSECONDS_PER_TICK;
20✔
131

132
    if (-1 == timer_settime(timerId, 0, &ts, NULL)) {
20!
133
      terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
134
      break;
×
135
    }
136

137
    int     signo;
138
    int32_t code = 0;
20✔
139
    while (!stopTimer) {
161,949!
140
      code = sigwait(&sigset, &signo);
161,949✔
141
      if (code) {
161,929!
142
        terrno = TAOS_SYSTEM_ERROR(code);
×
143
        continue;
×
144
      }
145
      /* //printf("Signal handling: number %d ......\n", signo); */
146
      callback(0);
161,929✔
147
    }
148
  } while (0);
149

150
  taosThreadCleanupPop(1);
×
151

152
  return NULL;
×
153
}
154
#pragma GCC diagnostic pop
155
#endif
156

157
int taosInitTimer(void (*callback)(int), int ms) {
20✔
158
#ifdef WINDOWS
159
  DWORD_PTR param = *((int64_t *)&callback);
160

161
  timerId = timeSetEvent(ms, 1, (LPTIMECALLBACK)taosWinOnTimer, param, TIME_PERIODIC);
162
  if (timerId == 0) {
163
    return -1;
164
  }
165
  return 0;
166
#elif defined(_TD_DARWIN_64)
167
  int r = 0;
168
  timer_kq = -1;
169
  timer_stop = 0;
170
  timer_ms = ms;
171
  timer_callback = callback;
172

173
  timer_kq = kqueue();
174
  if (timer_kq == -1) {
175
    fprintf(stderr, "==%s[%d]%s()==failed to create timer kq\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__);
176
    // since no caller of this func checks the return value for the moment
177
    abort();
178
  }
179

180
  r = taosThreadCreate(&timer_thread, NULL, timer_routine, NULL);
181
  if (r) {
182
    fprintf(stderr, "==%s[%d]%s()==failed to create timer thread\n", taosDirEntryBaseName(__FILE__), __LINE__,
183
            __func__);
184
    // since no caller of this func checks the return value for the moment
185
    abort();
186
  }
187
  return 0;
188
#else
189
  stopTimer = false;
20✔
190
  TdThreadAttr tattr;
191
  (void)taosThreadAttrInit(&tattr);
20✔
192
  int code = taosThreadCreate(&timerThread, &tattr, taosProcessAlarmSignal, callback);
20✔
193
  (void)taosThreadAttrDestroy(&tattr);
20✔
194
  if (code != 0) {
20!
195
    // printf("failed to create timer thread");
196
    return TAOS_SYSTEM_ERROR(code);
×
197
  }
198

199
  return 0;
20✔
200
#endif
201
}
202

203
void taosUninitTimer() {
×
204
#ifdef WINDOWS
205
  timeKillEvent(timerId);
206
#elif defined(_TD_DARWIN_64)
207
  int r = 0;
208
  timer_stop = 1;
209
  r = taosThreadJoin(timer_thread, NULL);
210
  if (r) {
211
    fprintf(stderr, "==%s[%d]%s()==failed to join timer thread\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__);
212
    // since no caller of this func checks the return value for the moment
213
    abort();
214
  }
215
  close(timer_kq);
216
  timer_kq = -1;
217
#else
218
  stopTimer = true;
×
219

220
  // printf("join timer thread:0x%08" PRIx64, taosGetPthreadId(timerThread));
221
  (void)taosThreadJoin(timerThread, NULL);
×
222
#endif
223
}
×
224

225
int64_t taosGetMonotonicMs() {
162,799✔
226
#if 0  
227
  return getMonotonicUs() / 1000;
228
#else
229
  return taosGetTimestampMs();
162,799✔
230
#endif
231
}
232

233
const char *taosMonotonicInit() {
80✔
234
#if 0
235
  return monotonicInit();
236
#else
237
  return NULL;
80✔
238
#endif
239
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc