在移植Linux的中間件時需要使用中間件自帶的測試程序進行測試,在測試線程嘗試獲取寫鎖時會遇到理論上應該有錯誤信息的,而在SylixOS上沒有錯誤提示從而導致測試程序失敗。測試模型如程序清單 1.1所示。
程序清單 1.1 線程讀寫鎖測試模型
#include <stdio.h>
#include <pthread.h>
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
int main(int argc, char const *argv[])
{
int iRet = -1;
iRet = pthread_rwlock_init(&rwlock, NULL);
if (iRet != 0) {
printf("pthread_rwlock_init failed.\n");
return (-1);
}
iRet = pthread_rwlock_trywrlock(&rwlock);
if (iRet != 0) {
printf("first trywrlock return %d\n", iRet);
return (-1);
}
/*
* do something
*/
iRet = pthread_rwlock_trywrlock(&rwlock);
if (iRet != 0) {
printf("second trywrlock return %d\n", iRet);
return (-1);
}
/*
* do something
*/
pthread_rwlock_destroy(&rwlock);
printf("posix rwlock success!\n");
return (0);
}
Linux上測試結果如圖 1.1所示,Linux下在第二次trywrlock時失敗(測試時有時候就需要測試錯誤信息)。
圖 1.1 Linux讀寫鎖測試結果
在SylixOS上測試結果如圖 1.2所示,程序正常運行。
圖 1.2 SylixOS讀寫鎖測試結果
因爲測試程序就是針對錯誤信息進行測試的,所以在SylixOS下該測試用例不通過。
根據SylixOS和Linux下的不同測試結果分析可知兩者區別便是:同一個線程在第一次獲得讀寫鎖後再一次trywrlock時是否返回成功。
2.1 SylixOS讀寫鎖實現
SylixOS線程在第二次trywrlock時做了一個判斷,如果該寫鎖被當前線程使用,則引用計數值加一且返回成功,源碼如圖 1.1所示。
圖 2.1 SylixOS寫鎖判斷
SylixOS認爲某個線程之前已經獲得寫鎖,現在該線程需要再次trywrlock則認爲獲取寫鎖成功(因爲該線程一直擁有寫鎖)。
2.2 Linux讀寫鎖實現
Linux線程在第二次trywrlock時,發現寫鎖被使用則直接返回EBUSY(EBUSY=16)即表示出錯,源碼如圖 2.2所示。
圖 2.2 Linux寫鎖實現原理
對於Linux trywrlock而言,只關心能否獲得鎖。能夠獲取成功則返回0,發現寫鎖被使用則返回出錯。
SylixOS的trywrlock關注的是當前線程能否進行寫操作,而Linux的trywrlock則關注能否獲取寫鎖(如果寫鎖被佔用則返回出錯)。