Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2010-2015 Wind River Systems, Inc.
3 : : * Copyright (c) 2017 Oticon A/S
4 : : *
5 : : * SPDX-License-Identifier: Apache-2.0
6 : : */
7 : :
8 : : /**
9 : : * @file
10 : : * @brief Thread support primitives
11 : : *
12 : : * This module provides core thread related primitives for the POSIX
13 : : * architecture
14 : : */
15 : :
16 : : #include <stdio.h>
17 : : #include <zephyr/toolchain.h>
18 : : #include <zephyr/kernel_structs.h>
19 : : #include <ksched.h>
20 : :
21 : : #include "posix_core.h"
22 : : #include <zephyr/arch/posix/posix_soc_if.h>
23 : :
24 : : #ifdef CONFIG_TRACING
25 : : #include <zephyr/tracing/tracing_macros.h>
26 : : #include <zephyr/tracing/tracing.h>
27 : : #endif
28 : :
29 : : /* Note that in this arch we cheat quite a bit: we use as stack a normal
30 : : * pthreads stack and therefore we ignore the stack size
31 : : */
32 : 48 : void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
33 : : char *stack_ptr, k_thread_entry_t entry,
34 : : void *p1, void *p2, void *p3)
35 : : {
36 : :
37 : 48 : posix_thread_status_t *thread_status;
38 : :
39 : : /* We store it in the same place where normal archs store the
40 : : * "initial stack frame"
41 : : */
42 : 48 : thread_status = Z_STACK_PTR_TO_FRAME(posix_thread_status_t, stack_ptr);
43 : :
44 : : /* z_thread_entry() arguments */
45 : 48 : thread_status->entry_point = entry;
46 : 48 : thread_status->arg1 = p1;
47 : 48 : thread_status->arg2 = p2;
48 : 48 : thread_status->arg3 = p3;
49 : : #if defined(CONFIG_ARCH_HAS_THREAD_ABORT)
50 : 48 : thread_status->aborted = 0;
51 : : #endif
52 : :
53 : 48 : thread->callee_saved.thread_status = thread_status;
54 : :
55 : 48 : thread_status->thread_idx = posix_new_thread((void *)thread_status);
56 : :
57 : : #ifdef CONFIG_ARCH_POSIX_UPDATE_STACK_INFO
58 : : /*
59 : : * Correct the stack_info to reflect the actual pthread stack.
60 : : * The POSIX arch uses native pthread stacks instead of the
61 : : * Zephyr-allocated stack, so stack_info needs to be updated.
62 : : * Save the original values so they can be restored during abort
63 : : * for consumers like CMSIS that derive thread identity from
64 : : * the stack address.
65 : : */
66 : : void *stack_addr;
67 : : unsigned long stack_size;
68 : :
69 : : thread_status->zephyr_stack_start = thread->stack_info.start;
70 : : thread_status->zephyr_stack_size = thread->stack_info.size;
71 : :
72 : : posix_arch_get_thread_stack(thread_status->thread_idx, &stack_addr, &stack_size);
73 : : thread->stack_info.start = (uintptr_t)stack_addr;
74 : : thread->stack_info.size = stack_size;
75 : : thread->stack_info.delta = 0;
76 : : #if defined(CONFIG_STACK_SENTINEL)
77 : : /* Set the stack sentinel again, but now where the kernel will check after updating the
78 : : * stack_info. This assumes the stack grows down, which is the case in most architectures
79 : : * including x86 and arm/aarch64.
80 : : */
81 : : *((uint32_t *)thread->stack_info.start) = STACK_SENTINEL;
82 : : #endif /* CONFIG_STACK_SENTINEL */
83 : : #endif /* CONFIG_ARCH_POSIX_UPDATE_STACK_INFO */
84 : 48 : }
85 : :
86 : 44 : int arch_thread_name_set(struct k_thread *thread, const char *str)
87 : : {
88 : : #define MAX_HOST_THREAD_NAME 16
89 : :
90 : 44 : int ret;
91 : 44 : int thread_index;
92 : 44 : posix_thread_status_t *thread_status;
93 : 44 : char th_name[MAX_HOST_THREAD_NAME];
94 : :
95 : 44 : thread_status = thread->callee_saved.thread_status;
96 [ - + ]: 44 : if (!thread_status) {
97 : : return -EAGAIN;
98 : : }
99 : :
100 : 44 : thread_index = thread_status->thread_idx;
101 : :
102 [ - + ]: 44 : if (!str) {
103 : : return -EAGAIN;
104 : : }
105 : :
106 : 44 : snprintf(th_name, MAX_HOST_THREAD_NAME,
107 : : #if (CONFIG_NATIVE_SIMULATOR_NUMBER_MCUS > 1)
108 : : STRINGIFY(CONFIG_NATIVE_SIMULATOR_MCU_N) ":"
109 : : #endif
110 : : "%s", str);
111 : :
112 : 44 : ret = posix_arch_thread_name_set(thread_index, th_name);
113 [ - + ]: 44 : if (ret) {
114 : : return -EAGAIN;
115 : : }
116 : :
117 : : return 0;
118 : : }
119 : :
120 : 47 : void posix_arch_thread_entry(void *pa_thread_status)
121 : : {
122 : 47 : posix_thread_status_t *ptr = pa_thread_status;
123 : 47 : posix_irq_full_unlock();
124 : 47 : z_thread_entry(ptr->entry_point, ptr->arg1, ptr->arg2, ptr->arg3);
125 : : }
126 : :
127 : : #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
128 : : int arch_float_disable(struct k_thread *thread)
129 : : {
130 : : ARG_UNUSED(thread);
131 : :
132 : : /* Posix always has FPU enabled so cannot be disabled */
133 : : return -ENOTSUP;
134 : : }
135 : :
136 : : int arch_float_enable(struct k_thread *thread, unsigned int options)
137 : : {
138 : : ARG_UNUSED(thread);
139 : : ARG_UNUSED(options);
140 : :
141 : : /* Posix always has FPU enabled so nothing to do here */
142 : : return 0;
143 : : }
144 : : #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */
145 : :
146 : 46 : int arch_coprocessors_disable(struct k_thread *thread)
147 : : {
148 : : /* Posix does not support coprocessors */
149 : 46 : return -ENOTSUP;
150 : : }
151 : :
152 : : #if defined(CONFIG_ARCH_HAS_THREAD_ABORT)
153 : 88 : void z_impl_k_thread_abort(k_tid_t thread)
154 : : {
155 : 88 : unsigned int key;
156 : 88 : int thread_idx;
157 : :
158 : 88 : SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_thread, abort, thread);
159 : :
160 : 88 : posix_thread_status_t *tstatus =
161 : : (posix_thread_status_t *)
162 : : thread->callee_saved.thread_status;
163 : :
164 : 88 : thread_idx = tstatus->thread_idx;
165 : :
166 : 88 : key = irq_lock();
167 : :
168 [ + + ]: 88 : if (_current == thread) {
169 : 46 : if (tstatus->aborted == 0) { /* LCOV_EXCL_BR_LINE */
170 : 46 : tstatus->aborted = 1;
171 : : } else {
172 : : posix_print_warning(/* LCOV_EXCL_LINE */
173 : : "POSIX arch: The kernel is trying to abort and swap "
174 : : "out of an already aborted thread %i. This "
175 : : "should NOT have happened\n",
176 : : thread_idx);
177 : : }
178 : 46 : posix_abort_thread(thread_idx);
179 : : }
180 : :
181 : : #ifdef CONFIG_ARCH_POSIX_UPDATE_STACK_INFO
182 : : /* Restore the original Zephyr stack info so that thread_abort_hook
183 : : * consumers (e.g. CMSIS) that derive thread identity from the
184 : : * stack address see the expected values.
185 : : */
186 : : thread->stack_info.start = tstatus->zephyr_stack_start;
187 : : thread->stack_info.size = tstatus->zephyr_stack_size;
188 : : #endif
189 : :
190 : 88 : z_thread_abort(thread);
191 : :
192 [ - + ]: 42 : if (tstatus->aborted == 0) {
193 : : PC_DEBUG("%s aborting now [%i] %i\n",
194 : : __func__,
195 : : posix_arch_get_unique_thread_id(thread_idx),
196 : 0 : thread_idx);
197 : :
198 : 0 : tstatus->aborted = 1;
199 : 0 : posix_abort_thread(thread_idx);
200 : : } else {
201 : : PC_DEBUG("%s ignoring re_abort of [%i] "
202 : : "%i\n",
203 : : __func__,
204 : : posix_arch_get_unique_thread_id(thread_idx),
205 : 42 : thread_idx);
206 : : }
207 : :
208 : : /* The abort handler might have altered the ready queue. */
209 : 42 : z_reschedule_irqlock(key);
210 : :
211 : 42 : SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_thread, abort, thread);
212 : 42 : }
213 : : #endif
|