Line data Source code
1 : /* Copyright 2024 Wikimedia Foundation
2 : *
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 :
16 : #include "excimer_os_timer.h"
17 :
18 : #include <signal.h>
19 : #include <stdint.h>
20 : #include <stdio.h>
21 : #include <string.h>
22 : #include "php.h"
23 : #include <pthread.h>
24 :
25 12 : int excimer_os_timer_create(int event_type, intptr_t timer_id, excimer_os_timer_t* os_timer, excimer_os_timer_notify_function_t* notify_function) {
26 :
27 : struct sigevent ev;
28 :
29 12 : memset(&ev, 0, sizeof(ev));
30 12 : ev.sigev_notify = SIGEV_THREAD;
31 12 : ev.sigev_notify_function = notify_function;
32 12 : ev.sigev_value.sival_ptr = (void*)timer_id;
33 :
34 : clockid_t clock_id;
35 :
36 12 : if (event_type == EXCIMER_CPU) {
37 1 : if (pthread_getcpuclockid(pthread_self(), &clock_id) != 0) {
38 0 : php_error_docref(NULL, E_WARNING, "Unable to get thread clock ID: %s",
39 0 : strerror(errno));
40 0 : return FAILURE;
41 : }
42 : } else {
43 11 : clock_id = CLOCK_MONOTONIC;
44 : }
45 :
46 12 : if (timer_create(clock_id, &ev, &os_timer->os_timer_id) != 0) {
47 0 : php_error_docref(NULL, E_WARNING, "Unable to create timer: %s",
48 0 : strerror(errno));
49 0 : return FAILURE;
50 : }
51 :
52 12 : os_timer->id = timer_id;
53 :
54 12 : return SUCCESS;
55 : }
56 :
57 12 : int excimer_os_timer_start(excimer_os_timer_t* os_timer, struct timespec *period, struct timespec *initial) {
58 : struct itimerspec its;
59 12 : its.it_interval = *period;
60 12 : its.it_value = *initial;
61 :
62 12 : if (timer_settime(os_timer->os_timer_id, 0, &its, NULL) != 0) {
63 0 : php_error_docref(NULL, E_WARNING, "timer_settime(): %s", strerror(errno));
64 0 : return FAILURE;
65 : }
66 :
67 12 : return SUCCESS;
68 : }
69 :
70 12 : int excimer_os_timer_stop(excimer_os_timer_t* os_timer) {
71 : struct itimerspec its;
72 12 : struct timespec zero = {0, 0};
73 12 : its.it_interval = zero;
74 12 : its.it_value = zero;
75 :
76 12 : if (timer_settime(os_timer->os_timer_id, 0, &its, NULL) != 0) {
77 0 : php_error_docref(NULL, E_WARNING, "timer_settime(): %s", strerror(errno));
78 0 : return FAILURE;
79 : }
80 :
81 12 : return SUCCESS;
82 : }
83 :
84 12 : int excimer_os_timer_delete(excimer_os_timer_t *os_timer) {
85 12 : if (timer_delete(os_timer->os_timer_id) != 0) {
86 0 : php_error_docref(NULL, E_WARNING, "timer_delete(): %s", strerror(errno));
87 0 : return FAILURE;
88 : }
89 :
90 12 : return SUCCESS;
91 : }
92 :
93 77 : zend_long excimer_os_timer_get_overrun_count(excimer_os_timer_t* os_timer) {
94 77 : return timer_getoverrun(os_timer->os_timer_id);
95 : }
96 :
97 1 : void excimer_os_timer_get_time(excimer_os_timer_t *timer, struct timespec *remaining) {
98 : struct itimerspec its;
99 :
100 1 : timer_gettime(timer->os_timer_id, &its);
101 1 : remaining->tv_sec = its.it_value.tv_sec;
102 1 : remaining->tv_nsec = its.it_value.tv_nsec;
103 1 : }
|