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 <zephyr/toolchain.h>
17 #include <zephyr/kernel_structs.h>
18 #include <ksched.h>
19 
20 #include "posix_core.h"
21 #include <zephyr/arch/posix/posix_soc_if.h>
22 
23 /* Note that in this arch we cheat quite a bit: we use as stack a normal
24  * pthreads stack and therefore we ignore the stack size
25  */
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)26 void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
27 		     char *stack_ptr, k_thread_entry_t entry,
28 		     void *p1, void *p2, void *p3)
29 {
30 
31 	posix_thread_status_t *thread_status;
32 
33 	/* We store it in the same place where normal archs store the
34 	 * "initial stack frame"
35 	 */
36 	thread_status = Z_STACK_PTR_TO_FRAME(posix_thread_status_t, stack_ptr);
37 
38 	/* z_thread_entry() arguments */
39 	thread_status->entry_point = entry;
40 	thread_status->arg1 = p1;
41 	thread_status->arg2 = p2;
42 	thread_status->arg3 = p3;
43 #if defined(CONFIG_ARCH_HAS_THREAD_ABORT)
44 	thread_status->aborted = 0;
45 #endif
46 
47 	thread->callee_saved.thread_status = thread_status;
48 
49 	thread_status->thread_idx = posix_new_thread((void *)thread_status);
50 }
51 
posix_arch_thread_entry(void * pa_thread_status)52 void posix_arch_thread_entry(void *pa_thread_status)
53 {
54 	posix_thread_status_t *ptr = pa_thread_status;
55 	posix_irq_full_unlock();
56 	z_thread_entry(ptr->entry_point, ptr->arg1, ptr->arg2, ptr->arg3);
57 }
58 
59 #if defined(CONFIG_ARCH_HAS_THREAD_ABORT)
z_impl_k_thread_abort(k_tid_t thread)60 void z_impl_k_thread_abort(k_tid_t thread)
61 {
62 	unsigned int key;
63 	int thread_idx;
64 
65 	posix_thread_status_t *tstatus =
66 					(posix_thread_status_t *)
67 					thread->callee_saved.thread_status;
68 
69 	thread_idx = tstatus->thread_idx;
70 
71 	key = irq_lock();
72 
73 	if (_current == thread) {
74 		if (tstatus->aborted == 0) { /* LCOV_EXCL_BR_LINE */
75 			tstatus->aborted = 1;
76 		} else {
77 			posix_print_warning(/* LCOV_EXCL_LINE */
78 				"POSIX arch: The kernel is trying to abort and swap "
79 				"out of an already aborted thread %i. This "
80 				"should NOT have happened\n",
81 				thread_idx);
82 		}
83 		posix_abort_thread(thread_idx);
84 	}
85 
86 	z_thread_abort(thread);
87 
88 	if (tstatus->aborted == 0) {
89 		PC_DEBUG("%s aborting now [%i] %i\n",
90 			__func__,
91 			posix_arch_get_unique_thread_id(thread_idx),
92 			thread_idx);
93 
94 		tstatus->aborted = 1;
95 		posix_abort_thread(thread_idx);
96 	} else {
97 		PC_DEBUG("%s ignoring re_abort of [%i] "
98 			"%i\n",
99 			__func__,
100 			posix_arch_get_unique_thread_id(thread_idx),
101 			thread_idx);
102 	}
103 
104 	/* The abort handler might have altered the ready queue. */
105 	z_reschedule_irqlock(key);
106 }
107 #endif
108