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 "tx_timer.h" 32 33 extern sem_t _tx_linux_isr_semaphore; 34 UINT _tx_linux_timer_waiting = 0; 35 /**************************************************************************/ 36 /* */ 37 /* FUNCTION RELEASE */ 38 /* */ 39 /* _tx_thread_context_restore SMP/Linux/GCC */ 40 /* 6.1 */ 41 /* AUTHOR */ 42 /* */ 43 /* William E. Lamie, Microsoft Corporation */ 44 /* */ 45 /* DESCRIPTION */ 46 /* */ 47 /* This function restores the interrupt context if it is processing a */ 48 /* nested interrupt. If not, it returns to the interrupt thread if no */ 49 /* preemption is necessary. Otherwise, if preemption is necessary or */ 50 /* if no thread was running, the function returns to the scheduler. */ 51 /* */ 52 /* INPUT */ 53 /* */ 54 /* None */ 55 /* */ 56 /* OUTPUT */ 57 /* */ 58 /* None */ 59 /* */ 60 /* CALLS */ 61 /* */ 62 /* _tx_linux_debug_entry_insert */ 63 /* _tx_linux_mutex_obtain */ 64 /* sem_trywait */ 65 /* tx_linux_sem_post */ 66 /* tx_linux_sem_wait */ 67 /* _tx_linux_thread_resume */ 68 /* _tx_linux_mutex_release_all */ 69 /* */ 70 /* CALLED BY */ 71 /* */ 72 /* ISRs Interrupt Service Routines */ 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_context_restore(VOID)81VOID _tx_thread_context_restore(VOID) 82 { 83 84 TX_THREAD *current_thread; 85 86 /* The critical section is already in force at this point. */ 87 88 /* Debug entry. */ 89 _tx_linux_debug_entry_insert("CONTEXT_RESTORE", __FILE__, __LINE__); 90 91 /* For Linux, ISRs are always mapped to core 0. */ 92 93 /* Decrement the nested interrupt count. */ 94 _tx_thread_system_state[0]--; 95 96 /* Pickup current thread. */ 97 current_thread = _tx_thread_current_ptr[0]; 98 99 /* Determine if this is the first nested interrupt and if a ThreadX 100 application thread was running at the time. */ 101 if ((!_tx_thread_system_state[0]) && (current_thread)) 102 { 103 104 /* Yes, this is the first and last interrupt processed. */ 105 106 /* Check to see if preemption is required. */ 107 if ((_tx_thread_preempt_disable == 0) && (current_thread != _tx_thread_execute_ptr[0])) 108 { 109 110 /* Preempt the running application thread. We don't need to suspend the 111 application thread since that is done in the context save processing. */ 112 113 /* Indicate that this thread was suspended asynchronously. */ 114 current_thread -> tx_thread_linux_suspension_type = 1; 115 116 /* Save the remaining time-slice and disable it. */ 117 if (_tx_timer_time_slice[0]) 118 { 119 120 current_thread -> tx_thread_time_slice = _tx_timer_time_slice[0]; 121 _tx_timer_time_slice[0] = 0; 122 } 123 124 /* Clear the current thread pointer. */ 125 _tx_thread_current_ptr[0] = TX_NULL; 126 127 /* Clear this mapping entry. */ 128 _tx_linux_virtual_cores[0].tx_thread_smp_core_mapping_thread = TX_NULL; 129 _tx_linux_virtual_cores[0].tx_thread_smp_core_mapping_linux_thread_id = 0; 130 131 /* Indicate that this thread is now ready for scheduling again by another core. */ 132 current_thread -> tx_thread_smp_core_control = 1; 133 134 /* Make sure semaphore is 0. */ 135 while(!sem_trywait(&_tx_linux_scheduler_semaphore)); 136 137 /* Indicate it is in timer ISR. */ 138 _tx_linux_timer_waiting = 1; 139 140 /* Wakeup the system thread by setting the system semaphore. */ 141 tx_linux_sem_post(&_tx_linux_scheduler_semaphore); 142 143 if(_tx_thread_execute_ptr[0]) 144 { 145 if(_tx_thread_execute_ptr[0] -> tx_thread_linux_suspension_type == 2) 146 { 147 148 /* Unlock linux mutex. */ 149 _tx_linux_mutex_release_all(&_tx_linux_mutex); 150 151 /* Wait until TX_THREAD start running. */ 152 tx_linux_sem_wait(&_tx_linux_isr_semaphore); 153 154 _tx_linux_mutex_obtain(&_tx_linux_mutex); 155 156 /* Make sure semaphore is 0. */ 157 while(!sem_trywait(&_tx_linux_isr_semaphore)); 158 } 159 } 160 161 /* Indicate it is not in timer ISR. */ 162 _tx_linux_timer_waiting = 0; 163 } 164 else 165 { 166 167 /* Since preemption is not required, resume the interrupted thread. */ 168 _tx_linux_thread_resume(current_thread -> tx_thread_linux_thread_id); 169 } 170 } 171 172 /* Unlock linux mutex. */ 173 _tx_thread_smp_unprotect(TX_INT_ENABLE); 174 } 175 176