1
1
/*
2
2
* Copyright (c) 2018 Intel Corporation
3
+ * Copyright (c) 2024, Meta
3
4
*
4
5
* SPDX-License-Identifier: Apache-2.0
5
6
*/
6
- #include <zephyr/kernel.h>
7
7
#include <errno.h>
8
- #include <string.h>
8
+
9
+ #include <zephyr/kernel.h>
10
+ #include <zephyr/logging/log.h>
9
11
#include <zephyr/posix/pthread.h>
10
- #include <zephyr/sys/printk.h>
11
12
#include <zephyr/posix/signal.h>
12
13
#include <zephyr/posix/time.h>
13
14
14
15
#define ACTIVE 1
15
16
#define NOT_ACTIVE 0
16
17
18
+ LOG_MODULE_REGISTER (posix_timer );
19
+
17
20
static void zephyr_timer_wrapper (struct k_timer * ztimer );
18
21
19
22
struct timer_obj {
20
23
struct k_timer ztimer ;
21
- struct sigevent sev ;
24
+ struct sigevent evp ;
22
25
struct k_sem sem_cond ;
23
26
pthread_t thread ;
24
27
struct timespec interval ; /* Reload value */
@@ -37,23 +40,53 @@ static void zephyr_timer_wrapper(struct k_timer *ztimer)
37
40
38
41
if (timer -> reload == 0U ) {
39
42
timer -> status = NOT_ACTIVE ;
43
+ LOG_DBG ("timer %p not active" , timer );
44
+ return ;
45
+ }
46
+
47
+ if (timer -> evp .sigev_notify == SIGEV_NONE ) {
48
+ LOG_DBG ("SIGEV_NONE" );
49
+ return ;
40
50
}
41
51
42
- (timer -> sev .sigev_notify_function )(timer -> sev .sigev_value );
52
+ if (timer -> evp .sigev_notify_function == NULL ) {
53
+ LOG_DBG ("NULL sigev_notify_function" );
54
+ return ;
55
+ }
56
+
57
+ LOG_DBG ("calling sigev_notify_function %p" , timer -> evp .sigev_notify_function );
58
+ (timer -> evp .sigev_notify_function )(timer -> evp .sigev_value );
43
59
}
44
60
45
61
static void * zephyr_thread_wrapper (void * arg )
46
62
{
63
+ int ret ;
47
64
struct timer_obj * timer = (struct timer_obj * )arg ;
48
65
66
+ ret = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS , NULL );
67
+ __ASSERT (ret == 0 , "pthread_setcanceltype() failed: %d" , ret );
68
+
69
+ if (timer -> evp .sigev_notify_attributes == NULL ) {
70
+ ret = pthread_detach (pthread_self ());
71
+ __ASSERT (ret == 0 , "pthread_detach() failed: %d" , ret );
72
+ }
73
+
49
74
while (1 ) {
50
75
if (timer -> reload == 0U ) {
51
76
timer -> status = NOT_ACTIVE ;
77
+ LOG_DBG ("timer %p not active" , timer );
52
78
}
53
79
54
- k_sem_take (& timer -> sem_cond , K_FOREVER );
80
+ ret = k_sem_take (& timer -> sem_cond , K_FOREVER );
81
+ __ASSERT (ret == 0 , "k_sem_take() failed: %d" , ret );
82
+
83
+ if (timer -> evp .sigev_notify_function == NULL ) {
84
+ LOG_DBG ("NULL sigev_notify_function" );
85
+ continue ;
86
+ }
55
87
56
- (timer -> sev .sigev_notify_function )(timer -> sev .sigev_value );
88
+ LOG_DBG ("calling sigev_notify_function %p" , timer -> evp .sigev_notify_function );
89
+ (timer -> evp .sigev_notify_function )(timer -> evp .sigev_value );
57
90
}
58
91
59
92
return NULL ;
@@ -77,52 +110,89 @@ static void zephyr_timer_interrupt(struct k_timer *ztimer)
77
110
*/
78
111
int timer_create (clockid_t clockid , struct sigevent * evp , timer_t * timerid )
79
112
{
113
+ int ret = 0 ;
114
+ int detachstate ;
80
115
struct timer_obj * timer ;
81
116
const k_timeout_t alloc_timeout = K_MSEC (CONFIG_TIMER_CREATE_WAIT );
82
117
83
- if (evp == NULL || (evp -> sigev_notify != SIGEV_NONE && evp -> sigev_notify != SIGEV_SIGNAL &&
84
- evp -> sigev_notify != SIGEV_THREAD )) {
118
+ if (evp == NULL || timerid == NULL ) {
85
119
errno = EINVAL ;
86
120
return -1 ;
87
121
}
88
122
89
- if (k_mem_slab_alloc (& posix_timer_slab , (void * * )& timer , alloc_timeout ) == 0 ) {
90
- (void )memset (timer , 0 , sizeof (struct timer_obj ));
91
- } else {
123
+ if (k_mem_slab_alloc (& posix_timer_slab , (void * * )& timer , alloc_timeout ) != 0 ) {
124
+ LOG_DBG ("k_mem_slab_alloc() failed: %d" , ret );
92
125
errno = ENOMEM ;
93
126
return -1 ;
94
127
}
95
128
96
- timer -> sev .sigev_notify_function = evp -> sigev_notify_function ;
97
- timer -> sev .sigev_value = evp -> sigev_value ;
98
- timer -> interval .tv_sec = 0 ;
99
- timer -> interval .tv_nsec = 0 ;
100
- timer -> reload = 0U ;
101
- timer -> status = NOT_ACTIVE ;
129
+ * timer = (struct timer_obj ){0 };
130
+ timer -> evp = * evp ;
131
+ evp = & timer -> evp ;
102
132
103
- if (evp -> sigev_notify == SIGEV_NONE ) {
133
+ switch (evp -> sigev_notify ) {
134
+ case SIGEV_NONE :
104
135
k_timer_init (& timer -> ztimer , NULL , NULL );
105
- } else if (evp -> sigev_notify == SIGEV_THREAD ) {
106
- int ret ;
136
+ break ;
137
+ case SIGEV_SIGNAL :
138
+ k_timer_init (& timer -> ztimer , zephyr_timer_wrapper , NULL );
139
+ break ;
140
+ case SIGEV_THREAD :
141
+ if (evp -> sigev_notify_attributes != NULL ) {
142
+ ret = pthread_attr_getdetachstate (evp -> sigev_notify_attributes ,
143
+ & detachstate );
144
+ if (ret != 0 ) {
145
+ LOG_DBG ("pthread_attr_getdetachstate() failed: %d" , ret );
146
+ errno = ret ;
147
+ ret = -1 ;
148
+ goto free_timer ;
149
+ }
150
+
151
+ if (detachstate != PTHREAD_CREATE_DETACHED ) {
152
+ ret = pthread_attr_setdetachstate (evp -> sigev_notify_attributes ,
153
+ PTHREAD_CREATE_DETACHED );
154
+ if (ret != 0 ) {
155
+ LOG_DBG ("pthread_attr_setdetachstate() failed: %d" , ret );
156
+ errno = ret ;
157
+ ret = -1 ;
158
+ goto free_timer ;
159
+ }
160
+ }
161
+ }
162
+
163
+ ret = k_sem_init (& timer -> sem_cond , 0 , 1 );
164
+ if (ret != 0 ) {
165
+ LOG_DBG ("k_sem_init() failed: %d" , ret );
166
+ errno = - ret ;
167
+ ret = -1 ;
168
+ goto free_timer ;
169
+ }
107
170
108
- timer -> sev .sigev_notify = SIGEV_THREAD ;
109
- k_sem_init (& timer -> sem_cond , 0 , 1 );
110
171
ret = pthread_create (& timer -> thread , evp -> sigev_notify_attributes ,
111
172
zephyr_thread_wrapper , timer );
112
173
if (ret != 0 ) {
113
- k_mem_slab_free (& posix_timer_slab , (void * ) & timer );
114
- return ret ;
174
+ LOG_DBG ("pthread_create() failed: %d" , ret );
175
+ errno = ret ;
176
+ ret = -1 ;
177
+ goto free_timer ;
115
178
}
116
179
117
- pthread_detach (timer -> thread );
118
180
k_timer_init (& timer -> ztimer , zephyr_timer_interrupt , NULL );
119
- } else {
120
- k_timer_init (& timer -> ztimer , zephyr_timer_wrapper , NULL );
181
+ break ;
182
+ default :
183
+ ret = -1 ;
184
+ errno = EINVAL ;
185
+ goto free_timer ;
121
186
}
122
187
123
188
* timerid = (timer_t )timer ;
189
+ goto out ;
124
190
125
- return 0 ;
191
+ free_timer :
192
+ k_mem_slab_free (& posix_timer_slab , (void * )& timer );
193
+
194
+ out :
195
+ return ret ;
126
196
}
127
197
128
198
/**
@@ -262,8 +332,8 @@ int timer_delete(timer_t timerid)
262
332
k_timer_stop (& timer -> ztimer );
263
333
}
264
334
265
- if (timer -> sev .sigev_notify == SIGEV_THREAD ) {
266
- pthread_cancel (timer -> thread );
335
+ if (timer -> evp .sigev_notify == SIGEV_THREAD ) {
336
+ ( void ) pthread_cancel (timer -> thread );
267
337
}
268
338
269
339
k_mem_slab_free (& posix_timer_slab , (void * )timer );
0 commit comments