| 29 | int* CTimer::_timers = NULL; |
| 30 | |
| 31 | int CTimer::createForThread(int tid) { |
| 32 | if (tid >= _max_timers) { |
| 33 | Log::warn("tid[%d] > pid_max[%d]. Restart profiler after changing pid_max", tid, _max_timers); |
| 34 | return -1; |
| 35 | } |
| 36 | |
| 37 | struct sigevent sev; |
| 38 | sev.sigev_value.sival_ptr = NULL; |
| 39 | sev.sigev_signo = _signal; |
| 40 | sev.sigev_notify = SIGEV_THREAD_ID; |
| 41 | (&sev.sigev_notify)[1] = tid; |
| 42 | |
| 43 | // Use raw syscalls, since libc wrapper allows only predefined clocks |
| 44 | clockid_t clock = thread_cpu_clock(tid); |
| 45 | int timer; |
| 46 | if (syscall(__NR_timer_create, clock, &sev, &timer) < 0) { |
| 47 | return -1; |
| 48 | } |
| 49 | |
| 50 | // Kernel timer ID may start with zero, but we use zero as an empty slot |
| 51 | if (!__sync_bool_compare_and_swap(&_timers[tid], 0, timer + 1)) { |
| 52 | // Lost race |
| 53 | syscall(__NR_timer_delete, timer); |
| 54 | return -1; |
| 55 | } |
| 56 | |
| 57 | struct itimerspec ts; |
| 58 | ts.it_interval.tv_sec = (time_t)(_interval / 1000000000); |
| 59 | ts.it_interval.tv_nsec = _interval % 1000000000; |
| 60 | ts.it_value = ts.it_interval; |
| 61 | syscall(__NR_timer_settime, timer, 0, &ts, NULL); |
| 62 | return 0; |
| 63 | } |
| 64 | |
| 65 | void CTimer::destroyForThread(int tid) { |
| 66 | if (tid >= _max_timers) { |
no test coverage detected