3 rt-thread posix 互斥量源码分析

rt-thread posix 互斥量源码分析

互斥锁控制块

每个互斥锁对应一个互斥锁控制块,包含对互斥锁进行的控制的一些信息。创建互斥锁前必须先定义一个 pthread_mutex_t 类型的变量,pthread_mutex_t 是 pthread_mutex 的重定义,pthread_mutex 数据结构定义在 pthread.h 头文件里,数据结构如下:

struct pthread_mutex
{
    pthread_mutexattr_t attr;    /* 互斥锁属性 */
    struct rt_mutex lock;    /* RT-Thread 互斥锁控制块 */
};
typedef struct pthread_mutex pthread_mutex_t;

rt_mutex 是 RT-Thread 内核里定义的一个数据结构,定义在 rtdef.h 头文件里,数据结构如下:

struct rt_mutex
{
    struct rt_ipc_object parent;                /* 继承自 ipc_object 类 */
    rt_uint16_t          value;                  /* 互斥锁的值 */
    rt_uint8_t           original_priority;     /* 持有线程的原始优先级 */
    rt_uint8_t           hold;                    /* 互斥锁持有计数  */
    struct rt_thread    *owner;                 /* 当前拥有互斥锁的线程 */
};
typedef struct rt_mutex* rt_mutex_t;        /* rt_mutext_t 为指向互斥锁结构体的指针 */

初始化互斥锁

#define PTHREAD_PROCESS_PRIVATE  		0  ///> 只能被初始化线程所属的进程中的线程共享
#define PTHREAD_PROCESS_SHARED   		1  ///> 互斥锁可以被跨进程共享
const pthread_mutexattr_t pthread_default_mutexattr = PTHREAD_PROCESS_PRIVATE;

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
{
    zs_err_t result;
    char name[ZS_NAME_MAX];
    static zs_uint16_t pthread_mutex_number = 0;
    if (!mutex)
        return EINVAL;
    /* build mutex name */
    snprintf(name, sizeof(name), "pmtx%02d", pthread_mutex_number ++);
    if (attr == ZS_NULL)
        mutex->attr = pthread_default_mutexattr;                        ///> (1)
    else
        mutex->attr = *attr;                                            ///> (2)
    /* init mutex lock */
    result = zs_mutex_init(&(mutex->lock), name, ZS_IPC_FLAG_FIFO);     ///> (3)
    if (result != ZS_EOK)
        return EINVAL;
    /* detach the object from system object container */
    zs_object_detach(&(mutex->lock.parent.parent));                     ///> (4)
    mutex->lock.parent.parent.type = ZS_Object_Class_Mutex;             ///> (5)
    return 0;
}

代码段(1):设置互斥量属性为默认 PTHREAD_PROCESS_PRIVATE。
代码段(2):设置互斥量属性为指定属性。
代码段(3):初始化操作系统(rt-thread)互斥量。
代码段(4):在操作系统(rt-thread)内脱离这个互斥量。
代码段(5):在操作系统(rt-thread)内互斥量类创建这个互斥量。

销毁互斥锁

int pthread_mutex_destroy(pthread_mutex_t *mutex)
{
    if (!mutex || mutex->attr == -1)                ///> (1)
        return EINVAL;
    /* it's busy */
    if (mutex->lock.owner != ZS_NULL)               ///> (2)
        return EBUSY;
    memset(mutex, 0, sizeof(pthread_mutex_t));      ///> (3)
    mutex->attr = -1;                               ///> (4)
    return 0;
}

代码段(1): 没有互斥量对象或者互斥量对象已经销毁,返回。
代码段(2): 互斥量正在运行,返回。
代码段(3): 将互斥量对象内容清0。
代码段(4): 设置对象属性,表示对象已经销毁。销毁后处于未初始化状态。

阻塞方式对互斥锁上锁

int pthread_mutex_lock(pthread_mutex_t *mutex)
{
    int mtype;
    zs_err_t result;
    if (!mutex)                                         ///> (1)
        return EINVAL;
    if (mutex->attr == -1)                              ///> (2)
    {
        /* init mutex */
        pthread_mutex_init(mutex, ZS_NULL);             ///> (3)
    }
    mtype = mutex->attr & MUTEXATTR_TYPE_MASK;          ///> (4)
    zs_enter_critical();                                ///> (5)
    if (mutex->lock.owner == zs_thread_self() && mtype != PTHREAD_MUTEX_RECURSIVE)  ///> (6)
    {
        zs_exit_critical();                             ///> (7)
        return EDEADLK;
    }
    zs_exit_critical();                                 ///> (8)
    result = zs_mutex_take(&(mutex->lock), ZS_WAITING_FOREVER);                     ///> (9)
    if (result == ZS_EOK)
        return 0;
    return EINVAL;
}

代码段(1): 没有互斥量对象,返回。
代码段(2): 互斥量对象是否销毁。
代码段(3): 互斥锁对象销毁,从新初始化互斥锁。
代码段(4): MUTEXATTR_TYPE_MASK 掩码,取后几位。
代码段(5): 进入临界区
代码段(6): 互斥锁是否在当前线程运行,互斥锁是否是 PTHREAD_MUTEX_RECURSIVE 类型。
代码段(7): 退出临界区。
代码段(8): 退出临界区。
代码段(9): 挂起线程,阻塞方式等待信号到来。

非阻塞方式对互斥锁上锁

int pthread_mutex_trylock(pthread_mutex_t *mutex)
{
    zs_err_t result;
    int mtype;
    if (!mutex)
        return EINVAL;
    if (mutex->attr == -1)
    {
        /* init mutex */
        pthread_mutex_init(mutex, ZS_NULL);
    }
    mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
    zs_enter_critical();
    if (mutex->lock.owner == zs_thread_self() && mtype != PTHREAD_MUTEX_RECURSIVE)
    {
        zs_exit_critical();
        return EDEADLK;
    }
    zs_exit_critical();
    result = zs_mutex_take(&(mutex->lock), 0);              ///> (1)
    if (result == ZS_EOK) return 0;
    return EBUSY;
}

代码段(1):非阻塞方式等待信号到来。

解锁互斥锁

int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
    zs_err_t result;
    if (!mutex)
        return EINVAL;
    if (mutex->attr == -1)
    {
        /* init mutex */
        pthread_mutex_init(mutex, ZS_NULL);
    }
    if (mutex->lock.owner != zs_thread_self())              ///> (1)
    {
        int mtype;
        mtype = mutex->attr & MUTEXATTR_TYPE_MASK;          ///> (2)
        /* error check, return EPERM */
        if (mtype == PTHREAD_MUTEX_ERRORCHECK)              ///> (3)
            return EPERM;
        /* no thread waiting on this mutex */
        if (mutex->lock.owner == ZS_NULL)                   ///> (4)
            return 0;
    }
    result = zs_mutex_release(&(mutex->lock));              ///> (5)
    if (result == ZS_EOK)
        return 0;    
    return EINVAL;
}

代码段(1):互斥锁对象所在线程是否为当前线程。
代码段(2):MUTEXATTR_TYPE_MASK 掩码,取后几位。
代码段(3):PTHREAD_MUTEX_ERRORCHECK错误,返回。
代码段(4):在这个互斥锁对象上没有线程等待,返回。
代码段(5):释放互斥锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值