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 /**   Module Manager                                                      */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define TX_SOURCE_CODE
23 
24 #include "tx_api.h"
25 #include "tx_trace.h"
26 #include "tx_thread.h"
27 #include "txm_module.h"
28 
29 /**************************************************************************/
30 /*                                                                        */
31 /*  FUNCTION                                               RELEASE        */
32 /*                                                                        */
33 /*    _txm_module_manager_thread_reset                    PORTABLE C      */
34 /*                                                           6.1          */
35 /*  AUTHOR                                                                */
36 /*                                                                        */
37 /*    Scott Larson, Microsoft Corporation                                 */
38 /*                                                                        */
39 /*  DESCRIPTION                                                           */
40 /*                                                                        */
41 /*    This function prepares the thread to run again from the entry       */
42 /*    point specified during thread creation. The application must        */
43 /*    call tx_thread_resume after this call completes for the thread      */
44 /*    to actually run.                                                    */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    thread_ptr                        Pointer to thread to reset        */
49 /*                                                                        */
50 /*  OUTPUT                                                                */
51 /*                                                                        */
52 /*    status                            Service return status             */
53 /*                                                                        */
54 /*  CALLS                                                                 */
55 /*                                                                        */
56 /*    _txm_module_manager_thread_stack_build    Build initial thread      */
57 /*                                                stack                   */
58 /*                                                                        */
59 /*  CALLED BY                                                             */
60 /*                                                                        */
61 /*    _txm_module_manager_kernel_dispatch   Kernel dispatch function      */
62 /*                                                                        */
63 /*  RELEASE HISTORY                                                       */
64 /*                                                                        */
65 /*    DATE              NAME                      DESCRIPTION             */
66 /*                                                                        */
67 /*  09-30-2020      Scott Larson            Initial Version 6.1           */
68 /*                                                                        */
69 /**************************************************************************/
_txm_module_manager_thread_reset(TX_THREAD * thread_ptr)70 UINT  _txm_module_manager_thread_reset(TX_THREAD *thread_ptr)
71 {
72 
73 TX_INTERRUPT_SAVE_AREA
74 
75 TX_THREAD       *current_thread;
76 UINT            status;
77 TXM_MODULE_INSTANCE             *module_instance;
78 TXM_MODULE_THREAD_ENTRY_INFO    *thread_entry_info;
79 
80     /* Default a successful completion status.  */
81     status =  TX_SUCCESS;
82 
83     /* Disable interrupts.  */
84     TX_DISABLE
85 
86     /* Pickup thread pointer.  */
87     TX_THREAD_GET_CURRENT(current_thread)
88 
89     /* Check for a call from the current thread, which is not allowed!  */
90     if (current_thread == thread_ptr)
91     {
92 
93         /* Restore interrupts.  */
94         TX_RESTORE
95 
96         /* Thread not completed or terminated - return an error!  */
97         status =  TX_NOT_DONE;
98     }
99     else
100     {
101 
102         /* Check for proper status of this thread to reset.  */
103         if (thread_ptr -> tx_thread_state != TX_COMPLETED)
104         {
105 
106             /* Now check for terminated state.  */
107             if (thread_ptr -> tx_thread_state != TX_TERMINATED)
108             {
109 
110                 /* Thread not completed or terminated - return an error!  */
111                 status =  TX_NOT_DONE;
112             }
113         }
114     }
115 
116     /* Is the request valid?  */
117     if (status == TX_SUCCESS)
118     {
119 
120         /* Modify the thread status to prevent additional reset calls.  */
121         thread_ptr -> tx_thread_state =  TX_NOT_DONE;
122 
123         /* Get the module instance.  */
124         module_instance =  thread_ptr -> tx_thread_module_instance_ptr;
125 
126         /* Execute Port-Specific completion processing. If needed, it is typically defined in txm_module_port.h.  */
127         TXM_MODULE_MANAGER_THREAD_RESET_PORT_COMPLETION(thread_ptr, module_instance)
128 
129         /* Restore interrupts.  */
130         TX_RESTORE
131 
132 #ifndef TX_DISABLE_STACK_FILLING
133 
134         /* Set the thread stack to a pattern prior to creating the initial
135            stack frame.  This pattern is used by the stack checking routines
136            to see how much has been used.  */
137         TX_MEMSET(thread_ptr -> tx_thread_stack_start, ((UCHAR) TX_STACK_FILL), thread_ptr -> tx_thread_stack_size);
138 #endif
139 
140         /* Setup pointer to the thread entry information structure, which will live at the top of each
141            module thread's stack. This will allow the module thread entry function to avoid direct
142            access to the actual thread control block.  */
143         thread_entry_info =  (TXM_MODULE_THREAD_ENTRY_INFO *) (((UCHAR *) thread_ptr -> tx_thread_stack_end) + (2*sizeof(ULONG)) + 1);
144         thread_entry_info =  (TXM_MODULE_THREAD_ENTRY_INFO *) (((ALIGN_TYPE)(thread_entry_info)) & (~0x3));
145 
146         /* Place the thread entry information pointer in the thread control block so it can be picked up
147            in the following stack build function. This is supplied to the module's shell entry function
148            to avoid direct access to the actual thread control block. Note that this is overwritten
149            with the actual stack pointer at the end of stack build.  */
150         thread_ptr -> tx_thread_stack_ptr =  (VOID *) thread_entry_info;
151 
152         /* Call the target specific stack frame building routine to build the
153            thread's initial stack and to setup the actual stack pointer in the
154            control block.  */
155         _txm_module_manager_thread_stack_build(thread_ptr, module_instance -> txm_module_instance_shell_entry_function);
156 
157         /* Disable interrupts.  */
158         TX_DISABLE
159 
160         /* Finally, move into a suspended state to allow for the thread to be resumed.  */
161         thread_ptr -> tx_thread_state =  TX_SUSPENDED;
162 
163         /* If trace is enabled, insert this event into the trace buffer.  */
164         TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESET, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS)
165 
166         /* Log this kernel call.  */
167         TX_EL_THREAD_RESET_INSERT
168 
169         /* Log the thread status change.  */
170         TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_SUSPENDED)
171     }
172 
173     /* Restore interrupts.  */
174     TX_RESTORE
175 
176     /* Return completion status to caller.  */
177     return(status);
178 }
179 
180