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
25
26 /* Include necessary system files. */
27
28 #include "tx_api.h"
29 #include "tx_thread.h"
30 #include <stdio.h>
31 #include <unistd.h>
32
33
34 /* Prototype for new thread entry function. */
35
36 void *_tx_linux_thread_entry(void *ptr);
37
38
39 /**************************************************************************/
40 /* */
41 /* FUNCTION RELEASE */
42 /* */
43 /* _tx_thread_stack_build Linux/GNU */
44 /* 6.1 */
45 /* AUTHOR */
46 /* */
47 /* William E. Lamie, Microsoft Corporation */
48 /* */
49 /* DESCRIPTION */
50 /* */
51 /* This function builds a stack frame on the supplied thread's stack. */
52 /* The stack frame results in a fake interrupt return to the supplied */
53 /* function pointer. */
54 /* */
55 /* INPUT */
56 /* */
57 /* thread_ptr Pointer to thread control blk */
58 /* function_ptr Pointer to return function */
59 /* */
60 /* OUTPUT */
61 /* */
62 /* None */
63 /* */
64 /* CALLS */
65 /* */
66 /* pthread_create */
67 /* pthread_setschedparam */
68 /* _tx_linux_thread_suspend */
69 /* sem_init */
70 /* printf */
71 /* _tx_linux_thread_resume */
72 /* */
73 /* CALLED BY */
74 /* */
75 /* _tx_thread_create Create thread service */
76 /* _tx_thread_reset Reset thread service */
77 /* */
78 /* RELEASE HISTORY */
79 /* */
80 /* DATE NAME DESCRIPTION */
81 /* */
82 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
83 /* */
84 /**************************************************************************/
_tx_thread_stack_build(TX_THREAD * thread_ptr,VOID (* function_ptr)(VOID))85 VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
86 {
87 struct sched_param sp;
88
89 (VOID)function_ptr;
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 if(pthread_create(&thread_ptr -> tx_thread_linux_thread_id, NULL, _tx_linux_thread_entry, thread_ptr))
105 {
106
107 /* Display an error message. */
108 printf("ThreadX Linux error creating thread!\n");
109 while(1)
110 {
111 }
112 }
113
114 /* Otherwise, we have a good thread create. */
115 sp.sched_priority = TX_LINUX_PRIORITY_USER_THREAD;
116 pthread_setschedparam(thread_ptr -> tx_thread_linux_thread_id, SCHED_FIFO, &sp);
117
118 /* Setup the thread suspension type to solicited thread suspension.
119 Pseudo interrupt handlers will suspend with this field set to 1. */
120 thread_ptr -> tx_thread_linux_suspension_type = 0;
121
122 /* Clear the disabled count that will keep track of the
123 tx_interrupt_control nesting. */
124 thread_ptr -> tx_thread_linux_int_disabled_flag = 0;
125
126 /* Setup a fake thread stack pointer. */
127 thread_ptr -> tx_thread_stack_ptr = (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8);
128
129 /* Clear the first word of the stack. */
130 *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0;
131 }
132
133
_tx_linux_thread_entry(void * ptr)134 void *_tx_linux_thread_entry(void *ptr)
135 {
136
137 TX_THREAD *thread_ptr;
138
139 /* Pickup the current thread pointer. */
140 thread_ptr = (TX_THREAD *) ptr;
141 _tx_linux_threadx_thread = 1;
142 nice(20);
143
144 /* Now suspend the thread initially. If the thread has already
145 been scheduled, this will return immediately. */
146 tx_linux_sem_wait(&thread_ptr -> tx_thread_linux_thread_run_semaphore);
147 tx_linux_sem_post_nolock(&_tx_linux_semaphore);
148
149 /* Call ThreadX thread entry point. */
150 _tx_thread_shell_entry();
151
152 return EXIT_SUCCESS;
153 }
154
155