Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2010-2014 Wind River Systems, Inc.
3 : : *
4 : : * SPDX-License-Identifier: Apache-2.0
5 : : */
6 : :
7 : : /**
8 : : * @file
9 : : * @brief Kernel thread support
10 : : *
11 : : * This module provides general purpose thread support.
12 : : */
13 : :
14 : : #include <zephyr/kernel.h>
15 : : #include <zephyr/spinlock.h>
16 : : #include <zephyr/sys/math_extras.h>
17 : : #include <zephyr/sys_clock.h>
18 : : #include <ksched.h>
19 : : #include <kthread.h>
20 : : #include <wait_q.h>
21 : : #include <zephyr/internal/syscall_handler.h>
22 : : #include <kernel_internal.h>
23 : : #include <kswap.h>
24 : : #include <zephyr/init.h>
25 : : #include <zephyr/tracing/tracing.h>
26 : : #include <string.h>
27 : : #include <stdbool.h>
28 : : #include <zephyr/sys/check.h>
29 : : #include <zephyr/random/random.h>
30 : : #include <zephyr/sys/atomic.h>
31 : : #include <zephyr/logging/log.h>
32 : : #include <zephyr/llext/symbol.h>
33 : : #include <zephyr/sys/iterable_sections.h>
34 : :
35 : : LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
36 : :
37 : : #ifdef CONFIG_OBJ_CORE_THREAD
38 : : static struct k_obj_type obj_type_thread;
39 : :
40 : : #ifdef CONFIG_OBJ_CORE_STATS_THREAD
41 : : static struct k_obj_core_stats_desc thread_stats_desc = {
42 : : .raw_size = sizeof(struct k_cycle_stats),
43 : : .query_size = sizeof(struct k_thread_runtime_stats),
44 : : .raw = z_thread_stats_raw,
45 : : .query = z_thread_stats_query,
46 : : .reset = z_thread_stats_reset,
47 : : .disable = z_thread_stats_disable,
48 : : .enable = z_thread_stats_enable,
49 : : };
50 : : #endif /* CONFIG_OBJ_CORE_STATS_THREAD */
51 : :
52 : : static int init_thread_obj_core_list(void)
53 : : {
54 : : /* Initialize mem_slab object type */
55 : :
56 : : #ifdef CONFIG_OBJ_CORE_THREAD
57 : : z_obj_type_init(&obj_type_thread, K_OBJ_TYPE_THREAD_ID,
58 : : offsetof(struct k_thread, obj_core));
59 : : #endif /* CONFIG_OBJ_CORE_THREAD */
60 : :
61 : : #ifdef CONFIG_OBJ_CORE_STATS_THREAD
62 : : k_obj_type_stats_init(&obj_type_thread, &thread_stats_desc);
63 : : #endif /* CONFIG_OBJ_CORE_STATS_THREAD */
64 : :
65 : : return 0;
66 : : }
67 : :
68 : : SYS_INIT(init_thread_obj_core_list, PRE_KERNEL_1,
69 : : CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
70 : : #endif /* CONFIG_OBJ_CORE_THREAD */
71 : :
72 : :
73 : : #define _FOREACH_STATIC_THREAD(thread_data) \
74 : : STRUCT_SECTION_FOREACH(_static_thread_data, thread_data)
75 : :
76 : 0 : bool k_is_in_isr(void)
77 : : {
78 : 0 : return arch_is_in_isr();
79 : : }
80 : : EXPORT_SYMBOL(k_is_in_isr);
81 : :
82 : : #ifdef CONFIG_THREAD_CUSTOM_DATA
83 : : void z_impl_k_thread_custom_data_set(void *value)
84 : : {
85 : : _current->custom_data = value;
86 : : }
87 : :
88 : : #ifdef CONFIG_USERSPACE
89 : : static inline void z_vrfy_k_thread_custom_data_set(void *data)
90 : : {
91 : : z_impl_k_thread_custom_data_set(data);
92 : : }
93 : : #include <zephyr/syscalls/k_thread_custom_data_set_mrsh.c>
94 : : #endif /* CONFIG_USERSPACE */
95 : :
96 : : void *z_impl_k_thread_custom_data_get(void)
97 : : {
98 : : return _current->custom_data;
99 : : }
100 : :
101 : : #ifdef CONFIG_USERSPACE
102 : : static inline void *z_vrfy_k_thread_custom_data_get(void)
103 : : {
104 : : return z_impl_k_thread_custom_data_get();
105 : : }
106 : : #include <zephyr/syscalls/k_thread_custom_data_get_mrsh.c>
107 : :
108 : : #endif /* CONFIG_USERSPACE */
109 : : #endif /* CONFIG_THREAD_CUSTOM_DATA */
110 : :
111 : 0 : int z_impl_k_is_preempt_thread(void)
112 : : {
113 [ # # # # ]: 0 : return !arch_is_in_isr() && thread_is_preemptible(_current);
114 : : }
115 : :
116 : : #ifdef CONFIG_USERSPACE
117 : : static inline int z_vrfy_k_is_preempt_thread(void)
118 : : {
119 : : return z_impl_k_is_preempt_thread();
120 : : }
121 : : #include <zephyr/syscalls/k_is_preempt_thread_mrsh.c>
122 : : #endif /* CONFIG_USERSPACE */
123 : :
124 : 0 : int z_impl_k_thread_priority_get(k_tid_t thread)
125 : : {
126 : 0 : return thread->base.prio;
127 : : }
128 : :
129 : : #ifdef CONFIG_USERSPACE
130 : : static inline int z_vrfy_k_thread_priority_get(k_tid_t thread)
131 : : {
132 : : K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD));
133 : : return z_impl_k_thread_priority_get(thread);
134 : : }
135 : : #include <zephyr/syscalls/k_thread_priority_get_mrsh.c>
136 : : #endif /* CONFIG_USERSPACE */
137 : :
138 : 42 : int z_impl_k_thread_name_set(k_tid_t thread, const char *str)
139 : : {
140 : : #ifdef CONFIG_THREAD_NAME
141 [ - + ]: 42 : if (thread == NULL) {
142 : 0 : thread = _current;
143 : : }
144 : :
145 : 42 : strncpy(thread->name, str, CONFIG_THREAD_MAX_NAME_LEN - 1);
146 : 42 : thread->name[CONFIG_THREAD_MAX_NAME_LEN - 1] = '\0';
147 : :
148 : : #ifdef CONFIG_ARCH_HAS_THREAD_NAME_HOOK
149 : 42 : arch_thread_name_set(thread, str);
150 : : #endif /* CONFIG_ARCH_HAS_THREAD_NAME_HOOK */
151 : :
152 : 42 : SYS_PORT_TRACING_OBJ_FUNC(k_thread, name_set, thread, 0);
153 : :
154 : 42 : return 0;
155 : : #else
156 : : ARG_UNUSED(thread);
157 : : ARG_UNUSED(str);
158 : :
159 : : SYS_PORT_TRACING_OBJ_FUNC(k_thread, name_set, thread, -ENOSYS);
160 : :
161 : : return -ENOSYS;
162 : : #endif /* CONFIG_THREAD_NAME */
163 : : }
164 : :
165 : : #ifdef CONFIG_USERSPACE
166 : : static inline int z_vrfy_k_thread_name_set(k_tid_t thread, const char *str)
167 : : {
168 : : #ifdef CONFIG_THREAD_NAME
169 : : char name[CONFIG_THREAD_MAX_NAME_LEN];
170 : :
171 : : if (thread != NULL) {
172 : : if (K_SYSCALL_OBJ(thread, K_OBJ_THREAD) != 0) {
173 : : return -EINVAL;
174 : : }
175 : : }
176 : :
177 : : /* In theory we could copy directly into thread->name, but
178 : : * the current z_vrfy / z_impl split does not provide a
179 : : * means of doing so.
180 : : */
181 : : if (k_usermode_string_copy(name, str, sizeof(name)) != 0) {
182 : : return -EFAULT;
183 : : }
184 : :
185 : : return z_impl_k_thread_name_set(thread, name);
186 : : #else
187 : : return -ENOSYS;
188 : : #endif /* CONFIG_THREAD_NAME */
189 : : }
190 : : #include <zephyr/syscalls/k_thread_name_set_mrsh.c>
191 : : #endif /* CONFIG_USERSPACE */
192 : :
193 : 0 : const char *k_thread_name_get(k_tid_t thread)
194 : : {
195 : : #ifdef CONFIG_THREAD_NAME
196 : 0 : return (const char *)thread->name;
197 : : #else
198 : : ARG_UNUSED(thread);
199 : : return NULL;
200 : : #endif /* CONFIG_THREAD_NAME */
201 : : }
202 : :
203 : 0 : int z_impl_k_thread_name_copy(k_tid_t thread, char *buf, size_t size)
204 : : {
205 : : #ifdef CONFIG_THREAD_NAME
206 : 0 : strncpy(buf, thread->name, size);
207 : 0 : return 0;
208 : : #else
209 : : ARG_UNUSED(thread);
210 : : ARG_UNUSED(buf);
211 : : ARG_UNUSED(size);
212 : : return -ENOSYS;
213 : : #endif /* CONFIG_THREAD_NAME */
214 : : }
215 : :
216 : 0 : static size_t copy_bytes(char *dest, size_t dest_size, const char *src, size_t src_size)
217 : : {
218 : 0 : size_t bytes_to_copy;
219 : :
220 : 0 : bytes_to_copy = min(dest_size, src_size);
221 : 0 : memcpy(dest, src, bytes_to_copy);
222 : :
223 : 0 : return bytes_to_copy;
224 : : }
225 : :
226 : 0 : const char *k_thread_state_str(k_tid_t thread_id, char *buf, size_t buf_size)
227 : : {
228 : 0 : size_t off = 0;
229 : 0 : uint8_t bit;
230 : 0 : uint8_t thread_state = thread_id->base.thread_state;
231 : : #define SS_ENT(s) { Z_STATE_STR_##s, _THREAD_##s, sizeof(Z_STATE_STR_##s) - 1 }
232 : 0 : static const struct {
233 : : const char *str;
234 : : uint16_t bit;
235 : : uint16_t len;
236 : : } state_string[] = {
237 : : SS_ENT(DUMMY),
238 : : SS_ENT(PENDING),
239 : : SS_ENT(SLEEPING),
240 : : SS_ENT(DEAD),
241 : : SS_ENT(SUSPENDED),
242 : : SS_ENT(ABORTING),
243 : : SS_ENT(SUSPENDING),
244 : : SS_ENT(QUEUED),
245 : : };
246 : : #undef SS_ENT
247 : :
248 [ # # ]: 0 : if ((buf == NULL) || (buf_size == 0)) {
249 : : return "";
250 : : }
251 : :
252 : 0 : buf_size--; /* Reserve 1 byte for end-of-string character */
253 : :
254 : : /*
255 : : * Loop through each bit in the thread_state. Stop once all have
256 : : * been processed. If more than one thread_state bit is set, then
257 : : * separate the descriptive strings with a '+'.
258 : : */
259 : :
260 : :
261 [ # # ]: 0 : for (unsigned int index = 0; thread_state != 0; index++) {
262 : 0 : bit = state_string[index].bit;
263 [ # # ]: 0 : if ((thread_state & bit) == 0) {
264 : 0 : continue;
265 : : }
266 : :
267 : 0 : off += copy_bytes(buf + off, buf_size - off,
268 : 0 : state_string[index].str,
269 : 0 : state_string[index].len);
270 : :
271 : 0 : thread_state &= ~bit;
272 : :
273 [ # # ]: 0 : if (thread_state != 0) {
274 : 0 : off += copy_bytes(buf + off, buf_size - off, "+", 1);
275 : : }
276 : : }
277 : :
278 : 0 : buf[off] = '\0';
279 : :
280 : 0 : return (const char *)buf;
281 : : }
282 : :
283 : : #ifdef CONFIG_USERSPACE
284 : : static inline int z_vrfy_k_thread_name_copy(k_tid_t thread,
285 : : char *buf, size_t size)
286 : : {
287 : : #ifdef CONFIG_THREAD_NAME
288 : : size_t len;
289 : : struct k_object *ko = k_object_find(thread);
290 : :
291 : : /* Special case: we allow reading the names of initialized threads
292 : : * even if we don't have permission on them
293 : : */
294 : : if ((thread == NULL) || (ko->type != K_OBJ_THREAD) ||
295 : : ((ko->flags & K_OBJ_FLAG_INITIALIZED) == 0)) {
296 : : return -EINVAL;
297 : : }
298 : : if (K_SYSCALL_MEMORY_WRITE(buf, size) != 0) {
299 : : return -EFAULT;
300 : : }
301 : : len = strlen(thread->name);
302 : : if ((len + 1) > size) {
303 : : return -ENOSPC;
304 : : }
305 : :
306 : : return k_usermode_to_copy((void *)buf, thread->name, len + 1);
307 : : #else
308 : : ARG_UNUSED(thread);
309 : : ARG_UNUSED(buf);
310 : : ARG_UNUSED(size);
311 : : return -ENOSYS;
312 : : #endif /* CONFIG_THREAD_NAME */
313 : : }
314 : : #include <zephyr/syscalls/k_thread_name_copy_mrsh.c>
315 : : #endif /* CONFIG_USERSPACE */
316 : :
317 : : #ifdef CONFIG_STACK_SENTINEL
318 : : /* Check that the stack sentinel is still present
319 : : *
320 : : * The stack sentinel feature writes a magic value to the lowest 4 bytes of
321 : : * the thread's stack when the thread is initialized. This value gets checked
322 : : * in a few places:
323 : : *
324 : : * 1) In k_yield() if the current thread is not swapped out
325 : : * 2) After servicing a non-nested interrupt
326 : : * 3) In z_swap(), check the sentinel in the outgoing thread
327 : : *
328 : : * Item 2 requires support in arch/ code.
329 : : *
330 : : * If the check fails, the thread will be terminated appropriately through
331 : : * the system fatal error handler.
332 : : */
333 : : void z_check_stack_sentinel(void)
334 : : {
335 : : uint32_t *stack;
336 : :
337 : : if ((_current->base.thread_state & _THREAD_DUMMY) != 0) {
338 : : return;
339 : : }
340 : :
341 : : stack = (uint32_t *)_current->stack_info.start;
342 : : if (*stack != STACK_SENTINEL) {
343 : : /* Restore it so further checks don't trigger this same error */
344 : : *stack = STACK_SENTINEL;
345 : : z_except_reason(K_ERR_STACK_CHK_FAIL);
346 : : }
347 : : }
348 : : #endif /* CONFIG_STACK_SENTINEL */
349 : :
350 : : #if defined(CONFIG_STACK_POINTER_RANDOM) && (CONFIG_STACK_POINTER_RANDOM != 0)
351 : : int z_stack_adjust_initialized;
352 : :
353 : : static size_t random_offset(size_t stack_size)
354 : : {
355 : : size_t random_val;
356 : :
357 : : if (!z_stack_adjust_initialized) {
358 : : z_early_rand_get((uint8_t *)&random_val, sizeof(random_val));
359 : : } else {
360 : : sys_rand_get((uint8_t *)&random_val, sizeof(random_val));
361 : : }
362 : :
363 : : /* Don't need to worry about alignment of the size here,
364 : : * arch_new_thread() is required to do it.
365 : : *
366 : : * FIXME: Not the best way to get a random number in a range.
367 : : * See #6493
368 : : */
369 : : const size_t fuzz = random_val % CONFIG_STACK_POINTER_RANDOM;
370 : :
371 : : if (unlikely(fuzz * 2 > stack_size)) {
372 : : return 0;
373 : : }
374 : :
375 : : return fuzz;
376 : : }
377 : : #if defined(CONFIG_STACK_GROWS_UP)
378 : : /* This is so rare not bothering for now */
379 : : #error "Stack pointer randomization not implemented for upward growing stacks"
380 : : #endif /* CONFIG_STACK_GROWS_UP */
381 : : #endif /* CONFIG_STACK_POINTER_RANDOM */
382 : :
383 : 48 : static char *setup_thread_stack(struct k_thread *new_thread,
384 : : k_thread_stack_t *stack, size_t stack_size)
385 : : {
386 : 48 : size_t stack_obj_size, stack_buf_size;
387 : 48 : char *stack_ptr, *stack_buf_start;
388 : 48 : size_t delta = 0;
389 : :
390 : : #ifdef CONFIG_USERSPACE
391 : : if (z_stack_is_user_capable(stack)) {
392 : : stack_obj_size = K_THREAD_STACK_LEN(stack_size);
393 : : stack_buf_start = K_THREAD_STACK_BUFFER(stack);
394 : : stack_buf_size = stack_obj_size - K_THREAD_STACK_RESERVED;
395 : : } else
396 : : #endif /* CONFIG_USERSPACE */
397 : : {
398 : : /* Object cannot host a user mode thread */
399 : 48 : stack_obj_size = K_KERNEL_STACK_LEN(stack_size);
400 : 48 : stack_buf_start = K_KERNEL_STACK_BUFFER(stack);
401 : 48 : stack_buf_size = stack_obj_size - K_KERNEL_STACK_RESERVED;
402 : :
403 : : #if defined(ARCH_KERNEL_STACK_RESERVED)
404 : : /* Zephyr treats stack overflow as an app bug. But
405 : : * this particular overflow can be seen by static
406 : : * analysis so needs to be handled somehow.
407 : : */
408 : : if (K_KERNEL_STACK_RESERVED > stack_obj_size) {
409 : : k_panic();
410 : : }
411 : : #endif
412 : : }
413 : :
414 : : #ifdef CONFIG_THREAD_STACK_MEM_MAPPED
415 : : /* Map the stack into virtual memory and use that as the base to
416 : : * calculate the initial stack pointer at the high end of the stack
417 : : * object. The stack pointer may be reduced later in this function
418 : : * by TLS or random offset.
419 : : *
420 : : * K_MEM_MAP_UNINIT is used to mimic the behavior of non-mapped
421 : : * stack. If CONFIG_INIT_STACKS is enabled, the stack will be
422 : : * cleared below.
423 : : */
424 : : void *stack_mapped = k_mem_map_phys_guard((uintptr_t)stack, stack_obj_size,
425 : : K_MEM_PERM_RW | K_MEM_CACHE_WB | K_MEM_MAP_UNINIT,
426 : : false);
427 : :
428 : : __ASSERT_NO_MSG((uintptr_t)stack_mapped != 0);
429 : :
430 : : #ifdef CONFIG_USERSPACE
431 : : if (z_stack_is_user_capable(stack)) {
432 : : stack_buf_start = K_THREAD_STACK_BUFFER(stack_mapped);
433 : : } else
434 : : #endif /* CONFIG_USERSPACE */
435 : : {
436 : : stack_buf_start = K_KERNEL_STACK_BUFFER(stack_mapped);
437 : : }
438 : :
439 : : stack_ptr = (char *)stack_mapped + stack_obj_size;
440 : :
441 : : /* Need to store the info on mapped stack so we can remove the mappings
442 : : * when the thread ends.
443 : : */
444 : : new_thread->stack_info.mapped.addr = stack_mapped;
445 : : new_thread->stack_info.mapped.sz = stack_obj_size;
446 : :
447 : : #else /* CONFIG_THREAD_STACK_MEM_MAPPED */
448 : :
449 : : /* Initial stack pointer at the high end of the stack object, may
450 : : * be reduced later in this function by TLS or random offset
451 : : */
452 : 48 : stack_ptr = (char *)stack + stack_obj_size;
453 : :
454 : : #endif /* CONFIG_THREAD_STACK_MEM_MAPPED */
455 : :
456 : 48 : LOG_DBG("stack %p for thread %p: obj_size=%zu buf_start=%p "
457 : : " buf_size %zu stack_ptr=%p",
458 : : stack, new_thread, stack_obj_size, (void *)stack_buf_start,
459 : : stack_buf_size, (void *)stack_ptr);
460 : :
461 : : #ifdef CONFIG_INIT_STACKS
462 : 48 : memset(stack_buf_start, 0xaa, stack_buf_size);
463 : : #endif /* CONFIG_INIT_STACKS */
464 : : #ifdef CONFIG_STACK_SENTINEL
465 : : /* Put the stack sentinel at the lowest 4 bytes of the stack area.
466 : : * We periodically check that it's still present and kill the thread
467 : : * if it isn't.
468 : : */
469 : : *((uint32_t *)stack_buf_start) = STACK_SENTINEL;
470 : : #endif /* CONFIG_STACK_SENTINEL */
471 : : #ifdef CONFIG_THREAD_LOCAL_STORAGE
472 : : /* TLS is always last within the stack buffer */
473 : : delta += arch_tls_stack_setup(new_thread, stack_ptr);
474 : : #endif /* CONFIG_THREAD_LOCAL_STORAGE */
475 : : #ifdef CONFIG_THREAD_USERSPACE_LOCAL_DATA
476 : : size_t tls_size = sizeof(struct _thread_userspace_local_data);
477 : :
478 : : /* reserve space on highest memory of stack buffer for local data */
479 : : delta += tls_size;
480 : : new_thread->userspace_local_data =
481 : : (struct _thread_userspace_local_data *)(stack_ptr - delta);
482 : : #endif /* CONFIG_THREAD_USERSPACE_LOCAL_DATA */
483 : : #if defined(CONFIG_STACK_POINTER_RANDOM) && (CONFIG_STACK_POINTER_RANDOM != 0)
484 : : delta += random_offset(stack_buf_size);
485 : : #endif /* CONFIG_STACK_POINTER_RANDOM */
486 : 48 : delta = ROUND_UP(delta, ARCH_STACK_PTR_ALIGN);
487 : : #ifdef CONFIG_THREAD_STACK_INFO
488 : : /* Initial values. Arches which implement MPU guards that "borrow"
489 : : * memory from the stack buffer (not tracked in K_THREAD_STACK_RESERVED)
490 : : * will need to appropriately update this.
491 : : *
492 : : * The bounds tracked here correspond to the area of the stack object
493 : : * that the thread can access, which includes TLS.
494 : : */
495 : : new_thread->stack_info.start = (uintptr_t)stack_buf_start;
496 : : new_thread->stack_info.size = stack_buf_size;
497 : : new_thread->stack_info.delta = delta;
498 : :
499 : : #ifdef CONFIG_THREAD_RUNTIME_STACK_SAFETY
500 : : new_thread->stack_info.usage.unused_threshold =
501 : : (CONFIG_THREAD_RUNTIME_STACK_SAFETY_DEFAULT_UNUSED_THRESHOLD_PCT *
502 : : stack_buf_size) / 100;
503 : : #endif
504 : : #endif /* CONFIG_THREAD_STACK_INFO */
505 : 48 : stack_ptr -= delta;
506 : :
507 : 48 : return stack_ptr;
508 : : }
509 : :
510 : : #ifdef CONFIG_HW_SHADOW_STACK
511 : : static void setup_shadow_stack(struct k_thread *new_thread,
512 : : k_thread_stack_t *stack)
513 : : {
514 : : int ret = -ENOENT;
515 : :
516 : : STRUCT_SECTION_FOREACH(_stack_to_hw_shadow_stack, stk_to_hw_shstk) {
517 : : if (stk_to_hw_shstk->stack == stack) {
518 : : ret = k_thread_hw_shadow_stack_attach(new_thread,
519 : : stk_to_hw_shstk->shstk_addr,
520 : : stk_to_hw_shstk->size);
521 : : if (ret != 0) {
522 : : LOG_ERR("Could not set thread %p shadow stack %p, got error %d",
523 : : new_thread, stk_to_hw_shstk->shstk_addr, ret);
524 : : k_panic();
525 : : }
526 : : break;
527 : : }
528 : : }
529 : :
530 : : /* Check if the stack isn't in a stack array, and use the corresponding
531 : : * shadow stack.
532 : : */
533 : : if (ret != -ENOENT) {
534 : : return;
535 : : }
536 : :
537 : : STRUCT_SECTION_FOREACH(_stack_to_hw_shadow_stack_arr, stk_to_hw_shstk) {
538 : : if ((uintptr_t)stack >= stk_to_hw_shstk->stack_addr &&
539 : : (uintptr_t)stack < stk_to_hw_shstk->stack_addr +
540 : : stk_to_hw_shstk->stack_size * stk_to_hw_shstk->nmemb) {
541 : : /* Now we have to guess which index of the stack array is being used */
542 : : uintptr_t stack_offset = (uintptr_t)stack - stk_to_hw_shstk->stack_addr;
543 : : uintptr_t stack_index = stack_offset / stk_to_hw_shstk->stack_size;
544 : : uintptr_t addr;
545 : :
546 : : if (stack_index >= stk_to_hw_shstk->nmemb) {
547 : : LOG_ERR("Could not find shadow stack for thread %p, stack %p",
548 : : new_thread, stack);
549 : : k_panic();
550 : : }
551 : :
552 : : addr = stk_to_hw_shstk->shstk_addr +
553 : : stk_to_hw_shstk->shstk_size * stack_index;
554 : : ret = k_thread_hw_shadow_stack_attach(new_thread,
555 : : (arch_thread_hw_shadow_stack_t *)addr,
556 : : stk_to_hw_shstk->shstk_size);
557 : : if (ret != 0) {
558 : : LOG_ERR("Could not set thread %p shadow stack 0x%lx, got error %d",
559 : : new_thread, stk_to_hw_shstk->shstk_addr, ret);
560 : : k_panic();
561 : : }
562 : : break;
563 : : }
564 : : }
565 : :
566 : : if (ret == -ENOENT) {
567 : : LOG_ERR("Could not find shadow stack for thread %p, stack %p",
568 : : new_thread, stack);
569 : : k_panic();
570 : : }
571 : : }
572 : : #endif
573 : :
574 : : /*
575 : : * The provided stack_size value is presumed to be either the result of
576 : : * K_THREAD_STACK_SIZEOF(stack), or the size value passed to the instance
577 : : * of K_THREAD_STACK_DEFINE() which defined 'stack'.
578 : : */
579 : 48 : char *z_setup_new_thread(struct k_thread *new_thread,
580 : : k_thread_stack_t *stack, size_t stack_size,
581 : : k_thread_entry_t entry,
582 : : void *p1, void *p2, void *p3,
583 : : int prio, uint32_t options, const char *name)
584 : : {
585 : 48 : char *stack_ptr;
586 : :
587 [ + + - + : 48 : Z_ASSERT_VALID_PRIO(prio, entry);
- + ]
588 : :
589 : : #ifdef CONFIG_THREAD_ABORT_NEED_CLEANUP
590 : : k_thread_abort_cleanup_check_reuse(new_thread);
591 : : #endif /* CONFIG_THREAD_ABORT_NEED_CLEANUP */
592 : :
593 : : #ifdef CONFIG_OBJ_CORE_THREAD
594 : : k_obj_core_init_and_link(K_OBJ_CORE(new_thread), &obj_type_thread);
595 : : #ifdef CONFIG_OBJ_CORE_STATS_THREAD
596 : : k_obj_core_stats_register(K_OBJ_CORE(new_thread),
597 : : &new_thread->base.usage,
598 : : sizeof(new_thread->base.usage));
599 : : #endif /* CONFIG_OBJ_CORE_STATS_THREAD */
600 : : #endif /* CONFIG_OBJ_CORE_THREAD */
601 : :
602 : : #ifdef CONFIG_USERSPACE
603 : : __ASSERT((options & K_USER) == 0U || z_stack_is_user_capable(stack),
604 : : "user thread %p with kernel-only stack %p",
605 : : new_thread, stack);
606 : : k_object_init(new_thread);
607 : : k_object_init(stack);
608 : : new_thread->stack_obj = stack;
609 : : new_thread->syscall_frame = NULL;
610 : :
611 : : /* Any given thread has access to itself */
612 : : k_object_access_grant(new_thread, new_thread);
613 : : #endif /* CONFIG_USERSPACE */
614 : 48 : z_waitq_init(&new_thread->join_queue);
615 : :
616 : : /* Initialize various struct k_thread members */
617 : 48 : z_init_thread_base(&new_thread->base, prio, _THREAD_SLEEPING, options);
618 : 48 : stack_ptr = setup_thread_stack(new_thread, stack, stack_size);
619 : :
620 : : #ifdef CONFIG_HW_SHADOW_STACK
621 : : setup_shadow_stack(new_thread, stack);
622 : : #endif
623 : :
624 : : #ifdef CONFIG_KERNEL_COHERENCE
625 : : /* Check that the thread object is safe, but that the stack is
626 : : * still cached!
627 : : */
628 : : __ASSERT_NO_MSG(sys_cache_is_mem_coherent(new_thread));
629 : :
630 : : /* When dynamic thread stack is available, the stack may come from
631 : : * uncached area.
632 : : */
633 : : #ifndef CONFIG_DYNAMIC_THREAD
634 : : __ASSERT_NO_MSG(!sys_cache_is_mem_coherent(stack));
635 : : #endif /* CONFIG_DYNAMIC_THREAD */
636 : :
637 : : #endif /* CONFIG_KERNEL_COHERENCE */
638 : :
639 : 48 : arch_new_thread(new_thread, stack, stack_ptr, entry, p1, p2, p3);
640 : :
641 : : /* static threads overwrite it afterwards with real value */
642 : 48 : new_thread->init_data = NULL;
643 : :
644 : : #ifdef CONFIG_USE_SWITCH
645 : : /* switch_handle must be non-null except when inside z_swap()
646 : : * for synchronization reasons. Historically some notional
647 : : * USE_SWITCH architectures have actually ignored the field
648 : : */
649 : : __ASSERT(new_thread->switch_handle != NULL,
650 : : "arch layer failed to initialize switch_handle");
651 : : #endif /* CONFIG_USE_SWITCH */
652 : : #ifdef CONFIG_THREAD_CUSTOM_DATA
653 : : /* Initialize custom data field (value is opaque to kernel) */
654 : : new_thread->custom_data = NULL;
655 : : #endif /* CONFIG_THREAD_CUSTOM_DATA */
656 : : #ifdef CONFIG_THREAD_MONITOR
657 : : new_thread->entry.pEntry = entry;
658 : : new_thread->entry.parameter1 = p1;
659 : : new_thread->entry.parameter2 = p2;
660 : : new_thread->entry.parameter3 = p3;
661 : :
662 : : k_spinlock_key_t key = k_spin_lock(&z_thread_monitor_lock);
663 : :
664 : : new_thread->next_thread = _kernel.threads;
665 : : _kernel.threads = new_thread;
666 : : k_spin_unlock(&z_thread_monitor_lock, key);
667 : : #endif /* CONFIG_THREAD_MONITOR */
668 : : #ifdef CONFIG_THREAD_NAME
669 [ + + ]: 48 : if (name != NULL) {
670 : 2 : strncpy(new_thread->name, name,
671 : : CONFIG_THREAD_MAX_NAME_LEN - 1);
672 : : /* Ensure NULL termination, truncate if longer */
673 : 2 : new_thread->name[CONFIG_THREAD_MAX_NAME_LEN - 1] = '\0';
674 : : #ifdef CONFIG_ARCH_HAS_THREAD_NAME_HOOK
675 : 2 : arch_thread_name_set(new_thread, name);
676 : : #endif /* CONFIG_ARCH_HAS_THREAD_NAME_HOOK */
677 : : } else {
678 : 46 : new_thread->name[0] = '\0';
679 : : }
680 : : #endif /* CONFIG_THREAD_NAME */
681 : : #ifdef CONFIG_SCHED_CPU_MASK
682 : 48 : if (IS_ENABLED(CONFIG_SCHED_CPU_MASK_PIN_ONLY)) {
683 : : new_thread->base.cpu_mask = 1; /* must specify only one cpu */
684 : : } else {
685 : 48 : new_thread->base.cpu_mask = -1; /* allow all cpus */
686 : : }
687 : : #endif /* CONFIG_SCHED_CPU_MASK */
688 : : #ifdef CONFIG_ARCH_HAS_CUSTOM_SWAP_TO_MAIN
689 : : /* _current may be null if the dummy thread is not used */
690 [ - + ]: 48 : if (!_current) {
691 : 0 : new_thread->resource_pool = NULL;
692 : 0 : return stack_ptr;
693 : : }
694 : : #endif /* CONFIG_ARCH_HAS_CUSTOM_SWAP_TO_MAIN */
695 : : #ifdef CONFIG_USERSPACE
696 : : z_mem_domain_init_thread(new_thread);
697 : :
698 : : if ((options & K_INHERIT_PERMS) != 0U) {
699 : : k_thread_perms_inherit(_current, new_thread);
700 : : }
701 : : #endif /* CONFIG_USERSPACE */
702 : : #ifdef CONFIG_SCHED_DEADLINE
703 : : new_thread->base.prio_deadline = 0;
704 : : #endif /* CONFIG_SCHED_DEADLINE */
705 : 48 : new_thread->resource_pool = _current->resource_pool;
706 : :
707 : : #ifdef CONFIG_SMP
708 : : z_waitq_init(&new_thread->halt_queue);
709 : : #endif /* CONFIG_SMP */
710 : :
711 : : #ifdef CONFIG_SCHED_THREAD_USAGE
712 : : new_thread->base.usage = (struct k_cycle_stats) {};
713 : : new_thread->base.usage.track_usage =
714 : : CONFIG_SCHED_THREAD_USAGE_AUTO_ENABLE;
715 : : #endif /* CONFIG_SCHED_THREAD_USAGE */
716 : :
717 : 48 : SYS_PORT_TRACING_OBJ_FUNC(k_thread, create, new_thread);
718 : :
719 : 48 : return stack_ptr;
720 : : }
721 : :
722 : : #ifdef CONFIG_THREAD_RUNTIME_STACK_SAFETY
723 : : int z_impl_k_thread_runtime_stack_safety_unused_threshold_pct_set(struct k_thread *thread,
724 : : uint32_t pct)
725 : : {
726 : : size_t unused_threshold;
727 : :
728 : : if (pct > 99) {
729 : : return -EINVAL; /* 100% unused stack and up is invalid */
730 : : }
731 : :
732 : : unused_threshold = (thread->stack_info.size * pct) / 100;
733 : :
734 : : thread->stack_info.usage.unused_threshold = unused_threshold;
735 : :
736 : : return 0;
737 : : }
738 : :
739 : : int z_impl_k_thread_runtime_stack_safety_unused_threshold_set(struct k_thread *thread,
740 : : size_t threshold)
741 : : {
742 : : if (threshold > thread->stack_info.size) {
743 : : return -EINVAL;
744 : : }
745 : :
746 : : thread->stack_info.usage.unused_threshold = threshold;
747 : :
748 : : return 0;
749 : : }
750 : :
751 : : size_t z_impl_k_thread_runtime_stack_safety_unused_threshold_get(struct k_thread *thread)
752 : : {
753 : : return thread->stack_info.usage.unused_threshold;
754 : : }
755 : :
756 : : #ifdef CONFIG_USERSPACE
757 : : int z_vrfy_k_thread_runtime_stack_safety_unused_threshold_pct_set(struct k_thread *thread,
758 : : uint32_t pct)
759 : : {
760 : : K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD));
761 : :
762 : : return z_impl_k_thread_runtime_stack_safety_unused_threshold_pct_set(thread, pct);
763 : : }
764 : : #include <zephyr/syscalls/k_thread_runtime_stack_safety_unused_threshold_pct_set_mrsh.c>
765 : :
766 : : int z_vrfy_k_thread_runtime_stack_safety_unused_threshold_set(struct k_thread *thread,
767 : : size_t threshold)
768 : : {
769 : : K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD));
770 : :
771 : : return z_impl_k_thread_runtime_stack_safety_unused_threshold_set(thread, threshold);
772 : : }
773 : : #include <zephyr/syscalls/k_thread_runtime_stack_safety_unused_threshold_set_mrsh.c>
774 : :
775 : : size_t z_vrfy_k_thread_runtime_stack_safety_unused_threshold_get(struct k_thread *thread)
776 : : {
777 : : K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD));
778 : :
779 : : return z_impl_k_thread_runtime_stack_safety_unused_threshold_get(thread);
780 : : }
781 : : #include <zephyr/syscalls/k_thread_runtime_stack_safety_unused_threshold_get_mrsh.c>
782 : : #endif /* CONFIG_USERSPACE */
783 : : #endif /* CONFIG_THREAD_RUNTIME_STACK_SAFETY */
784 : :
785 : 46 : k_tid_t z_impl_k_thread_create(struct k_thread *new_thread,
786 : : k_thread_stack_t *stack,
787 : : size_t stack_size, k_thread_entry_t entry,
788 : : void *p1, void *p2, void *p3,
789 : : int prio, uint32_t options, k_timeout_t delay)
790 : : {
791 [ - + ]: 46 : __ASSERT(!arch_is_in_isr(), "Threads may not be created in ISRs");
792 : :
793 : 46 : z_setup_new_thread(new_thread, stack, stack_size, entry, p1, p2, p3,
794 : : prio, options, NULL);
795 : :
796 [ + + ]: 46 : if (!K_TIMEOUT_EQ(delay, K_FOREVER)) {
797 : 4 : thread_schedule_new(new_thread, delay);
798 : : }
799 : :
800 : 46 : return new_thread;
801 : : }
802 : :
803 : : #ifdef CONFIG_USERSPACE
804 : : bool z_stack_is_user_capable(k_thread_stack_t *stack)
805 : : {
806 : : return k_object_find(stack) != NULL;
807 : : }
808 : :
809 : : k_tid_t z_vrfy_k_thread_create(struct k_thread *new_thread,
810 : : k_thread_stack_t *stack,
811 : : size_t stack_size, k_thread_entry_t entry,
812 : : void *p1, void *p2, void *p3,
813 : : int prio, uint32_t options, k_timeout_t delay)
814 : : {
815 : : size_t total_size, stack_obj_size;
816 : : struct k_object *stack_object;
817 : :
818 : : /* The thread and stack objects *must* be in an uninitialized state */
819 : : K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(new_thread, K_OBJ_THREAD));
820 : :
821 : : /* No need to check z_stack_is_user_capable(), it won't be in the
822 : : * object table if it isn't
823 : : */
824 : : stack_object = k_object_find(stack);
825 : : K_OOPS(K_SYSCALL_VERIFY_MSG(k_object_validation_check(stack_object, stack,
826 : : K_OBJ_THREAD_STACK_ELEMENT,
827 : : _OBJ_INIT_FALSE) == 0,
828 : : "bad stack object"));
829 : :
830 : : /* Verify that the stack size passed in is OK by computing the total
831 : : * size and comparing it with the size value in the object metadata
832 : : */
833 : : K_OOPS(K_SYSCALL_VERIFY_MSG(!size_add_overflow(K_THREAD_STACK_RESERVED,
834 : : stack_size, &total_size),
835 : : "stack size overflow (%zu+%zu)",
836 : : stack_size,
837 : : K_THREAD_STACK_RESERVED));
838 : :
839 : : /* Testing less-than-or-equal since additional room may have been
840 : : * allocated for alignment constraints
841 : : */
842 : : #ifdef CONFIG_GEN_PRIV_STACKS
843 : : stack_obj_size = stack_object->data.stack_data->size;
844 : : #else
845 : : stack_obj_size = stack_object->data.stack_size;
846 : : #endif /* CONFIG_GEN_PRIV_STACKS */
847 : : K_OOPS(K_SYSCALL_VERIFY_MSG(total_size <= stack_obj_size,
848 : : "stack size %zu is too big, max is %zu",
849 : : total_size, stack_obj_size));
850 : :
851 : : /* User threads may only create other user threads and they can't
852 : : * be marked as essential
853 : : */
854 : : K_OOPS(K_SYSCALL_VERIFY(options & K_USER));
855 : : K_OOPS(K_SYSCALL_VERIFY(!(options & K_ESSENTIAL)));
856 : :
857 : : /* Check validity of prio argument; must be the same or worse priority
858 : : * than the caller
859 : : */
860 : : K_OOPS(K_SYSCALL_VERIFY(_is_valid_prio(prio, NULL)));
861 : : K_OOPS(K_SYSCALL_VERIFY(z_is_prio_lower_or_equal(prio,
862 : : _current->base.prio)));
863 : :
864 : : z_setup_new_thread(new_thread, stack, stack_size,
865 : : entry, p1, p2, p3, prio, options, NULL);
866 : :
867 : : if (!K_TIMEOUT_EQ(delay, K_FOREVER)) {
868 : : thread_schedule_new(new_thread, delay);
869 : : }
870 : :
871 : : return new_thread;
872 : : }
873 : : #include <zephyr/syscalls/k_thread_create_mrsh.c>
874 : : #endif /* CONFIG_USERSPACE */
875 : :
876 : 48 : void z_init_thread_base(struct _thread_base *thread_base, int priority,
877 : : uint32_t initial_state, unsigned int options)
878 : : {
879 : : /* k_q_node is initialized upon first insertion in a list */
880 : 48 : thread_base->pended_on = NULL;
881 : 48 : thread_base->user_options = (uint16_t)options;
882 : 48 : thread_base->thread_state = (uint8_t)initial_state;
883 : :
884 : 48 : thread_base->prio = priority;
885 : :
886 : 48 : thread_base->sched_locked = 0U;
887 : :
888 : : #ifdef CONFIG_SMP
889 : : thread_base->is_idle = 0;
890 : :
891 : : /*
892 : : * Pretend that the thread was last executing on CPU0 to prevent
893 : : * out-of-bounds memory accesses to the _kernel.cpus[] array.
894 : : */
895 : : thread_base->cpu = 0;
896 : : #endif /* CONFIG_SMP */
897 : :
898 : : #ifdef CONFIG_TIMESLICE_PER_THREAD
899 : : thread_base->slice_ticks = 0;
900 : : thread_base->slice_expired = NULL;
901 : : #endif /* CONFIG_TIMESLICE_PER_THREAD */
902 : :
903 : : /* swap_data does not need to be initialized */
904 : :
905 : 48 : z_init_thread_timeout(thread_base);
906 : 48 : }
907 : :
908 : 0 : FUNC_NORETURN void k_thread_user_mode_enter(k_thread_entry_t entry,
909 : : void *p1, void *p2, void *p3)
910 : : {
911 : 0 : SYS_PORT_TRACING_FUNC(k_thread, user_mode_enter);
912 : :
913 : 0 : _current->base.user_options |= K_USER;
914 : 0 : z_thread_essential_clear(_current);
915 : : #ifdef CONFIG_THREAD_MONITOR
916 : : _current->entry.pEntry = entry;
917 : : _current->entry.parameter1 = p1;
918 : : _current->entry.parameter2 = p2;
919 : : _current->entry.parameter3 = p3;
920 : : #endif /* CONFIG_THREAD_MONITOR */
921 : : #ifdef CONFIG_USERSPACE
922 : : __ASSERT(z_stack_is_user_capable(_current->stack_obj),
923 : : "dropping to user mode with kernel-only stack object");
924 : : #ifdef CONFIG_THREAD_USERSPACE_LOCAL_DATA
925 : : memset(_current->userspace_local_data, 0,
926 : : sizeof(struct _thread_userspace_local_data));
927 : : #endif /* CONFIG_THREAD_USERSPACE_LOCAL_DATA */
928 : : #ifdef CONFIG_THREAD_LOCAL_STORAGE
929 : : arch_tls_stack_setup(_current,
930 : : (char *)(_current->stack_info.start +
931 : : _current->stack_info.size));
932 : : #endif /* CONFIG_THREAD_LOCAL_STORAGE */
933 : : arch_user_mode_enter(entry, p1, p2, p3);
934 : : #else
935 : : /* XXX In this case we do not reset the stack */
936 : 0 : z_thread_entry(entry, p1, p2, p3);
937 : : #endif /* CONFIG_USERSPACE */
938 : : }
939 : :
940 : : #if defined(CONFIG_INIT_STACKS) && defined(CONFIG_THREAD_STACK_INFO)
941 : : #ifdef CONFIG_STACK_GROWS_UP
942 : : #error "Unsupported configuration for stack analysis"
943 : : #endif /* CONFIG_STACK_GROWS_UP */
944 : :
945 : : int z_stack_space_get(const uint8_t *stack_start, size_t size, size_t *unused_ptr)
946 : : {
947 : : size_t unused = 0;
948 : : const uint8_t *checked_stack = stack_start;
949 : : /* Take the address of any local variable as a shallow bound for the
950 : : * stack pointer. Addresses above it are guaranteed to be
951 : : * accessible.
952 : : */
953 : : const uint8_t *stack_pointer = (const uint8_t *)&stack_start;
954 : :
955 : : /* If we are currently running on the stack being analyzed, some
956 : : * memory management hardware will generate an exception if we
957 : : * read unused stack memory.
958 : : *
959 : : * This never happens when invoked from user mode, as user mode
960 : : * will always run this function on the privilege elevation stack.
961 : : */
962 : : if ((stack_pointer > stack_start) && (stack_pointer <= (stack_start + size)) &&
963 : : IS_ENABLED(CONFIG_NO_UNUSED_STACK_INSPECTION)) {
964 : : /* TODO: We could add an arch_ API call to temporarily
965 : : * disable the stack checking in the CPU, but this would
966 : : * need to be properly managed wrt context switches/interrupts
967 : : */
968 : : return -ENOTSUP;
969 : : }
970 : :
971 : : if (IS_ENABLED(CONFIG_STACK_SENTINEL)) {
972 : : /* First 4 bytes of the stack buffer reserved for the
973 : : * sentinel value, it won't be 0xAAAAAAAA for thread
974 : : * stacks.
975 : : *
976 : : * FIXME: thread->stack_info.start ought to reflect
977 : : * this!
978 : : */
979 : : checked_stack += 4;
980 : : size -= 4;
981 : : }
982 : :
983 : : for (size_t i = 0; i < size; i++) {
984 : : if ((checked_stack[i]) == 0xaaU) {
985 : : unused++;
986 : : } else {
987 : : break;
988 : : }
989 : : }
990 : :
991 : : *unused_ptr = unused;
992 : :
993 : : return 0;
994 : : }
995 : :
996 : : #ifdef CONFIG_THREAD_RUNTIME_STACK_SAFETY
997 : : int k_thread_runtime_stack_safety_full_check(const struct k_thread *thread,
998 : : size_t *unused_ptr,
999 : : k_thread_stack_safety_handler_t handler,
1000 : : void *arg)
1001 : : {
1002 : : int rv;
1003 : : size_t unused_space;
1004 : :
1005 : : __ASSERT_NO_MSG(thread != NULL);
1006 : :
1007 : : rv = z_stack_space_get((const uint8_t *)thread->stack_info.start,
1008 : : thread->stack_info.size, &unused_space);
1009 : :
1010 : : if (rv != 0) {
1011 : : return rv;
1012 : : }
1013 : :
1014 : : if (unused_ptr != NULL) {
1015 : : *unused_ptr = unused_space;
1016 : : }
1017 : :
1018 : : if ((unused_space < thread->stack_info.usage.unused_threshold) &&
1019 : : (handler != NULL)) {
1020 : : handler(thread, unused_space, arg);
1021 : : }
1022 : :
1023 : : return 0;
1024 : : }
1025 : :
1026 : : int k_thread_runtime_stack_safety_threshold_check(const struct k_thread *thread,
1027 : : size_t *unused_ptr,
1028 : : k_thread_stack_safety_handler_t handler,
1029 : : void *arg)
1030 : : {
1031 : : int rv;
1032 : : size_t unused_space;
1033 : :
1034 : : __ASSERT_NO_MSG(thread != NULL);
1035 : :
1036 : : rv = z_stack_space_get((const uint8_t *)thread->stack_info.start,
1037 : : thread->stack_info.usage.unused_threshold,
1038 : : &unused_space);
1039 : :
1040 : : if (rv != 0) {
1041 : : return rv;
1042 : : }
1043 : :
1044 : : if (unused_ptr != NULL) {
1045 : : *unused_ptr = unused_space;
1046 : : }
1047 : :
1048 : : if ((unused_space < thread->stack_info.usage.unused_threshold) &&
1049 : : (handler != NULL)) {
1050 : : handler(thread, unused_space, arg);
1051 : : }
1052 : :
1053 : : return 0;
1054 : : }
1055 : :
1056 : : #ifdef CONFIG_USERSPACE
1057 : : int z_vrfy_k_thread_runtime_stack_safety_unused_threshold_get(struct k_thread *thread)
1058 : : {
1059 : : K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD));
1060 : :
1061 : : return z_impl_k_thread_runtime_stack_safety_unused_threshold_set(thread);
1062 : : }
1063 : : #include <zephyr/syscalls/k_thread_runtime_stack_safety_unused_threshold_get_mrsh.c>
1064 : : #endif /* CONFIG_USERSPACE */
1065 : : #endif /* CONFIG_THREAD_RUNTIME_STACK_SAFETY */
1066 : :
1067 : : int z_impl_k_thread_stack_space_get(const struct k_thread *thread,
1068 : : size_t *unused_ptr)
1069 : : {
1070 : : #ifdef CONFIG_THREAD_STACK_MEM_MAPPED
1071 : : if (thread->stack_info.mapped.addr == NULL) {
1072 : : return -EINVAL;
1073 : : }
1074 : : #endif /* CONFIG_THREAD_STACK_MEM_MAPPED */
1075 : :
1076 : : return z_stack_space_get((const uint8_t *)thread->stack_info.start,
1077 : : thread->stack_info.size, unused_ptr);
1078 : : }
1079 : :
1080 : : #ifdef CONFIG_USERSPACE
1081 : : int z_vrfy_k_thread_stack_space_get(const struct k_thread *thread,
1082 : : size_t *unused_ptr)
1083 : : {
1084 : : size_t unused;
1085 : : int ret;
1086 : :
1087 : : ret = K_SYSCALL_OBJ(thread, K_OBJ_THREAD);
1088 : : CHECKIF(ret != 0) {
1089 : : return ret;
1090 : : }
1091 : :
1092 : : ret = z_impl_k_thread_stack_space_get(thread, &unused);
1093 : : CHECKIF(ret != 0) {
1094 : : return ret;
1095 : : }
1096 : :
1097 : : ret = k_usermode_to_copy(unused_ptr, &unused, sizeof(size_t));
1098 : : CHECKIF(ret != 0) {
1099 : : return ret;
1100 : : }
1101 : :
1102 : : return 0;
1103 : : }
1104 : : #include <zephyr/syscalls/k_thread_stack_space_get_mrsh.c>
1105 : : #endif /* CONFIG_USERSPACE */
1106 : : #endif /* CONFIG_INIT_STACKS && CONFIG_THREAD_STACK_INFO */
1107 : :
1108 : : #ifdef CONFIG_USERSPACE
1109 : : static inline k_ticks_t z_vrfy_k_thread_timeout_remaining_ticks(
1110 : : const struct k_thread *thread)
1111 : : {
1112 : : K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD));
1113 : : return z_impl_k_thread_timeout_remaining_ticks(thread);
1114 : : }
1115 : : #include <zephyr/syscalls/k_thread_timeout_remaining_ticks_mrsh.c>
1116 : :
1117 : : static inline k_ticks_t z_vrfy_k_thread_timeout_expires_ticks(
1118 : : const struct k_thread *thread)
1119 : : {
1120 : : K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD));
1121 : : return z_impl_k_thread_timeout_expires_ticks(thread);
1122 : : }
1123 : : #include <zephyr/syscalls/k_thread_timeout_expires_ticks_mrsh.c>
1124 : : #endif /* CONFIG_USERSPACE */
1125 : :
1126 : : #ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING
1127 : : void z_thread_mark_switched_in(void)
1128 : : {
1129 : : #if defined(CONFIG_SCHED_THREAD_USAGE) && !defined(CONFIG_USE_SWITCH)
1130 : : z_sched_usage_start(_current);
1131 : : #endif /* CONFIG_SCHED_THREAD_USAGE && !CONFIG_USE_SWITCH */
1132 : :
1133 : : #ifdef CONFIG_TRACING
1134 : : SYS_PORT_TRACING_FUNC(k_thread, switched_in);
1135 : : #endif /* CONFIG_TRACING */
1136 : : }
1137 : :
1138 : : void z_thread_mark_switched_out(void)
1139 : : {
1140 : : #if defined(CONFIG_SCHED_THREAD_USAGE) && !defined(CONFIG_USE_SWITCH)
1141 : : z_sched_usage_stop();
1142 : : #endif /*CONFIG_SCHED_THREAD_USAGE && !CONFIG_USE_SWITCH */
1143 : :
1144 : : #ifdef CONFIG_TRACING
1145 : : #ifdef CONFIG_THREAD_LOCAL_STORAGE
1146 : : /* Dummy thread won't have TLS set up to run arbitrary code */
1147 : : if (!_current ||
1148 : : (_current->base.thread_state & _THREAD_DUMMY) != 0) {
1149 : : return;
1150 : : }
1151 : : #endif /* CONFIG_THREAD_LOCAL_STORAGE */
1152 : : SYS_PORT_TRACING_FUNC(k_thread, switched_out);
1153 : : #endif /* CONFIG_TRACING */
1154 : : }
1155 : : #endif /* CONFIG_INSTRUMENT_THREAD_SWITCHING */
1156 : :
1157 : 0 : int k_thread_runtime_stats_get(k_tid_t thread,
1158 : : k_thread_runtime_stats_t *stats)
1159 : : {
1160 [ # # ]: 0 : if ((thread == NULL) || (stats == NULL)) {
1161 : 0 : return -EINVAL;
1162 : : }
1163 : :
1164 : : #ifdef CONFIG_SCHED_THREAD_USAGE
1165 : : z_sched_thread_usage(thread, stats);
1166 : : #else
1167 : : *stats = (k_thread_runtime_stats_t) {};
1168 : : #endif /* CONFIG_SCHED_THREAD_USAGE */
1169 : :
1170 : : return 0;
1171 : : }
1172 : :
1173 : 0 : int k_thread_runtime_stats_all_get(k_thread_runtime_stats_t *stats)
1174 : : {
1175 : : #ifdef CONFIG_SCHED_THREAD_USAGE_ALL
1176 : : k_thread_runtime_stats_t tmp_stats;
1177 : : #endif /* CONFIG_SCHED_THREAD_USAGE_ALL */
1178 : :
1179 [ # # ]: 0 : if (stats == NULL) {
1180 : 0 : return -EINVAL;
1181 : : }
1182 : :
1183 : : *stats = (k_thread_runtime_stats_t) {};
1184 : :
1185 : : #ifdef CONFIG_SCHED_THREAD_USAGE_ALL
1186 : : /* Retrieve the usage stats for each core and amalgamate them. */
1187 : :
1188 : : unsigned int num_cpus = arch_num_cpus();
1189 : :
1190 : : for (uint8_t i = 0; i < num_cpus; i++) {
1191 : : z_sched_cpu_usage(i, &tmp_stats);
1192 : :
1193 : : stats->execution_cycles += tmp_stats.execution_cycles;
1194 : : stats->total_cycles += tmp_stats.total_cycles;
1195 : : #ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS
1196 : : stats->current_cycles += tmp_stats.current_cycles;
1197 : : stats->peak_cycles += tmp_stats.peak_cycles;
1198 : : stats->average_cycles += tmp_stats.average_cycles;
1199 : : #endif /* CONFIG_SCHED_THREAD_USAGE_ANALYSIS */
1200 : : stats->idle_cycles += tmp_stats.idle_cycles;
1201 : : }
1202 : : #endif /* CONFIG_SCHED_THREAD_USAGE_ALL */
1203 : :
1204 : : return 0;
1205 : : }
1206 : :
1207 : 0 : int k_thread_runtime_stats_cpu_get(int cpu, k_thread_runtime_stats_t *stats)
1208 : : {
1209 [ # # ]: 0 : if (stats == NULL) {
1210 : 0 : return -EINVAL;
1211 : : }
1212 : :
1213 : : *stats = (k_thread_runtime_stats_t) {};
1214 : :
1215 : : #ifdef CONFIG_SCHED_THREAD_USAGE_ALL
1216 : : #ifdef CONFIG_SMP
1217 : : z_sched_cpu_usage(cpu, stats);
1218 : : #else
1219 : : __ASSERT(cpu == 0, "cpu filter out of bounds");
1220 : : ARG_UNUSED(cpu);
1221 : : z_sched_cpu_usage(0, stats);
1222 : : #endif
1223 : : #endif
1224 : :
1225 : : return 0;
1226 : : }
1227 : :
1228 : : #ifdef CONFIG_THREAD_ABORT_NEED_CLEANUP
1229 : : /** Pointer to thread which needs to be cleaned up. */
1230 : : static struct k_thread *thread_to_cleanup;
1231 : :
1232 : : /** Spinlock for thread abort cleanup. */
1233 : : static struct k_spinlock thread_cleanup_lock;
1234 : :
1235 : : #ifdef CONFIG_THREAD_STACK_MEM_MAPPED
1236 : : static void *thread_cleanup_stack_addr;
1237 : : static size_t thread_cleanup_stack_sz;
1238 : : #endif /* CONFIG_THREAD_STACK_MEM_MAPPED */
1239 : :
1240 : : void defer_thread_cleanup(struct k_thread *thread)
1241 : : {
1242 : : /* Note when adding new deferred cleanup steps:
1243 : : * - The thread object may have been overwritten by the time
1244 : : * the actual cleanup is being done (e.g. thread object
1245 : : * allocated on a stack). So stash any necessary data here
1246 : : * that will be used in the actual cleanup steps.
1247 : : */
1248 : : thread_to_cleanup = thread;
1249 : :
1250 : : #ifdef CONFIG_THREAD_STACK_MEM_MAPPED
1251 : : /* Note that the permission of the stack should have been
1252 : : * stripped of user thread access due to the thread having
1253 : : * already exited from a memory domain. That is done via
1254 : : * k_thread_abort().
1255 : : */
1256 : :
1257 : : /* Stash the address and size so the region can be unmapped
1258 : : * later.
1259 : : */
1260 : : thread_cleanup_stack_addr = thread->stack_info.mapped.addr;
1261 : : thread_cleanup_stack_sz = thread->stack_info.mapped.sz;
1262 : :
1263 : : /* The stack is now considered un-usable. This should prevent any functions
1264 : : * from looking directly into the mapped stack if they are made to be aware
1265 : : * of memory mapped stacks, e.g., z_stack_space_get().
1266 : : */
1267 : : thread->stack_info.mapped.addr = NULL;
1268 : : thread->stack_info.mapped.sz = 0;
1269 : : #endif /* CONFIG_THREAD_STACK_MEM_MAPPED */
1270 : : }
1271 : :
1272 : : void do_thread_cleanup(struct k_thread *thread)
1273 : : {
1274 : : /* Note when adding new actual cleanup steps:
1275 : : * - The thread object may have been overwritten when this is
1276 : : * called. So avoid using any data from the thread object.
1277 : : */
1278 : : ARG_UNUSED(thread);
1279 : :
1280 : : #ifdef CONFIG_THREAD_STACK_MEM_MAPPED
1281 : : if (thread_cleanup_stack_addr != NULL) {
1282 : : k_mem_unmap_phys_guard(thread_cleanup_stack_addr,
1283 : : thread_cleanup_stack_sz, false);
1284 : :
1285 : : thread_cleanup_stack_addr = NULL;
1286 : : }
1287 : : #endif /* CONFIG_THREAD_STACK_MEM_MAPPED */
1288 : : }
1289 : :
1290 : : void k_thread_abort_cleanup(struct k_thread *thread)
1291 : : {
1292 : : K_SPINLOCK(&thread_cleanup_lock) {
1293 : : if (thread_to_cleanup != NULL) {
1294 : : /* Finish the pending one first. */
1295 : : do_thread_cleanup(thread_to_cleanup);
1296 : : thread_to_cleanup = NULL;
1297 : : }
1298 : :
1299 : : if (thread == _current) {
1300 : : /* Need to defer for current running thread as the cleanup
1301 : : * might result in exception. Actual cleanup will be done
1302 : : * at the next time k_thread_abort() is called, or at thread
1303 : : * creation if the same thread object is being reused. This
1304 : : * is to make sure the cleanup code no longer needs this
1305 : : * thread's stack. This is not exactly ideal as the stack
1306 : : * may still be memory mapped for a while. However, this is
1307 : : * a simple solution without a) the need to workaround
1308 : : * the schedule lock during k_thread_abort(), b) creating
1309 : : * another thread to perform the cleanup, and c) does not
1310 : : * require architecture code support (e.g. via exception).
1311 : : */
1312 : : defer_thread_cleanup(thread);
1313 : : } else {
1314 : : /* Not the current running thread, so we are safe to do
1315 : : * cleanups.
1316 : : */
1317 : : do_thread_cleanup(thread);
1318 : : }
1319 : : }
1320 : : }
1321 : :
1322 : : void k_thread_abort_cleanup_check_reuse(struct k_thread *thread)
1323 : : {
1324 : : K_SPINLOCK(&thread_cleanup_lock) {
1325 : : /* This is to guard reuse of the same thread object and make sure
1326 : : * any pending cleanups of it needs to be finished before the thread
1327 : : * object can be reused.
1328 : : */
1329 : : if (thread_to_cleanup == thread) {
1330 : : do_thread_cleanup(thread_to_cleanup);
1331 : : thread_to_cleanup = NULL;
1332 : : }
1333 : : }
1334 : : }
1335 : :
1336 : : #endif /* CONFIG_THREAD_ABORT_NEED_CLEANUP */
1337 : :
1338 : 1 : void z_dummy_thread_init(struct k_thread *dummy_thread)
1339 : : {
1340 : 1 : dummy_thread->base.thread_state = _THREAD_DUMMY;
1341 : : #ifdef CONFIG_SCHED_CPU_MASK
1342 : 1 : dummy_thread->base.cpu_mask = -1;
1343 : : #endif /* CONFIG_SCHED_CPU_MASK */
1344 : 1 : dummy_thread->base.user_options = K_ESSENTIAL;
1345 : : #ifdef CONFIG_THREAD_STACK_INFO
1346 : : dummy_thread->stack_info.start = 0U;
1347 : : dummy_thread->stack_info.size = 0U;
1348 : : #endif /* CONFIG_THREAD_STACK_INFO */
1349 : : #ifdef CONFIG_USERSPACE
1350 : : dummy_thread->mem_domain_info.mem_domain = &k_mem_domain_default;
1351 : : #endif /* CONFIG_USERSPACE */
1352 : : #if (K_HEAP_MEM_POOL_SIZE > 0)
1353 : : k_thread_system_pool_assign(dummy_thread);
1354 : : #else
1355 : 1 : dummy_thread->resource_pool = NULL;
1356 : : #endif /* K_HEAP_MEM_POOL_SIZE */
1357 : :
1358 : : #ifdef CONFIG_USE_SWITCH
1359 : : dummy_thread->switch_handle = NULL;
1360 : : #endif /* CONFIG_USE_SWITCH */
1361 : :
1362 : : #ifdef CONFIG_TIMESLICE_PER_THREAD
1363 : : dummy_thread->base.slice_ticks = 0;
1364 : : #endif /* CONFIG_TIMESLICE_PER_THREAD */
1365 : :
1366 : 1 : z_current_thread_set(dummy_thread);
1367 : 1 : }
|