4 rt-thread posix 條件變數原始碼分析
阿新 • • 發佈:2020-12-30
技術標籤:RT-Thread
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):時間沒有溢位,沒有獲取到訊號,退出臨界區。退出。