Threadx 信号量semaphore

news/2024/7/8 3:51:30 标签: semaphore

文章目录

    • 信号量控制块
    • 信号量队列
    • 信号量API
    • 优先级翻转
    • 信号量创建_tx_semaphore_create
    • 删除信号量_tx_semaphore_delete

信号量(semaphore)用来保护共享资源,临界区访问,同步;可以用于生产者-消费者模式中提供事件通知。
如果信号量计数器最大为1,其值可能为0或1,成为二进制信号量。二进制信号量作用类似互斥量,但信号量不支持所有权,不支持优先级继承。

信号量控制块

Threadx中信号量控制块(SCB)用来保持运行时(run-time)信号量状态的数据结构。

/* Define the semaphore structure utilized by the application.  */

typedef struct TX_SEMAPHORE_STRUCT
{

    /* Define the semaphore ID used for error checking.  */
    ULONG       tx_semaphore_id;

    /* Define the semaphore's name.  */
    CHAR_PTR    tx_semaphore_name;

    /* Define the actual semaphore count.  A zero means that no semaphore
       instance is available.  */
    ULONG       tx_semaphore_count;

    /* Define the semaphore suspension list head along with a count of
       how many threads are suspended.  */
    struct TX_THREAD_STRUCT  *tx_semaphore_suspension_list;
    ULONG                    tx_semaphore_suspended_count;

    /* Define the created list next and previous pointers.  */
    struct TX_SEMAPHORE_STRUCT
        *tx_semaphore_created_next,
        *tx_semaphore_created_previous;

    TX_THREAD *sema_last_owner;
} TX_SEMAPHORE;
意义
tx_semaphore_id信号量ID
tx_semaphore_name信号量名字指针
tx_semaphore_count信号量计数器
tx_semaphore_suspension_list信号量挂起队列
tx_semaphore_suspended_count信号量挂起队列中元素个数
tx_semaphore_created_next指向下一个信号量指针
tx_semaphore_created_previous指向前一个信号量指针
sema_last_owner最后一个获取信号量线程指针

信号量队列

系统中所有信号量控制块挂载一个双向链表_tx_semaphore_created_ptr中,tx_semaphore_created_next 指向下一个信号量指针,tx_semaphore_created_previous指向前一个信号量指针。
在这里插入图片描述

信号量API

函数描述
_tx_semaphore_create创建信号量
_tx_semaphore_delete删除信号量
_tx_semaphore_get申请信号量
_tx_semaphore_info_get获取信号量信息
_tx_semaphore_prioritize调整信号量挂起队列,使优先级最高线程在最前面
_tx_semaphore_put释放信号量

优先级翻转

优先级翻转是指较低优先级已经获得信号量,这时较高优先级线程也需要获得的这个信号量时,较高优先级线程会被挂起,等待信号量释放。如果这时中等优先级任务抢占了低优先级任务,就出现了低优先级任务先执行,高优先级任务在等待,而且时间也变得不确定。
解决信号量导致的优先级翻转方法:开发人员通过合理设置优先级避免优先级翻转,或暂时提高拥有信号量的线程优先级避免优先级翻转。
互斥量支持优先级继承功能来提高拥有信号量的线程优先级。
信号量不支持优先级继承功能来提高拥有信号量的线程优先级。

semaphore_create_66">信号量创建_tx_semaphore_create

_tx_semaphore_create用来创建信号量,入参为信号量指针,信号量名字指针,信号量计数器初值。

UINT    _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr,
                             CHAR *name_ptr, ULONG initial_count)
{

    TX_INTERRUPT_SAVE_AREA

    TX_SEMAPHORE   *tail_ptr;                   /* Working semaphore pointer  */


    /* Setup the basic semaphore fields.  */
    #def 设置初始化值
    semaphore_ptr -> tx_semaphore_name =             name_ptr;
    semaphore_ptr -> tx_semaphore_count =            initial_count;
    semaphore_ptr -> tx_semaphore_suspension_list =  TX_NULL;
    semaphore_ptr -> tx_semaphore_suspended_count =  0;

    /* Disable interrupts to place the semaphore on the created list.  */
    TX_DISABLE

    /* Setup the semaphore ID to make it valid.  */
    semaphore_ptr -> tx_semaphore_id =  TX_SEMAPHORE_ID;

    /* Place the semaphore on the list of created semaphores.  First,
       check for an empty list.  */
       #def 插入_tx_semaphore_created_ptr list尾部
    if (_tx_semaphore_created_ptr)
    {

        /* Pickup tail pointer.  */
        tail_ptr =  _tx_semaphore_created_ptr -> tx_semaphore_created_previous;

        /* Place the new semaphore in the list.  */
        _tx_semaphore_created_ptr -> tx_semaphore_created_previous =  semaphore_ptr;
        tail_ptr -> tx_semaphore_created_next =                       semaphore_ptr;

        /* Setup this semaphore's next and previous created links.  */
        semaphore_ptr -> tx_semaphore_created_previous =  tail_ptr;
        semaphore_ptr -> tx_semaphore_created_next =      _tx_semaphore_created_ptr;
    }
    else
    {

        /* The created semaphore list is empty.  Add semaphore to empty list.  */
        _tx_semaphore_created_ptr =                       semaphore_ptr;
        semaphore_ptr -> tx_semaphore_created_next =      semaphore_ptr;
        semaphore_ptr -> tx_semaphore_created_previous =  semaphore_ptr;
    }

    /* Increment the number of semaphores created counter.  */
    _tx_semaphore_created_count++;

    /* Restore interrupts.  */
    TX_RESTORE

    /* Return TX_SUCCESS.  */
    return (TX_SUCCESS);
}

semaphore_delete_129">删除信号量_tx_semaphore_delete

删除信号量,如果tx_semaphore_suspension_list挂起队列中有线程,需要恢复线程

UINT    _tx_semaphore_delete(TX_SEMAPHORE *semaphore_ptr)
{

    TX_INTERRUPT_SAVE_AREA

    TX_THREAD       *thread_ptr;                /* Working thread pointer  */


    /* Disable interrupts to remove the semaphore from the created list.  */
    TX_DISABLE

    /* Decrement the number of semaphores created.  */
    _tx_semaphore_created_count--;

    /* Clear the semaphore ID to make it invalid.  */
    semaphore_ptr -> tx_semaphore_id =  0;
	
	#def 从_tx_semaphore_created_ptr 队列移除信号量
    /* See if the semaphore is the only one on the list.  */
    if (semaphore_ptr == semaphore_ptr -> tx_semaphore_created_next)
    {

        /* Only created semaphore, just set the created list to NULL.  */
        _tx_semaphore_created_ptr =  TX_NULL;
    }
    else
    {

        /* Link-up the neighbors.  */
        (semaphore_ptr -> tx_semaphore_created_next) -> tx_semaphore_created_previous =
            semaphore_ptr -> tx_semaphore_created_previous;
        (semaphore_ptr -> tx_semaphore_created_previous) -> tx_semaphore_created_next =
            semaphore_ptr -> tx_semaphore_created_next;

        /* See if we have to update the created list head pointer.  */
        if (_tx_semaphore_created_ptr == semaphore_ptr)

            /* Yes, move the head pointer to the next link. */
            _tx_semaphore_created_ptr =  semaphore_ptr -> tx_semaphore_created_next;
    }

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

    /* Restore interrupts.  */
    TX_RESTORE

    /* Walk through the semaphore list to resume any and all threads suspended
       on this semaphore.  */
    #def 删除tx_semaphore_suspension_list中所有线程,相应数据结构信息,并恢复线程
    thread_ptr =  semaphore_ptr -> tx_semaphore_suspension_list;
    while (semaphore_ptr -> tx_semaphore_suspended_count)
    {
        /* Lockout interrupts.  */
        TX_DISABLE

        /* Clear the cleanup pointer, this prevents the timeout from doing
           anything.  */
        thread_ptr -> tx_suspend_cleanup =  TX_NULL;

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

        /* Restore interrupts.  */
        TX_RESTORE
		
		#def 去激活定时器
        /* Yes, deactivate the thread's timer just in case.  */
        _tx_timer_deactivate(&(thread_ptr -> tx_thread_timer));

        /* Set the return status in the thread to TX_DELETED.  */
        thread_ptr -> tx_suspend_status =  TX_DELETED;

        /* Move the thread pointer ahead.  */
        thread_ptr =  thread_ptr -> tx_suspended_next;
		
		#def 恢复线程
        /* Resume the thread.  */
        _tx_thread_resume(thread_ptr -> tx_suspended_previous);

        /* Decrease the suspended count.  */
        semaphore_ptr -> tx_semaphore_suspended_count--;
    }

    /* Disable interrupts.  */
    TX_DISABLE

    /* Release previous preempt disable.  */
    _tx_thread_preempt_disable--;

    /* Restore interrupts.  */
    TX_RESTORE

	#def 开中断(可以抢占了),有可能更高级线程需要执行,例如_tx_thread_resume会恢复高优先级线程,这里进行调度
    /* Check for preemption.  */
    if (_tx_thread_current_ptr != _tx_thread_execute_ptr)

        /* Transfer control to system.  */
        _tx_thread_system_return();

    /* Return TX_SUCCESS.  */
    return (TX_SUCCESS);
}

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

相关文章

Threadx 申请信号量_tx_semaphore_get

申请信号量_tx_semaphore_get 1,如果信号量计数器tx_semaphore_count不为0,就减一,返回申请成功。 2,如果信号量计数器tx_semaphore_count为0,说明资源都被占用,挂起当前线程到tx_semaphore_suspension_li…

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初始化系统一系列与时间,定时器相关全局变量,链表,线程等。…