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