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 
32 
33 /* Prototype for new thread entry function.  */
34 
35 DWORD WINAPI _tx_win32_thread_entry(LPVOID p);
36 
37 
38 /**************************************************************************/
39 /*                                                                        */
40 /*  FUNCTION                                               RELEASE        */
41 /*                                                                        */
42 /*    _tx_thread_stack_build                            Win32/Visual      */
43 /*                                                           6.1          */
44 /*  AUTHOR                                                                */
45 /*                                                                        */
46 /*    William E. Lamie, Microsoft Corporation                             */
47 /*                                                                        */
48 /*  DESCRIPTION                                                           */
49 /*                                                                        */
50 /*    This function builds a stack frame on the supplied thread's stack.  */
51 /*    The stack frame results in a fake interrupt return to the supplied  */
52 /*    function pointer.                                                   */
53 /*                                                                        */
54 /*  INPUT                                                                 */
55 /*                                                                        */
56 /*    thread_ptr                            Pointer to thread control blk */
57 /*    function_ptr                          Pointer to return function    */
58 /*                                                                        */
59 /*  OUTPUT                                                                */
60 /*                                                                        */
61 /*    None                                                                */
62 /*                                                                        */
63 /*  CALLS                                                                 */
64 /*                                                                        */
65 /*    CreateThread                          Win32 create thread           */
66 /*    ResumeThread                          Win32 resume thread           */
67 /*    SetThreadPriority                     Win32 set thread priority     */
68 /*                                                                        */
69 /*  CALLED BY                                                             */
70 /*                                                                        */
71 /*    _tx_thread_create                     Create thread service         */
72 /*    _tx_thread_reset                      Reset thread service          */
73 /*                                                                        */
74 /*  RELEASE HISTORY                                                       */
75 /*                                                                        */
76 /*    DATE              NAME                      DESCRIPTION             */
77 /*                                                                        */
78 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
79 /*                                                                        */
80 /**************************************************************************/
_tx_thread_stack_build(TX_THREAD * thread_ptr,VOID (* function_ptr)(VOID))81 VOID   _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
82 {
83 
84     /* Create a Win32 thread for the application thread.  */
85     thread_ptr -> tx_thread_win32_thread_handle =
86         CreateThread(NULL, 0, _tx_win32_thread_entry, (LPVOID) thread_ptr, CREATE_SUSPENDED,
87                         &(thread_ptr -> tx_thread_win32_thread_id));
88 
89     /* Check for a good thread create.  */
90     if (!thread_ptr -> tx_thread_win32_thread_handle)
91     {
92 
93         /* Display an error message.  */
94         printf("ThreadX Win32 error creating thread!\n");
95         while(1)
96         {
97         }
98     }
99 
100     /* Otherwise, we have a good thread create.  Now set the priority to
101        a lower level.  */
102     SetThreadPriority(thread_ptr -> tx_thread_win32_thread_handle, THREAD_PRIORITY_LOWEST);
103 
104     /* Create the run semaphore for the thread.  This will allow the scheduler
105        control over when the thread actually runs.  */
106     thread_ptr -> tx_thread_win32_thread_run_semaphore =  CreateSemaphore(NULL, 0, 1, NULL);
107 
108     /* Determine if the run semaphore was created successfully.  */
109     if (!thread_ptr -> tx_thread_win32_thread_run_semaphore)
110     {
111 
112         /* Display an error message.  */
113         printf("ThreadX Win32 error creating thread running semaphore!\n");
114         while(1)
115         {
116         }
117     }
118 
119     /* Setup the thread suspension type to solicited thread suspension.
120        Pseudo interrupt handlers will suspend with this field set to 1.  */
121     thread_ptr -> tx_thread_win32_suspension_type =  0;
122 
123     /* Clear the disabled count that will keep track of the
124        tx_interrupt_control nesting.  */
125     thread_ptr -> tx_thread_win32_int_disabled_flag =  0;
126 
127     /* Setup a fake thread stack pointer.   */
128     thread_ptr -> tx_thread_stack_ptr =  (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8);
129 
130     /* Clear the first word of the stack.  */
131     *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) =  0;
132 
133     /* Make the thread initially ready so it will run to the initial wait on
134        its run semaphore.  */
135     ResumeThread(thread_ptr -> tx_thread_win32_thread_handle);
136 }
137 
138 
_tx_win32_thread_entry(LPVOID ptr)139 DWORD WINAPI _tx_win32_thread_entry(LPVOID ptr)
140 {
141 
142 TX_THREAD  *thread_ptr;
143 
144     /* Pickup the current thread pointer.  */
145     thread_ptr =  (TX_THREAD *) ptr;
146 
147     /* Now suspend the thread initially.  If the thread has already
148        been scheduled, this will return immediately.  */
149     WaitForSingleObject(thread_ptr -> tx_thread_win32_thread_run_semaphore, INFINITE);
150 
151     /* Call ThreadX thread entry point.  */
152     _tx_thread_shell_entry();
153 
154     return EXIT_SUCCESS;
155 }
156 
157