1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** ThreadX Component */
16 /** */
17 /** Thread */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22
23 #define TX_SOURCE_CODE
24 #define TX_THREAD_SMP_SOURCE_CODE
25
26
27 /* Include necessary system files. */
28
29 #include "tx_api.h"
30 #include "tx_thread.h"
31 #include <stdio.h>
32 #include <unistd.h>
33
34
35 /* Prototype for new thread entry function. */
36
37 void *_tx_linux_thread_entry(void *ptr);
38
39
40 /**************************************************************************/
41 /* */
42 /* FUNCTION RELEASE */
43 /* */
44 /* _tx_thread_stack_build SMP/Linux/GCC */
45 /* 6.1 */
46 /* AUTHOR */
47 /* */
48 /* William E. Lamie, Microsoft Corporation */
49 /* */
50 /* DESCRIPTION */
51 /* */
52 /* This function builds a stack frame on the supplied thread's stack. */
53 /* The stack frame results in a fake interrupt return to the supplied */
54 /* function pointer. */
55 /* */
56 /* INPUT */
57 /* */
58 /* thread_ptr Pointer to thread control blk */
59 /* function_ptr Pointer to return function */
60 /* */
61 /* OUTPUT */
62 /* */
63 /* None */
64 /* */
65 /* CALLS */
66 /* */
67 /* pthread_create */
68 /* pthread_setschedparam */
69 /* _tx_linux_thread_suspend */
70 /* sem_init */
71 /* printf */
72 /* _tx_linux_thread_resume */
73 /* */
74 /* CALLED BY */
75 /* */
76 /* _tx_thread_create Create thread service */
77 /* _tx_thread_reset Reset thread service */
78 /* */
79 /* RELEASE HISTORY */
80 /* */
81 /* DATE NAME DESCRIPTION */
82 /* */
83 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
84 /* */
85 /**************************************************************************/
_tx_thread_stack_build(TX_THREAD * thread_ptr,VOID (* function_ptr)(VOID))86 VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
87 {
88 struct sched_param sp;
89 pthread_attr_t attrs;
90
91 /* Create the run semaphore for the thread. This will allow the scheduler
92 control over when the thread actually runs. */
93 if(sem_init(&thread_ptr -> tx_thread_linux_thread_run_semaphore, 0, 0))
94 {
95
96 /* Display an error message. */
97 printf("ThreadX Linux error creating thread running semaphore!\n");
98 while(1)
99 {
100 }
101 }
102
103 /* Create a Linux thread for the application thread. */
104 pthread_attr_init(&attrs);
105 pthread_attr_setstacksize(&attrs, TX_LINUX_THREAD_STACK_SIZE);
106 if(pthread_create(&thread_ptr -> tx_thread_linux_thread_id, &attrs, _tx_linux_thread_entry, thread_ptr))
107 {
108
109 /* Display an error message. */
110 printf("ThreadX Linux error creating thread!\n");
111 while(1)
112 {
113 }
114 }
115
116 /* Otherwise, we have a good thread create. */
117 sp.sched_priority = TX_LINUX_PRIORITY_USER_THREAD;
118 pthread_setschedparam(thread_ptr -> tx_thread_linux_thread_id, SCHED_FIFO, &sp);
119
120 /* Setup the thread suspension type to solicited thread suspension.
121 Pseudo interrupt handlers will suspend with this field set to 1. */
122 thread_ptr -> tx_thread_linux_suspension_type = 2;
123
124 /* Clear the disabled count that will keep track of the
125 tx_interrupt_control nesting. */
126 thread_ptr -> tx_thread_linux_mutex_access = TX_FALSE;
127
128 /* Setup a fake thread stack pointer. */
129 thread_ptr -> tx_thread_stack_ptr = (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8);
130
131 /* Clear the first word of the stack. */
132 *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0;
133
134 /* Indicate that this thread is now ready for scheduling again by another core. */
135 thread_ptr -> tx_thread_smp_core_control = 1;
136 }
137
138
_tx_linux_thread_entry(void * ptr)139 void *_tx_linux_thread_entry(void *ptr)
140 {
141
142 TX_THREAD *thread_ptr;
143
144 /* Pickup the current thread pointer. */
145 thread_ptr = (TX_THREAD *) ptr;
146 _tx_linux_threadx_thread = 1;
147 nice(20);
148
149 /* Now suspend the thread initially. If the thread has already
150 been scheduled, this will return immediately. */
151 tx_linux_sem_wait(&thread_ptr -> tx_thread_linux_thread_run_semaphore);
152 tx_linux_sem_post(&_tx_linux_scheduler_semaphore);
153
154 /* Call ThreadX thread entry point. */
155 _tx_thread_shell_entry();
156
157 return EXIT_SUCCESS;
158 }
159
160