@@ -143,6 +143,31 @@ static void zephyr_thread_wrapper(void *arg1, void *arg2, void *arg3)
143143 pthread_exit (NULL );
144144}
145145
146+ static bool pthread_attr_is_valid (const struct pthread_attr * attr )
147+ {
148+ /*
149+ * FIXME: Pthread attribute must be non-null and it provides stack
150+ * pointer and stack size. So even though POSIX 1003.1 spec accepts
151+ * attrib as NULL but zephyr needs it initialized with valid stack.
152+ */
153+ if (attr == NULL || attr -> initialized == 0U || attr -> stack == NULL ||
154+ attr -> stacksize == 0 ) {
155+ return false;
156+ }
157+
158+ /* require a valid scheduler policy */
159+ if (!valid_posix_policy (attr -> schedpolicy )) {
160+ return false;
161+ }
162+
163+ /* require a valid detachstate */
164+ if (!(attr -> detachstate == PTHREAD_JOINABLE || attr -> detachstate == PTHREAD_DETACHED )) {
165+ return false;
166+ }
167+
168+ return true;
169+ }
170+
146171/**
147172 * @brief Create a new thread.
148173 *
@@ -154,7 +179,6 @@ static void zephyr_thread_wrapper(void *arg1, void *arg2, void *arg3)
154179int pthread_create (pthread_t * newthread , const pthread_attr_t * _attr ,
155180 void * (* threadroutine )(void * ), void * arg )
156181{
157- int rv ;
158182 int32_t prio ;
159183 k_spinlock_key_t key ;
160184 uint32_t pthread_num ;
@@ -163,22 +187,21 @@ int pthread_create(pthread_t *newthread, const pthread_attr_t *_attr,
163187 struct posix_thread * thread ;
164188 const struct pthread_attr * attr = (const struct pthread_attr * )_attr ;
165189
166- /*
167- * FIXME: Pthread attribute must be non-null and it provides stack
168- * pointer and stack size. So even though POSIX 1003.1 spec accepts
169- * attrib as NULL but zephyr needs it initialized with valid stack.
170- */
171- if ((attr == NULL ) || (attr -> initialized == 0U )
172- || (attr -> stack == NULL ) || (attr -> stacksize == 0 )) {
190+ if (!pthread_attr_is_valid (attr )) {
173191 return EINVAL ;
174192 }
175193
176194 key = k_spin_lock (& pthread_pool_lock );
177- for (pthread_num = 0 ;
178- pthread_num < CONFIG_MAX_PTHREAD_COUNT ; pthread_num ++ ) {
195+ for (pthread_num = 0 ; pthread_num < CONFIG_MAX_PTHREAD_COUNT ; pthread_num ++ ) {
179196 thread = & posix_thread_pool [pthread_num ];
180197 if (thread -> state == PTHREAD_TERMINATED ) {
181- thread -> state = PTHREAD_JOINABLE ;
198+ if (pthread_mutex_init (& thread -> state_lock , NULL ) == 0 ) {
199+ thread -> state = attr -> detachstate ;
200+ sys_slist_init (& thread -> key_list );
201+ } else {
202+ /* cannot allocate resources so break early and return EAGAIN */
203+ pthread_num = CONFIG_MAX_PTHREAD_COUNT ;
204+ }
182205 break ;
183206 }
184207 }
@@ -188,27 +211,14 @@ int pthread_create(pthread_t *newthread, const pthread_attr_t *_attr,
188211 return EAGAIN ;
189212 }
190213
191- rv = pthread_mutex_init (& thread -> state_lock , NULL );
192- if (rv != 0 ) {
193- key = k_spin_lock (& pthread_pool_lock );
194- thread -> state = PTHREAD_EXITED ;
195- k_spin_unlock (& pthread_pool_lock , key );
196- return rv ;
197- }
198-
199214 prio = posix_to_zephyr_priority (attr -> priority , attr -> schedpolicy );
200215
201216 cancel_key = k_spin_lock (& thread -> cancel_lock );
202217 thread -> cancel_state = (1 << _PTHREAD_CANCEL_POS ) & attr -> flags ;
203218 thread -> cancel_pending = 0 ;
204219 k_spin_unlock (& thread -> cancel_lock , cancel_key );
205220
206- pthread_mutex_lock (& thread -> state_lock );
207- thread -> state = attr -> detachstate ;
208- pthread_mutex_unlock (& thread -> state_lock );
209-
210221 pthread_cond_init (& thread -> state_cond , & cond_attr );
211- sys_slist_init (& thread -> key_list );
212222
213223 * newthread = pthread_num ;
214224 k_thread_create (& thread -> thread , attr -> stack , attr -> stacksize ,
@@ -217,7 +227,6 @@ int pthread_create(pthread_t *newthread, const pthread_attr_t *_attr,
217227 return 0 ;
218228}
219229
220-
221230/**
222231 * @brief Set cancelability State.
223232 *
@@ -377,6 +386,7 @@ int pthread_once(pthread_once_t *once, void (*init_func)(void))
377386 */
378387void pthread_exit (void * retval )
379388{
389+ bool destroy = false;
380390 k_spinlock_key_t cancel_key ;
381391 struct posix_thread * self = to_posix_thread (pthread_self ());
382392 pthread_key_obj * key_obj ;
@@ -397,6 +407,7 @@ void pthread_exit(void *retval)
397407 self -> retval = retval ;
398408 pthread_cond_broadcast (& self -> state_cond );
399409 } else {
410+ destroy = true;
400411 self -> state = PTHREAD_TERMINATED ;
401412 }
402413
@@ -411,11 +422,15 @@ void pthread_exit(void *retval)
411422 }
412423
413424 pthread_mutex_unlock (& self -> state_lock );
414- pthread_mutex_destroy (& self -> state_lock );
425+
426+ if (destroy ) {
427+ /* A detached thread must have its resources destroyed by pthread_exit() */
428+ pthread_mutex_destroy (& self -> state_lock );
429+ }
415430
416431 pthread_cond_destroy (& self -> state_cond );
417432
418- k_thread_abort (( k_tid_t ) self );
433+ k_thread_abort (& self -> thread );
419434}
420435
421436/**
@@ -425,6 +440,7 @@ void pthread_exit(void *retval)
425440 */
426441int pthread_join (pthread_t thread , void * * status )
427442{
443+ bool destroy = false;
428444 struct posix_thread * pthread = to_posix_thread (thread );
429445 int ret = 0 ;
430446
@@ -443,17 +459,19 @@ int pthread_join(pthread_t thread, void **status)
443459 }
444460
445461 if (pthread -> state == PTHREAD_EXITED ) {
462+ destroy = true;
463+ pthread -> state = PTHREAD_TERMINATED ;
446464 if (status != NULL ) {
447465 * status = pthread -> retval ;
448466 }
449- } else if (pthread -> state == PTHREAD_DETACHED ) {
450- ret = EINVAL ;
451467 } else {
452468 ret = ESRCH ;
453469 }
454470
455471 pthread_mutex_unlock (& pthread -> state_lock );
456- if (pthread -> state == PTHREAD_EXITED ) {
472+
473+ if (destroy ) {
474+ /* A joined thread must have its resources destroyed by pthread_join() */
457475 pthread_mutex_destroy (& pthread -> state_lock );
458476 }
459477
@@ -467,6 +485,7 @@ int pthread_join(pthread_t thread, void **status)
467485 */
468486int pthread_detach (pthread_t thread )
469487{
488+ bool join = false;
470489 struct posix_thread * pthread = to_posix_thread (thread );
471490 int ret = 0 ;
472491
@@ -485,10 +504,7 @@ int pthread_detach(pthread_t thread)
485504 pthread_cond_broadcast (& pthread -> state_cond );
486505 break ;
487506 case PTHREAD_EXITED :
488- pthread -> state = PTHREAD_TERMINATED ;
489- /* THREAD has already exited.
490- * Pthread remained to provide exit status.
491- */
507+ join = true;
492508 break ;
493509 case PTHREAD_TERMINATED :
494510 ret = ESRCH ;
@@ -499,6 +515,11 @@ int pthread_detach(pthread_t thread)
499515 }
500516
501517 pthread_mutex_unlock (& pthread -> state_lock );
518+
519+ if (join ) {
520+ pthread_join (thread , NULL );
521+ }
522+
502523 return ret ;
503524}
504525
@@ -718,7 +739,7 @@ static int posix_thread_pool_init(void)
718739
719740
720741 for (i = 0 ; i < CONFIG_MAX_PTHREAD_COUNT ; ++ i ) {
721- posix_thread_pool [i ].state = PTHREAD_EXITED ;
742+ posix_thread_pool [i ].state = PTHREAD_TERMINATED ;
722743 }
723744
724745 return 0 ;
0 commit comments