RTX笔记7 - 互斥信号量Mutex

  互斥锁(Mutex)可用于同步资源访问。

  互斥(通常称为Mutex)用于各种操作系统的资源管理。微控制器设备中的许多资源可以被重复使用,但一次只能被一个线程使用(例如通信通道、内存和文件)。互斥锁用于保护对共享资源的访问。创建一个互斥锁,然后在线程之间传递(它们可以获取和释放互斥锁)。

 

 

   互斥锁是信号量的特殊版本。像信号量一样,互斥锁也是一个令牌容器,但是有一个令牌,代表一个资源。因此,互斥锁令牌是二值的且有边界的。

  互斥锁的优点是它引入了线程所有权。当一个线程获得一个互斥锁并成为它的所有者时,后续从该线程获取互斥锁时将立即成功,没有任何延迟(如果指定了osMutexRecursive属性)。因此,互斥锁的获取/释放可以嵌套。

 

 

   Note:互斥锁相关函数不能被中断程序调用。

  互斥锁属性:

osMutexAttr_t Data Fields
const char * name name of the mutex

Pointer to a constant string with a human readable name (displayed during debugging) of the mutex object.

Default: NULL no name specified.

uint32_t attr_bits attribute bits

The following bit masks can be used to set options:

  • osMutexRecursive : a thread can consume the mutex multiple times without locking itself.
  • osMutexPrioInherit : the owner thread inherits the priority of a (higher priority) waiting thread.
  • osMutexRobust : the mutex is automatically released when owner thread is terminated.

Use logical 'OR' operation to select multiple options, for example:

Default: 0 which specifies:

  • non recursive mutex: a thread cannot consume the mutex multiple times.
  • non priority raising: the priority of an owning thread is not changed.
  • mutex is not automatically release: the mutex object must be always is automatically released when owner thread is terminated.
void * cb_mem memory for control block

Pointer to a memory for the mutex control block object. Refer to Static Object Memory for more information.

Default: NULL to use Automatic Dynamic Allocation for the mutex control block.

uint32_t cb_size size of provided memory for control block

The size (in bytes) of memory block passed with cb_mem. For RTX, the minimum value is defined with osRtxMutexCbSize (higher values are permitted).

Default: 0 as the default is no memory provided with cb_mem.

  osMutexRecursive:互斥锁嵌套属性,同一个线程可以在不锁定自身的情况下多次使用互斥锁。每当拥有互斥锁的线程获得互斥锁时,锁计数就会增加。互斥锁也必须被释放多次,直到锁定计数为零。当互斥量达到0时,互斥量实际上会被释放,其他线程可以获取互斥量。

  osMutexPrioInherit:优先级继承属性,使用优先级继承属性的互斥锁将 ”等待线程“ 的优先级转移给当前互斥锁的所有者(如果所有者的线程优先级较低)。这确保了低优先级线程不会阻塞高优先级线程。否则,低优先级线程可能持有互斥锁,但由于另一个中优先级线程而没有获得执行时间。如果没有优先级继承,等待互斥锁的高优先级线程将被中优先级线程阻塞,称为优先级反转

  osMutexRobust:互斥锁健壮属性,如果拥有的线程被终止(通过osThreadExit或osThreadTerminate),健壮的互斥锁将被自动释放。非健壮互斥锁不会被释放,用户必须手动确保释放互斥锁。

 

  osMutexId_t osMutexNew (const osMutexAttr_t *attr):

    创建一个互斥锁,attr是互斥锁的属性,返回执行互斥锁ID或者NULL。

  osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout):

    申请互斥锁。timeout是等待互斥锁的节拍数,0代表立即返回,不阻塞;osWaitForever代表一直等待,直到互斥锁可用。

    返回值:

      osOK:获取互斥锁成功。

      osErrorTimeout:等待超时失败。

      osErrorResource当没有指定超时时间时,获得互斥锁失败。

      osErrorParametermutex_id参数错误。

      osErrorISR中断调用错误。

  osStatus_t osMutexRelease (osMutexId_t mutex_id):

    释放互斥锁。

    返回值:

      osOK:释放互斥锁成功。

      osErrorResource互斥锁不能被释放。当前进程没有获取互斥锁或者不是互斥锁的拥有者。

      osErrorParametermutex_id参数错误。

      osErrorISR中断调用错误。

 1 osMutexId_t mutex;
 2 const osMutexAttr_t mutex_attr = {
 3     .name = "_ledThread mutex",
 4     .attr_bits = osMutexRecursive | osMutexPrioInherit,
 5     .cb_mem = NULL,
 6     .cb_size = 0,
 7 };
 8 
 9 static void _ledThread(void *argument);
10 
11 void
12 test_mutex(void)
13 {
14     osThreadId_t thread;
15     
16     mutex = osMutexNew(&mutex_attr);
17     
18     osThreadNew(_ledThread, (void *)1, NULL);
19     osThreadNew(_ledThread, (void *)2, NULL);
20 }
21 
22 static void
23 _ledThread(void *argument)
24 {
25     osStatus_t status;
26     uint32_t id = (uint32_t)argument;
27     uint32_t delay;
28     
29     if(1 == id) {
30         delay = 500;
31     } else {
32         delay = 1000;
33     }
34         
35     for(;;) {
36         status = osMutexAcquire(mutex, osWaitForever);
37         if(osOK == status) {
38             menuShow(&seg_led, delay, 0);
39             osDelay(delay);
40             osMutexRelease(mutex);
41         }
42     }
43 }

 

posted @ 2021-10-04 18:16  Ivan0512  阅读(1494)  评论(0编辑  收藏  举报