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