posix 条件变量源码分析
初始化条件变量
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
{
zs_err_t result;
char cond_name[ZS_NAME_MAX];
static zs_uint16_t cond_num = 0;
/* parameter check */
if (cond == ZS_NULL)
return EINVAL;
if ((attr != ZS_NULL) && (*attr != PTHREAD_PROCESS_PRIVATE)) ///> (1)
return EINVAL;
snprintf(cond_name, sizeof(cond_name), "cond%02d", cond_num++);
if (attr == ZS_NULL) /* use default value */
cond->attr = PTHREAD_PROCESS_PRIVATE; ///> (2)
else
cond->attr = *attr;
result = zs_sem_init(&cond->sem, cond_name, 0, ZS_IPC_FLAG_FIFO); ///> (3)
if (result != ZS_EOK)
return EINVAL;
/* detach the object from system object container */
zs_object_detach(&(cond->sem.parent.parent)); ///> (4)
cond->sem.parent.parent.type = ZS_Object_Class_Semaphore; ///> (5)
return 0;
}
代码段(1):判断属性为空;不是同一个进程创建的线程,不能处理该互斥锁。
代码段(2):设置默认的属性值。
代码段(3):设置指定的属性值。
代码段(4):将此条件变量在object类链表上分离。
代码段(5):添加此条件变量 在object 信号类的链表中。
销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond)
{
zs_err_t result;
if (cond == ZS_NULL) ///>(1)
return EINVAL;
if (cond->attr == -1) ///>(2)
return 0; /* which is not initialized */
result = zs_sem_trytake(&(cond->sem)); ///>(3)
if (result != ZS_EOK)
return EBUSY;
/* clean condition */
memset(cond, 0, sizeof(pthread_cond_t)); ///>(4)
cond->attr = -1; ///>(5)
return 0;
}
代码段(1):没有条件变量对象,返回。
代码段(2):条件变量属性没有初始化,返回。
代码段(3):非阻塞的方式获取信号量,result 不等于 0,忙。等于 0,空闲。
代码段(4):将条件变量对象的信息清0。
代码段(5):设置条件变量的属性为未初始化的状态。
阻塞方式获取条件变量
zs_err_t _pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, zs_int32_t timeout)
{
zs_err_t result;
if (!cond || !mutex) ///> (2)
return -ZS_ERROR;
/* check whether initialized */
if (cond->attr == -1) ///> (3)
pthread_cond_init(cond, ZS_NULL);
/* The mutex was not owned by the current thread at the time of the call. */
if (mutex->lock.owner != zs_thread_self()) ///> (4)
return -ZS_ERROR;
/* unlock a mutex failed */
if (pthread_mutex_unlock(mutex) != 0) ///> (5)
return -ZS_ERROR;
result = zs_sem_take(&(cond->sem), timeout); ///> (6)
/* lock mutex again */
pthread_mutex_lock(mutex); ///> (7)
return result;
}
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
{
zs_err_t result;
result = _pthread_cond_timedwait(cond, mutex, ZS_WAITING_FOREVER); ///> (1)
if (result == ZS_EOK)
return 0;
return EINVAL;
}
代码段(1):阻塞方式等待条件变量。
代码段(2):条件对象为空;互斥锁为空。退出。
代码段(3):条件对象没有初始化。退出。
代码段(4):调用时互斥锁不属于当前线程。
代码段(5):互斥锁解锁。失败,退出。
代码段(6):阻塞方式调用互斥锁。
代码段(7):互斥锁上锁。
指定阻塞时间获取时间获取条件变量
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
{
int timeout;
zs_err_t result;
timeout = clock_time_to_tick(abstime); ///> (1)
result = _pthread_cond_timedwait(cond, mutex, timeout); ///> (2)
if (result == ZS_EOK) ///> (3)
return 0;
if (result == -ZS_ETIMEOUT) ///> (4)
return ETIMEDOUT;
return EINVAL;
}
代码段(1):将用户设置的时间转换为rtc时间。
代码段(2):非阻塞方式创建定时时间。
代码段(3):条件变量已释放。
代码段(4):指定时间内条件变量未释放。
发送满足条件信号量
int pthread_cond_signal(pthread_cond_t *cond)
{
zs_err_t result;
if (cond == ZS_NULL)
return EINVAL;
if (cond->attr == -1)
pthread_cond_init(cond, ZS_NULL); ///> (1)
result = zs_sem_release(&(cond->sem)); ///> (2)
if (result == ZS_EOK)
return 0;
return 0;
}
代码段(1):条件变量对象属性未设置时,初始化条件变量对象。
代码段(2):释放信号量。
广播
int pthread_cond_broadcast(pthread_cond_t *cond)
{
zs_err_t result;
if (cond == ZS_NULL)
return EINVAL;
if (cond->attr == -1)
pthread_cond_init(cond, ZS_NULL);
zs_enter_critical();
while (1)
{
/* try to take condition semaphore */
result = zs_sem_trytake(&(cond->sem)); ///> (1)
if (result == -ZS_ETIMEOUT)
{
/* it's timeout, release this semaphore */
zs_sem_release(&(cond->sem)); ///> (2)
}
else if (result == ZS_EOK)
{
/* has taken this semaphore, release it */
zs_sem_release(&(cond->sem)); ///> (3)
break;
}
else
{
zs_exit_critical(); ///> (4)
return EINVAL;
}
}
zs_exit_critical();
return 0;
}
代码段(1):非阻塞方式获取条件变量。
代码段(2):时间溢出,释放信号量。
代码段(3):获取到条件变量,释放信号量。继续获取条件变量。
代码段(4):时间没有溢出,没有获取到信号,退出临界区。退出。