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