ThreadX学习(3)——互斥锁
学习参考:
- 《Real-Time Embedded Multithreading: Using ThreadX and ARM》
(链接:https://pan.baidu.com/s/1GMScXSlHq13yS4AVxP_zPw 提取码:ysuw ) - 安富莱_STM32-V7开发板ThreadX内核教程(V0.7)——硬汉嵌入式论坛
MCB
互斥控制块 Mutex Control Block (MCB):
互斥锁挂起列表
当一个线程因为等待互斥而被挂起时,它会以FIFO先进先出的方式被放在互斥锁的挂起列表中。
当互斥锁可用时,挂起列表中的第一个线程(不管优先级如何)将获得该互斥锁的所有权。
tx_ mutex_priority可以将互斥锁挂起列表的最高优先级线程放在列表的最前面,所有其他线程保持相同的FIFO顺序。
互斥锁所有权计数
tx_mutex_ownership_count:
当线程获取互斥锁,其所有权计数将加一。相同线程重复获取同一互斥锁,所有权计数重复加一。
当线程释放互斥锁,其所有权计数将减一。相同线程重复释放同一互斥锁,所有权计数重复减一。所有权计数变为零,互斥锁就可用了。
除互斥锁拥有者以外的线程,不会改变所有权计数。
死锁
应用程序级的预防是实时系统避免死锁的唯一方法。
确保不存在死锁的唯一方法是允许一个线程在任何时候最多拥有一个互斥锁。如果线程必须拥有多个互斥锁,通常可以让线程以相同的顺序获取互斥锁。
互斥锁不同于信号量,可以让互斥锁的数量尽可能的少,整体复杂度减少。
另外,还可以在获取互斥锁时启用超时特效,设置最长等待时间。
另一个线程调用tx_thread_wait_abort服务可以中止陷入死锁中的线程的挂起。
优先级继承
创建互斥锁时,可以选择启用优先级继承。
当启用时,线程获取互斥锁后将会提高自身优先级,数值为互斥锁挂起列表中的最高优先级值。当线程释放互斥锁,优先级会恢复。
若线程启用抢占阈值,则在上述过程中抢占阈值与优先级一致(即无效),释放后恢复。
API
1.tx_mutex_create
TX_MUTEX my_mutex; //先定义再创建
UINT tx_mutex_create( TX_MUTEX *mutex_ptr,
CHAR *name_ptr,
UINT inherit)
创建互斥锁:
- 第 1 个参数 mutex_ptr 是MCB地址。
- 第 2 个参数 name_ptr 是互斥锁名。
- 第 3 个参数 inherit 是该互斥锁是否开启优先级继承。TX_INHERIT(0x01)为是,TX_NO_INHERIT(0x00)为否。
- 返回值:
- TX_SUCCESS(0x00)成功创建互斥锁。
- TX_MUTEX_ERROR: (0x1C)无效的互斥指针。要么指针为NULL,要么互斥锁已经创建。
- TX_CALLER_ERROR:(0x13)无效的服务调用者。
- TX_INHERIT_ERROR:(0x1F)无效的优先级继承参数。
2.tx_mutex_delete
UINT tx_mutex_delete(TX_MUTEX *mutex_ptr)
删除互斥锁:
- 第 1 个参数 mutex_ptr 是MCB地址。
- 返回值:
- TX_SUCCESS(0x00)成功删除互斥锁。
- TX_MUTEX_ERROR: (0x1C)无效的互斥指针。
- TX_CALLER_ERROR:(0x13)无效的服务调用者。
当一个互斥锁被删除时,所有因为等待该锁而挂起的线程都会被恢复(放到就绪列表中)。这些线程都将从tx_mutex_get的调用中接收一个TX_DELETED返回状态。
3.tx_mutex_get
UINT _tx_mutex_get(TX_MUTEX *mutex_ptr,
ULONG wait_option)
获取互斥锁:
- 第 1 个参数 mutex_ptr 是MCB地址。
- 第 2 个参数 wait_option 是等待选项:
- TX_NO_WAIT:不等待,直接返回结果。
- TX_WAIT_FOREVER:一直等待直到获取互斥锁。
- timeout value:设置等待时间(时钟脉冲)。
- 返回值:
- TX_SUCCESS(0x00)成功获取互斥锁。
- TX_DELETED: (0x01)线程挂起时删除了互斥锁。
- TX_NOT_AVAILABLE: (0x1D)服务无法在指定的等待时间内获得互斥锁的所有权。
- TX_WAIT_ABORTED: (0x1A)挂起被另一个线程、计时器或ISR中止。
- TX_MUTEX_ERROR: (0x1C)无效的互斥锁指针。
- TX_WAIT_ERROR: (0x04)在非线程调用时指定了TX_NO_WAIT以外的等待选项。
- TX_CALLER_ERROR:(0x13)无效的服务调用者。
如果该线程已经拥有该互斥锁,那么将增加MCB中tx_mutex_ownership_count计数器并返回成功状态。
4.tx_mutex_info_get
UINT tx_mutex_info_get(TX_MUTEX *mutex_ptr,
CHAR **name,
ULONG *count,
TX_THREAD **owner,
TX_THREAD **first_suspended,
ULONG *suspended_count,
TX_MUTEX **next_mutex)
获取互斥锁信息:
- 第 1 个参数 mutex_ptr 是MCB指针。
- 第 2 个参数 name 是互斥锁名字符串,获取后存储的指针。
- 第 3 个参数 count 是互斥锁所有权计数tx_mutex_ownership_count,获取后存储的指针。
- 第 4 个参数 owner 是互斥锁拥有者线程TCB指针,获取后存储的指针。
- 第 5 个参数 first_suspended 是等待该互斥锁(MCB中的挂起列表)的第一个线程TCB指针,获取后存储的指针。
- 第 6 个参数 suspended_count 是等待该互斥锁(MCB中的挂起列表)的线程数,获取后存储的指针。
- 第 7 个参数 next_mutex 是互斥锁列表的下一个互斥锁MCB指针,获取后存储的指针。
- 返回值:
- TX_SUCCESS(0x00)成功获取互斥锁信息。
- TX_MUTEX_ERROR: (0x1C)无效的互斥锁指针。
5.tx_mutex_prioritize
UINT tx_mutex_prioritize(TX_MUTEX *mutex_ptr)
互斥锁挂起列表的最高优先级线程置队头:
- 第 1 个参数 mutex_ptr 是MCB指针。
- 返回值:
- TX_SUCCESS(0x00)成功或挂起列表为空。
- TX_MUTEX_ERROR: (0x1C)无效的互斥锁指针。
6.tx_mutex_put
UINT tx_mutex_put(TX_MUTEX *mutex_ptr)
释放互斥锁:
- 第 1 个参数 mutex_ptr 是MCB指针。
- 返回值:
- TX_SUCCESS(0x00)成功释放。
- TX_NOT_OWNED(0x1E)该线程不是互斥锁拥有者。
- TX_MUTEX_ERROR:(0x1C)指向互斥的指针无效。
- TX_CALLER_ERROR:(0x13)无效的服务调用者。
如果互斥锁可用,并且启用了优先级继承,那么释放互斥锁将恢复线程到它最初的优先级。在拥有互斥锁期间对线程所做的任何其他优先级更改也可能被撤消。