前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >POSIX之Mutex

POSIX之Mutex

作者头像
Taishan3721
发布2022-12-05 15:50:13
9850
发布2022-12-05 15:50:13
举报
文章被收录于专栏:这里只有VxWorks

多任务共享资源需要互斥,VxWorks里可以使用互斥信号量。Posix也定义类似的概念:用于Thread的Mutex

Mutex用于解决Multi-Threading的数据访问冲突,它有两种状态: unlocked (不属于任何线程)、locked (属于某线程,不可能同时属于两个不同的线程)。获得Mutex的线程可以完成"读-改-写"的操作,然后释放给其它线程。其它尝试获得Mutex的线程只能等待。这样"读-改-写"就组成一个原子操作

代码语言:javascript
复制
int pthread_mutex_init(pthread_mutex_t *pMutex, const pthread_mutexattr_t *pAttr);
int pthread_mutex_destroy(pthread_mutex_t *pMutex);

使用pthread_mutex_init(),根据属性pAttr来初始化pMutex。如果pAttr为NULL,则使用默认属性。不同版本的属性定义略有区别

代码语言:javascript
复制
/* Vx6 Kernel */
typedef struct
    {
    int mutexAttrStatus;
    int mutexAttrProtocol;
    int mutexAttrPrioceiling;
    } pthread_mutexattr_t;

/* Vx6 RTP */
typedef struct
    {
    int mutexAttrStatus;
    int mutexAttrProtocol;
    int mutexAttrPrioceiling; 
    int mutexAttrType;
    } pthread_mutexattr_t;

/* Vx7 */
typedef struct
    {
    int mutexAttrStatus;
    int mutexAttrFlags;
    int mutexAttrProtocol;
    int mutexAttrPrioceiling;
    int mutexAttrType;
    } pthread_mutexattr_t;

与属性相关的API有这些

代码语言:javascript
复制
/*
 * mutexAttrStatus
 *   PTHREAD_INITIALIZED_OBJ   - 默认值
 *   PTHREAD_DESTROYED_OBJ
 */
int pthread_mutexattr_init(pthread_mutexattr_t *);
int pthread_mutexattr_destroy(pthread_mutexattr_t *);
/* 
 * mutexAttrType指的是Thread再次lock同一个Mutex时的不同操作
 *   PTHREAD_MUTEX_NORMAL- 这是默认值,挂起当前Thread(如果是tryLock,则返回EBUSY)
 *   PTHREAD_MUTEX_ERRORCHECK - 返回EDEADLK(如果是tryLock,则返回EBUSY)
 *   PTHREAD_MUTEX_RECURSIVE - 成功
 */
int pthread_mutexattr_settype(pthread_mutexattr_t *pAttr, int type);
int pthread_mutexattr_gettype(pthread_mutexattr_t *pAttr, int *pType);

/* mutexAttrFlags
 *   PTHREAD_PROCESS_PRIVATE - 这是默认值
 *   PTHREAD_PROCESS_SHARED - 这个Mutex可以在RTP之间共享
 */
int pthread_mutexattr_getpshared(pthread_mutexattr_t *pAttr, int *pPshared);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *pAttr, int shared);

/* mutexAttrFlags
 *   PTHREAD_MUTEX_STALLED - 这是默认值
 *   PTHREAD_MUTEX_ROBUST - 已经lock这个Mutex的Thread如果terminated,
 *                          其它Thread再lock时,就会返回EOWNERDEAD,
 *                          其它Thread可以调用pthread_mutex_consistent()来修复Muxte,然后调用pthread_mutex_unlock()。
 *                          如果修复失败,也需要调用pthread_mutex_unlock(),然后再有Thread尝试lock时,就会返回ENOTRECOVERABLE
 */
int pthread_mutexattr_getrobust(pthread_mutexattr_t *pAttr, int *pRobustness);
int pthread_mutexattr_setrobust(pthread_mutexattr_t *pAttr, int robustness);

/*
 * mutexAttrProtocol
 *   PTHREAD_PRIO_NONE    - 这是默认值
 *   PTHREAD_PRIO_INHERIT - 底层的互斥信号量使能SEM_INVERSION_SAFE选项
 *   PTHREAD_PRIO_PROTECT - 使用这种Protocol之后,lock这个Mutex的Thread会将其优先级提升到mutexAttrPrioceiling。
 *                          unlock时再恢复优先级。
 * PTHREAD_PRIO_INHERIT和PTHREAD_PRIO_PROTECT的目的都是解决Priority Inversion的问题。
 * PTHREAD_PRIO_INHERIT的效率略高一些,因为它只在必要时改变优先级。
 * PTHREAD_PRIO_PROTECT还会阻止优先级高于mutexAttrPrioceiling的Thread。
 */
int pthread_mutexattr_setprotocol(pthread_mutexattr_t *pAttr, int protocol);
int pthread_mutexattr_getprotocol(pthread_mutexattr_t *pAttr, int *pProtocol);

/* mutexAttrPrioceiling,仅在PTHREAD_PRIO_PROTECT时使用 */
int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *pAttr, int prioceiling);
int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *pAttr, int *pPrioceiling);

/* mutexAttr.mutexAttrPrioceiling,仅在PTHREAD_PRIO_PROTECT时使用 */
int pthread_mutex_setprioceiling(pthread_mutex_t *pAttr, int prioceiling, int *pOldPrioceiling);
int pthread_mutex_getprioceiling(pthread_mutex_t *pAttr, int *pPrioceiling);

int pthread_mutex_consistent(pthread_mutex_t *pMutex);

操作Mutex的API有

代码语言:javascript
复制
/*
 * 此函数用于lock pMutex
 * 如果pMutex处于unlocked状态, 将其置为locked, 并将当前Thread置为其owner.
 * 然后pthread_mutex_lock()立即返回.
 *
 * 如果pMutex已经被其它Thread lock,
 * pthread_mutex_lock()阻塞当前Thread,直到Mutex变成unlocked.
 *
 * 如果Thread再次lock已经被自己lock的Mutex, 那接下来的行为取决于mutexAttrType
 */
int pthread_mutex_lock(pthread_mutex_t *pMutex);
/*
 * 如果pMutex已经被其它Thread lock,
 * pthread_mutex_lock()阻塞当前Thread,直到Mutex变成unlocked或超时.
 * pAbstime是绝对时间
 *
 * 其它行为与pthread_mutex_lock()一致
 */
int pthread_mutex_timedlock(pthread_mutex_t *pMutex, struct timespec *pAbstime);
/*
 * 如果pMutex已经被其它Thread lock, pthread_mutex_trylock()返回EBUSY
 *
 * 其它行为与pthread_mutex_lock()类似
 */
int pthread_mutex_trylock(pthread_mutex_t *pMutex);
/*
 * unlock pMutex
 * 如果当前Thread并没有lock这个Mutex,则返回EPERM
 * 如果Mutex是PTHREAD_MUTEX_RECURSIVE,且当前Thread已执行过多次lock,则将lock的次数减一
 * 否则将Mutex置为unlocked
 */
int pthread_mutex_unlock(pthread_mutex_t *pMutex);

pthread_mutex_lock()的流程图如下,PTHREAD_MUTEX_NORMAL在Linux叫做fast,相应的处理方式是deadlock

pthread_mutex_trylock()的流程图

Vx69里写个RTP的例子

代码语言:javascript
复制
/*
 * 版权所有  公众号  VxWorks567
 */

#include <stdio.h>    /* printf() */
#include <unistd.h>   /* sleep() */
#include <pthread.h>  /* pthread_create() */

static pthread_mutex_t mutexid;

static void *thread1(void *arg)
    {
    int ret;

    sleep(1);
    /* #define EBUSY   16  Device or resource busy */
    printf("Test Mutex: in thread1 0x%x, pthread_mutex_trylock %p begin\n\n", (int)pthread_self(), &mutexid);
    ret = pthread_mutex_trylock (&mutexid);
    printf("Test Mutex: in thread1 0x%x, pthread_mutex_trylock %p end = %d\n", (int)pthread_self(), &mutexid, ret);

    printf("Test Mutex: in thread1 0x%x, pthread_mutex_lock %p begin\n\n", (int)pthread_self(), &mutexid);
    ret = pthread_mutex_lock (&mutexid);
    printf("Test Mutex: in thread1 0x%x, pthread_mutex_lock %p end = %d\n", (int)pthread_self(), &mutexid, ret);

#if 0
    /* #define EDEADLK 35  Resource deadlock would occur */
    printf("Test Mutex: in thread1 0x%x, pthread_mutex_lock %p begin\n\n", (int)pthread_self(), &mutexid);
    ret = pthread_mutex_lock (&mutexid);
    printf("Test Mutex: in thread1 0x%x, pthread_mutex_lock %p end = %d\n", (int)pthread_self(), &mutexid, ret);

    printf("Test Mutex: in thread1 0x%x, pthread_mutex_unlock %p begin\n", (int)pthread_self(), &mutexid);
    ret = pthread_mutex_unlock (&mutexid);
    printf("Test Mutex: in thread1 0x%x, pthread_mutex_unlock %p end = %d\n", (int)pthread_self(), &mutexid, ret);
#endif

    /* #define EPERM   1  Operation not permitted */
    printf("Test Mutex: in thread1 0x%x, pthread_mutex_unlock %p begin\n", (int)pthread_self(), &mutexid);
    ret = pthread_mutex_unlock (&mutexid);
    printf("Test Mutex: in thread1 0x%x, pthread_mutex_unlock %p end = %d\n", (int)pthread_self(), &mutexid, ret);
    return NULL;
    }
    
static void *thread2(void *arg)
    {
    int ret;

    printf("Test Mutex: in thread2 0x%x, pthread_mutex_lock %p begin\n", (int)pthread_self(), &mutexid);
    ret = pthread_mutex_lock (&mutexid);
    printf("Test Mutex: in thread2 0x%x, pthread_mutex_lock %p end\n\n", (int)pthread_self(), &mutexid);

    sleep(2);

    printf("Test Mutex: in thread2 0x%x, pthread_mutex_unlock %p begin\n", (int)pthread_self(), &mutexid);
    ret = pthread_mutex_unlock (&mutexid);
    printf("Test Mutex: in thread2 0x%x, pthread_mutex_unlock %p end\n", (int)pthread_self(), &mutexid);
    return NULL;
    }

int main()
    {
    pthread_t tid1;
    pthread_t tid2;
    int ret;

    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
#if 1
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
#elif 1
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
#else
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
#endif
    pthread_mutex_init(&mutexid, &attr);
    pthread_mutexattr_destroy(&attr);

    printf("Test Mutex: in thread0 0x%x, pthread_mutex_init %p\n", (int)pthread_self(), &mutexid);

    ret = pthread_create(&tid1, NULL, &thread1, NULL);
    ret = pthread_create(&tid2, NULL, &thread2, NULL);
    ret = pthread_join(tid1, NULL);
    ret = pthread_join(tid2, NULL);

    ret = pthread_mutex_destroy (&mutexid);
    printf("Test Mutex: in thread0 0x%x, pthread_mutex_destroy %p\n", (int)pthread_self(), &mutexid);
    return 0;
    }
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 这里只有VxWorks 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档