1. 程式人生 > 其它 >4 rt-thread posix 條件變數原始碼分析

4 rt-thread posix 條件變數原始碼分析

技術標籤: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):時間沒有溢位,沒有獲取到訊號,退出臨界區。退出。