Threadx 申请信号量_tx_semaphore_get

news/2024/7/8 4:30:52 标签: semaphore

semaphore_get_1">申请信号量_tx_semaphore_get

1,如果信号量计数器tx_semaphore_count不为0,就减一,返回申请成功。
2,如果信号量计数器tx_semaphore_count为0,说明资源都被占用,挂起当前线程到tx_semaphore_suspension_list队列,挂入队列的尾部,FIFO, 后续恢复时按住FIFO,而不是按照线程优先级

UINT    _tx_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option)
{

    TX_INTERRUPT_SAVE_AREA

    REG_1   UINT        status;                 /* Return status           */
    REG_2   TX_THREAD   *thread_ptr;            /* Working thread pointer  */


    /* Disable interrupts to get an instance from the semaphore.  */
    #def 禁止中断,防止打断对全局变量操作。如果更高优先级线程不需要信号量呢,是否有必要禁止中断
    TX_DISABLE

    /* Determine if there is an instance of the semaphore.  */
    #def 还有信号量资源
    if (semaphore_ptr -> tx_semaphore_count)
    {

        /* Decrement the semaphore count.  */
        #def 计数器减1,少一个可用信号量资源
        semaphore_ptr -> tx_semaphore_count--;
		
		#def 记录最后一个申请到资源的线程
        semaphore_ptr->sema_last_owner = _tx_thread_current_ptr;
        /* Set status to success.  */
        status =  TX_SUCCESS;
    }
    else
    {
		#def 没有信号量资源,并且wait_option不为0,挂起线程
        /* Determine if the request specifies suspension.  */
        if (wait_option)
        {
           
            /* Prepare for suspension of this thread.  */

            /* Pickup thread pointer.  */
            thread_ptr =  _tx_thread_current_ptr;

            /* Setup cleanup routine pointer.  */
            #def 由于获取不到信号量而挂起,所以设置清除函数为信号量相关的函数_tx_semaphore_cleanup,当定时器超时或线程中止时,回调这个函数,释放清除和信号量相关数据,比如从tx_semaphore_suspension_list队列移除线程
            thread_ptr -> tx_suspend_cleanup =  _tx_semaphore_cleanup;

            /* Setup cleanup information, i.e. this semaphore control
               block.  */
            thread_ptr -> tx_suspend_control_block = (VOID_PTR) semaphore_ptr;

            /* Setup suspension list.  */
            #def 插入队列的尾部,fifo,所以后续恢复时也是按照fifo,并不是按照优先级高低 恢复线程
            if (semaphore_ptr -> tx_semaphore_suspension_list)
            {

                /* This list is not NULL, add current thread to the end. */
                thread_ptr -> tx_suspended_next =
                    semaphore_ptr -> tx_semaphore_suspension_list;
                thread_ptr -> tx_suspended_previous =
                    (semaphore_ptr -> tx_semaphore_suspension_list) -> tx_suspended_previous;
                ((semaphore_ptr -> tx_semaphore_suspension_list) -> tx_suspended_previous) -> tx_suspended_next =
                    thread_ptr;
                (semaphore_ptr -> tx_semaphore_suspension_list) -> tx_suspended_previous =   thread_ptr;
            }
            else
            {

                /* No other threads are suspended.  Setup the head pointer and
                   just setup this threads pointers to itself.  */
                semaphore_ptr -> tx_semaphore_suspension_list =  thread_ptr;
                thread_ptr -> tx_suspended_next =                thread_ptr;
                thread_ptr -> tx_suspended_previous =            thread_ptr;
            }

            /* Increment the suspended thread count.  */
            semaphore_ptr -> tx_semaphore_suspended_count++;

            /* Set the state to suspended.  */
            #def 线程状态改为挂起
            thread_ptr -> tx_state =    TX_SEMAPHORE_SUSP;

            /* Set the suspending flag.  */
            #def 开始进行挂起过程标志
            thread_ptr -> tx_suspending =  TX_TRUE;

            /* Temporarily disable preemption.  */
            _tx_thread_preempt_disable++;

            /* Save the timeout value.  */
            thread_ptr -> tx_thread_timer.tx_remaining_ticks =  wait_option;

            /* Restore interrupts.  */
            #def 恢复中断,后续可能被抢占了,线程可能被恢复
            TX_RESTORE

            /* See if we need to start a timer.  */
            #def 不是TX_WAIT_FOREVER永久挂起是,开启定时器
            if (wait_option != TX_WAIT_FOREVER)
            {

                /* A timeout is required.  */
                _tx_timer_activate(&(thread_ptr -> tx_thread_timer));
            }

            /* Call actual thread suspension routine.  */
            #def 挂起,执行到这个函数时,这个 线程可能又被标记为恢复了,会检查tx_suspending 标志
            _tx_thread_suspend(thread_ptr);

            /* Return the completion status.  */
            return (thread_ptr -> tx_suspend_status);
        }
        else

            /* Immediate return, return error completion.  */
            status =  TX_NO_INSTANCE;
    }

    /* Restore interrupts.  */
    TX_RESTORE

    /* Return completion status.  */
    return (status);
}

http://www.niftyadmin.cn/n/1428572.html

相关文章

Threadx 释放信号量_tx_semaphore_put

释放信号量_tx_semaphore_put 1,如果tx_semaphore_suspension_list挂起队列为空,那么直接把tx_semaphore_count计数器加一 2,如果tx_semaphore_suspension_list挂起队列不为空,那么tx_semaphore_suspension_list最前面线程获取释…

Threadx 消息队列 queue

文章目录消息传递规则消息大小消息队列控制块消息队列list消息队列API创建消息队列_tx_queue_create删除队列_tx_queue_delete清空消息队列_tx_queue_flushThreadx提供了消息队列进行线程间通信。消息队列中消息通常按照先进先出规则传递,同时提供了把消息直接存储到…

Threadx 消息队列-发送消息_tx_queue_send

消息队列-发送消息_tx_queue_send 1,发送消息会插入到队列尾部。 2,如果消息队列有挂起的接收线程,发送消息时,可以直接把消息放到接收线程的缓冲中,这可以降低消息传递延时。 TX_THREAD线程控制块中tx_additional_su…

Threadx 消息队列-接收消息_tx_queue_receive

消息队列-接收消息_tx_queue_receive 1,如果消息队列有消息,从队列头部取出消息 (1)并且tx_queue_suspension_list有挂起线程,说明发送线程由于消息队列已满而挂起,挂起时把发送的消息 存放到了发送线程的…

Threadx 定时器timer

文章目录定时器管理结构定时器链表定时器激活链表定时器工作原理定时器API定时器创建_tx_timer_create删除定时器_tx_timer_delete修改_tx_timer_changeThreadx 操作系统定时器提供单次定时和周期性定时功能。定时器由周期性定时中断驱动,每一个定时中断称为一个时钟…

Threadx 激活定时器和去激活定时器tx_timer_activate

文章目录tx_timer_activatetx_timer_deactivate_tx_timer_deactivate分析激活定时器和去激活定时器函数。tx_timer_activate _tx_timer_activate_api(TX_TIMER *timer_ptr) 用来激活已经创建的定时器。 UINT _tx_timer_activate_api(TX_TIMER *timer_ptr) {/* Check for a…

Threadx 系统定时器线程_tx_timer_thread_entry

“System Timer Thread” 系统定时器线程用于判断定时器超时,并调用定时器超时处理函数。 _tx_timer_initialize 先来看看定时器线程创建初始化。_tx_timer_initialize初始化系统一系列与时间,定时器相关全局变量,链表,线程等。…

Threadx 内存管理-内存字节池

文章目录内存池控制块内存池链表内存池初始化内存分配内存释放内存整理字节池内存API小结_tx_byte_pool_create_tx_byte_pool_deleteThreadx 提供字节内存池进行内存管理,字节内存池是一块连续字节块,可以以字节为单位申请内存。字节内存池中连续内存初始…