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 <kernel.h>
15 : : #include <spinlock.h>
16 : : #include <sys/math_extras.h>
17 : : #include <sys_clock.h>
18 : : #include <ksched.h>
19 : : #include <wait_q.h>
20 : : #include <syscall_handler.h>
21 : : #include <kernel_internal.h>
22 : : #include <kswap.h>
23 : : #include <init.h>
24 : : #include <tracing/tracing.h>
25 : : #include <string.h>
26 : : #include <stdbool.h>
27 : : #include <irq_offload.h>
28 : : #include <sys/check.h>
29 : : #include <random/rand32.h>
30 : : #include <sys/atomic.h>
31 : : #include <logging/log.h>
32 : : LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
33 : :
34 : : #ifdef CONFIG_THREAD_MONITOR
35 : : /* This lock protects the linked list of active threads; i.e. the
36 : : * initial _kernel.threads pointer and the linked list made up of
37 : : * thread->next_thread (until NULL)
38 : : */
39 : : static struct k_spinlock z_thread_monitor_lock;
40 : : #endif /* CONFIG_THREAD_MONITOR */
41 : :
42 : : #define _FOREACH_STATIC_THREAD(thread_data) \
43 : : STRUCT_SECTION_FOREACH(_static_thread_data, thread_data)
44 : :
45 : 0 : void k_thread_foreach(k_thread_user_cb_t user_cb, void *user_data)
46 : : {
47 : : #if defined(CONFIG_THREAD_MONITOR)
48 : : struct k_thread *thread;
49 : : k_spinlock_key_t key;
50 : :
51 : : __ASSERT(user_cb != NULL, "user_cb can not be NULL");
52 : :
53 : : /*
54 : : * Lock is needed to make sure that the _kernel.threads is not being
55 : : * modified by the user_cb either directly or indirectly.
56 : : * The indirect ways are through calling k_thread_create and
57 : : * k_thread_abort from user_cb.
58 : : */
59 : : key = k_spin_lock(&z_thread_monitor_lock);
60 : :
61 : : SYS_PORT_TRACING_FUNC_ENTER(k_thread, foreach);
62 : :
63 : : for (thread = _kernel.threads; thread; thread = thread->next_thread) {
64 : : user_cb(thread, user_data);
65 : : }
66 : :
67 : : SYS_PORT_TRACING_FUNC_EXIT(k_thread, foreach);
68 : :
69 : : k_spin_unlock(&z_thread_monitor_lock, key);
70 : : #endif
71 : 0 : }
72 : :
73 : 0 : void k_thread_foreach_unlocked(k_thread_user_cb_t user_cb, void *user_data)
74 : : {
75 : : #if defined(CONFIG_THREAD_MONITOR)
76 : : struct k_thread *thread;
77 : : k_spinlock_key_t key;
78 : :
79 : : __ASSERT(user_cb != NULL, "user_cb can not be NULL");
80 : :
81 : : key = k_spin_lock(&z_thread_monitor_lock);
82 : :
83 : : SYS_PORT_TRACING_FUNC_ENTER(k_thread, foreach_unlocked);
84 : :
85 : : for (thread = _kernel.threads; thread; thread = thread->next_thread) {
86 : : k_spin_unlock(&z_thread_monitor_lock, key);
87 : : user_cb(thread, user_data);
88 : : key = k_spin_lock(&z_thread_monitor_lock);
89 : : }
90 : :
91 : : SYS_PORT_TRACING_FUNC_EXIT(k_thread, foreach_unlocked);
92 : :
93 : : k_spin_unlock(&z_thread_monitor_lock, key);
94 : : #endif
95 : 0 : }
96 : :
97 : 44318 : bool k_is_in_isr(void)
98 : : {
99 : 44318 : return arch_is_in_isr();
100 : : }
101 : :
102 : : /*
103 : : * This function tags the current thread as essential to system operation.
104 : : * Exceptions raised by this thread will be treated as a fatal system error.
105 : : */
106 : 0 : void z_thread_essential_set(void)
107 : : {
108 : 0 : _current->base.user_options |= K_ESSENTIAL;
109 : 0 : }
110 : :
111 : : /*
112 : : * This function tags the current thread as not essential to system operation.
113 : : * Exceptions raised by this thread may be recoverable.
114 : : * (This is the default tag for a thread.)
115 : : */
116 : 0 : void z_thread_essential_clear(void)
117 : : {
118 : 0 : _current->base.user_options &= ~K_ESSENTIAL;
119 : 0 : }
120 : :
121 : : /*
122 : : * This routine indicates if the current thread is an essential system thread.
123 : : *
124 : : * Returns true if current thread is essential, false if it is not.
125 : : */
126 : 0 : bool z_is_thread_essential(void)
127 : : {
128 : 0 : return (_current->base.user_options & K_ESSENTIAL) == K_ESSENTIAL;
129 : : }
130 : :
131 : : #ifdef CONFIG_THREAD_CUSTOM_DATA
132 : : void z_impl_k_thread_custom_data_set(void *value)
133 : : {
134 : : _current->custom_data = value;
135 : : }
136 : :
137 : : #ifdef CONFIG_USERSPACE
138 : : static inline void z_vrfy_k_thread_custom_data_set(void *data)
139 : : {
140 : : z_impl_k_thread_custom_data_set(data);
141 : : }
142 : : #include <syscalls/k_thread_custom_data_set_mrsh.c>
143 : : #endif
144 : :
145 : : void *z_impl_k_thread_custom_data_get(void)
146 : : {
147 : : return _current->custom_data;
148 : : }
149 : :
150 : : #ifdef CONFIG_USERSPACE
151 : : static inline void *z_vrfy_k_thread_custom_data_get(void)
152 : : {
153 : : return z_impl_k_thread_custom_data_get();
154 : : }
155 : : #include <syscalls/k_thread_custom_data_get_mrsh.c>
156 : :
157 : : #endif /* CONFIG_USERSPACE */
158 : : #endif /* CONFIG_THREAD_CUSTOM_DATA */
159 : :
160 : : #if defined(CONFIG_THREAD_MONITOR)
161 : : /*
162 : : * Remove a thread from the kernel's list of active threads.
163 : : */
164 : : void z_thread_monitor_exit(struct k_thread *thread)
165 : : {
166 : : k_spinlock_key_t key = k_spin_lock(&z_thread_monitor_lock);
167 : :
168 : : if (thread == _kernel.threads) {
169 : : _kernel.threads = _kernel.threads->next_thread;
170 : : } else {
171 : : struct k_thread *prev_thread;
172 : :
173 : : prev_thread = _kernel.threads;
174 : : while ((prev_thread != NULL) &&
175 : : (thread != prev_thread->next_thread)) {
176 : : prev_thread = prev_thread->next_thread;
177 : : }
178 : : if (prev_thread != NULL) {
179 : : prev_thread->next_thread = thread->next_thread;
180 : : }
181 : : }
182 : :
183 : : k_spin_unlock(&z_thread_monitor_lock, key);
184 : : }
185 : : #endif
186 : :
187 : 1 : int z_impl_k_thread_name_set(struct k_thread *thread, const char *value)
188 : : {
189 : : #ifdef CONFIG_THREAD_NAME
190 [ - + ]: 1 : if (thread == NULL) {
191 : 0 : thread = _current;
192 : : }
193 : :
194 : 1 : strncpy(thread->name, value, CONFIG_THREAD_MAX_NAME_LEN - 1);
195 : 1 : thread->name[CONFIG_THREAD_MAX_NAME_LEN - 1] = '\0';
196 : :
197 : : SYS_PORT_TRACING_OBJ_FUNC(k_thread, name_set, thread, 0);
198 : :
199 : 1 : return 0;
200 : : #else
201 : : ARG_UNUSED(thread);
202 : : ARG_UNUSED(value);
203 : :
204 : : SYS_PORT_TRACING_OBJ_FUNC(k_thread, name_set, thread, -ENOSYS);
205 : :
206 : : return -ENOSYS;
207 : : #endif /* CONFIG_THREAD_NAME */
208 : : }
209 : :
210 : : #ifdef CONFIG_USERSPACE
211 : : static inline int z_vrfy_k_thread_name_set(struct k_thread *thread, const char *str)
212 : : {
213 : : #ifdef CONFIG_THREAD_NAME
214 : : char name[CONFIG_THREAD_MAX_NAME_LEN];
215 : :
216 : : if (thread != NULL) {
217 : : if (Z_SYSCALL_OBJ(thread, K_OBJ_THREAD) != 0) {
218 : : return -EINVAL;
219 : : }
220 : : }
221 : :
222 : : /* In theory we could copy directly into thread->name, but
223 : : * the current z_vrfy / z_impl split does not provide a
224 : : * means of doing so.
225 : : */
226 : : if (z_user_string_copy(name, (char *)str, sizeof(name)) != 0) {
227 : : return -EFAULT;
228 : : }
229 : :
230 : : return z_impl_k_thread_name_set(thread, name);
231 : : #else
232 : : return -ENOSYS;
233 : : #endif /* CONFIG_THREAD_NAME */
234 : : }
235 : : #include <syscalls/k_thread_name_set_mrsh.c>
236 : : #endif /* CONFIG_USERSPACE */
237 : :
238 : 0 : const char *k_thread_name_get(struct k_thread *thread)
239 : : {
240 : : #ifdef CONFIG_THREAD_NAME
241 : 0 : return (const char *)thread->name;
242 : : #else
243 : : ARG_UNUSED(thread);
244 : : return NULL;
245 : : #endif /* CONFIG_THREAD_NAME */
246 : : }
247 : :
248 : 0 : int z_impl_k_thread_name_copy(k_tid_t thread, char *buf, size_t size)
249 : : {
250 : : #ifdef CONFIG_THREAD_NAME
251 : 0 : strncpy(buf, thread->name, size);
252 : 0 : return 0;
253 : : #else
254 : : ARG_UNUSED(thread);
255 : : ARG_UNUSED(buf);
256 : : ARG_UNUSED(size);
257 : : return -ENOSYS;
258 : : #endif /* CONFIG_THREAD_NAME */
259 : : }
260 : :
261 : 0 : const char *k_thread_state_str(k_tid_t thread_id)
262 : : {
263 [ # # # # : 0 : switch (thread_id->base.thread_state) {
# # # #
# ]
264 : 0 : case 0:
265 : 0 : return "";
266 : 0 : case _THREAD_DUMMY:
267 : 0 : return "dummy";
268 : 0 : case _THREAD_PENDING:
269 : 0 : return "pending";
270 : 0 : case _THREAD_PRESTART:
271 : 0 : return "prestart";
272 : 0 : case _THREAD_DEAD:
273 : 0 : return "dead";
274 : 0 : case _THREAD_SUSPENDED:
275 : 0 : return "suspended";
276 : 0 : case _THREAD_ABORTING:
277 : 0 : return "aborting";
278 : 0 : case _THREAD_QUEUED:
279 : 0 : return "queued";
280 : 0 : default:
281 : : /* Add a break, some day when another case gets added at the end,
282 : : * this bit of defensive programming will be useful
283 : : */
284 : 0 : break;
285 : : }
286 : 0 : return "unknown";
287 : : }
288 : :
289 : : #ifdef CONFIG_USERSPACE
290 : : static inline int z_vrfy_k_thread_name_copy(k_tid_t thread,
291 : : char *buf, size_t size)
292 : : {
293 : : #ifdef CONFIG_THREAD_NAME
294 : : size_t len;
295 : : struct z_object *ko = z_object_find(thread);
296 : :
297 : : /* Special case: we allow reading the names of initialized threads
298 : : * even if we don't have permission on them
299 : : */
300 : : if (thread == NULL || ko->type != K_OBJ_THREAD ||
301 : : (ko->flags & K_OBJ_FLAG_INITIALIZED) == 0) {
302 : : return -EINVAL;
303 : : }
304 : : if (Z_SYSCALL_MEMORY_WRITE(buf, size) != 0) {
305 : : return -EFAULT;
306 : : }
307 : : len = strlen(thread->name);
308 : : if (len + 1 > size) {
309 : : return -ENOSPC;
310 : : }
311 : :
312 : : return z_user_to_copy((void *)buf, thread->name, len + 1);
313 : : #else
314 : : ARG_UNUSED(thread);
315 : : ARG_UNUSED(buf);
316 : : ARG_UNUSED(size);
317 : : return -ENOSYS;
318 : : #endif /* CONFIG_THREAD_NAME */
319 : : }
320 : : #include <syscalls/k_thread_name_copy_mrsh.c>
321 : : #endif /* CONFIG_USERSPACE */
322 : :
323 : :
324 : : #ifdef CONFIG_MULTITHREADING
325 : : #ifdef CONFIG_STACK_SENTINEL
326 : : /* Check that the stack sentinel is still present
327 : : *
328 : : * The stack sentinel feature writes a magic value to the lowest 4 bytes of
329 : : * the thread's stack when the thread is initialized. This value gets checked
330 : : * in a few places:
331 : : *
332 : : * 1) In k_yield() if the current thread is not swapped out
333 : : * 2) After servicing a non-nested interrupt
334 : : * 3) In z_swap(), check the sentinel in the outgoing thread
335 : : *
336 : : * Item 2 requires support in arch/ code.
337 : : *
338 : : * If the check fails, the thread will be terminated appropriately through
339 : : * the system fatal error handler.
340 : : */
341 : : void z_check_stack_sentinel(void)
342 : : {
343 : : uint32_t *stack;
344 : :
345 : : if ((_current->base.thread_state & _THREAD_DUMMY) != 0) {
346 : : return;
347 : : }
348 : :
349 : : stack = (uint32_t *)_current->stack_info.start;
350 : : if (*stack != STACK_SENTINEL) {
351 : : /* Restore it so further checks don't trigger this same error */
352 : : *stack = STACK_SENTINEL;
353 : : z_except_reason(K_ERR_STACK_CHK_FAIL);
354 : : }
355 : : }
356 : : #endif /* CONFIG_STACK_SENTINEL */
357 : :
358 : 1 : void z_impl_k_thread_start(struct k_thread *thread)
359 : : {
360 : : SYS_PORT_TRACING_OBJ_FUNC(k_thread, start, thread);
361 : :
362 : 1 : z_sched_start(thread);
363 : 1 : }
364 : :
365 : : #ifdef CONFIG_USERSPACE
366 : : static inline void z_vrfy_k_thread_start(struct k_thread *thread)
367 : : {
368 : : Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD));
369 : : return z_impl_k_thread_start(thread);
370 : : }
371 : : #include <syscalls/k_thread_start_mrsh.c>
372 : : #endif
373 : : #endif
374 : :
375 : : #ifdef CONFIG_MULTITHREADING
376 : 0 : static void schedule_new_thread(struct k_thread *thread, k_timeout_t delay)
377 : : {
378 : : #ifdef CONFIG_SYS_CLOCK_EXISTS
379 [ # # ]: 0 : if (K_TIMEOUT_EQ(delay, K_NO_WAIT)) {
380 : 0 : k_thread_start(thread);
381 : : } else {
382 : 0 : z_add_thread_timeout(thread, delay);
383 : : }
384 : : #else
385 : : ARG_UNUSED(delay);
386 : : k_thread_start(thread);
387 : : #endif
388 : 0 : }
389 : : #endif
390 : :
391 : : #if CONFIG_STACK_POINTER_RANDOM
392 : : int z_stack_adjust_initialized;
393 : :
394 : : static size_t random_offset(size_t stack_size)
395 : : {
396 : : size_t random_val;
397 : :
398 : : if (!z_stack_adjust_initialized) {
399 : : z_early_boot_rand_get((uint8_t *)&random_val, sizeof(random_val));
400 : : } else {
401 : : sys_rand_get((uint8_t *)&random_val, sizeof(random_val));
402 : : }
403 : :
404 : : /* Don't need to worry about alignment of the size here,
405 : : * arch_new_thread() is required to do it.
406 : : *
407 : : * FIXME: Not the best way to get a random number in a range.
408 : : * See #6493
409 : : */
410 : : const size_t fuzz = random_val % CONFIG_STACK_POINTER_RANDOM;
411 : :
412 : : if (unlikely(fuzz * 2 > stack_size)) {
413 : : return 0;
414 : : }
415 : :
416 : : return fuzz;
417 : : }
418 : : #if defined(CONFIG_STACK_GROWS_UP)
419 : : /* This is so rare not bothering for now */
420 : : #error "Stack pointer randomization not implemented for upward growing stacks"
421 : : #endif /* CONFIG_STACK_GROWS_UP */
422 : : #endif /* CONFIG_STACK_POINTER_RANDOM */
423 : :
424 : 3 : static char *setup_thread_stack(struct k_thread *new_thread,
425 : : k_thread_stack_t *stack, size_t stack_size)
426 : : {
427 : : size_t stack_obj_size, stack_buf_size;
428 : : char *stack_ptr, *stack_buf_start;
429 : 3 : size_t delta = 0;
430 : :
431 : : #ifdef CONFIG_USERSPACE
432 : : if (z_stack_is_user_capable(stack)) {
433 : : stack_obj_size = Z_THREAD_STACK_SIZE_ADJUST(stack_size);
434 : : stack_buf_start = Z_THREAD_STACK_BUFFER(stack);
435 : : stack_buf_size = stack_obj_size - K_THREAD_STACK_RESERVED;
436 : : } else
437 : : #endif
438 : : {
439 : : /* Object cannot host a user mode thread */
440 : 3 : stack_obj_size = Z_KERNEL_STACK_SIZE_ADJUST(stack_size);
441 : 3 : stack_buf_start = Z_KERNEL_STACK_BUFFER(stack);
442 : 3 : stack_buf_size = stack_obj_size - K_KERNEL_STACK_RESERVED;
443 : : }
444 : :
445 : : /* Initial stack pointer at the high end of the stack object, may
446 : : * be reduced later in this function by TLS or random offset
447 : : */
448 : 3 : stack_ptr = (char *)stack + stack_obj_size;
449 : :
450 [ + - ]: 3 : LOG_DBG("stack %p for thread %p: obj_size=%zu buf_start=%p "
451 : : " buf_size %zu stack_ptr=%p",
452 : : stack, new_thread, stack_obj_size, stack_buf_start,
453 : : stack_buf_size, stack_ptr);
454 : :
455 : : #ifdef CONFIG_INIT_STACKS
456 : : memset(stack_buf_start, 0xaa, stack_buf_size);
457 : : #endif
458 : : #ifdef CONFIG_STACK_SENTINEL
459 : : /* Put the stack sentinel at the lowest 4 bytes of the stack area.
460 : : * We periodically check that it's still present and kill the thread
461 : : * if it isn't.
462 : : */
463 : : *((uint32_t *)stack_buf_start) = STACK_SENTINEL;
464 : : #endif /* CONFIG_STACK_SENTINEL */
465 : : #ifdef CONFIG_THREAD_LOCAL_STORAGE
466 : : /* TLS is always last within the stack buffer */
467 : : delta += arch_tls_stack_setup(new_thread, stack_ptr);
468 : : #endif /* CONFIG_THREAD_LOCAL_STORAGE */
469 : : #ifdef CONFIG_THREAD_USERSPACE_LOCAL_DATA
470 : : size_t tls_size = sizeof(struct _thread_userspace_local_data);
471 : :
472 : : /* reserve space on highest memory of stack buffer for local data */
473 : : delta += tls_size;
474 : : new_thread->userspace_local_data =
475 : : (struct _thread_userspace_local_data *)(stack_ptr - delta);
476 : : #endif
477 : : #if CONFIG_STACK_POINTER_RANDOM
478 : : delta += random_offset(stack_buf_size);
479 : : #endif
480 : 3 : delta = ROUND_UP(delta, ARCH_STACK_PTR_ALIGN);
481 : : #ifdef CONFIG_THREAD_STACK_INFO
482 : : /* Initial values. Arches which implement MPU guards that "borrow"
483 : : * memory from the stack buffer (not tracked in K_THREAD_STACK_RESERVED)
484 : : * will need to appropriately update this.
485 : : *
486 : : * The bounds tracked here correspond to the area of the stack object
487 : : * that the thread can access, which includes TLS.
488 : : */
489 : 3 : new_thread->stack_info.start = (uintptr_t)stack_buf_start;
490 : 3 : new_thread->stack_info.size = stack_buf_size;
491 : 3 : new_thread->stack_info.delta = delta;
492 : : #endif
493 : 3 : stack_ptr -= delta;
494 : :
495 : 3 : return stack_ptr;
496 : : }
497 : :
498 : : /*
499 : : * The provided stack_size value is presumed to be either the result of
500 : : * K_THREAD_STACK_SIZEOF(stack), or the size value passed to the instance
501 : : * of K_THREAD_STACK_DEFINE() which defined 'stack'.
502 : : */
503 : 3 : char *z_setup_new_thread(struct k_thread *new_thread,
504 : : k_thread_stack_t *stack, size_t stack_size,
505 : : k_thread_entry_t entry,
506 : : void *p1, void *p2, void *p3,
507 : : int prio, uint32_t options, const char *name)
508 : : {
509 : : char *stack_ptr;
510 : :
511 [ + + - + : 3 : Z_ASSERT_VALID_PRIO(prio, entry);
+ - - + ]
512 : :
513 : : #ifdef CONFIG_USERSPACE
514 : : __ASSERT((options & K_USER) == 0U || z_stack_is_user_capable(stack),
515 : : "user thread %p with kernel-only stack %p",
516 : : new_thread, stack);
517 : : z_object_init(new_thread);
518 : : z_object_init(stack);
519 : : new_thread->stack_obj = stack;
520 : : new_thread->syscall_frame = NULL;
521 : :
522 : : /* Any given thread has access to itself */
523 : : k_object_access_grant(new_thread, new_thread);
524 : : #endif
525 : 3 : z_waitq_init(&new_thread->join_queue);
526 : :
527 : : /* Initialize various struct k_thread members */
528 : 3 : z_init_thread_base(&new_thread->base, prio, _THREAD_PRESTART, options);
529 : 3 : stack_ptr = setup_thread_stack(new_thread, stack, stack_size);
530 : :
531 : : #ifdef CONFIG_KERNEL_COHERENCE
532 : : /* Check that the thread object is safe, but that the stack is
533 : : * still cached!
534 : : */
535 : : __ASSERT_NO_MSG(arch_mem_coherent(new_thread));
536 : : __ASSERT_NO_MSG(!arch_mem_coherent(stack));
537 : : #endif
538 : :
539 : 3 : arch_new_thread(new_thread, stack, stack_ptr, entry, p1, p2, p3);
540 : :
541 : : /* static threads overwrite it afterwards with real value */
542 : 3 : new_thread->init_data = NULL;
543 : :
544 : : #ifdef CONFIG_USE_SWITCH
545 : : /* switch_handle must be non-null except when inside z_swap()
546 : : * for synchronization reasons. Historically some notional
547 : : * USE_SWITCH architectures have actually ignored the field
548 : : */
549 : : __ASSERT(new_thread->switch_handle != NULL,
550 : : "arch layer failed to initialize switch_handle");
551 : : #endif
552 : : #ifdef CONFIG_THREAD_CUSTOM_DATA
553 : : /* Initialize custom data field (value is opaque to kernel) */
554 : : new_thread->custom_data = NULL;
555 : : #endif
556 : : #ifdef CONFIG_THREAD_MONITOR
557 : : new_thread->entry.pEntry = entry;
558 : : new_thread->entry.parameter1 = p1;
559 : : new_thread->entry.parameter2 = p2;
560 : : new_thread->entry.parameter3 = p3;
561 : :
562 : : k_spinlock_key_t key = k_spin_lock(&z_thread_monitor_lock);
563 : :
564 : : new_thread->next_thread = _kernel.threads;
565 : : _kernel.threads = new_thread;
566 : : k_spin_unlock(&z_thread_monitor_lock, key);
567 : : #endif
568 : : #ifdef CONFIG_THREAD_NAME
569 [ + + ]: 3 : if (name != NULL) {
570 : 2 : strncpy(new_thread->name, name,
571 : : CONFIG_THREAD_MAX_NAME_LEN - 1);
572 : : /* Ensure NULL termination, truncate if longer */
573 : 2 : new_thread->name[CONFIG_THREAD_MAX_NAME_LEN - 1] = '\0';
574 : : } else {
575 : 1 : new_thread->name[0] = '\0';
576 : : }
577 : : #endif
578 : : #ifdef CONFIG_SCHED_CPU_MASK
579 : : if (IS_ENABLED(CONFIG_SCHED_CPU_MASK_PIN_ONLY)) {
580 : : new_thread->base.cpu_mask = 1; /* must specify only one cpu */
581 : : } else {
582 : : new_thread->base.cpu_mask = -1; /* allow all cpus */
583 : : }
584 : : #endif
585 : : #ifdef CONFIG_ARCH_HAS_CUSTOM_SWAP_TO_MAIN
586 : : /* _current may be null if the dummy thread is not used */
587 [ - + ]: 3 : if (!_current) {
588 : 0 : new_thread->resource_pool = NULL;
589 : 0 : return stack_ptr;
590 : : }
591 : : #endif
592 : : #ifdef CONFIG_USERSPACE
593 : : z_mem_domain_init_thread(new_thread);
594 : :
595 : : if ((options & K_INHERIT_PERMS) != 0U) {
596 : : z_thread_perms_inherit(_current, new_thread);
597 : : }
598 : : #endif
599 : : #ifdef CONFIG_SCHED_DEADLINE
600 : : new_thread->base.prio_deadline = 0;
601 : : #endif
602 : 3 : new_thread->resource_pool = _current->resource_pool;
603 : :
604 : : #ifdef CONFIG_SCHED_THREAD_USAGE
605 : : new_thread->base.usage = (struct k_cycle_stats) {};
606 : : new_thread->base.usage.track_usage =
607 : : CONFIG_SCHED_THREAD_USAGE_AUTO_ENABLE;
608 : : #endif
609 : :
610 : : SYS_PORT_TRACING_OBJ_FUNC(k_thread, create, new_thread);
611 : :
612 : 3 : return stack_ptr;
613 : : }
614 : :
615 : : #ifdef CONFIG_MULTITHREADING
616 : 1 : k_tid_t z_impl_k_thread_create(struct k_thread *new_thread,
617 : : k_thread_stack_t *stack,
618 : : size_t stack_size, k_thread_entry_t entry,
619 : : void *p1, void *p2, void *p3,
620 : : int prio, uint32_t options, k_timeout_t delay)
621 : : {
622 [ - + ]: 1 : __ASSERT(!arch_is_in_isr(), "Threads may not be created in ISRs");
623 : :
624 : 1 : z_setup_new_thread(new_thread, stack, stack_size, entry, p1, p2, p3,
625 : : prio, options, NULL);
626 : :
627 [ - + ]: 1 : if (!K_TIMEOUT_EQ(delay, K_FOREVER)) {
628 : 0 : schedule_new_thread(new_thread, delay);
629 : : }
630 : :
631 : 1 : return new_thread;
632 : : }
633 : :
634 : :
635 : : #ifdef CONFIG_USERSPACE
636 : : bool z_stack_is_user_capable(k_thread_stack_t *stack)
637 : : {
638 : : return z_object_find(stack) != NULL;
639 : : }
640 : :
641 : : k_tid_t z_vrfy_k_thread_create(struct k_thread *new_thread,
642 : : k_thread_stack_t *stack,
643 : : size_t stack_size, k_thread_entry_t entry,
644 : : void *p1, void *p2, void *p3,
645 : : int prio, uint32_t options, k_timeout_t delay)
646 : : {
647 : : size_t total_size, stack_obj_size;
648 : : struct z_object *stack_object;
649 : :
650 : : /* The thread and stack objects *must* be in an uninitialized state */
651 : : Z_OOPS(Z_SYSCALL_OBJ_NEVER_INIT(new_thread, K_OBJ_THREAD));
652 : :
653 : : /* No need to check z_stack_is_user_capable(), it won't be in the
654 : : * object table if it isn't
655 : : */
656 : : stack_object = z_object_find(stack);
657 : : Z_OOPS(Z_SYSCALL_VERIFY_MSG(z_obj_validation_check(stack_object, stack,
658 : : K_OBJ_THREAD_STACK_ELEMENT,
659 : : _OBJ_INIT_FALSE) == 0,
660 : : "bad stack object"));
661 : :
662 : : /* Verify that the stack size passed in is OK by computing the total
663 : : * size and comparing it with the size value in the object metadata
664 : : */
665 : : Z_OOPS(Z_SYSCALL_VERIFY_MSG(!size_add_overflow(K_THREAD_STACK_RESERVED,
666 : : stack_size, &total_size),
667 : : "stack size overflow (%zu+%zu)",
668 : : stack_size,
669 : : K_THREAD_STACK_RESERVED));
670 : :
671 : : /* Testing less-than-or-equal since additional room may have been
672 : : * allocated for alignment constraints
673 : : */
674 : : #ifdef CONFIG_GEN_PRIV_STACKS
675 : : stack_obj_size = stack_object->data.stack_data->size;
676 : : #else
677 : : stack_obj_size = stack_object->data.stack_size;
678 : : #endif
679 : : Z_OOPS(Z_SYSCALL_VERIFY_MSG(total_size <= stack_obj_size,
680 : : "stack size %zu is too big, max is %zu",
681 : : total_size, stack_obj_size));
682 : :
683 : : /* User threads may only create other user threads and they can't
684 : : * be marked as essential
685 : : */
686 : : Z_OOPS(Z_SYSCALL_VERIFY(options & K_USER));
687 : : Z_OOPS(Z_SYSCALL_VERIFY(!(options & K_ESSENTIAL)));
688 : :
689 : : /* Check validity of prio argument; must be the same or worse priority
690 : : * than the caller
691 : : */
692 : : Z_OOPS(Z_SYSCALL_VERIFY(_is_valid_prio(prio, NULL)));
693 : : Z_OOPS(Z_SYSCALL_VERIFY(z_is_prio_lower_or_equal(prio,
694 : : _current->base.prio)));
695 : :
696 : : z_setup_new_thread(new_thread, stack, stack_size,
697 : : entry, p1, p2, p3, prio, options, NULL);
698 : :
699 : : if (!K_TIMEOUT_EQ(delay, K_FOREVER)) {
700 : : schedule_new_thread(new_thread, delay);
701 : : }
702 : :
703 : : return new_thread;
704 : : }
705 : : #include <syscalls/k_thread_create_mrsh.c>
706 : : #endif /* CONFIG_USERSPACE */
707 : : #endif /* CONFIG_MULTITHREADING */
708 : :
709 : : #ifdef CONFIG_MULTITHREADING
710 : : #ifdef CONFIG_USERSPACE
711 : :
712 : : static void grant_static_access(void)
713 : : {
714 : : STRUCT_SECTION_FOREACH(z_object_assignment, pos) {
715 : : for (int i = 0; pos->objects[i] != NULL; i++) {
716 : : k_object_access_grant(pos->objects[i],
717 : : pos->thread);
718 : : }
719 : : }
720 : : }
721 : : #endif /* CONFIG_USERSPACE */
722 : :
723 : 1 : void z_init_static_threads(void)
724 : : {
725 [ - + - + ]: 1 : _FOREACH_STATIC_THREAD(thread_data) {
726 : 0 : z_setup_new_thread(
727 : : thread_data->init_thread,
728 : : thread_data->init_stack,
729 : : thread_data->init_stack_size,
730 : : thread_data->init_entry,
731 : : thread_data->init_p1,
732 : : thread_data->init_p2,
733 : : thread_data->init_p3,
734 : : thread_data->init_prio,
735 : : thread_data->init_options,
736 : : thread_data->init_name);
737 : :
738 : 0 : thread_data->init_thread->init_data = thread_data;
739 : : }
740 : :
741 : : #ifdef CONFIG_USERSPACE
742 : : grant_static_access();
743 : : #endif
744 : :
745 : : /*
746 : : * Non-legacy static threads may be started immediately or
747 : : * after a previously specified delay. Even though the
748 : : * scheduler is locked, ticks can still be delivered and
749 : : * processed. Take a sched lock to prevent them from running
750 : : * until they are all started.
751 : : *
752 : : * Note that static threads defined using the legacy API have a
753 : : * delay of K_FOREVER.
754 : : */
755 : 1 : k_sched_lock();
756 [ - + - + ]: 1 : _FOREACH_STATIC_THREAD(thread_data) {
757 [ # # ]: 0 : if (thread_data->init_delay != K_TICKS_FOREVER) {
758 : 0 : schedule_new_thread(thread_data->init_thread,
759 : 0 : K_MSEC(thread_data->init_delay));
760 : : }
761 : : }
762 : 1 : k_sched_unlock();
763 : 1 : }
764 : : #endif
765 : :
766 : 3 : void z_init_thread_base(struct _thread_base *thread_base, int priority,
767 : : uint32_t initial_state, unsigned int options)
768 : : {
769 : : /* k_q_node is initialized upon first insertion in a list */
770 : 3 : thread_base->pended_on = NULL;
771 : 3 : thread_base->user_options = (uint8_t)options;
772 : 3 : thread_base->thread_state = (uint8_t)initial_state;
773 : :
774 : 3 : thread_base->prio = priority;
775 : :
776 : 3 : thread_base->sched_locked = 0U;
777 : :
778 : : #ifdef CONFIG_SMP
779 : : thread_base->is_idle = 0;
780 : : #endif
781 : :
782 : : #ifdef CONFIG_TIMESLICE_PER_THREAD
783 : : thread_base->slice_ticks = 0;
784 : : thread_base->slice_expired = NULL;
785 : : #endif
786 : :
787 : : /* swap_data does not need to be initialized */
788 : :
789 : 3 : z_init_thread_timeout(thread_base);
790 : 3 : }
791 : :
792 : 0 : FUNC_NORETURN void k_thread_user_mode_enter(k_thread_entry_t entry,
793 : : void *p1, void *p2, void *p3)
794 : : {
795 : : SYS_PORT_TRACING_FUNC(k_thread, user_mode_enter);
796 : :
797 : 0 : _current->base.user_options |= K_USER;
798 : 0 : z_thread_essential_clear();
799 : : #ifdef CONFIG_THREAD_MONITOR
800 : : _current->entry.pEntry = entry;
801 : : _current->entry.parameter1 = p1;
802 : : _current->entry.parameter2 = p2;
803 : : _current->entry.parameter3 = p3;
804 : : #endif
805 : : #ifdef CONFIG_USERSPACE
806 : : __ASSERT(z_stack_is_user_capable(_current->stack_obj),
807 : : "dropping to user mode with kernel-only stack object");
808 : : #ifdef CONFIG_THREAD_USERSPACE_LOCAL_DATA
809 : : memset(_current->userspace_local_data, 0,
810 : : sizeof(struct _thread_userspace_local_data));
811 : : #endif
812 : : #ifdef CONFIG_THREAD_LOCAL_STORAGE
813 : : arch_tls_stack_setup(_current,
814 : : (char *)(_current->stack_info.start +
815 : : _current->stack_info.size));
816 : : #endif
817 : : arch_user_mode_enter(entry, p1, p2, p3);
818 : : #else
819 : : /* XXX In this case we do not reset the stack */
820 : 0 : z_thread_entry(entry, p1, p2, p3);
821 : : #endif
822 : : }
823 : :
824 : : /* These spinlock assertion predicates are defined here because having
825 : : * them in spinlock.h is a giant header ordering headache.
826 : : */
827 : : #ifdef CONFIG_SPIN_VALIDATE
828 : 45 : bool z_spin_lock_valid(struct k_spinlock *l)
829 : : {
830 : 45 : uintptr_t thread_cpu = l->thread_cpu;
831 : :
832 [ - + ]: 45 : if (thread_cpu != 0U) {
833 [ # # ]: 0 : if ((thread_cpu & 3U) == _current_cpu->id) {
834 : 0 : return false;
835 : : }
836 : : }
837 : 45 : return true;
838 : : }
839 : :
840 : 45 : bool z_spin_unlock_valid(struct k_spinlock *l)
841 : : {
842 [ - + ]: 45 : if (l->thread_cpu != (_current_cpu->id | (uintptr_t)_current)) {
843 : 0 : return false;
844 : : }
845 : 45 : l->thread_cpu = 0;
846 : 45 : return true;
847 : : }
848 : :
849 : 45 : void z_spin_lock_set_owner(struct k_spinlock *l)
850 : : {
851 : 45 : l->thread_cpu = _current_cpu->id | (uintptr_t)_current;
852 : 45 : }
853 : :
854 : : #ifdef CONFIG_KERNEL_COHERENCE
855 : : bool z_spin_lock_mem_coherent(struct k_spinlock *l)
856 : : {
857 : : return arch_mem_coherent((void *)l);
858 : : }
859 : : #endif /* CONFIG_KERNEL_COHERENCE */
860 : :
861 : : #endif /* CONFIG_SPIN_VALIDATE */
862 : :
863 : 0 : int z_impl_k_float_disable(struct k_thread *thread)
864 : : {
865 : : #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
866 : : return arch_float_disable(thread);
867 : : #else
868 : 0 : return -ENOTSUP;
869 : : #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */
870 : : }
871 : :
872 : 0 : int z_impl_k_float_enable(struct k_thread *thread, unsigned int options)
873 : : {
874 : : #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
875 : : return arch_float_enable(thread, options);
876 : : #else
877 : 0 : return -ENOTSUP;
878 : : #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */
879 : : }
880 : :
881 : : #ifdef CONFIG_USERSPACE
882 : : static inline int z_vrfy_k_float_disable(struct k_thread *thread)
883 : : {
884 : : Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD));
885 : : return z_impl_k_float_disable(thread);
886 : : }
887 : : #include <syscalls/k_float_disable_mrsh.c>
888 : : #endif /* CONFIG_USERSPACE */
889 : :
890 : : #ifdef CONFIG_IRQ_OFFLOAD
891 : : /* Make offload_sem visible outside under testing, in order to release
892 : : * it outside when error happened.
893 : : */
894 : : K_SEM_DEFINE(offload_sem, 1, 1);
895 : :
896 : : void irq_offload(irq_offload_routine_t routine, const void *parameter)
897 : : {
898 : : #ifdef CONFIG_IRQ_OFFLOAD_NESTED
899 : : arch_irq_offload(routine, parameter);
900 : : #else
901 : : k_sem_take(&offload_sem, K_FOREVER);
902 : : arch_irq_offload(routine, parameter);
903 : : k_sem_give(&offload_sem);
904 : : #endif
905 : : }
906 : : #endif
907 : :
908 : : #if defined(CONFIG_INIT_STACKS) && defined(CONFIG_THREAD_STACK_INFO)
909 : : #ifdef CONFIG_STACK_GROWS_UP
910 : : #error "Unsupported configuration for stack analysis"
911 : : #endif
912 : :
913 : : int z_stack_space_get(const uint8_t *stack_start, size_t size, size_t *unused_ptr)
914 : : {
915 : : size_t unused = 0;
916 : : const uint8_t *checked_stack = stack_start;
917 : : /* Take the address of any local variable as a shallow bound for the
918 : : * stack pointer. Addresses above it are guaranteed to be
919 : : * accessible.
920 : : */
921 : : const uint8_t *stack_pointer = (const uint8_t *)&stack_start;
922 : :
923 : : /* If we are currently running on the stack being analyzed, some
924 : : * memory management hardware will generate an exception if we
925 : : * read unused stack memory.
926 : : *
927 : : * This never happens when invoked from user mode, as user mode
928 : : * will always run this function on the privilege elevation stack.
929 : : */
930 : : if ((stack_pointer > stack_start) && (stack_pointer <= (stack_start + size)) &&
931 : : IS_ENABLED(CONFIG_NO_UNUSED_STACK_INSPECTION)) {
932 : : /* TODO: We could add an arch_ API call to temporarily
933 : : * disable the stack checking in the CPU, but this would
934 : : * need to be properly managed wrt context switches/interrupts
935 : : */
936 : : return -ENOTSUP;
937 : : }
938 : :
939 : : if (IS_ENABLED(CONFIG_STACK_SENTINEL)) {
940 : : /* First 4 bytes of the stack buffer reserved for the
941 : : * sentinel value, it won't be 0xAAAAAAAA for thread
942 : : * stacks.
943 : : *
944 : : * FIXME: thread->stack_info.start ought to reflect
945 : : * this!
946 : : */
947 : : checked_stack += 4;
948 : : size -= 4;
949 : : }
950 : :
951 : : for (size_t i = 0; i < size; i++) {
952 : : if ((checked_stack[i]) == 0xaaU) {
953 : : unused++;
954 : : } else {
955 : : break;
956 : : }
957 : : }
958 : :
959 : : *unused_ptr = unused;
960 : :
961 : : return 0;
962 : : }
963 : :
964 : : int z_impl_k_thread_stack_space_get(const struct k_thread *thread,
965 : : size_t *unused_ptr)
966 : : {
967 : : return z_stack_space_get((const uint8_t *)thread->stack_info.start,
968 : : thread->stack_info.size, unused_ptr);
969 : : }
970 : :
971 : : #ifdef CONFIG_USERSPACE
972 : : int z_vrfy_k_thread_stack_space_get(const struct k_thread *thread,
973 : : size_t *unused_ptr)
974 : : {
975 : : size_t unused;
976 : : int ret;
977 : :
978 : : ret = Z_SYSCALL_OBJ(thread, K_OBJ_THREAD);
979 : : CHECKIF(ret != 0) {
980 : : return ret;
981 : : }
982 : :
983 : : ret = z_impl_k_thread_stack_space_get(thread, &unused);
984 : : CHECKIF(ret != 0) {
985 : : return ret;
986 : : }
987 : :
988 : : ret = z_user_to_copy(unused_ptr, &unused, sizeof(size_t));
989 : : CHECKIF(ret != 0) {
990 : : return ret;
991 : : }
992 : :
993 : : return 0;
994 : : }
995 : : #include <syscalls/k_thread_stack_space_get_mrsh.c>
996 : : #endif /* CONFIG_USERSPACE */
997 : : #endif /* CONFIG_INIT_STACKS && CONFIG_THREAD_STACK_INFO */
998 : :
999 : : #ifdef CONFIG_USERSPACE
1000 : : static inline k_ticks_t z_vrfy_k_thread_timeout_remaining_ticks(
1001 : : const struct k_thread *t)
1002 : : {
1003 : : Z_OOPS(Z_SYSCALL_OBJ(t, K_OBJ_THREAD));
1004 : : return z_impl_k_thread_timeout_remaining_ticks(t);
1005 : : }
1006 : : #include <syscalls/k_thread_timeout_remaining_ticks_mrsh.c>
1007 : :
1008 : : static inline k_ticks_t z_vrfy_k_thread_timeout_expires_ticks(
1009 : : const struct k_thread *t)
1010 : : {
1011 : : Z_OOPS(Z_SYSCALL_OBJ(t, K_OBJ_THREAD));
1012 : : return z_impl_k_thread_timeout_expires_ticks(t);
1013 : : }
1014 : : #include <syscalls/k_thread_timeout_expires_ticks_mrsh.c>
1015 : : #endif
1016 : :
1017 : : #ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING
1018 : : void z_thread_mark_switched_in(void)
1019 : : {
1020 : : #if defined(CONFIG_SCHED_THREAD_USAGE) && !defined(CONFIG_USE_SWITCH)
1021 : : z_sched_usage_start(_current);
1022 : : #endif
1023 : :
1024 : : #ifdef CONFIG_TRACING
1025 : : SYS_PORT_TRACING_FUNC(k_thread, switched_in);
1026 : : #endif
1027 : : }
1028 : :
1029 : : void z_thread_mark_switched_out(void)
1030 : : {
1031 : : #if defined(CONFIG_SCHED_THREAD_USAGE) && !defined(CONFIG_USE_SWITCH)
1032 : : z_sched_usage_stop();
1033 : : #endif
1034 : :
1035 : : #ifdef CONFIG_TRACING
1036 : : SYS_PORT_TRACING_FUNC(k_thread, switched_out);
1037 : : #endif
1038 : : }
1039 : : #endif /* CONFIG_INSTRUMENT_THREAD_SWITCHING */
1040 : :
1041 : 0 : int k_thread_runtime_stats_get(k_tid_t thread,
1042 : : k_thread_runtime_stats_t *stats)
1043 : : {
1044 [ # # # # ]: 0 : if ((thread == NULL) || (stats == NULL)) {
1045 : 0 : return -EINVAL;
1046 : : }
1047 : :
1048 : : #ifdef CONFIG_SCHED_THREAD_USAGE
1049 : : z_sched_thread_usage(thread, stats);
1050 : : #else
1051 : 0 : *stats = (k_thread_runtime_stats_t) {};
1052 : : #endif
1053 : :
1054 : 0 : return 0;
1055 : : }
1056 : :
1057 : 0 : int k_thread_runtime_stats_all_get(k_thread_runtime_stats_t *stats)
1058 : : {
1059 : : #ifdef CONFIG_SCHED_THREAD_USAGE_ALL
1060 : : k_thread_runtime_stats_t tmp_stats;
1061 : : #endif
1062 : :
1063 [ # # ]: 0 : if (stats == NULL) {
1064 : 0 : return -EINVAL;
1065 : : }
1066 : :
1067 : 0 : *stats = (k_thread_runtime_stats_t) {};
1068 : :
1069 : : #ifdef CONFIG_SCHED_THREAD_USAGE_ALL
1070 : : /* Retrieve the usage stats for each core and amalgamate them. */
1071 : :
1072 : : for (uint8_t i = 0; i < CONFIG_MP_NUM_CPUS; i++) {
1073 : : z_sched_cpu_usage(i, &tmp_stats);
1074 : :
1075 : : stats->execution_cycles += tmp_stats.execution_cycles;
1076 : : stats->total_cycles += tmp_stats.total_cycles;
1077 : : #ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS
1078 : : stats->peak_cycles += tmp_stats.peak_cycles;
1079 : : stats->average_cycles += tmp_stats.average_cycles;
1080 : : #endif
1081 : : stats->idle_cycles += tmp_stats.idle_cycles;
1082 : : }
1083 : : #endif
1084 : :
1085 : 0 : return 0;
1086 : : }
|