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):释放互斥锁。