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 */
arch_new_thread(struct k_thread * thread,k_thread_stack_t * stack,char * stack_ptr,k_thread_entry_t entry,void * p1,void * p2,void * p3)32 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 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 thread_status = Z_STACK_PTR_TO_FRAME(posix_thread_status_t, stack_ptr);
43
44 /* z_thread_entry() arguments */
45 thread_status->entry_point = entry;
46 thread_status->arg1 = p1;
47 thread_status->arg2 = p2;
48 thread_status->arg3 = p3;
49 #if defined(CONFIG_ARCH_HAS_THREAD_ABORT)
50 thread_status->aborted = 0;
51 #endif
52
53 thread->callee_saved.thread_status = thread_status;
54
55 thread_status->thread_idx = posix_new_thread((void *)thread_status);
56 }
57
arch_thread_name_set(struct k_thread * thread,const char * str)58 int arch_thread_name_set(struct k_thread *thread, const char *str)
59 {
60 #define MAX_HOST_THREAD_NAME 16
61
62 int ret;
63 int thread_index;
64 posix_thread_status_t *thread_status;
65 char th_name[MAX_HOST_THREAD_NAME];
66
67 thread_status = thread->callee_saved.thread_status;
68 if (!thread_status) {
69 return -EAGAIN;
70 }
71
72 thread_index = thread_status->thread_idx;
73
74 if (!str) {
75 return -EAGAIN;
76 }
77
78 snprintf(th_name, MAX_HOST_THREAD_NAME,
79 #if (CONFIG_NATIVE_SIMULATOR_NUMBER_MCUS > 1)
80 STRINGIFY(CONFIG_NATIVE_SIMULATOR_MCU_N) ":"
81 #endif
82 "%s", str);
83
84 ret = posix_arch_thread_name_set(thread_index, th_name);
85 if (ret) {
86 return -EAGAIN;
87 }
88
89 return 0;
90 }
91
posix_arch_thread_entry(void * pa_thread_status)92 void posix_arch_thread_entry(void *pa_thread_status)
93 {
94 posix_thread_status_t *ptr = pa_thread_status;
95 posix_irq_full_unlock();
96 z_thread_entry(ptr->entry_point, ptr->arg1, ptr->arg2, ptr->arg3);
97 }
98
99 #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
arch_float_disable(struct k_thread * thread)100 int arch_float_disable(struct k_thread *thread)
101 {
102 ARG_UNUSED(thread);
103
104 /* Posix always has FPU enabled so cannot be disabled */
105 return -ENOTSUP;
106 }
107
arch_float_enable(struct k_thread * thread,unsigned int options)108 int arch_float_enable(struct k_thread *thread, unsigned int options)
109 {
110 ARG_UNUSED(thread);
111 ARG_UNUSED(options);
112
113 /* Posix always has FPU enabled so nothing to do here */
114 return 0;
115 }
116 #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */
117
118 #if defined(CONFIG_ARCH_HAS_THREAD_ABORT)
z_impl_k_thread_abort(k_tid_t thread)119 void z_impl_k_thread_abort(k_tid_t thread)
120 {
121 unsigned int key;
122 int thread_idx;
123
124 SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_thread, abort, thread);
125
126 posix_thread_status_t *tstatus =
127 (posix_thread_status_t *)
128 thread->callee_saved.thread_status;
129
130 thread_idx = tstatus->thread_idx;
131
132 key = irq_lock();
133
134 if (arch_current_thread() == thread) {
135 if (tstatus->aborted == 0) { /* LCOV_EXCL_BR_LINE */
136 tstatus->aborted = 1;
137 } else {
138 posix_print_warning(/* LCOV_EXCL_LINE */
139 "POSIX arch: The kernel is trying to abort and swap "
140 "out of an already aborted thread %i. This "
141 "should NOT have happened\n",
142 thread_idx);
143 }
144 posix_abort_thread(thread_idx);
145 }
146
147 z_thread_abort(thread);
148
149 if (tstatus->aborted == 0) {
150 PC_DEBUG("%s aborting now [%i] %i\n",
151 __func__,
152 posix_arch_get_unique_thread_id(thread_idx),
153 thread_idx);
154
155 tstatus->aborted = 1;
156 posix_abort_thread(thread_idx);
157 } else {
158 PC_DEBUG("%s ignoring re_abort of [%i] "
159 "%i\n",
160 __func__,
161 posix_arch_get_unique_thread_id(thread_idx),
162 thread_idx);
163 }
164
165 /* The abort handler might have altered the ready queue. */
166 z_reschedule_irqlock(key);
167
168 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_thread, abort, thread);
169 }
170 #endif
171