|
|
@ -1,6 +1,6 @@
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
|
|
|
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
|
|
|
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
|
|
|
|
* Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
|
|
* are permitted provided that the following conditions are met:
|
|
|
|
* are permitted provided that the following conditions are met:
|
|
|
@ -43,30 +43,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef LOSCFG_KERNEL_VM
|
|
|
|
#ifdef LOSCFG_KERNEL_VM
|
|
|
|
|
|
|
|
|
|
|
|
#define OS_FUTEX_FROM_FUTEXLIST(ptr) LOS_DL_LIST_ENTRY(ptr, FutexNode, futexList) // 通过快锁节点找到结构体
|
|
|
|
#define OS_FUTEX_FROM_FUTEXLIST(ptr) LOS_DL_LIST_ENTRY(ptr, FutexNode, futexList)
|
|
|
|
#define OS_FUTEX_FROM_QUEUELIST(ptr) LOS_DL_LIST_ENTRY(ptr, FutexNode, queueList) // 通过队列节点找到结构体
|
|
|
|
#define OS_FUTEX_FROM_QUEUELIST(ptr) LOS_DL_LIST_ENTRY(ptr, FutexNode, queueList)
|
|
|
|
#define OS_FUTEX_KEY_BASE USER_ASPACE_BASE ///< 进程用户空间基址
|
|
|
|
#define OS_FUTEX_KEY_BASE USER_ASPACE_BASE
|
|
|
|
#define OS_FUTEX_KEY_MAX (USER_ASPACE_BASE + USER_ASPACE_SIZE) ///< 进程用户空间尾址
|
|
|
|
#define OS_FUTEX_KEY_MAX (USER_ASPACE_BASE + USER_ASPACE_SIZE)
|
|
|
|
|
|
|
|
|
|
|
|
/* private: 0~63 hash index_num
|
|
|
|
/* private: 0~63 hash index_num
|
|
|
|
* shared: 64~79 hash index_num */
|
|
|
|
* shared: 64~79 hash index_num */
|
|
|
|
#define FUTEX_INDEX_PRIVATE_MAX 64 ///< 0~63号桶用于存放私有锁(以虚拟地址进行哈希),同一进程不同线程共享futex变量,表明变量在进程地址空间中的位置
|
|
|
|
#define FUTEX_INDEX_PRIVATE_MAX 64
|
|
|
|
///< 它告诉内核,这个futex是进程专有的,不可以与其他进程共享。它仅仅用作同一进程的线程间同步。
|
|
|
|
#define FUTEX_INDEX_SHARED_MAX 16
|
|
|
|
#define FUTEX_INDEX_SHARED_MAX 16 ///< 64~79号桶用于存放共享锁(以物理地址进行哈希),不同进程间通过文件共享futex变量,表明该变量在文件中的位置
|
|
|
|
#define FUTEX_INDEX_MAX (FUTEX_INDEX_PRIVATE_MAX + FUTEX_INDEX_SHARED_MAX)
|
|
|
|
#define FUTEX_INDEX_MAX (FUTEX_INDEX_PRIVATE_MAX + FUTEX_INDEX_SHARED_MAX) ///< 80个哈希桶
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define FUTEX_INDEX_SHARED_POS FUTEX_INDEX_PRIVATE_MAX ///< 共享锁开始位置
|
|
|
|
#define FUTEX_INDEX_SHARED_POS FUTEX_INDEX_PRIVATE_MAX
|
|
|
|
#define FUTEX_HASH_PRIVATE_MASK (FUTEX_INDEX_PRIVATE_MAX - 1)
|
|
|
|
#define FUTEX_HASH_PRIVATE_MASK (FUTEX_INDEX_PRIVATE_MAX - 1)
|
|
|
|
#define FUTEX_HASH_SHARED_MASK (FUTEX_INDEX_SHARED_MAX - 1)
|
|
|
|
#define FUTEX_HASH_SHARED_MASK (FUTEX_INDEX_SHARED_MAX - 1)
|
|
|
|
/// 单独哈希桶,上面挂了一个个 FutexNode
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
typedef struct {
|
|
|
|
LosMux listLock;///< 内核操作lockList的互斥锁
|
|
|
|
LosMux listLock;
|
|
|
|
LOS_DL_LIST lockList;///< 用于挂载 FutexNode (Fast userspace mutex,用户态快速互斥锁)
|
|
|
|
LOS_DL_LIST lockList;
|
|
|
|
} FutexHash;
|
|
|
|
} FutexHash;
|
|
|
|
|
|
|
|
|
|
|
|
FutexHash g_futexHash[FUTEX_INDEX_MAX];///< 80个哈希桶
|
|
|
|
FutexHash g_futexHash[FUTEX_INDEX_MAX];
|
|
|
|
|
|
|
|
|
|
|
|
/// 对互斥锁封装
|
|
|
|
|
|
|
|
STATIC INT32 OsFutexLock(LosMux *lock)
|
|
|
|
STATIC INT32 OsFutexLock(LosMux *lock)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
UINT32 ret = LOS_MuxLock(lock, LOS_WAIT_FOREVER);
|
|
|
|
UINT32 ret = LOS_MuxLock(lock, LOS_WAIT_FOREVER);
|
|
|
@ -86,15 +84,15 @@ STATIC INT32 OsFutexUnlock(LosMux *lock)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return LOS_OK;
|
|
|
|
return LOS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
///< 初始化Futex(Fast userspace mutex,用户态快速互斥锁)模块
|
|
|
|
|
|
|
|
UINT32 OsFutexInit(VOID)
|
|
|
|
UINT32 OsFutexInit(VOID)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
INT32 count;
|
|
|
|
INT32 count;
|
|
|
|
UINT32 ret;
|
|
|
|
UINT32 ret;
|
|
|
|
// 初始化 80个哈希桶
|
|
|
|
|
|
|
|
for (count = 0; count < FUTEX_INDEX_MAX; count++) {
|
|
|
|
for (count = 0; count < FUTEX_INDEX_MAX; count++) {
|
|
|
|
LOS_ListInit(&g_futexHash[count].lockList); // 初始化双向链表,上面挂 FutexNode
|
|
|
|
LOS_ListInit(&g_futexHash[count].lockList);
|
|
|
|
ret = LOS_MuxInit(&(g_futexHash[count].listLock), NULL);//初始化互斥锁
|
|
|
|
ret = LOS_MuxInit(&(g_futexHash[count].listLock), NULL);
|
|
|
|
if (ret) {
|
|
|
|
if (ret) {
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -103,7 +101,7 @@ UINT32 OsFutexInit(VOID)
|
|
|
|
return LOS_OK;
|
|
|
|
return LOS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LOS_MODULE_INIT(OsFutexInit, LOS_INIT_LEVEL_KMOD_EXTENDED);///< 注册Futex模块
|
|
|
|
LOS_MODULE_INIT(OsFutexInit, LOS_INIT_LEVEL_KMOD_EXTENDED);
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef LOS_FUTEX_DEBUG
|
|
|
|
#ifdef LOS_FUTEX_DEBUG
|
|
|
|
STATIC VOID OsFutexShowTaskNodeAttr(const LOS_DL_LIST *futexList)
|
|
|
|
STATIC VOID OsFutexShowTaskNodeAttr(const LOS_DL_LIST *futexList)
|
|
|
@ -154,63 +152,63 @@ VOID OsFutexHashShow(VOID)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/// 通过用户空间地址获取哈希key
|
|
|
|
|
|
|
|
STATIC INLINE UINTPTR OsFutexFlagsToKey(const UINT32 *userVaddr, const UINT32 flags)
|
|
|
|
STATIC INLINE UINTPTR OsFutexFlagsToKey(const UINT32 *userVaddr, const UINT32 flags)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
UINTPTR futexKey;
|
|
|
|
UINTPTR futexKey;
|
|
|
|
|
|
|
|
|
|
|
|
if (flags & FUTEX_PRIVATE) {
|
|
|
|
if (flags & FUTEX_PRIVATE) {
|
|
|
|
futexKey = (UINTPTR)userVaddr;//私有锁(以虚拟地址进行哈希)
|
|
|
|
futexKey = (UINTPTR)userVaddr;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
futexKey = (UINTPTR)LOS_PaddrQuery((UINT32 *)userVaddr);//共享锁(以物理地址进行哈希)
|
|
|
|
futexKey = (UINTPTR)LOS_PaddrQuery((UINT32 *)userVaddr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return futexKey;
|
|
|
|
return futexKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 通过哈希key获取索引
|
|
|
|
|
|
|
|
STATIC INLINE UINT32 OsFutexKeyToIndex(const UINTPTR futexKey, const UINT32 flags)
|
|
|
|
STATIC INLINE UINT32 OsFutexKeyToIndex(const UINTPTR futexKey, const UINT32 flags)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
UINT32 index = LOS_HashFNV32aBuf(&futexKey, sizeof(UINTPTR), FNV1_32A_INIT);//获取哈希桶索引
|
|
|
|
UINT32 index = LOS_HashFNV32aBuf(&futexKey, sizeof(UINTPTR), FNV1_32A_INIT);
|
|
|
|
|
|
|
|
|
|
|
|
if (flags & FUTEX_PRIVATE) {
|
|
|
|
if (flags & FUTEX_PRIVATE) {
|
|
|
|
index &= FUTEX_HASH_PRIVATE_MASK;//将index锁定在 0 ~ 63号
|
|
|
|
index &= FUTEX_HASH_PRIVATE_MASK;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
index &= FUTEX_HASH_SHARED_MASK;
|
|
|
|
index &= FUTEX_HASH_SHARED_MASK;
|
|
|
|
index += FUTEX_INDEX_SHARED_POS;//共享锁索引,将index锁定在 64 ~ 79号
|
|
|
|
index += FUTEX_INDEX_SHARED_POS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return index;
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 设置快锁哈希key
|
|
|
|
|
|
|
|
STATIC INLINE VOID OsFutexSetKey(UINTPTR futexKey, UINT32 flags, FutexNode *node)
|
|
|
|
STATIC INLINE VOID OsFutexSetKey(UINTPTR futexKey, UINT32 flags, FutexNode *node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
node->key = futexKey;//哈希key
|
|
|
|
node->key = futexKey;
|
|
|
|
node->index = OsFutexKeyToIndex(futexKey, flags);//哈希桶索引
|
|
|
|
node->index = OsFutexKeyToIndex(futexKey, flags);
|
|
|
|
node->pid = (flags & FUTEX_PRIVATE) ? LOS_GetCurrProcessID() : OS_INVALID;//获取进程ID,共享快锁时 快锁节点没有进程ID
|
|
|
|
node->pid = (flags & FUTEX_PRIVATE) ? LOS_GetCurrProcessID() : OS_INVALID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//析构参数节点
|
|
|
|
|
|
|
|
STATIC INLINE VOID OsFutexDeinitFutexNode(FutexNode *node)
|
|
|
|
STATIC INLINE VOID OsFutexDeinitFutexNode(FutexNode *node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
node->index = OS_INVALID_VALUE;
|
|
|
|
node->index = OS_INVALID_VALUE;
|
|
|
|
node->pid = 0;
|
|
|
|
node->pid = 0;
|
|
|
|
LOS_ListDelete(&node->queueList);
|
|
|
|
LOS_ListDelete(&node->queueList);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 新旧两个节点交换 futexList 位置
|
|
|
|
|
|
|
|
STATIC INLINE VOID OsFutexReplaceQueueListHeadNode(FutexNode *oldHeadNode, FutexNode *newHeadNode)
|
|
|
|
STATIC INLINE VOID OsFutexReplaceQueueListHeadNode(FutexNode *oldHeadNode, FutexNode *newHeadNode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LOS_DL_LIST *futexList = oldHeadNode->futexList.pstPrev;
|
|
|
|
LOS_DL_LIST *futexList = oldHeadNode->futexList.pstPrev;
|
|
|
|
LOS_ListDelete(&oldHeadNode->futexList);//将旧节点从futexList链表上摘除
|
|
|
|
LOS_ListDelete(&oldHeadNode->futexList);
|
|
|
|
LOS_ListHeadInsert(futexList, &newHeadNode->futexList);//将新节点从头部插入futexList链表
|
|
|
|
LOS_ListHeadInsert(futexList, &newHeadNode->futexList);
|
|
|
|
if ((newHeadNode->queueList.pstNext == NULL) || (newHeadNode->queueList.pstPrev == NULL)) {//新节点前后没有等待这把锁的任务
|
|
|
|
if ((newHeadNode->queueList.pstNext == NULL) || (newHeadNode->queueList.pstPrev == NULL)) {
|
|
|
|
LOS_ListInit(&newHeadNode->queueList);//初始化等锁任务链表
|
|
|
|
LOS_ListInit(&newHeadNode->queueList);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 将参数节点从futexList上摘除
|
|
|
|
|
|
|
|
STATIC INLINE VOID OsFutexDeleteKeyFromFutexList(FutexNode *node)
|
|
|
|
STATIC INLINE VOID OsFutexDeleteKeyFromFutexList(FutexNode *node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LOS_ListDelete(&node->futexList);
|
|
|
|
LOS_ListDelete(&node->futexList);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 从哈希桶中删除快锁节点
|
|
|
|
|
|
|
|
STATIC VOID OsFutexDeleteKeyNodeFromHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags)
|
|
|
|
STATIC VOID OsFutexDeleteKeyNodeFromHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
FutexNode *nextNode = NULL;
|
|
|
|
FutexNode *nextNode = NULL;
|
|
|
@ -219,8 +217,8 @@ STATIC VOID OsFutexDeleteKeyNodeFromHash(FutexNode *node, BOOL isDeleteHead, Fut
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (LOS_ListEmpty(&node->queueList)) {//如果没有任务在等锁
|
|
|
|
if (LOS_ListEmpty(&node->queueList)) {
|
|
|
|
OsFutexDeleteKeyFromFutexList(node);//从快锁链表上摘除
|
|
|
|
OsFutexDeleteKeyFromFutexList(node);
|
|
|
|
if (queueFlags != NULL) {
|
|
|
|
if (queueFlags != NULL) {
|
|
|
|
*queueFlags = TRUE;
|
|
|
|
*queueFlags = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -228,10 +226,10 @@ STATIC VOID OsFutexDeleteKeyNodeFromHash(FutexNode *node, BOOL isDeleteHead, Fut
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* FutexList is not NULL, but the header node of queueList */
|
|
|
|
/* FutexList is not NULL, but the header node of queueList */
|
|
|
|
if (node->futexList.pstNext != NULL) {//是头节点
|
|
|
|
if (node->futexList.pstNext != NULL) {
|
|
|
|
if (isDeleteHead == TRUE) {//是否要删除头节点
|
|
|
|
if (isDeleteHead == TRUE) {
|
|
|
|
nextNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_FIRST(&node->queueList));//取出第一个快锁节点
|
|
|
|
nextNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_FIRST(&node->queueList));
|
|
|
|
OsFutexReplaceQueueListHeadNode(node, nextNode);//两个节点交换位置
|
|
|
|
OsFutexReplaceQueueListHeadNode(node, nextNode);
|
|
|
|
if (headNode != NULL) {
|
|
|
|
if (headNode != NULL) {
|
|
|
|
*headNode = nextNode;
|
|
|
|
*headNode = nextNode;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -244,22 +242,22 @@ EXIT:
|
|
|
|
OsFutexDeinitFutexNode(node);
|
|
|
|
OsFutexDeinitFutexNode(node);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 从哈希桶上删除快锁
|
|
|
|
|
|
|
|
VOID OsFutexNodeDeleteFromFutexHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags)
|
|
|
|
VOID OsFutexNodeDeleteFromFutexHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
FutexHash *hashNode = NULL;
|
|
|
|
FutexHash *hashNode = NULL;
|
|
|
|
//通过key找到桶号
|
|
|
|
|
|
|
|
UINT32 index = OsFutexKeyToIndex(node->key, (node->pid == OS_INVALID) ? 0 : FUTEX_PRIVATE);
|
|
|
|
UINT32 index = OsFutexKeyToIndex(node->key, (node->pid == OS_INVALID) ? 0 : FUTEX_PRIVATE);
|
|
|
|
if (index >= FUTEX_INDEX_MAX) {
|
|
|
|
if (index >= FUTEX_INDEX_MAX) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
hashNode = &g_futexHash[index];//找到hash桶
|
|
|
|
hashNode = &g_futexHash[index];
|
|
|
|
if (OsMuxLockUnsafe(&hashNode->listLock, LOS_WAIT_FOREVER)) {
|
|
|
|
if (OsMuxLockUnsafe(&hashNode->listLock, LOS_WAIT_FOREVER)) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (node->index != index) {//快锁节点桶号需和哈希桶号一致
|
|
|
|
if (node->index != index) {
|
|
|
|
goto EXIT;
|
|
|
|
goto EXIT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -272,6 +270,7 @@ EXIT:
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STATIC FutexNode *OsFutexDeleteAlreadyWakeTaskAndGetNext(const FutexNode *node, FutexNode **headNode, BOOL isDeleteHead)
|
|
|
|
STATIC FutexNode *OsFutexDeleteAlreadyWakeTaskAndGetNext(const FutexNode *node, FutexNode **headNode, BOOL isDeleteHead)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
FutexNode *tempNode = (FutexNode *)node;
|
|
|
|
FutexNode *tempNode = (FutexNode *)node;
|
|
|
@ -293,7 +292,7 @@ STATIC FutexNode *OsFutexDeleteAlreadyWakeTaskAndGetNext(const FutexNode *node,
|
|
|
|
|
|
|
|
|
|
|
|
return tempNode;
|
|
|
|
return tempNode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 插入一把新Futex锁到哈希桶中,只有是新的key时才会插入,因为其实存在多个FutexNode是一个key
|
|
|
|
|
|
|
|
STATIC VOID OsFutexInsertNewFutexKeyToHash(FutexNode *node)
|
|
|
|
STATIC VOID OsFutexInsertNewFutexKeyToHash(FutexNode *node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
FutexNode *headNode = NULL;
|
|
|
|
FutexNode *headNode = NULL;
|
|
|
@ -323,16 +322,16 @@ STATIC VOID OsFutexInsertNewFutexKeyToHash(FutexNode *node)
|
|
|
|
futexList != &(hashNode->lockList);
|
|
|
|
futexList != &(hashNode->lockList);
|
|
|
|
futexList = futexList->pstNext) {
|
|
|
|
futexList = futexList->pstNext) {
|
|
|
|
headNode = OS_FUTEX_FROM_FUTEXLIST(futexList);
|
|
|
|
headNode = OS_FUTEX_FROM_FUTEXLIST(futexList);
|
|
|
|
if (node->key <= headNode->key) {
|
|
|
|
if (node->key <= headNode->key) {
|
|
|
|
LOS_ListTailInsert(&(headNode->futexList), &(node->futexList));
|
|
|
|
LOS_ListTailInsert(&(headNode->futexList), &(node->futexList));
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EXIT:
|
|
|
|
EXIT:
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STATIC INT32 OsFutexInsertFindFormBackToFront(LOS_DL_LIST *queueList, const LosTaskCB *runTask, FutexNode *node)
|
|
|
|
STATIC INT32 OsFutexInsertFindFormBackToFront(LOS_DL_LIST *queueList, const LosTaskCB *runTask, FutexNode *node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LOS_DL_LIST *listHead = queueList;
|
|
|
|
LOS_DL_LIST *listHead = queueList;
|
|
|
@ -408,54 +407,55 @@ STATIC INT32 OsFutexRecycleAndFindHeadNode(FutexNode *headNode, FutexNode *node,
|
|
|
|
|
|
|
|
|
|
|
|
return LOS_OK;
|
|
|
|
return LOS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
///< 将快锁挂到任务的阻塞链表上
|
|
|
|
|
|
|
|
STATIC INT32 OsFutexInsertTasktoPendList(FutexNode **firstNode, FutexNode *node, const LosTaskCB *run)
|
|
|
|
STATIC INT32 OsFutexInsertTasktoPendList(FutexNode **firstNode, FutexNode *node, const LosTaskCB *run)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LosTaskCB *taskHead = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&((*firstNode)->pendList)));//获取阻塞链表首个任务
|
|
|
|
LosTaskCB *taskHead = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&((*firstNode)->pendList)));
|
|
|
|
LOS_DL_LIST *queueList = &((*firstNode)->queueList);
|
|
|
|
LOS_DL_LIST *queueList = &((*firstNode)->queueList);
|
|
|
|
|
|
|
|
|
|
|
|
INT32 ret1 = OsSchedParamCompare(run, taskHead);
|
|
|
|
INT32 ret1 = OsSchedParamCompare(run, taskHead);
|
|
|
|
if (ret1 < 0) {
|
|
|
|
if (ret1 < 0) {
|
|
|
|
/* The one with the highest priority is inserted at the top of the queue */
|
|
|
|
/* The one with the highest priority is inserted at the top of the queue */
|
|
|
|
LOS_ListTailInsert(queueList, &(node->queueList));//查到queueList的尾部
|
|
|
|
LOS_ListTailInsert(queueList, &(node->queueList));
|
|
|
|
OsFutexReplaceQueueListHeadNode(*firstNode, node);//同时交换futexList链表上的位置
|
|
|
|
OsFutexReplaceQueueListHeadNode(*firstNode, node);
|
|
|
|
*firstNode = node;
|
|
|
|
*firstNode = node;
|
|
|
|
return LOS_OK;
|
|
|
|
return LOS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//如果等锁链表上没有任务或者当前任务大于链表首个任务
|
|
|
|
|
|
|
|
if (LOS_ListEmpty(queueList) && (ret1 >= 0)) {
|
|
|
|
if (LOS_ListEmpty(queueList) && (ret1 >= 0)) {
|
|
|
|
/* Insert the next position in the queue with equal priority */
|
|
|
|
/* Insert the next position in the queue with equal priority */
|
|
|
|
LOS_ListHeadInsert(queueList, &(node->queueList));//从头部插入当前任务,当前任务是要被挂起的
|
|
|
|
LOS_ListHeadInsert(queueList, &(node->queueList));
|
|
|
|
return LOS_OK;
|
|
|
|
return LOS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FutexNode *tailNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_LAST(queueList));//获取尾部节点
|
|
|
|
FutexNode *tailNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_LAST(queueList));
|
|
|
|
LosTaskCB *taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tailNode->pendList)));//获取阻塞任务的最后一个
|
|
|
|
LosTaskCB *taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tailNode->pendList)));
|
|
|
|
INT32 ret2 = OsSchedParamCompare(taskTail, run);
|
|
|
|
INT32 ret2 = OsSchedParamCompare(taskTail, run);
|
|
|
|
if ((ret2 <= 0) || (ret1 > ret2)) {
|
|
|
|
if ((ret2 <= 0) || (ret1 > ret2)) {
|
|
|
|
return OsFutexInsertFindFormBackToFront(queueList, run, node);//从后往前插入
|
|
|
|
return OsFutexInsertFindFormBackToFront(queueList, run, node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return OsFutexInsertFindFromFrontToBack(queueList, run, node);//否则从前往后插入
|
|
|
|
return OsFutexInsertFindFromFrontToBack(queueList, run, node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 由指定快锁找到对应哈希桶
|
|
|
|
|
|
|
|
STATIC FutexNode *OsFindFutexNode(const FutexNode *node)
|
|
|
|
STATIC FutexNode *OsFindFutexNode(const FutexNode *node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
FutexHash *hashNode = &g_futexHash[node->index];//先找到所在哈希桶
|
|
|
|
FutexHash *hashNode = &g_futexHash[node->index];
|
|
|
|
LOS_DL_LIST *futexList = &(hashNode->lockList);
|
|
|
|
LOS_DL_LIST *futexList = &(hashNode->lockList);
|
|
|
|
FutexNode *headNode = NULL;
|
|
|
|
FutexNode *headNode = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
for (futexList = futexList->pstNext;
|
|
|
|
for (futexList = futexList->pstNext;
|
|
|
|
futexList != &(hashNode->lockList);//判断循环结束条件,相等时说明跑完一轮了
|
|
|
|
futexList != &(hashNode->lockList);
|
|
|
|
futexList = futexList->pstNext) {
|
|
|
|
futexList = futexList->pstNext) {
|
|
|
|
headNode = OS_FUTEX_FROM_FUTEXLIST(futexList);//拿到快锁节点实体
|
|
|
|
headNode = OS_FUTEX_FROM_FUTEXLIST(futexList);
|
|
|
|
if ((headNode->key == node->key) && (headNode->pid == node->pid)) {//已经存在这个节点,注意这里的比较
|
|
|
|
if ((headNode->key == node->key) && (headNode->pid == node->pid)) {
|
|
|
|
return headNode;//是key和pid 一起比较,因为只有这样才能确定唯一性
|
|
|
|
return headNode;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
///< 查找快锁并插入哈希桶中
|
|
|
|
|
|
|
|
STATIC INT32 OsFindAndInsertToHash(FutexNode *node)
|
|
|
|
STATIC INT32 OsFindAndInsertToHash(FutexNode *node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
FutexNode *headNode = NULL;
|
|
|
|
FutexNode *headNode = NULL;
|
|
|
@ -464,7 +464,7 @@ STATIC INT32 OsFindAndInsertToHash(FutexNode *node)
|
|
|
|
INT32 ret;
|
|
|
|
INT32 ret;
|
|
|
|
|
|
|
|
|
|
|
|
headNode = OsFindFutexNode(node);
|
|
|
|
headNode = OsFindFutexNode(node);
|
|
|
|
if (headNode == NULL) {//没有找到,说明这是一把新锁
|
|
|
|
if (headNode == NULL) {
|
|
|
|
OsFutexInsertNewFutexKeyToHash(node);
|
|
|
|
OsFutexInsertNewFutexKeyToHash(node);
|
|
|
|
LOS_ListInit(&(node->queueList));
|
|
|
|
LOS_ListInit(&(node->queueList));
|
|
|
|
return LOS_OK;
|
|
|
|
return LOS_OK;
|
|
|
@ -483,14 +483,14 @@ STATIC INT32 OsFindAndInsertToHash(FutexNode *node)
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 共享内存检查
|
|
|
|
|
|
|
|
STATIC INT32 OsFutexKeyShmPermCheck(const UINT32 *userVaddr, const UINT32 flags)
|
|
|
|
STATIC INT32 OsFutexKeyShmPermCheck(const UINT32 *userVaddr, const UINT32 flags)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
PADDR_T paddr;
|
|
|
|
PADDR_T paddr;
|
|
|
|
|
|
|
|
|
|
|
|
/* Check whether the futexKey is a shared lock */
|
|
|
|
/* Check whether the futexKey is a shared lock */
|
|
|
|
if (!(flags & FUTEX_PRIVATE)) {//非私有快锁
|
|
|
|
if (!(flags & FUTEX_PRIVATE)) {
|
|
|
|
paddr = (UINTPTR)LOS_PaddrQuery((UINT32 *)userVaddr);//能否查询到物理地址
|
|
|
|
paddr = (UINTPTR)LOS_PaddrQuery((UINT32 *)userVaddr);
|
|
|
|
if (paddr == 0) return LOS_NOK;
|
|
|
|
if (paddr == 0) return LOS_NOK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -549,13 +549,13 @@ STATIC INT32 OsFutexDeleteTimeoutTaskNode(FutexHash *hashNode, FutexNode *node)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return LOS_ETIMEDOUT;
|
|
|
|
return LOS_ETIMEDOUT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 将快锁节点插入任务
|
|
|
|
|
|
|
|
STATIC INT32 OsFutexInsertTaskToHash(LosTaskCB **taskCB, FutexNode **node, const UINTPTR futexKey, const UINT32 flags)
|
|
|
|
STATIC INT32 OsFutexInsertTaskToHash(LosTaskCB **taskCB, FutexNode **node, const UINTPTR futexKey, const UINT32 flags)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
INT32 ret;
|
|
|
|
INT32 ret;
|
|
|
|
*taskCB = OsCurrTaskGet(); //获取当前任务
|
|
|
|
*taskCB = OsCurrTaskGet();
|
|
|
|
*node = &((*taskCB)->futex); //获取当前任务的快锁节点
|
|
|
|
*node = &((*taskCB)->futex);
|
|
|
|
OsFutexSetKey(futexKey, flags, *node);//设置参数 key index pid
|
|
|
|
OsFutexSetKey(futexKey, flags, *node);
|
|
|
|
|
|
|
|
|
|
|
|
ret = OsFindAndInsertToHash(*node);
|
|
|
|
ret = OsFindAndInsertToHash(*node);
|
|
|
|
if (ret) {
|
|
|
|
if (ret) {
|
|
|
@ -565,33 +565,33 @@ STATIC INT32 OsFutexInsertTaskToHash(LosTaskCB **taskCB, FutexNode **node, const
|
|
|
|
LOS_ListInit(&((*node)->pendList));
|
|
|
|
LOS_ListInit(&((*node)->pendList));
|
|
|
|
return LOS_OK;
|
|
|
|
return LOS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 将当前任务挂入等待链表中
|
|
|
|
|
|
|
|
STATIC INT32 OsFutexWaitTask(const UINT32 *userVaddr, const UINT32 flags, const UINT32 val, const UINT32 timeout)
|
|
|
|
STATIC INT32 OsFutexWaitTask(const UINT32 *userVaddr, const UINT32 flags, const UINT32 val, const UINT32 timeout)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
INT32 futexRet;
|
|
|
|
INT32 futexRet;
|
|
|
|
UINT32 intSave, lockVal;
|
|
|
|
UINT32 intSave, lockVal;
|
|
|
|
LosTaskCB *taskCB = NULL;
|
|
|
|
LosTaskCB *taskCB = NULL;
|
|
|
|
FutexNode *node = NULL;
|
|
|
|
FutexNode *node = NULL;
|
|
|
|
UINTPTR futexKey = OsFutexFlagsToKey(userVaddr, flags);//通过地址和flags 找到 key
|
|
|
|
UINTPTR futexKey = OsFutexFlagsToKey(userVaddr, flags);
|
|
|
|
UINT32 index = OsFutexKeyToIndex(futexKey, flags);//通过key找到哈希桶
|
|
|
|
UINT32 index = OsFutexKeyToIndex(futexKey, flags);
|
|
|
|
FutexHash *hashNode = &g_futexHash[index];
|
|
|
|
FutexHash *hashNode = &g_futexHash[index];
|
|
|
|
|
|
|
|
|
|
|
|
if (OsFutexLock(&hashNode->listLock)) {//操作快锁节点链表前先上互斥锁
|
|
|
|
if (OsFutexLock(&hashNode->listLock)) {
|
|
|
|
return LOS_EINVAL;
|
|
|
|
return LOS_EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//userVaddr必须是用户空间虚拟地址
|
|
|
|
|
|
|
|
if (LOS_ArchCopyFromUser(&lockVal, userVaddr, sizeof(UINT32))) {//将值拷贝到内核空间
|
|
|
|
if (LOS_ArchCopyFromUser(&lockVal, userVaddr, sizeof(UINT32))) {
|
|
|
|
PRINT_ERR("Futex wait param check failed! copy from user failed!\n");
|
|
|
|
PRINT_ERR("Futex wait param check failed! copy from user failed!\n");
|
|
|
|
futexRet = LOS_EINVAL;
|
|
|
|
futexRet = LOS_EINVAL;
|
|
|
|
goto EXIT_ERR;
|
|
|
|
goto EXIT_ERR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (lockVal != val) {//对参数内部逻辑检查
|
|
|
|
if (lockVal != val) {
|
|
|
|
futexRet = LOS_EBADF;
|
|
|
|
futexRet = LOS_EBADF;
|
|
|
|
goto EXIT_ERR;
|
|
|
|
goto EXIT_ERR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//注意第二个参数 FutexNode *node = NULL
|
|
|
|
|
|
|
|
if (OsFutexInsertTaskToHash(&taskCB, &node, futexKey, flags)) {// node = taskCB->futex
|
|
|
|
if (OsFutexInsertTaskToHash(&taskCB, &node, futexKey, flags)) {
|
|
|
|
futexRet = LOS_NOK;
|
|
|
|
futexRet = LOS_NOK;
|
|
|
|
goto EXIT_ERR;
|
|
|
|
goto EXIT_ERR;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -602,7 +602,7 @@ STATIC INT32 OsFutexWaitTask(const UINT32 *userVaddr, const UINT32 flags, const
|
|
|
|
taskCB->ops->wait(taskCB, &(node->pendList), timeout);
|
|
|
|
taskCB->ops->wait(taskCB, &(node->pendList), timeout);
|
|
|
|
LOS_SpinUnlock(&g_taskSpin);
|
|
|
|
LOS_SpinUnlock(&g_taskSpin);
|
|
|
|
|
|
|
|
|
|
|
|
futexRet = OsFutexUnlock(&hashNode->listLock);//
|
|
|
|
futexRet = OsFutexUnlock(&hashNode->listLock);
|
|
|
|
if (futexRet) {
|
|
|
|
if (futexRet) {
|
|
|
|
OsSchedUnlock();
|
|
|
|
OsSchedUnlock();
|
|
|
|
LOS_IntRestore(intSave);
|
|
|
|
LOS_IntRestore(intSave);
|
|
|
@ -632,21 +632,21 @@ EXIT_ERR:
|
|
|
|
EXIT_UNLOCK_ERR:
|
|
|
|
EXIT_UNLOCK_ERR:
|
|
|
|
return futexRet;
|
|
|
|
return futexRet;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 设置线程等待 | 向Futex表中插入代表被阻塞的线程的node
|
|
|
|
|
|
|
|
INT32 OsFutexWait(const UINT32 *userVaddr, UINT32 flags, UINT32 val, UINT32 absTime)
|
|
|
|
INT32 OsFutexWait(const UINT32 *userVaddr, UINT32 flags, UINT32 val, UINT32 absTime)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
INT32 ret;
|
|
|
|
INT32 ret;
|
|
|
|
UINT32 timeout = LOS_WAIT_FOREVER;
|
|
|
|
UINT32 timeout = LOS_WAIT_FOREVER;
|
|
|
|
|
|
|
|
|
|
|
|
ret = OsFutexWaitParamCheck(userVaddr, flags, absTime);//参数检查
|
|
|
|
ret = OsFutexWaitParamCheck(userVaddr, flags, absTime);
|
|
|
|
if (ret) {
|
|
|
|
if (ret) {
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (absTime != LOS_WAIT_FOREVER) {//转换时间 , 内核的时间单位是 tick
|
|
|
|
if (absTime != LOS_WAIT_FOREVER) {
|
|
|
|
timeout = OsNS2Tick((UINT64)absTime * OS_SYS_NS_PER_US); //转成 tick
|
|
|
|
timeout = OsNS2Tick((UINT64)absTime * OS_SYS_NS_PER_US);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return OsFutexWaitTask(userVaddr, flags, val, timeout);//将任务挂起 timeOut 时长
|
|
|
|
return OsFutexWaitTask(userVaddr, flags, val, timeout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STATIC INT32 OsFutexWakeParamCheck(const UINT32 *userVaddr, UINT32 flags)
|
|
|
|
STATIC INT32 OsFutexWakeParamCheck(const UINT32 *userVaddr, UINT32 flags)
|
|
|
@ -657,12 +657,12 @@ STATIC INT32 OsFutexWakeParamCheck(const UINT32 *userVaddr, UINT32 flags)
|
|
|
|
PRINT_ERR("Futex wake param check failed! error flags: 0x%x\n", flags);
|
|
|
|
PRINT_ERR("Futex wake param check failed! error flags: 0x%x\n", flags);
|
|
|
|
return LOS_EINVAL;
|
|
|
|
return LOS_EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//地址必须在用户空间
|
|
|
|
|
|
|
|
if ((vaddr % sizeof(INT32)) || (vaddr < OS_FUTEX_KEY_BASE) || (vaddr >= OS_FUTEX_KEY_MAX)) {
|
|
|
|
if ((vaddr % sizeof(INT32)) || (vaddr < OS_FUTEX_KEY_BASE) || (vaddr >= OS_FUTEX_KEY_MAX)) {
|
|
|
|
PRINT_ERR("Futex wake param check failed! error userVaddr: 0x%x\n", userVaddr);
|
|
|
|
PRINT_ERR("Futex wake param check failed! error userVaddr: 0x%x\n", userVaddr);
|
|
|
|
return LOS_EINVAL;
|
|
|
|
return LOS_EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//必须得是个共享内存地址
|
|
|
|
|
|
|
|
if (flags && (OsFutexKeyShmPermCheck(userVaddr, flags) != LOS_OK)) {
|
|
|
|
if (flags && (OsFutexKeyShmPermCheck(userVaddr, flags) != LOS_OK)) {
|
|
|
|
PRINT_ERR("Futex wake param check failed! error shared memory perm userVaddr: 0x%x\n", userVaddr);
|
|
|
|
PRINT_ERR("Futex wake param check failed! error shared memory perm userVaddr: 0x%x\n", userVaddr);
|
|
|
|
return LOS_EINVAL;
|
|
|
|
return LOS_EINVAL;
|
|
|
@ -672,8 +672,7 @@ STATIC INT32 OsFutexWakeParamCheck(const UINT32 *userVaddr, UINT32 flags)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Check to see if the task to be awakened has timed out
|
|
|
|
/* Check to see if the task to be awakened has timed out
|
|
|
|
* if time out, to weak next pend task.
|
|
|
|
* if time out, to weak next pend task.
|
|
|
|
* | 查看要唤醒的任务是否超时,如果超时,就唤醒,并查看下一个挂起的任务。
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
STATIC VOID OsFutexCheckAndWakePendTask(FutexNode *headNode, const INT32 wakeNumber,
|
|
|
|
STATIC VOID OsFutexCheckAndWakePendTask(FutexNode *headNode, const INT32 wakeNumber,
|
|
|
|
FutexHash *hashNode, FutexNode **nextNode, BOOL *wakeAny)
|
|
|
|
FutexHash *hashNode, FutexNode **nextNode, BOOL *wakeAny)
|
|
|
@ -708,7 +707,6 @@ STATIC VOID OsFutexCheckAndWakePendTask(FutexNode *headNode, const INT32 wakeNum
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
STATIC INT32 OsFutexWakeTask(UINTPTR futexKey, UINT32 flags, INT32 wakeNumber, FutexNode **newHeadNode, BOOL *wakeAny)
|
|
|
|
STATIC INT32 OsFutexWakeTask(UINTPTR futexKey, UINT32 flags, INT32 wakeNumber, FutexNode **newHeadNode, BOOL *wakeAny)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -717,13 +715,13 @@ STATIC INT32 OsFutexWakeTask(UINTPTR futexKey, UINT32 flags, INT32 wakeNumber, F
|
|
|
|
FutexNode *headNode = NULL;
|
|
|
|
FutexNode *headNode = NULL;
|
|
|
|
UINT32 index = OsFutexKeyToIndex(futexKey, flags);
|
|
|
|
UINT32 index = OsFutexKeyToIndex(futexKey, flags);
|
|
|
|
FutexHash *hashNode = &g_futexHash[index];
|
|
|
|
FutexHash *hashNode = &g_futexHash[index];
|
|
|
|
FutexNode tempNode = { //先组成一个临时快锁节点,目的是为了找到哈希桶中是否有这个节点
|
|
|
|
FutexNode tempNode = {
|
|
|
|
.key = futexKey,
|
|
|
|
.key = futexKey,
|
|
|
|
.index = index,
|
|
|
|
.index = index,
|
|
|
|
.pid = (flags & FUTEX_PRIVATE) ? LOS_GetCurrProcessID() : OS_INVALID,
|
|
|
|
.pid = (flags & FUTEX_PRIVATE) ? LOS_GetCurrProcessID() : OS_INVALID,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
node = OsFindFutexNode(&tempNode);//找快锁节点
|
|
|
|
node = OsFindFutexNode(&tempNode);
|
|
|
|
if (node == NULL) {
|
|
|
|
if (node == NULL) {
|
|
|
|
return LOS_EBADF;
|
|
|
|
return LOS_EBADF;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -731,7 +729,7 @@ STATIC INT32 OsFutexWakeTask(UINTPTR futexKey, UINT32 flags, INT32 wakeNumber, F
|
|
|
|
headNode = node;
|
|
|
|
headNode = node;
|
|
|
|
|
|
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
|
OsFutexCheckAndWakePendTask(headNode, wakeNumber, hashNode, newHeadNode, wakeAny);//再找到等这把锁的唤醒指向数量的任务
|
|
|
|
OsFutexCheckAndWakePendTask(headNode, wakeNumber, hashNode, newHeadNode, wakeAny);
|
|
|
|
if ((*newHeadNode) != NULL) {
|
|
|
|
if ((*newHeadNode) != NULL) {
|
|
|
|
OsFutexReplaceQueueListHeadNode(headNode, *newHeadNode);
|
|
|
|
OsFutexReplaceQueueListHeadNode(headNode, *newHeadNode);
|
|
|
|
OsFutexDeinitFutexNode(headNode);
|
|
|
|
OsFutexDeinitFutexNode(headNode);
|
|
|
@ -743,7 +741,7 @@ STATIC INT32 OsFutexWakeTask(UINTPTR futexKey, UINT32 flags, INT32 wakeNumber, F
|
|
|
|
|
|
|
|
|
|
|
|
return LOS_OK;
|
|
|
|
return LOS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 唤醒一个被指定锁阻塞的线程
|
|
|
|
|
|
|
|
INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber)
|
|
|
|
INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
INT32 ret, futexRet;
|
|
|
|
INT32 ret, futexRet;
|
|
|
@ -752,11 +750,11 @@ INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber)
|
|
|
|
FutexHash *hashNode = NULL;
|
|
|
|
FutexHash *hashNode = NULL;
|
|
|
|
FutexNode *headNode = NULL;
|
|
|
|
FutexNode *headNode = NULL;
|
|
|
|
BOOL wakeAny = FALSE;
|
|
|
|
BOOL wakeAny = FALSE;
|
|
|
|
//1.检查参数
|
|
|
|
|
|
|
|
if (OsFutexWakeParamCheck(userVaddr, flags)) {
|
|
|
|
if (OsFutexWakeParamCheck(userVaddr, flags)) {
|
|
|
|
return LOS_EINVAL;
|
|
|
|
return LOS_EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//2.找到指定用户空间地址对应的桶
|
|
|
|
|
|
|
|
futexKey = OsFutexFlagsToKey(userVaddr, flags);
|
|
|
|
futexKey = OsFutexFlagsToKey(userVaddr, flags);
|
|
|
|
index = OsFutexKeyToIndex(futexKey, flags);
|
|
|
|
index = OsFutexKeyToIndex(futexKey, flags);
|
|
|
|
|
|
|
|
|
|
|
@ -764,7 +762,7 @@ INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber)
|
|
|
|
if (OsFutexLock(&hashNode->listLock)) {
|
|
|
|
if (OsFutexLock(&hashNode->listLock)) {
|
|
|
|
return LOS_EINVAL;
|
|
|
|
return LOS_EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//3.换起等待该锁的进程
|
|
|
|
|
|
|
|
ret = OsFutexWakeTask(futexKey, flags, wakeNumber, &headNode, &wakeAny);
|
|
|
|
ret = OsFutexWakeTask(futexKey, flags, wakeNumber, &headNode, &wakeAny);
|
|
|
|
if (ret) {
|
|
|
|
if (ret) {
|
|
|
|
goto EXIT_ERR;
|
|
|
|
goto EXIT_ERR;
|
|
|
@ -778,7 +776,7 @@ INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber)
|
|
|
|
if (futexRet) {
|
|
|
|
if (futexRet) {
|
|
|
|
goto EXIT_UNLOCK_ERR;
|
|
|
|
goto EXIT_UNLOCK_ERR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//4.根据指定参数决定是否发起调度
|
|
|
|
|
|
|
|
if (wakeAny == TRUE) {
|
|
|
|
if (wakeAny == TRUE) {
|
|
|
|
LOS_MpSchedule(OS_MP_CPU_ALL);
|
|
|
|
LOS_MpSchedule(OS_MP_CPU_ALL);
|
|
|
|
LOS_Schedule();
|
|
|
|
LOS_Schedule();
|
|
|
@ -887,7 +885,7 @@ STATIC VOID OsFutexRequeueSplitTwoLists(FutexHash *oldHashNode, FutexNode *oldHe
|
|
|
|
tailNode->queueList.pstNext = &newHeadNode->queueList;
|
|
|
|
tailNode->queueList.pstNext = &newHeadNode->queueList;
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 删除旧key并获取头节点
|
|
|
|
|
|
|
|
STATIC FutexNode *OsFutexRequeueRemoveOldKeyAndGetHead(UINTPTR oldFutexKey, UINT32 flags, INT32 wakeNumber,
|
|
|
|
STATIC FutexNode *OsFutexRequeueRemoveOldKeyAndGetHead(UINTPTR oldFutexKey, UINT32 flags, INT32 wakeNumber,
|
|
|
|
UINTPTR newFutexKey, INT32 requeueCount, BOOL *wakeAny)
|
|
|
|
UINTPTR newFutexKey, INT32 requeueCount, BOOL *wakeAny)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -923,7 +921,7 @@ STATIC FutexNode *OsFutexRequeueRemoveOldKeyAndGetHead(UINTPTR oldFutexKey, UINT
|
|
|
|
|
|
|
|
|
|
|
|
return oldHeadNode;
|
|
|
|
return oldHeadNode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 检查锁在Futex表中的状态
|
|
|
|
|
|
|
|
STATIC INT32 OsFutexRequeueParamCheck(const UINT32 *oldUserVaddr, UINT32 flags, const UINT32 *newUserVaddr)
|
|
|
|
STATIC INT32 OsFutexRequeueParamCheck(const UINT32 *oldUserVaddr, UINT32 flags, const UINT32 *newUserVaddr)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
VADDR_T oldVaddr = (VADDR_T)(UINTPTR)oldUserVaddr;
|
|
|
|
VADDR_T oldVaddr = (VADDR_T)(UINTPTR)oldUserVaddr;
|
|
|
@ -932,12 +930,12 @@ STATIC INT32 OsFutexRequeueParamCheck(const UINT32 *oldUserVaddr, UINT32 flags,
|
|
|
|
if (oldVaddr == newVaddr) {
|
|
|
|
if (oldVaddr == newVaddr) {
|
|
|
|
return LOS_EINVAL;
|
|
|
|
return LOS_EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//检查标记
|
|
|
|
|
|
|
|
if ((flags & (~FUTEX_PRIVATE)) != FUTEX_REQUEUE) {
|
|
|
|
if ((flags & (~FUTEX_PRIVATE)) != FUTEX_REQUEUE) {
|
|
|
|
PRINT_ERR("Futex requeue param check failed! error flags: 0x%x\n", flags);
|
|
|
|
PRINT_ERR("Futex requeue param check failed! error flags: 0x%x\n", flags);
|
|
|
|
return LOS_EINVAL;
|
|
|
|
return LOS_EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//检查地址范围,必须在用户空间
|
|
|
|
|
|
|
|
if ((oldVaddr % sizeof(INT32)) || (oldVaddr < OS_FUTEX_KEY_BASE) || (oldVaddr >= OS_FUTEX_KEY_MAX)) {
|
|
|
|
if ((oldVaddr % sizeof(INT32)) || (oldVaddr < OS_FUTEX_KEY_BASE) || (oldVaddr >= OS_FUTEX_KEY_MAX)) {
|
|
|
|
PRINT_ERR("Futex requeue param check failed! error old userVaddr: 0x%x\n", oldUserVaddr);
|
|
|
|
PRINT_ERR("Futex requeue param check failed! error old userVaddr: 0x%x\n", oldUserVaddr);
|
|
|
|
return LOS_EINVAL;
|
|
|
|
return LOS_EINVAL;
|
|
|
@ -950,7 +948,7 @@ STATIC INT32 OsFutexRequeueParamCheck(const UINT32 *oldUserVaddr, UINT32 flags,
|
|
|
|
|
|
|
|
|
|
|
|
return LOS_OK;
|
|
|
|
return LOS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// 调整指定锁在Futex表中的位置
|
|
|
|
|
|
|
|
INT32 OsFutexRequeue(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber, INT32 count, const UINT32 *newUserVaddr)
|
|
|
|
INT32 OsFutexRequeue(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber, INT32 count, const UINT32 *newUserVaddr)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
INT32 ret;
|
|
|
|
INT32 ret;
|
|
|
@ -967,12 +965,12 @@ INT32 OsFutexRequeue(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber, IN
|
|
|
|
return LOS_EINVAL;
|
|
|
|
return LOS_EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
oldFutexKey = OsFutexFlagsToKey(userVaddr, flags);//先拿key
|
|
|
|
oldFutexKey = OsFutexFlagsToKey(userVaddr, flags);
|
|
|
|
newFutexKey = OsFutexFlagsToKey(newUserVaddr, flags);
|
|
|
|
newFutexKey = OsFutexFlagsToKey(newUserVaddr, flags);
|
|
|
|
oldIndex = OsFutexKeyToIndex(oldFutexKey, flags);//再拿所在哈希桶位置,共有80个哈希桶
|
|
|
|
oldIndex = OsFutexKeyToIndex(oldFutexKey, flags);
|
|
|
|
newIndex = OsFutexKeyToIndex(newFutexKey, flags);
|
|
|
|
newIndex = OsFutexKeyToIndex(newFutexKey, flags);
|
|
|
|
|
|
|
|
|
|
|
|
oldHashNode = &g_futexHash[oldIndex];//拿到对应哈希桶实体
|
|
|
|
oldHashNode = &g_futexHash[oldIndex];
|
|
|
|
if (OsFutexLock(&oldHashNode->listLock)) {
|
|
|
|
if (OsFutexLock(&oldHashNode->listLock)) {
|
|
|
|
return LOS_EINVAL;
|
|
|
|
return LOS_EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|