Release mutex put
1. Only threads with mutex can release mutex
2. After the counter is subtracted by 1, the value is not 0, indicating that the thread has applied for the mutex multiple times. Then the thread continues to occupy the mutex and the function returns
3. If there are threads waiting for mutex resources in the suspended queue, you need to resume the suspended threads
4. The priority of the thread in the suspended queue must be higher than that of the thread with mutex, because after the mutex is obtained by the low priority, only the high priority thread can interrupt the low priority thread, and try to obtain the mutex, and hang in the suspended queue. If the high priority thread gets the mutex first, it is impossible for the low priority thread to interrupt the high priority thread.
5. If priority inheritance is set, put the highest priority thread at the front of the suspended queue to ensure that the highest priority resumes execution first. If priority inheritance is not set, the recovered thread is the top of the TX ﹐ mutex ﹐ suspension ﹐ list queue, not necessarily the highest priority queue, which is in and out according to the FIFO principle
6. If priority inheritance is set, it is necessary to restore the mutex with the priority of the thread as the original priority
UINT _tx_mutex_put(TX_MUTEX *mutex_ptr) { TX_INTERRUPT_SAVE_AREA REG_1 TX_THREAD *thread_ptr = NULL; /* Working thread pointer */ REG_2 TX_THREAD *old_owner = NULL; /* Remember previous mutex owner */ REG_3 UINT old_priority; /* Original thread priority */ REG_3 UINT old_threshold; /* Original thread threshold */ /* Disable interrupts to put an instance back to the mutex. */ TX_DISABLE /* Determine if this thread owns the mutex. */ #def only threads with mutex can release mutex if ((mutex_ptr -> tx_mutex_ownership_count) && (mutex_ptr -> tx_mutex_owner == _tx_thread_current_ptr)) { /* Yes, this thread does own the mutex. */ /* Decrement the mutex ownership count. */ #def counter minus 1 mutex_ptr -> tx_mutex_ownership_count--; /* Determine if the mutex is still owned by the current thread. */ #After the def counter is minus 1, the value is not 0, indicating that the thread has applied for the mutex multiple times. Then the thread continues to occupy the mutex, and the function returns if (mutex_ptr -> tx_mutex_ownership_count) { /* Restore interrupts. */ TX_RESTORE /* Mutex is still owned, just return successful status. */ return (TX_SUCCESS); } else { #The def counter is 0 after subtracting 1, indicating that this thread no longer has mutex. See if there are other threads waiting for the mutex, that is, if there are any mounted threads in the TX mutex suspension list queue /* Yes, the mutex is available we now need to check for a waiting thread. */ /* Determine if priority inheritance is in effect. */ #def sets priority inheritance, puts the highest priority thread at the front of the suspended queue, and ensures that the highest priority resumes execution first #If priority inheritance is not set for def, the recovered thread is the front of TX ﹣ mutex ﹣ suspension ﹣ list queue, not necessarily the highest priority queue, but in and out according to FIFO principle. if ((mutex_ptr -> tx_mutex_inherit) && (mutex_ptr -> tx_mutex_suspension_list)) { /* Temporarily disable preemption. */ _tx_thread_preempt_disable++; /* Restore interrupts. */ TX_RESTORE /* Call the mutex prioritize processing to ensure the highest priority thread is resumed. */ #def puts the highest priority thread at the top of the suspended queue _tx_mutex_prioritize(mutex_ptr); /* At this point, the highest priority thread is at the front of the suspension list. */ /* Disable interrupts. */ TX_DISABLE /* Back off the preemption disable. */ _tx_thread_preempt_disable--; } #def the suspend queue is empty, indicating that there is no thread waiting for mutex, and it is not necessary to resume the suspended thread if (mutex_ptr -> tx_mutex_suspension_list == TX_NULL) { /* Temporarily disable preemption. */ _tx_thread_preempt_disable++; /* Restore interrupts. */ TX_RESTORE /* Mutex is not owned, but it is possible that a thread that caused a priority inheritance to occur is no longer waiting on the mutex. */ #def if priority inheritance is set when applying for mutual exclusion, that is, changing the priority of low priority process to that of high priority process, you need to set it as the original priority if ((mutex_ptr -> tx_mutex_inherit) && (_tx_thread_current_ptr) && (_tx_thread_current_ptr -> tx_priority != mutex_ptr -> tx_mutex_original_priority)) { /* Restore the current priority and threshold of thread. */ _tx_mutex_priority_change(mutex_ptr -> tx_mutex_owner, mutex_ptr -> tx_mutex_original_priority, mutex_ptr -> tx_mutex_original_threshold); } /* Disable interrupts again. */ TX_DISABLE /* Back off the preemption disable. */ _tx_thread_preempt_disable--; /* Restore interrupts. */ TX_RESTORE /* Check for a preemption condition that might be present. */ #After def is interrupted, a higher priority thread may become an executable thread, which needs to be switched if ((_tx_thread_current_ptr != _tx_thread_execute_ptr) && (_tx_thread_system_state == 0)) { /* Return control to the system. */ #def to switch _tx_thread_system_return(); } /* Return success. */ return (TX_SUCCESS); } else { #def if there are threads waiting for mutex resources in the suspended queue, you need to resume the suspended threads #The priority of threads in def suspended queue must be higher than that of threads with mutex, because after the mutex is obtained by low priority, only high priority threads can interrupt low priority threads, try to obtain mutex, and hang in the suspended queue. If the high priority thread gets the mutex first, it is impossible for the low priority thread to interrupt the high priority thread #def if priority inheritance is set, put the highest priority thread at the front of the suspended queue to ensure that the highest priority resumes execution first. If priority inheritance is not set, the recovered thread is the top of the TX ﹐ mutex ﹐ suspension ﹐ list queue, not necessarily the highest priority queue, which is in and out according to the FIFO principle #def if priority inheritance is set, you need to restore the mutex with the priority of the thread as the original priority /* Pickup the thread a the front of the suspension list. */ thread_ptr = mutex_ptr ->tx_mutex_suspension_list; /* Save the previous ownership information, if inheritance is in effect. */ if (mutex_ptr ->tx_mutex_inherit) { #def is a temporary record. The mutex to be recovered later has the priority of the thread as the original priority old_owner = mutex_ptr ->tx_mutex_owner; old_priority = mutex_ptr->tx_mutex_original_priority; old_threshold = mutex_ptr->tx_mutex_original_threshold; #Def thread? PTR must be the highest priority thread because the queue has been adjusted before. Save original priority mutex_ptr ->tx_mutex_original_priority = thread_ptr ->tx_priority; mutex_ptr ->tx_mutex_original_threshold = thread_ptr ->tx_preempt_threshold; } /* Mark the Mutex as owned and fill in the corresponding information. */ #def sets the new counter to 1 and the owner to a new thread mutex_ptr ->tx_mutex_ownership_count = 1; mutex_ptr ->tx_mutex_owner = thread_ptr; /* Remove the suspended thread from the list. */ /* See if this is the only suspended thread on the list. */ if (thread_ptr == thread_ptr ->tx_suspended_next) { /* Yes, the only suspended thread. */ /* Update the head pointer. */ mutex_ptr ->tx_mutex_suspension_list = TX_NULL; } else { /* At least one more thread is on the same expiration list. */ /* Update the list head pointer. */ mutex_ptr -> tx_mutex_suspension_list = thread_ptr -> tx_suspended_next; /* Update the links of the adjacent threads. */ (thread_ptr -> tx_suspended_next) -> tx_suspended_previous = thread_ptr -> tx_suspended_previous; (thread_ptr -> tx_suspended_previous) -> tx_suspended_next = thread_ptr -> tx_suspended_next; } /* Decrement the suspension count. */ mutex_ptr -> tx_mutex_suspended_count--; /* Prepare for resumption of the first thread. */ /* Clear cleanup routine to avoid timeout. */ thread_ptr -> tx_suspend_cleanup = TX_NULL; /* Temporarily disable preemption. */ _tx_thread_preempt_disable++; /* Restore interrupts. */ TX_RESTORE #def timer set before shutdown /* Deactivate the timeout timer if necessary. */ if (thread_ptr -> tx_thread_timer.tx_list_head) { /* Deactivate the thread's timeout timer. */ _tx_timer_deactivate(&(thread_ptr -> tx_thread_timer)); } else { /* Clear the remaining time to ensure timer doesn't get activated. */ thread_ptr -> tx_thread_timer.tx_remaining_ticks = 0; } /* Put return status into the thread control block. */ thread_ptr -> tx_suspend_status = TX_SUCCESS; /* Restore previous priority needs to be restored after priority inheritance. */ #def restore the priority of the old thread if ((mutex_ptr ->tx_mutex_inherit) && (old_owner) && (old_owner ->tx_priority != old_priority)) { /* Restore the current priority and threshold of thread. */ _tx_mutex_priority_change(old_owner, old_priority, old_threshold); } /* Resume thread. */ #def restore new mutex owner thread if (_tx_thread_resume(thread_ptr)) /* Return control to the system. */ _tx_thread_system_return(); /* Return a successful status. */ return (TX_SUCCESS); } } } /* Restore interrupts. */ TX_RESTORE /* Caller does not own the mutex. */ return (TX_NOT_OWNED); }