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