1 /**************************************************************************/ 2 /* */ 3 /* Copyright (c) Microsoft Corporation. All rights reserved. */ 4 /* */ 5 /* This software is licensed under the Microsoft Software License */ 6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */ 7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ 8 /* and in the root directory of this software. */ 9 /* */ 10 /**************************************************************************/ 11 12 13 /**************************************************************************/ 14 /**************************************************************************/ 15 /** */ 16 /** ThreadX Component */ 17 /** */ 18 /** Thread */ 19 /** */ 20 /**************************************************************************/ 21 /**************************************************************************/ 22 23 24 #define TX_SOURCE_CODE 25 #define TX_THREAD_SMP_SOURCE_CODE 26 27 28 /* Include necessary system files. */ 29 30 #include "tx_api.h" 31 #include "tx_thread.h" 32 #include "tx_timer.h" 33 34 extern sem_t _tx_linux_isr_semaphore; 35 UINT _tx_linux_timer_waiting = 0; 36 /**************************************************************************/ 37 /* */ 38 /* FUNCTION RELEASE */ 39 /* */ 40 /* _tx_thread_context_restore SMP/Linux/GCC */ 41 /* 6.1 */ 42 /* AUTHOR */ 43 /* */ 44 /* William E. Lamie, Microsoft Corporation */ 45 /* */ 46 /* DESCRIPTION */ 47 /* */ 48 /* This function restores the interrupt context if it is processing a */ 49 /* nested interrupt. If not, it returns to the interrupt thread if no */ 50 /* preemption is necessary. Otherwise, if preemption is necessary or */ 51 /* if no thread was running, the function returns to the scheduler. */ 52 /* */ 53 /* INPUT */ 54 /* */ 55 /* None */ 56 /* */ 57 /* OUTPUT */ 58 /* */ 59 /* None */ 60 /* */ 61 /* CALLS */ 62 /* */ 63 /* _tx_linux_debug_entry_insert */ 64 /* _tx_linux_mutex_obtain */ 65 /* sem_trywait */ 66 /* tx_linux_sem_post */ 67 /* tx_linux_sem_wait */ 68 /* _tx_linux_thread_resume */ 69 /* _tx_linux_mutex_release_all */ 70 /* */ 71 /* CALLED BY */ 72 /* */ 73 /* ISRs Interrupt Service Routines */ 74 /* */ 75 /* RELEASE HISTORY */ 76 /* */ 77 /* DATE NAME DESCRIPTION */ 78 /* */ 79 /* 09-30-2020 William E. Lamie Initial Version 6.1 */ 80 /* */ 81 /**************************************************************************/ _tx_thread_context_restore(VOID)82VOID _tx_thread_context_restore(VOID) 83 { 84 85 TX_THREAD *current_thread; 86 87 /* The critical section is already in force at this point. */ 88 89 /* Debug entry. */ 90 _tx_linux_debug_entry_insert("CONTEXT_RESTORE", __FILE__, __LINE__); 91 92 /* For Linux, ISRs are always mapped to core 0. */ 93 94 /* Decrement the nested interrupt count. */ 95 _tx_thread_system_state[0]--; 96 97 /* Pickup current thread. */ 98 current_thread = _tx_thread_current_ptr[0]; 99 100 /* Determine if this is the first nested interrupt and if a ThreadX 101 application thread was running at the time. */ 102 if ((!_tx_thread_system_state[0]) && (current_thread)) 103 { 104 105 /* Yes, this is the first and last interrupt processed. */ 106 107 /* Check to see if preemption is required. */ 108 if ((_tx_thread_preempt_disable == 0) && (current_thread != _tx_thread_execute_ptr[0])) 109 { 110 111 /* Preempt the running application thread. We don't need to suspend the 112 application thread since that is done in the context save processing. */ 113 114 /* Indicate that this thread was suspended asynchronously. */ 115 current_thread -> tx_thread_linux_suspension_type = 1; 116 117 /* Save the remaining time-slice and disable it. */ 118 if (_tx_timer_time_slice[0]) 119 { 120 121 current_thread -> tx_thread_time_slice = _tx_timer_time_slice[0]; 122 _tx_timer_time_slice[0] = 0; 123 } 124 125 /* Clear the current thread pointer. */ 126 _tx_thread_current_ptr[0] = TX_NULL; 127 128 /* Clear this mapping entry. */ 129 _tx_linux_virtual_cores[0].tx_thread_smp_core_mapping_thread = TX_NULL; 130 _tx_linux_virtual_cores[0].tx_thread_smp_core_mapping_linux_thread_id = 0; 131 132 /* Indicate that this thread is now ready for scheduling again by another core. */ 133 current_thread -> tx_thread_smp_core_control = 1; 134 135 /* Make sure semaphore is 0. */ 136 while(!sem_trywait(&_tx_linux_scheduler_semaphore)); 137 138 /* Indicate it is in timer ISR. */ 139 _tx_linux_timer_waiting = 1; 140 141 /* Wakeup the system thread by setting the system semaphore. */ 142 tx_linux_sem_post(&_tx_linux_scheduler_semaphore); 143 144 if(_tx_thread_execute_ptr[0]) 145 { 146 if(_tx_thread_execute_ptr[0] -> tx_thread_linux_suspension_type == 2) 147 { 148 149 /* Unlock linux mutex. */ 150 _tx_linux_mutex_release_all(&_tx_linux_mutex); 151 152 /* Wait until TX_THREAD start running. */ 153 tx_linux_sem_wait(&_tx_linux_isr_semaphore); 154 155 _tx_linux_mutex_obtain(&_tx_linux_mutex); 156 157 /* Make sure semaphore is 0. */ 158 while(!sem_trywait(&_tx_linux_isr_semaphore)); 159 } 160 } 161 162 /* Indicate it is not in timer ISR. */ 163 _tx_linux_timer_waiting = 0; 164 } 165 else 166 { 167 168 /* Since preemption is not required, resume the interrupted thread. */ 169 _tx_linux_thread_resume(current_thread -> tx_thread_linux_thread_id); 170 } 171 } 172 173 /* Unlock linux mutex. */ 174 _tx_thread_smp_unprotect(TX_INT_ENABLE); 175 } 176 177