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 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 Linux/GNU */ 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_lock */ 64 /* sem_trywait */ 65 /* tx_linux_sem_post */ 66 /* tx_linux_sem_wait */ 67 /* _tx_linux_thread_resume */ 68 /* tx_linux_mutex_recursive_unlock */ 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 /* Debug entry. */ 85 _tx_linux_debug_entry_insert("CONTEXT_RESTORE", __FILE__, __LINE__); 86 87 /* Lock mutex to ensure other threads are not playing with 88 the core ThreadX data structures. */ 89 tx_linux_mutex_lock(_tx_linux_mutex); 90 91 /* Decrement the nested interrupt count. */ 92 _tx_thread_system_state--; 93 94 /* Determine if this is the first nested interrupt and if a ThreadX 95 application thread was running at the time. */ 96 if ((!_tx_thread_system_state) && (_tx_thread_current_ptr)) 97 { 98 99 /* Yes, this is the first and last interrupt processed. */ 100 101 /* Check to see if preemption is required. */ 102 if ((_tx_thread_preempt_disable == 0) && (_tx_thread_current_ptr != _tx_thread_execute_ptr)) 103 { 104 105 /* Preempt the running application thread. We don't need to suspend the 106 application thread since that is done in the context save processing. */ 107 108 /* Indicate that this thread was suspended asynchronously. */ 109 _tx_thread_current_ptr -> tx_thread_linux_suspension_type = 1; 110 111 /* Save the remaining time-slice and disable it. */ 112 if (_tx_timer_time_slice) 113 { 114 115 _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; 116 _tx_timer_time_slice = 0; 117 } 118 119 /* Clear the current thread pointer. */ 120 _tx_thread_current_ptr = TX_NULL; 121 122 /* Make sure semaphore is 0. */ 123 while(!sem_trywait(&_tx_linux_semaphore)); 124 125 /* Indicate it is in timer ISR. */ 126 _tx_linux_timer_waiting = 1; 127 128 /* Wakeup the system thread by setting the system semaphore. */ 129 tx_linux_sem_post(&_tx_linux_semaphore); 130 131 if(_tx_thread_execute_ptr) 132 { 133 if(_tx_thread_execute_ptr -> tx_thread_linux_suspension_type == 0) 134 { 135 136 /* Unlock linux mutex. */ 137 tx_linux_mutex_recursive_unlock(_tx_linux_mutex); 138 139 /* Wait until TX_THREAD start running. */ 140 tx_linux_sem_wait(&_tx_linux_isr_semaphore); 141 142 tx_linux_mutex_lock(_tx_linux_mutex); 143 144 /* Make sure semaphore is 0. */ 145 while(!sem_trywait(&_tx_linux_isr_semaphore)); 146 } 147 } 148 149 /* Indicate it is not in timer ISR. */ 150 _tx_linux_timer_waiting = 0; 151 } 152 else 153 { 154 155 /* Since preemption is not required, resume the interrupted thread. */ 156 _tx_linux_thread_resume(_tx_thread_current_ptr -> tx_thread_linux_thread_id); 157 } 158 } 159 160 /* Unlock linux mutex. */ 161 tx_linux_mutex_recursive_unlock(_tx_linux_mutex); 162 } 163 164