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