`

rt_mutex里owner的作用

    博客分类:
  • RTOS
 
阅读更多

在rt-thread源码中的rt_mutex_take()里有这样一段代码

if (mutex->owner == thread)
    {
        /* it's the same thread */
        mutex->hold ++;
    }

 之前不理解在什么情况下线程会重复进入其所持有锁的保护区域,后来看到Vxworks Programmers Guide5.5里的一段解释和对应的例子

 

Mutual-exclusion semaphores can be taken recursively. This means that the semaphore can be taken more than once by the task that holds it before finally being released. Recursion is useful for a set of routines that must call each other but that also require mutually exclusive access to a resource.
/* Function A requires access to a resource which it acquires by taking 
 * mySem;  
 * Function A may also need to call function B, which also requires mySem: 
 */ 
 
/* includes */ 
#include "vxWorks.h" 
#include "semLib.h" 
SEM_ID mySem; 
 
/* Create a mutual-exclusion semaphore. */ 
init () 
    { 
    mySem = semMCreate (SEM_Q_PRIORITY); 
    } 
funcA () 
    { 
    semTake (mySem, WAIT_FOREVER); 
    printf ("funcA: Got mutual-exclusion semaphore\n"); 
    ...  
    funcB (); 
    ... 
     semGive (mySem); 
    printf ("funcA: Released mutual-exclusion semaphore\n"); 
    } 
funcB () 
    { 
    semTake (mySem, WAIT_FOREVER); 
    printf ("funcB: Got mutual-exclusion semaphore\n"); 
    ...  
    semGive (mySem); 
    printf ("funcB: Releases mutual-exclusion semaphore\n"); 
    }

假设thread1调用funcA(),funcA再调用funcB(),这是没有问题的
假设thread2直接调用funB(),funB()里的这段临界区也是可以被保护的
这都得益于mutex的owner机制,如果是二值信号量这样操作的话,funcB()试图获得mySem的时候就会挂起,不能返回funcA(),mySem就一直得不到释放,形成死锁,也就是rt-thread manual里提到的

 

这个特性与一般的二值信号量有很大的不同,在信号量中,因为已经不存在实例,线程递归持有会发生主动挂起(最终形成死锁)

 

owner机制还有一个作用,就是通过优先级继承实现优先级翻转,参考stackoverflow上的一个解答

Because the recursive mutex has a sense of ownership, the thread that grabs the mutex must be the same thread that release the mutex. In the case of non-recursive mutexes, there is no sense of ownership and any thread can usually release the mutex no matter which thread originally took the mutex. In many cases, this type of "mutex" is really more of a semaphore action, where you are not necessarily using the mutex as an exclusion device but use it as synchronization or signaling device between two or more threads.

Another property that comes with a sense of ownership in a mutex is the ability to support priority inheritance. Because the kernel can track the thread owning the mutex and also the identity of all the blocker(s), in a priority threaded system it becomes possible to escalate the priority of the thread that currently owns the mutex to the priority of the highest priority thread that is currently blocking on the mutex. This inheritance prevents the problem of priority inversion that can occur in such cases. (Note that not all systems support priority inheritance on such mutexes, but it is another feature that becomes possible via the notion of ownership).

If you refer to classic VxWorks RTOS kernel, they define three mechanisms:

mutex - supports recursion, and optionally priority inheritance
binary semaphore - no recursion, no inheritance, simple exclusion, taker and giver does not have to be same thread, broadcast release available
counting semaphore - no recursion or inheritance, acts as a coherent resource counter from any desired initial count, threads only block where net count against the resource is zero.

 

在使用rt_mutex_release()释放锁的时候,除了将mutex的value加1(mutex->value++),还需要将mutex的owner指向NULL(mutex->owner = RT_NULL),否则如果该mutex的owner还是这个线程,当下次这个锁未被占有,而这个线程又试图通过rt_mutex_take()获得锁的时候,就只有hold++,而没有value--,起不到临界区保护的作用


补充:Linux系统里是不支持recursive lock的(参考《Linux Kernel Development》第三版),内核里对应上锁的API是mutex_lock()

Linux, thankfully, does not provide recursive locks. This is widely considered a good thing. Although recursive locks might alleviate the self-deadlock problem, they very readily lead to sloppy locking semantics

 
但是,在应用层编程上, pthread_mutexattr_settype()里可以设置flag为PTHREAD_MUTEX_RECURSIVE,对应上锁的API是pthread_mutex_lock()

 

0
0
分享到:
评论

相关推荐

    pthread_mutex

    通过在临界区前后分别调用`pthread_mutex_lock()`和`pthread_mutex_unlock()`,可以确保同一时刻只有一个线程在执行临界区内的代码。 `1_pthread_mutex.tgz`、`1_pthread_mutex`、`1_pthread_deadlock`和`1_pthread...

    __lll_mutex_lock_wait的错误原因

    #0 0x00002b9405ea1c38 in __lll_mutex_lock_wait () from /lib64/libc.so.6 #1 0x00002b9405e45e5f in _L_lock_4026 () from /lib64/libc.so.6 #2 0x00002b9405e42df1 in free () from /lib64/libc.so.6 #3 0x00002...

    RT-Thread常见函数.zip_RTT_rt thread_rt-thread函数_rt_thread函数_手册

    `rt_sem_take`和`rt_sem_give`用于信号量操作,`rt_mutex_take`和`rt_mutex_release`用于互斥锁,`rt_msg_send`和`rt_msg_recv`处理消息队列,`rt_event_recv`接收事件,这些函数确保了资源的安全访问。 3. **...

    lib_mutex_linux.rar_Over

    pthread库提供了一个名为`pthread_mutex_t`的数据结构来表示互斥锁,并提供了以下两个主要函数: 1. `pthread_mutex_init()`: 初始化互斥锁。这个函数用于创建一个新的互斥锁并设置其属性。例如,你可以选择是否让...

    create-mutex.zip_Mutex_mutex in ucos_uCOS mutex_ucos mutex

    在嵌入式操作系统领域,UCOS...总之,Mutex在UCOS-II中的作用是确保资源的安全访问,防止竞争条件,同时也解决了优先级反转问题。通过熟练掌握Mutex的创建、获取和释放,开发者能够编写出高效、可靠的嵌入式应用程序。

    mutexs application.rar_Mutex_mutex 多线程

    在“mutexs application.rar_Mutex_mutex 多线程”这个程序示例中,我们可以通过源代码深入理解Mutex的工作原理及其在实际应用中的使用方法。 1. **Mutex的基本概念** Mutex,源于英文“mutual exclusion”,意为...

    3_pthread_sync_mutex_with_productor_and_consumer.tgz

    具体来说,`pthread_mutex_t`类型表示一个互斥锁对象,可以通过`pthread_mutex_init()`初始化,`pthread_mutex_lock()`锁定,`pthread_mutex_unlock()`解锁。在消费者和生产者之间,通常会有一个共享资源(如缓冲区...

    pthread_mutex_t_is_too_small_for_large_pids_in_aosp_bionic.patch

    32位android中bionic是32位的,其中的mutex只有一半也就是16位能够存储pid,当通过docker运行android时,大概率pid会超过16位的范围,就可能会导致android中mutex死锁,表现为应用卡住黑屏。 [32-bit ABI bugs]...

    RT_thread1.20源码

    2. **互斥锁(Mutex)**:确保同一时刻只有一个任务可以访问共享资源,防止数据竞争问题。 3. **消息队列(Message Queue)**:任务间的数据传递通道,支持异步通信,提高系统效率。 四、内存管理 RT_Thread提供了...

    5_sysv_sync_mutex.tgz

    - **锁定与解锁**:`pthread_mutex_lock()`用于锁定互斥量,只有持有锁的线程才能执行解锁操作,即`pthread_mutex_unlock()`。其他尝试获取锁的线程会阻塞直到锁被释放。 - **死锁预防**:互斥量的一个关键作用是...

    thread_mutex.c 文件

    多线程之间的同步与互斥,详情看博客:http://blog.csdn.net/mybelief321/article/details/9390707

    MPI_Mutex:MPI的互斥体仿真

    MPI_Mutex MPI的互斥体仿真 用法 该互斥锁旨在锁定特定的远程内存(RM... MPI_Comm_dup (MPI_COMM_WORLD, &mutex_Comm); if (world_rank == 0 ) { // mpi mutex ************************************************

    STM32F103移植RT_Thread

    - 互斥锁:保护共享资源,如rt_mutex_init()初始化互斥锁。 - 消息队列:线程间传递结构化数据,rt_msgqueue_init()创建消息队列。 通过以上步骤,STM32F103ZET6便成功移植了RT_Thread,实现了一个具备多任务处理...

    Latch_Lock_And_Mutex_Contention_Troubleshooting

    标题与描述:“Latch_Lock_And_Mutex_Contention_Troubleshooting” 知识点详述: ### 1. Latch机制概述 Latch是Oracle数据库中用于管理内存结构并发访问的一种低级机制,主要用于保护短暂访问的内存结构,如缓存...

    rtthread-api手册

    `rt_mutex_create()`、`rt_mutex_take()`、`rt_mutex_release()`和`rt_mutex_delete()`分别对应互斥锁的创建、获取、释放和删除操作。 4. **邮箱与消息队列**:邮箱和消息队列用于线程间通信,传输数据。`rt_mq_...

    FeedDogSys_v3.0_mutex.zip

    在"FeedDogSys_v3.0_mutex.zip"中,"mutex"(互斥锁)是UCOS中的一种同步机制,用于确保同一时间只有一个任务访问特定的资源,防止数据竞争,确保程序的正确性。 用户界面(UI)设计是用户体验的关键部分。在这个...

    ThreadX API查询手册.chm

    tx_mutex_create, tx_mutex_delete, tx_mutex_get, tx_mutex_info_get, tx_mutex_prioritize, tx_mutex_put. 队列相关API tx_queue_create, tx_queue_delete, tx_queue_flush, tx_queue_front_send, tx_queue_...

    3.线程间同步和通信之互斥锁(静态)

    RT-thread中的互斥锁API包括`rt_mutex_init`、`rt_mutex_take`、`rt_mutex_release`和`rt_mutex_destroy`等函数。 1. `rt_mutex_init`:初始化互斥锁。这个函数会创建一个新的互斥锁对象,并将其状态设置为未锁定。...

    1.操作系统实验2_1线程抢占导致临界区问题1

    mutex = rt_mutex_create("mutex", RT_IPC_FLAG_PRIO); if (mutex == RT_NULL) { rt_kprintf("Mutex create failed!\n"); return; } share_var = 0; rt_kprintf("share_var = %d\n", share_var); for (i ...

    debug_mutex:C / C ++调试互斥库-开源

    互斥锁的跨平台实现会自动检查所有内容,您可能做错了:-死锁-无效的互斥锁离开顺序-线程关闭,同时仍保持互斥锁-销毁... 可以很容易地禁用Debug_mutex并将其简单地用作跨平台互斥体库Debug_mutex可以静态或外部链接

Global site tag (gtag.js) - Google Analytics