ThreadX * TX * thread * suspend thread

The execution thread can call "TX" thread "suspend itself, Or call "TX" thread "suspend to...

The execution thread can call "TX" thread "suspend itself,
Or call "TX" thread "suspend to suspend a thread

Set TX? State or TX? Suspending before thread suspending

/* Set the suspending flag. */ thread_ptr -> tx_suspending = TX_TRUE;

If the suspended thread is the current execution thread (self suspended), you need to select the next highest priority thread from the ready queue as the execution thread. Self suspension indicates that the current thread is the highest priority thread:
1. If there are other threads in the current thread ready queue, select the next thread in the same ready queue
2. If the current thread is the only thread in the ready queue, find the next highest priority ready queue, and select the first thread as the execution thread.
3. When selecting the next highest level ready queue, it is necessary to consider the preemption based on the preempt threshold

VOID _tx_thread_suspend(TX_THREAD *thread_ptr) { TX_INTERRUPT_SAVE_AREA REG_1 UINT priority; /* Thread priority */ REG_2 ULONG priority_map; /* Working priority map */ REG_3 UCHAR priority_group; /* Priority group */ /* Lockout interrupts while the thread is being suspended. */ #def off interrupt to prevent preemption TX_DISABLE /* Decrement the preemption disable variable. */ #def has turned off interrupt. Preemption is forbidden. Call the external function of this function++ _tx_thread_preempt_disable--; /* Check to make sure the thread suspending flag is still set. If not, it has already been resumed. */ #def calls the function of this function to set TX ﹣ suspending to TX ﹣ true. If it is not TX ﹣ true, the thread has been resumed. For example, interrupt processing and high priority thread have resumed the thread to be suspended if (thread_ptr -> tx_suspending) { #def continue pending process /* Log the thread status change. */ TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, thread_ptr -> tx_state); /* Actually suspend this thread. But first, clear the suspending flag. */ thread_ptr -> tx_suspending = TX_FALSE; /* Pickup priority of thread. */ priority = thread_ptr -> tx_priority; /* Determine if there are other threads at this priority that are ready. */ #def there are other threads in the same priority ready queue; remove the suspended thread from the queue if (thread_ptr -> tx_ready_next != thread_ptr) { /* Yes, there are other threads at this priority ready. */ /* Just remove this thread from the priority list. */ (thread_ptr -> tx_ready_next) -> tx_ready_previous = thread_ptr -> tx_ready_previous; (thread_ptr -> tx_ready_previous) -> tx_ready_next = thread_ptr -> tx_ready_next; /* Determine if this is the head of the priority list. */ #def suspend thread is the first thread in the ready queue, so it may be the currently executing thread. Only the first thread in the ready queue can be the current executing thread. if (_tx_thread_priority_list[priority] == thread_ptr) { /* Update the head pointer of this priority list. */ _tx_thread_priority_list[priority] = thread_ptr -> tx_ready_next; /* Check for a thread preempted that had preemption threshold set. */ #def if this thread has been preempted and the "TX" thread "preempted" map is set, clear it here if (_tx_thread_preempted_map) { /* Ensure that this thread's priority is clear in the preempt map. */ _tx_thread_preempted_map = _tx_thread_preempted_map & ~(thread_ptr -> tx_priority_bit); } /* Determine if this thread is the thread designated to execute. */ #def the suspended thread is the execution thread, and the highest priority thread needs to be re selected as the execution thread. Because the suspended thread is the execution thread, it means that the ready queue is the highest priority, so the next thread in the ready queue is actually selected here if (thread_ptr == _tx_thread_execute_ptr) { /* Pickup the highest priority thread to execute. */ _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority]; } } /* Restore interrupts. */ #def interrupt enable TX_RESTORE /* Determine if we need to return to the system. This needs to happen if a self suspension takes place or if a higher-priority thread was resumed by an ISR in the part of the suspension process that has interrupts enabled. */ #The execution thread selected by def is no longer the current thread for scheduling #def 1. If the thread is suspended by itself (the suspended thread is the current thread), the selected thread must not be the current thread #def 2, the above interrupt is enabled. Before executing the following code, there may be an interrupt. In the interrupt processing, the high priority thread is awakened and the current executing thread is suspended if ((_tx_thread_current_ptr != _tx_thread_execute_ptr) && (_tx_thread_system_state == 0)) { /* Return control to the system. */ #def schedule switch thread _tx_thread_system_return(); } /* Return to caller. */ return; } else { #def suspend thread is in the ready queue without other threads #def 1 if another thread calls a suspended thread, you only need to delete the thread that needs to be suspended #If def 2 is self suspend, the current execution thread is the highest priority thread, and the next highest priority thread needs to be selected /* This is the only thread at this priority ready to run. Set the head pointer to NULL. */ _tx_thread_priority_list[priority] = TX_NULL; /* Clear this priority bit in the ready priority bit map. */ #def ready queue has only one pending thread, so you need to clear the corresponding bitmap bit _tx_thread_priority_map = _tx_thread_priority_map & ~(thread_ptr -> tx_priority_bit); /* Check for a thread preempted that had preemption threshold set. */ if (_tx_thread_preempted_map) { /* Ensure that this thread's priority is clear in the preempt map. */ _tx_thread_preempted_map = _tx_thread_preempted_map & ~(thread_ptr -> tx_priority_bit); } /* Put the priority map in a working copy. */ priority_map = _tx_thread_priority_map; /* Find the next highest priority. */ #ABCD low_ Bit [1] is 0, bit [2], the lowest bit 1 of index 2 (0b0010) is bit1, so bit [1] is 1, bit [3], the lowest bit 1 of index 3 (0b0011) is bit0, so bit [1] is 0 /* Check for priorities 0-7. */ #def first calculates the offset of bit0-bit7 with the lowest bit 1 in priority map priority, that is, the highest priority priority_group = (UCHAR) (priority_map & TX_THREAD_PRIORITY_GROUP_MASK); if (priority_group) _tx_thread_highest_priority = _tx_thread_lowest_bit[priority_group]; else { /* Check for priorities 8-15. */ priority_map = priority_map >> TX_THREAD_GROUP_SIZE; priority_group = (UCHAR) (priority_map & TX_THREAD_PRIORITY_GROUP_MASK); if (priority_group) _tx_thread_highest_priority = TX_THREAD_GROUP_1 + _tx_thread_lowest_bit[priority_group]; else { /* Check for priorities 16-23. */ priority_map = priority_map >> TX_THREAD_GROUP_SIZE; priority_group = (UCHAR) (priority_map & TX_THREAD_PRIORITY_GROUP_MASK); if (priority_group) _tx_thread_highest_priority = TX_THREAD_GROUP_2 + _tx_thread_lowest_bit[priority_group]; else { priority_map = priority_map >> TX_THREAD_GROUP_SIZE; priority_group = (UCHAR) (priority_map & TX_THREAD_PRIORITY_GROUP_MASK); if (priority_group) _tx_thread_highest_priority = TX_THREAD_GROUP_3 + _tx_thread_lowest_bit[priority_group]; else { /* Nothing else is ready. Set highest priority and execute thread accordingly. */ _tx_thread_highest_priority = TX_MAX_PRIORITIES; _tx_thread_execute_ptr = TX_NULL; /* Restore interrupts. */ TX_RESTORE /* Return control to the system. */ _tx_thread_system_return(); /* Return to caller. */ return; } } } } /* Determine if this thread is the thread designated to execute. */ #def self suspend if (thread_ptr == _tx_thread_execute_ptr) { /* Pickup the highest priority thread to execute. */ #def first set the highest priority (calculated earlier) thread as the execution thread _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority]; /* Determine if a previous thread with preemption threshold was preempted. */ #If the "TX" thread "preempted" map is not 0, it means that preemption based on the preemption threshold has occurred before, then the next execution thread selection must consider the preemption threshold if (_tx_thread_preempted_map) { /* Disable preemption. */ _tx_thread_preempt_disable++; /* Restore interrupts. */ TX_RESTORE /* Interrupts are enabled briefly here to keep the interrupt lockout time deterministic. */ /* Disable interrupts again. */ TX_DISABLE /* Decrement the preemption disable variable. */ _tx_thread_preempt_disable--; /* Calculate the thread with preemption threshold set that was interrupted by a thread above the preemption level. */ /* Put the preempt map in a working copy. */ priority_map = _tx_thread_preempted_map; /* Find the highest priority preempted thread. */ #def selects the highest priority to be preempted /* Check for priorities 0-7. */ priority_group = (UCHAR) (priority_map & TX_THREAD_PRIORITY_GROUP_MASK); if (priority_group) priority = _tx_thread_lowest_bit[priority_group]; else { /* Check for priorities 8-15. */ priority_map = priority_map >> TX_THREAD_GROUP_SIZE; priority_group = (UCHAR) (priority_map & TX_THREAD_PRIORITY_GROUP_MASK); if (priority_group) priority = TX_THREAD_GROUP_1 + _tx_thread_lowest_bit[priority_group]; else { /* Check for priorities 16-23. */ priority_map = priority_map >> TX_THREAD_GROUP_SIZE; priority_group = (UCHAR) (priority_map & TX_THREAD_PRIORITY_GROUP_MASK); if (priority_group) priority = TX_THREAD_GROUP_2 + _tx_thread_lowest_bit[priority_group]; else { priority_map = priority_map >> TX_THREAD_GROUP_SIZE; priority_group = (UCHAR) (priority_map & TX_THREAD_PRIORITY_GROUP_MASK); priority = TX_THREAD_GROUP_3 + _tx_thread_lowest_bit[priority_group]; } } } /* Determine if the next highest priority thread is above the highest priority threshold value. */ #def if the selected highest priority preemption threshold is lower than the highest priority, the execution thread is set to the highest priority preempted thread if (_tx_thread_highest_priority >= (_tx_thread_priority_list[priority] -> tx_preempt_threshold)) { /* Thread not allowed to execute until earlier preempted thread finishes or lowers its preemption threshold. */ _tx_thread_execute_ptr = _tx_thread_priority_list[priority]; /* Clear the corresponding bit in the preempted map, since the preemption has been restored. */ _tx_thread_preempted_map = _tx_thread_preempted_map & ~(_tx_thread_execute_ptr -> tx_priority_bit); } } } /* Restore interrupts. */ TX_RESTORE /* Determine if we need to return to the system. This needs to happen if a self suspension takes place or if a higher-priority thread was resumed by an ISR in the part of the suspension process that has interrupts enabled. */ if ((_tx_thread_current_ptr != _tx_thread_execute_ptr) && (_tx_thread_system_state == 0)) { /* Return control to the system. */ _tx_thread_system_return(); } /* Return to caller. */ return; } } else { #def doesn't need to be suspended anymore, it returns directly. /* Thread not still suspending... Restore interrupts. */ TX_RESTORE /* Check for a preemption condition that might have occurred from an ISR. */ if ((_tx_thread_current_ptr != _tx_thread_execute_ptr) && (_tx_thread_system_state == 0)) /* Return control to the system. */ _tx_thread_system_return(); } }
osnet 27 original articles published, praised 2, visits 2414 Private letter follow

4 February 2020, 13:47 | Views: 8389

Add new comment

For adding a comment, please log in
or create account

0 comments