6
6
7
7
#include <kernel.h>
8
8
#include <stdio.h>
9
+ #include <stdlib.h>
9
10
#include <sys/atomic.h>
10
11
#include <ksched.h>
11
12
#include <wait_q.h>
12
13
#include <posix/pthread.h>
13
14
#include <sys/slist.h>
14
15
16
+ #ifdef CONFIG_PTHREAD_DYNAMIC_STACK_DEFAULT_SIZE
17
+ #define DYNAMIC_STACK_SIZE CONFIG_PTHREAD_DYNAMIC_STACK_DEFAULT_SIZE
18
+ #else
19
+ #define DYNAMIC_STACK_SIZE 0
20
+ #endif
21
+
15
22
#define PTHREAD_INIT_FLAGS PTHREAD_CANCEL_ENABLE
16
23
#define PTHREAD_CANCELED ((void *) -1)
17
24
@@ -115,7 +122,10 @@ int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,
115
122
static void zephyr_thread_wrapper (void * arg1 , void * arg2 , void * arg3 )
116
123
{
117
124
void * (* fun_ptr )(void * ) = arg3 ;
118
-
125
+ struct _thread_stack_info * stack_info
126
+ = & k_current_get ()-> stack_info ;
127
+ stack_info -> delta = (size_t )
128
+ ((uint8_t * )stack_info -> start - (uint8_t * )arg2 );
119
129
fun_ptr (arg1 );
120
130
pthread_exit (NULL );
121
131
}
@@ -135,17 +145,43 @@ int pthread_create(pthread_t *newthread, const pthread_attr_t *attr,
135
145
uint32_t pthread_num ;
136
146
pthread_condattr_t cond_attr ;
137
147
struct posix_thread * thread ;
148
+ pthread_attr_t dynamic_attr ;
149
+ k_thread_stack_t * dynamic_stack = NULL ;
150
+ /* a non-const pthread_attr_t* that we can modify, if needed */
151
+ pthread_attr_t * mattr = (pthread_attr_t * )attr ;
138
152
139
- /*
140
- * FIXME: Pthread attribute must be non-null and it provides stack
141
- * pointer and stack size. So even though POSIX 1003.1 spec accepts
142
- * attrib as NULL but zephyr needs it initialized with valid stack.
143
- */
144
- if ((attr == NULL ) || (attr -> initialized == 0U )
145
- || (attr -> stack == NULL ) || (attr -> stacksize == 0 )) {
153
+ if (mattr != NULL && mattr -> initialized == 0 ) {
146
154
return EINVAL ;
147
155
}
148
156
157
+ if (mattr == NULL || mattr -> stack == NULL ) {
158
+ if (IS_ENABLED (CONFIG_PTHREAD_DYNAMIC_STACK )) {
159
+ /*
160
+ * We dynamically allocate space when either
161
+ * 1) attr == NULL -> use DYNAMIC_STACK_SIZE, or
162
+ * 2) attr != NULL && attr->stack == NULL
163
+ * -> allocate attr->stacksize
164
+ */
165
+ if (mattr == NULL ) {
166
+ (void ) pthread_attr_init (& dynamic_attr );
167
+ dynamic_attr .stacksize = DYNAMIC_STACK_SIZE ;
168
+ mattr = & dynamic_attr ;
169
+ }
170
+
171
+ dynamic_stack = k_aligned_alloc (ARCH_STACK_PTR_ALIGN ,
172
+ Z_KERNEL_STACK_SIZE_ADJUST (mattr -> stacksize ));
173
+ if (dynamic_stack == NULL ) {
174
+ return EAGAIN ;
175
+ }
176
+
177
+ __ASSERT_NO_MSG (dynamic_stack != NULL );
178
+ mattr -> stack = dynamic_stack ;
179
+ mattr -> flags |= K_STACK_ON_HEAP ;
180
+ } else {
181
+ return EINVAL ;
182
+ }
183
+ }
184
+
149
185
pthread_mutex_lock (& pthread_pool_lock );
150
186
for (pthread_num = 0 ;
151
187
pthread_num < CONFIG_MAX_PTHREAD_COUNT ; pthread_num ++ ) {
@@ -158,10 +194,14 @@ int pthread_create(pthread_t *newthread, const pthread_attr_t *attr,
158
194
pthread_mutex_unlock (& pthread_pool_lock );
159
195
160
196
if (pthread_num >= CONFIG_MAX_PTHREAD_COUNT ) {
197
+ if (IS_ENABLED (CONFIG_PTHREAD_DYNAMIC_STACK )
198
+ && dynamic_stack != NULL ) {
199
+ k_free (dynamic_stack );
200
+ }
161
201
return EAGAIN ;
162
202
}
163
203
164
- prio = posix_to_zephyr_priority (attr -> priority , attr -> schedpolicy );
204
+ prio = posix_to_zephyr_priority (mattr -> priority , mattr -> schedpolicy );
165
205
166
206
thread = & posix_thread_pool [pthread_num ];
167
207
/*
@@ -172,25 +212,25 @@ int pthread_create(pthread_t *newthread, const pthread_attr_t *attr,
172
212
(void )pthread_mutex_init (& thread -> cancel_lock , NULL );
173
213
174
214
pthread_mutex_lock (& thread -> cancel_lock );
175
- thread -> cancel_state = (1 << _PTHREAD_CANCEL_POS ) & attr -> flags ;
215
+ thread -> cancel_state = (1 << _PTHREAD_CANCEL_POS ) & mattr -> flags ;
176
216
thread -> cancel_pending = 0 ;
177
217
pthread_mutex_unlock (& thread -> cancel_lock );
178
218
179
219
pthread_mutex_lock (& thread -> state_lock );
180
- thread -> state = attr -> detachstate ;
220
+ thread -> state = mattr -> detachstate ;
181
221
pthread_mutex_unlock (& thread -> state_lock );
182
222
183
223
pthread_cond_init (& thread -> state_cond , & cond_attr );
184
224
sys_slist_init (& thread -> key_list );
185
225
186
- * newthread = (pthread_t ) k_thread_create (& thread -> thread , attr -> stack ,
187
- attr -> stacksize ,
226
+ * newthread = (pthread_t ) k_thread_create (& thread -> thread , mattr -> stack ,
227
+ mattr -> stacksize ,
188
228
(k_thread_entry_t )
189
229
zephyr_thread_wrapper ,
190
- (void * )arg , NULL ,
230
+ (void * )arg , dynamic_stack ,
191
231
threadroutine , prio ,
192
- (~K_ESSENTIAL & attr -> flags ),
193
- K_MSEC (attr -> delayedstart ));
232
+ (~K_ESSENTIAL & mattr -> flags ),
233
+ K_MSEC (mattr -> delayedstart ));
194
234
return 0 ;
195
235
}
196
236
@@ -347,6 +387,23 @@ int pthread_once(pthread_once_t *once, void (*init_func)(void))
347
387
return 0 ;
348
388
}
349
389
390
+ #ifdef CONFIG_PTHREAD_DYNAMIC_STACK
391
+ static void zephyr_pthread_stack_reclaim (struct k_thread * thread )
392
+ {
393
+ uint8_t * p = (uint8_t * )thread -> stack_info .start ;
394
+
395
+ p -= thread -> stack_info .delta ;
396
+ memset ((void * )thread -> stack_info .start , 0 ,
397
+ thread -> stack_info .size );
398
+ k_free (p );
399
+ }
400
+ #else
401
+ static inline void zephyr_pthread_stack_reclaim (struct k_thread * thread )
402
+ {
403
+ ARG_UNUSED (thread );
404
+ }
405
+ #endif
406
+
350
407
/**
351
408
* @brief Terminate calling thread.
352
409
*
@@ -385,6 +442,10 @@ void pthread_exit(void *retval)
385
442
}
386
443
}
387
444
445
+ if ((self -> thread .base .user_options & K_STACK_ON_HEAP ) != 0 ) {
446
+ self -> thread .fn_abort = zephyr_pthread_stack_reclaim ;
447
+ }
448
+
388
449
pthread_mutex_unlock (& self -> state_lock );
389
450
k_thread_abort ((k_tid_t )self );
390
451
}
@@ -534,6 +595,21 @@ int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
534
595
return 0 ;
535
596
}
536
597
598
+ /**
599
+ * @brief Set stack size attribute in thread attributes object.
600
+ *
601
+ * See IEEE 1003.1
602
+ */
603
+ int pthread_attr_setstacksize (pthread_attr_t * attr , size_t stacksize )
604
+ {
605
+ if ((attr == NULL ) || (attr -> initialized == 0U )) {
606
+ return EINVAL ;
607
+ }
608
+
609
+ attr -> stacksize = stacksize ;
610
+ return 0 ;
611
+ }
612
+
537
613
/**
538
614
* @brief Get stack size attribute in thread attributes object.
539
615
*
0 commit comments