8
8
#include <ksched.h>
9
9
#include <zephyr/wait_q.h>
10
10
#include <zephyr/posix/pthread.h>
11
+ #include <zephyr/sys/bitarray.h>
11
12
12
13
#include "posix_internal.h"
13
14
14
15
extern struct k_spinlock z_pthread_spinlock ;
15
16
16
17
int64_t timespec_to_timeoutms (const struct timespec * abstime );
17
18
18
- static int cond_wait (pthread_cond_t * cv , pthread_mutex_t * mu ,
19
- k_timeout_t timeout )
19
+ static struct posix_cond posix_cond_pool [CONFIG_MAX_PTHREAD_COND_COUNT ];
20
+ SYS_BITARRAY_DEFINE_STATIC (posix_cond_bitarray , CONFIG_MAX_PTHREAD_COND_COUNT );
21
+
22
+ /*
23
+ * We reserve the MSB to mark a pthread_cond_t as initialized (from the
24
+ * perspective of the application). With a linear space, this means that
25
+ * the theoretical pthread_cond_t range is [0,2147483647].
26
+ */
27
+ BUILD_ASSERT (CONFIG_MAX_PTHREAD_COND_COUNT < PTHREAD_OBJ_MASK_INIT ,
28
+ "CONFIG_MAX_PTHREAD_COND_COUNT is too high" );
29
+
30
+ static inline size_t posix_cond_to_offset (struct posix_cond * cv )
31
+ {
32
+ return cv - posix_cond_pool ;
33
+ }
34
+
35
+ static inline size_t to_posix_cond_idx (pthread_cond_t cond )
36
+ {
37
+ return mark_pthread_obj_uninitialized (cond );
38
+ }
39
+
40
+ struct posix_cond * get_posix_cond (pthread_cond_t cond )
41
+ {
42
+ int actually_initialized ;
43
+ size_t bit = to_posix_cond_idx (cond );
44
+
45
+ /* if the provided cond does not claim to be initialized, its invalid */
46
+ if (!is_pthread_obj_initialized (cond )) {
47
+ return NULL ;
48
+ }
49
+
50
+ /* Mask off the MSB to get the actual bit index */
51
+ if (sys_bitarray_test_bit (& posix_cond_bitarray , bit , & actually_initialized ) < 0 ) {
52
+ return NULL ;
53
+ }
54
+
55
+ if (actually_initialized == 0 ) {
56
+ /* The cond claims to be initialized but is actually not */
57
+ return NULL ;
58
+ }
59
+
60
+ return & posix_cond_pool [bit ];
61
+ }
62
+
63
+ struct posix_cond * to_posix_cond (pthread_cond_t * cvar )
64
+ {
65
+ size_t bit ;
66
+ struct posix_cond * cv ;
67
+
68
+ if (* cvar != PTHREAD_COND_INITIALIZER ) {
69
+ return get_posix_cond (* cvar );
70
+ }
71
+
72
+ /* Try and automatically associate a posix_cond */
73
+ if (sys_bitarray_alloc (& posix_cond_bitarray , 1 , & bit ) < 0 ) {
74
+ /* No conds left to allocate */
75
+ return NULL ;
76
+ }
77
+
78
+ /* Record the associated posix_cond in mu and mark as initialized */
79
+ * cvar = mark_pthread_obj_initialized (bit );
80
+ cv = & posix_cond_pool [bit ];
81
+
82
+ /* Initialize the condition variable here */
83
+ z_waitq_init (& cv -> wait_q );
84
+
85
+ return cv ;
86
+ }
87
+
88
+ static int cond_wait (pthread_cond_t * cond , pthread_mutex_t * mu , k_timeout_t timeout )
20
89
{
21
90
int ret ;
22
91
k_spinlock_key_t key ;
92
+ struct posix_cond * cv ;
23
93
struct posix_mutex * m ;
24
94
25
95
key = k_spin_lock (& z_pthread_spinlock );
@@ -29,6 +99,12 @@ static int cond_wait(pthread_cond_t *cv, pthread_mutex_t *mu,
29
99
return EINVAL ;
30
100
}
31
101
102
+ cv = to_posix_cond (cond );
103
+ if (cv == NULL ) {
104
+ k_spin_unlock (& z_pthread_spinlock , key );
105
+ return EINVAL ;
106
+ }
107
+
32
108
__ASSERT_NO_MSG (m -> lock_count == 1U );
33
109
m -> lock_count = 0U ;
34
110
m -> owner = NULL ;
@@ -48,14 +124,41 @@ static int cond_wait(pthread_cond_t *cv, pthread_mutex_t *mu,
48
124
return ret == - EAGAIN ? ETIMEDOUT : ret ;
49
125
}
50
126
51
- int pthread_cond_signal (pthread_cond_t * cv )
127
+ int pthread_cond_signal (pthread_cond_t * cvar )
52
128
{
129
+ k_spinlock_key_t key ;
130
+ struct posix_cond * cv ;
131
+
132
+ key = k_spin_lock (& z_pthread_spinlock );
133
+
134
+ cv = to_posix_cond (cvar );
135
+ if (cv == NULL ) {
136
+ k_spin_unlock (& z_pthread_spinlock , key );
137
+ return EINVAL ;
138
+ }
139
+
140
+ k_spin_unlock (& z_pthread_spinlock , key );
141
+
53
142
z_sched_wake (& cv -> wait_q , 0 , NULL );
143
+
54
144
return 0 ;
55
145
}
56
146
57
- int pthread_cond_broadcast (pthread_cond_t * cv )
147
+ int pthread_cond_broadcast (pthread_cond_t * cvar )
58
148
{
149
+ k_spinlock_key_t key ;
150
+ struct posix_cond * cv ;
151
+
152
+ key = k_spin_lock (& z_pthread_spinlock );
153
+
154
+ cv = to_posix_cond (cvar );
155
+ if (cv == NULL ) {
156
+ k_spin_unlock (& z_pthread_spinlock , key );
157
+ return EINVAL ;
158
+ }
159
+
160
+ k_spin_unlock (& z_pthread_spinlock , key );
161
+
59
162
z_sched_wake_all (& cv -> wait_q , 0 , NULL );
60
163
return 0 ;
61
164
}
@@ -65,9 +168,53 @@ int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mut)
65
168
return cond_wait (cv , mut , K_FOREVER );
66
169
}
67
170
68
- int pthread_cond_timedwait (pthread_cond_t * cv , pthread_mutex_t * mut ,
69
- const struct timespec * abstime )
171
+ int pthread_cond_timedwait (pthread_cond_t * cv , pthread_mutex_t * mut , const struct timespec * abstime )
70
172
{
71
173
int32_t timeout = (int32_t )timespec_to_timeoutms (abstime );
72
174
return cond_wait (cv , mut , K_MSEC (timeout ));
73
175
}
176
+
177
+ int pthread_cond_init (pthread_cond_t * cvar , const pthread_condattr_t * att )
178
+ {
179
+ k_spinlock_key_t key ;
180
+ struct posix_cond * cv ;
181
+
182
+ ARG_UNUSED (att );
183
+ * cvar = PTHREAD_COND_INITIALIZER ;
184
+
185
+ key = k_spin_lock (& z_pthread_spinlock );
186
+
187
+ cv = to_posix_cond (cvar );
188
+ if (cv == NULL ) {
189
+ k_spin_unlock (& z_pthread_spinlock , key );
190
+ return EINVAL ;
191
+ }
192
+
193
+ k_spin_unlock (& z_pthread_spinlock , key );
194
+
195
+ return 0 ;
196
+ }
197
+
198
+ int pthread_cond_destroy (pthread_cond_t * cvar )
199
+ {
200
+ __unused int rc ;
201
+ k_spinlock_key_t key ;
202
+ struct posix_cond * cv ;
203
+ pthread_cond_t c = * cvar ;
204
+ size_t bit = to_posix_cond_idx (c );
205
+
206
+ key = k_spin_lock (& z_pthread_spinlock );
207
+
208
+ cv = get_posix_cond (c );
209
+ if (cv == NULL ) {
210
+ k_spin_unlock (& z_pthread_spinlock , key );
211
+ return EINVAL ;
212
+ }
213
+
214
+ rc = sys_bitarray_free (& posix_cond_bitarray , 1 , bit );
215
+ __ASSERT (rc == 0 , "failed to free bit %zu" , bit );
216
+
217
+ k_spin_unlock (& z_pthread_spinlock , key );
218
+
219
+ return 0 ;
220
+ }
0 commit comments