Threadx _tx_thread_suspend线程挂起

别说谁变了你拦得住时间么 提交于 2020-02-04 19:48:33

执行线程可以调用_tx_thread_suspend自我挂起,
或者调用_tx_thread_suspend挂起某个线程

线程挂起前,先设置tx_state 或tx_suspending

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

如果挂起线程是当前执行线程(自我挂起),需要从就绪队列中选择出下一个最高优先级线程为执行线程,自我挂起说明当前线程是最高优先级线程:
1,如果当前线程就绪队列还有其它线程,那么选择同一个就绪队列中下一个线程.
2, 如果当前线程是就绪队列中唯一线程,那么找出下一个最高优先级就绪队列,选择其中第一个线程为执行线程。
3,选择下一个最高级就绪队列时,需要考虑基于tx_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 关中断,防止被抢占
    TX_DISABLE

    /* Decrement the preemption disable variable.  */
    #def 已经关中断,禁止抢占--, 调用这个函数的外部函数进行了++
    _tx_thread_preempt_disable--;

    /* Check to make sure the thread suspending flag is still set.  If not, it
       has already been resumed.  */
    #def 调用这个函数的函数设置tx_suspending为TX_TRUE,如果不为TX_TRUE,说明线程已经resume,比如中断处理以及高优先级线程又恢复了这个要挂起的线程
    if (thread_ptr -> tx_suspending)
    {
	#def 继续挂起过程
	
        /* 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 同优先级就绪队列中还有其它线程;把挂起线程从队列中删除
        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 挂起线程是就绪队列中第一个线程,那么可能是当前正执行的线程。 只有就绪队列中第一个线程才可能是当前执行线程。
            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 如果之前这个线程被抢占过,并设置了_tx_thread_preempted_map,这里清除掉
                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 挂起线程为执行线程,需要重新选择最高优先级线程为执行线程,由于挂起线程为执行线程,说明所在的就绪队列为最高优先级,那么这里实际选择的就是就绪队列中下一个线程
                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 中断使能
            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.  */
               #def 选择出的执行线程不再是当前线程,进行调度
               #def 1,如果是自己挂起(挂起线程就是当前线程),那么选择出的线程肯定不是当前线程
               #def 2,上面中断使能了,执行下面代码前,有可能来了中断,中断处理中唤醒了高优先级线程,并且挂起当前执行线程
            if ((_tx_thread_current_ptr != _tx_thread_execute_ptr) && (_tx_thread_system_state == 0))
            {
                /* Return control to the system.  */
                #def 调度切换线程
                _tx_thread_system_return();
            }

            /* Return to caller.  */
            return;
        }
        else
        {
	#def 挂起线程所在就绪队列没有其它线程
	#def 1 如果是其它线程调用挂起线程,那只需要删除需要挂起的线程就可以了
	#def 2 如果是自我挂起,那么当前执行线程是最高优先级线程,需要选出下一个最高优先级线程
	
            /* 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 就绪队列只有一个挂起线程,所以需要清除对应位图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.  */
		#def 选择出下一个最高优先级线程,为了减少计算,采用了分组方式进行判断,_tx_thread_lowest_bit[]数组存储了索引0-255个整数最低位1的偏移,例如 _tx_thread_lowest_bit[0], 索引0没有1,所以_tx_thread_lowest_bit[0]为0,_tx_thread_lowest_bit[1],索引1的最低位1在bit0,所以_tx_thread_lowest_bit[1]为0,_tx_thread_lowest_bit[2],索引2(0b0010)的最低位1在bit1,所以_tx_thread_lowest_bit[1]为1,_tx_thread_lowest_bit[3],索引3(0b0011)的最低位1在bit0,所以_tx_thread_lowest_bit[1]为0
		
            /* Check for priorities 0-7.  */
            #def 先计算priority_map 优先级中bit0-bit7最低位为1的偏移,也就是最高优先级
            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 自我挂起
            if (thread_ptr == _tx_thread_execute_ptr)
            {

                /* Pickup the highest priority thread to execute.  */
                #def 先设置最高优先级(前面计算出来的)线程为执行线程
                _tx_thread_execute_ptr =  _tx_thread_priority_list[_tx_thread_highest_priority];

                /* Determine if a previous thread with preemption threshold was 
                   preempted.  */
                #def 如果_tx_thread_preempted_map不为0,说明之前发生了基于preemption threshold门限值的抢占,那么下一个执行线程选择必须考虑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 选择出被抢占的最高优先级
                    /* 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 (_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 不在需要挂起,直接返回。
        /* 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();
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!