Merge pull request 'some ipc' (#31) from gonghao_branch into main

pull/32/head
piyl8cs5f 1 year ago
commit 88242a3652

@ -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-2022 Huawei Device Co., Ltd. All rights reserved. * Copyright (c) 2020-2021 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:
@ -39,8 +39,8 @@
#ifdef LOSCFG_BASE_CORE_SWTMR_ENABLE #ifdef LOSCFG_BASE_CORE_SWTMR_ENABLE
#include "los_exc.h" #include "los_exc.h"
#endif #endif
/*
*/ /// 初始化一个事件控制块
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB) LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB)
{ {
UINT32 intSave; UINT32 intSave;
@ -49,14 +49,14 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB)
return LOS_ERRNO_EVENT_PTR_NULL; return LOS_ERRNO_EVENT_PTR_NULL;
} }
intSave = LOS_IntLock(); intSave = LOS_IntLock();//锁中断
eventCB->uwEventID = 0; eventCB->uwEventID = 0;//事件类型初始化
LOS_ListInit(&eventCB->stEventList); LOS_ListInit(&eventCB->stEventList);//事件链表初始化
LOS_IntRestore(intSave); LOS_IntRestore(intSave);//恢复中断
OsHookCall(LOS_HOOK_TYPE_EVENT_INIT, eventCB); OsHookCall(LOS_HOOK_TYPE_EVENT_INIT, eventCB);
return LOS_OK; return LOS_OK;
} }
///事件参数检查
LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck(const VOID *ptr, UINT32 eventMask, UINT32 mode) LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck(const VOID *ptr, UINT32 eventMask, UINT32 mode)
{ {
if (ptr == NULL) { if (ptr == NULL) {
@ -78,52 +78,53 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck(const VOID *ptr, UINT32 eventMa
} }
return LOS_OK; return LOS_OK;
} }
///根据用户传入的事件值、事件掩码及校验模式,返回用户传入的事件是否符合预期
LITE_OS_SEC_TEXT UINT32 OsEventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode) LITE_OS_SEC_TEXT UINT32 OsEventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode)
{ {
UINT32 ret = 0; UINT32 ret = 0;
LOS_ASSERT(OsIntLocked()); LOS_ASSERT(OsIntLocked());//断言不允许中断了
LOS_ASSERT(LOS_SpinHeld(&g_taskSpin)); LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));//任务自旋锁
if (mode & LOS_WAITMODE_OR) { if (mode & LOS_WAITMODE_OR) {//如果模式是读取掩码中任意事件
if ((*eventID & eventMask) != 0) { if ((*eventID & eventMask) != 0) {
ret = *eventID & eventMask; ret = *eventID & eventMask;
} }
} else { } else {//等待全部事件发生
if ((eventMask != 0) && (eventMask == (*eventID & eventMask))) { if ((eventMask != 0) && (eventMask == (*eventID & eventMask))) {//必须满足全部事件发生
ret = *eventID & eventMask; ret = *eventID & eventMask;
} }
} }
if (ret && (mode & LOS_WAITMODE_CLR)) { if (ret && (mode & LOS_WAITMODE_CLR)) {//读取完成后清除事件
*eventID = *eventID & ~ret; *eventID = *eventID & ~ret;
} }
return ret; return ret;
} }
///检查读事件
LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadCheck(const PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode) LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadCheck(const PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode)
{ {
UINT32 ret; UINT32 ret;
LosTaskCB *runTask = NULL; LosTaskCB *runTask = NULL;
ret = OsEventParamCheck(eventCB, eventMask, mode);
ret = OsEventParamCheck(eventCB, eventMask, mode);//事件参数检查
if (ret != LOS_OK) { if (ret != LOS_OK) {
return ret; return ret;
} }
if (OS_INT_ACTIVE) { if (OS_INT_ACTIVE) {//中断正在进行
return LOS_ERRNO_EVENT_READ_IN_INTERRUPT; return LOS_ERRNO_EVENT_READ_IN_INTERRUPT;//不能在中断发送时读事件
} }
runTask = OsCurrTaskGet(); runTask = OsCurrTaskGet();//获取当前任务
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) { if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {//任务属于系统任务
OsBackTrace(); OsBackTrace();
return LOS_ERRNO_EVENT_READ_IN_SYSTEM_TASK; return LOS_ERRNO_EVENT_READ_IN_SYSTEM_TASK;//不能在系统任务中读取事件
} }
return LOS_OK; return LOS_OK;
} }
/// 读取指定事件类型的实现函数超时时间为相对时间单位为Tick
LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode,
UINT32 timeout, BOOL once) UINT32 timeout, BOOL once)
{ {
@ -132,56 +133,56 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventM
OsHookCall(LOS_HOOK_TYPE_EVENT_READ, eventCB, eventMask, mode, timeout); OsHookCall(LOS_HOOK_TYPE_EVENT_READ, eventCB, eventMask, mode, timeout);
if (once == FALSE) { if (once == FALSE) {
ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode); ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode);//检测事件是否符合预期
} }
if (ret == 0) { if (ret == 0) {//不符合预期时
if (timeout == 0) { if (timeout == 0) {//不等待的情况
return ret; return ret;
} }
if (!OsPreemptableInSched()) { if (!OsPreemptableInSched()) {//不能抢占式调度
return LOS_ERRNO_EVENT_READ_IN_LOCK; return LOS_ERRNO_EVENT_READ_IN_LOCK;
} }
runTask->eventMask = eventMask; runTask->eventMask = eventMask; //等待事件
runTask->eventMode = mode; runTask->eventMode = mode; //事件模式
runTask->taskEvent = eventCB; runTask->taskEvent = eventCB; //事件控制块
OsTaskWaitSetPendMask(OS_TASK_WAIT_EVENT, eventMask, timeout); OsTaskWaitSetPendMask(OS_TASK_WAIT_EVENT, eventMask, timeout);//任务进入等待状态,等待事件的到来并设置时长和掩码
ret = runTask->ops->wait(runTask, &eventCB->stEventList, timeout); ret = runTask->ops->wait(runTask, &eventCB->stEventList, timeout);
if (ret == LOS_ERRNO_TSK_TIMEOUT) { if (ret == LOS_ERRNO_TSK_TIMEOUT) {
return LOS_ERRNO_EVENT_READ_TIMEOUT; return LOS_ERRNO_EVENT_READ_TIMEOUT;
} }
ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode); ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode);//检测事件是否符合预期
} }
return ret; return ret;
} }
///读取指定事件类型超时时间为相对时间单位为Tick
LITE_OS_SEC_TEXT STATIC UINT32 OsEventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout, LITE_OS_SEC_TEXT STATIC UINT32 OsEventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout,
BOOL once) BOOL once)
{ {
UINT32 ret; UINT32 ret;
UINT32 intSave; UINT32 intSave;
ret = OsEventReadCheck(eventCB, eventMask, mode); ret = OsEventReadCheck(eventCB, eventMask, mode);//读取事件检查
if (ret != LOS_OK) { if (ret != LOS_OK) {
return ret; return ret;
} }
SCHEDULER_LOCK(intSave); SCHEDULER_LOCK(intSave);
ret = OsEventReadImp(eventCB, eventMask, mode, timeout, once); ret = OsEventReadImp(eventCB, eventMask, mode, timeout, once);//读事件实现函数
SCHEDULER_UNLOCK(intSave); SCHEDULER_UNLOCK(intSave);
return ret; return ret;
} }
///事件恢复操作
LITE_OS_SEC_TEXT STATIC UINT8 OsEventResume(LosTaskCB *resumedTask, const PEVENT_CB_S eventCB, UINT32 events) LITE_OS_SEC_TEXT STATIC UINT8 OsEventResume(LosTaskCB *resumedTask, const PEVENT_CB_S eventCB, UINT32 events)
{ {
UINT8 exitFlag = 0; UINT8 exitFlag = 0;//是否唤醒
if (((resumedTask->eventMode & LOS_WAITMODE_OR) && ((resumedTask->eventMask & events) != 0)) || if (((resumedTask->eventMode & LOS_WAITMODE_OR) && ((resumedTask->eventMask & events) != 0)) ||
((resumedTask->eventMode & LOS_WAITMODE_AND) && ((resumedTask->eventMode & LOS_WAITMODE_AND) &&
((resumedTask->eventMask & eventCB->uwEventID) == resumedTask->eventMask))) { ((resumedTask->eventMask & eventCB->uwEventID) == resumedTask->eventMask))) {//逻辑与 和 逻辑或 的处理
exitFlag = 1; exitFlag = 1;
resumedTask->taskEvent = NULL; resumedTask->taskEvent = NULL;
@ -191,33 +192,33 @@ LITE_OS_SEC_TEXT STATIC UINT8 OsEventResume(LosTaskCB *resumedTask, const PEVENT
return exitFlag; return exitFlag;
} }
///以不安全的方式写事件
LITE_OS_SEC_TEXT VOID OsEventWriteUnsafe(PEVENT_CB_S eventCB, UINT32 events, BOOL once, UINT8 *exitFlag) LITE_OS_SEC_TEXT VOID OsEventWriteUnsafe(PEVENT_CB_S eventCB, UINT32 events, BOOL once, UINT8 *exitFlag)
{ {
LosTaskCB *resumedTask = NULL; LosTaskCB *resumedTask = NULL;
LosTaskCB *nextTask = NULL; LosTaskCB *nextTask = NULL;
BOOL schedFlag = FALSE; BOOL schedFlag = FALSE;
OsHookCall(LOS_HOOK_TYPE_EVENT_WRITE, eventCB, events); OsHookCall(LOS_HOOK_TYPE_EVENT_WRITE, eventCB, events);
eventCB->uwEventID |= events; eventCB->uwEventID |= events;//对应位贴上标签
if (!LOS_ListEmpty(&eventCB->stEventList)) { if (!LOS_ListEmpty(&eventCB->stEventList)) {//等待事件链表判断,处理等待事件的任务
for (resumedTask = LOS_DL_LIST_ENTRY((&eventCB->stEventList)->pstNext, LosTaskCB, pendList); for (resumedTask = LOS_DL_LIST_ENTRY((&eventCB->stEventList)->pstNext, LosTaskCB, pendList);
&resumedTask->pendList != &eventCB->stEventList;) { &resumedTask->pendList != &eventCB->stEventList;) {//循环获取任务链表
nextTask = LOS_DL_LIST_ENTRY(resumedTask->pendList.pstNext, LosTaskCB, pendList); nextTask = LOS_DL_LIST_ENTRY(resumedTask->pendList.pstNext, LosTaskCB, pendList);//获取任务实体
if (OsEventResume(resumedTask, eventCB, events)) { if (OsEventResume(resumedTask, eventCB, events)) {//是否恢复任务
schedFlag = TRUE; schedFlag = TRUE;//任务已加至就绪队列,申请发生一次调度
} }
if (once == TRUE) { if (once == TRUE) {//是否只处理一次任务
break; break;//退出循环
} }
resumedTask = nextTask; resumedTask = nextTask;//检查链表中下一个任务
} }
} }
if ((exitFlag != NULL) && (schedFlag == TRUE)) { if ((exitFlag != NULL) && (schedFlag == TRUE)) {//是否让外面调度
*exitFlag = 1; *exitFlag = 1;
} }
} }
///写入事件
LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite(PEVENT_CB_S eventCB, UINT32 events, BOOL once) LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite(PEVENT_CB_S eventCB, UINT32 events, BOOL once)
{ {
UINT32 intSave; UINT32 intSave;
@ -231,54 +232,54 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite(PEVENT_CB_S eventCB, UINT32 events,
return LOS_ERRNO_EVENT_SETBIT_INVALID; return LOS_ERRNO_EVENT_SETBIT_INVALID;
} }
SCHEDULER_LOCK(intSave); SCHEDULER_LOCK(intSave); //禁止调度
OsEventWriteUnsafe(eventCB, events, once, &exitFlag); OsEventWriteUnsafe(eventCB, events, once, &exitFlag);//写入事件
SCHEDULER_UNLOCK(intSave); SCHEDULER_UNLOCK(intSave); //允许调度
if (exitFlag == 1) { if (exitFlag == 1) { //需要发生调度
LOS_MpSchedule(OS_MP_CPU_ALL); LOS_MpSchedule(OS_MP_CPU_ALL);//通知所有CPU调度
LOS_Schedule(); LOS_Schedule();//执行调度
} }
return LOS_OK; return LOS_OK;
} }
///根据用户传入的事件值、事件掩码及校验模式,返回用户传入的事件是否符合预期
LITE_OS_SEC_TEXT UINT32 LOS_EventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode) LITE_OS_SEC_TEXT UINT32 LOS_EventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode)
{ {
UINT32 ret; UINT32 ret;
UINT32 intSave; UINT32 intSave;
//事件参数检查
ret = OsEventParamCheck((VOID *)eventID, eventMask, mode); ret = OsEventParamCheck((VOID *)eventID, eventMask, mode);
if (ret != LOS_OK) { if (ret != LOS_OK) {
return ret; return ret;
} }
SCHEDULER_LOCK(intSave); SCHEDULER_LOCK(intSave);//申请任务自旋锁
ret = OsEventPoll(eventID, eventMask, mode); ret = OsEventPoll(eventID, eventMask, mode);
SCHEDULER_UNLOCK(intSave); SCHEDULER_UNLOCK(intSave);
return ret; return ret;
} }
///读取指定事件类型超时时间为相对时间单位为Tick
LITE_OS_SEC_TEXT UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout) LITE_OS_SEC_TEXT UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout)
{ {
return OsEventRead(eventCB, eventMask, mode, timeout, FALSE); return OsEventRead(eventCB, eventMask, mode, timeout, FALSE);
} }
///写指定的事件类型
LITE_OS_SEC_TEXT UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events) LITE_OS_SEC_TEXT UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events)
{ {
return OsEventWrite(eventCB, events, FALSE); return OsEventWrite(eventCB, events, FALSE);
} }
///只读一次事件
LITE_OS_SEC_TEXT_MINOR UINT32 OsEventReadOnce(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, LITE_OS_SEC_TEXT_MINOR UINT32 OsEventReadOnce(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode,
UINT32 timeout) UINT32 timeout)
{ {
return OsEventRead(eventCB, eventMask, mode, timeout, TRUE); return OsEventRead(eventCB, eventMask, mode, timeout, TRUE);
} }
///只写一次事件
LITE_OS_SEC_TEXT_MINOR UINT32 OsEventWriteOnce(PEVENT_CB_S eventCB, UINT32 events) LITE_OS_SEC_TEXT_MINOR UINT32 OsEventWriteOnce(PEVENT_CB_S eventCB, UINT32 events)
{ {
return OsEventWrite(eventCB, events, TRUE); return OsEventWrite(eventCB, events, TRUE);
} }
///销毁指定的事件控制块
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB) LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB)
{ {
UINT32 intSave; UINT32 intSave;
@ -299,7 +300,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB)
OsHookCall(LOS_HOOK_TYPE_EVENT_DESTROY, eventCB); OsHookCall(LOS_HOOK_TYPE_EVENT_DESTROY, eventCB);
return LOS_OK; return LOS_OK;
} }
///清除指定的事件类型
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 eventMask) LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 eventMask)
{ {
UINT32 intSave; UINT32 intSave;
@ -314,7 +315,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 eventMa
return LOS_OK; return LOS_OK;
} }
///有条件式读事件
#ifdef LOSCFG_COMPAT_POSIX #ifdef LOSCFG_COMPAT_POSIX
LITE_OS_SEC_TEXT UINT32 OsEventReadWithCond(const EventCond *cond, PEVENT_CB_S eventCB, LITE_OS_SEC_TEXT UINT32 OsEventReadWithCond(const EventCond *cond, PEVENT_CB_S eventCB,
UINT32 eventMask, UINT32 mode, UINT32 timeout) UINT32 eventMask, UINT32 mode, UINT32 timeout)

@ -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-2022 Huawei Device Co., Ltd. All rights reserved. * Copyright (c) 2020-2021 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,28 +43,30 @@
#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 #define FUTEX_INDEX_PRIVATE_MAX 64 ///< 0~63号桶用于存放私有锁以虚拟地址进行哈希,同一进程不同线程共享futex变量表明变量在进程地址空间中的位置
#define FUTEX_INDEX_SHARED_MAX 16 ///< 它告诉内核这个futex是进程专有的不可以与其他进程共享。它仅仅用作同一进程的线程间同步。
#define FUTEX_INDEX_MAX (FUTEX_INDEX_PRIVATE_MAX + FUTEX_INDEX_SHARED_MAX) #define FUTEX_INDEX_SHARED_MAX 16 ///< 64~79号桶用于存放共享锁以物理地址进行哈希,不同进程间通过文件共享futex变量表明该变量在文件中的位置
#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; LosMux listLock;///< 内核操作lockList的互斥锁
LOS_DL_LIST lockList; LOS_DL_LIST lockList;///< 用于挂载 FutexNode (Fast userspace mutex用户态快速互斥锁)
} FutexHash; } FutexHash;
FutexHash g_futexHash[FUTEX_INDEX_MAX]; FutexHash g_futexHash[FUTEX_INDEX_MAX];///< 80个哈希桶
/// 对互斥锁封装
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);
@ -84,15 +86,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); LOS_ListInit(&g_futexHash[count].lockList); // 初始化双向链表,上面挂 FutexNode
ret = LOS_MuxInit(&(g_futexHash[count].listLock), NULL); ret = LOS_MuxInit(&(g_futexHash[count].listLock), NULL);//初始化互斥锁
if (ret) { if (ret) {
return ret; return ret;
} }
@ -101,7 +103,7 @@ UINT32 OsFutexInit(VOID)
return LOS_OK; return LOS_OK;
} }
LOS_MODULE_INIT(OsFutexInit, LOS_INIT_LEVEL_KMOD_EXTENDED); LOS_MODULE_INIT(OsFutexInit, LOS_INIT_LEVEL_KMOD_EXTENDED);///< 注册Futex模块
#ifdef LOS_FUTEX_DEBUG #ifdef LOS_FUTEX_DEBUG
STATIC VOID OsFutexShowTaskNodeAttr(const LOS_DL_LIST *futexList) STATIC VOID OsFutexShowTaskNodeAttr(const LOS_DL_LIST *futexList)
@ -152,63 +154,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 &= FUTEX_HASH_PRIVATE_MASK;//将index锁定在 0 ~ 63号
} else { } else {
index &= FUTEX_HASH_SHARED_MASK; index &= FUTEX_HASH_SHARED_MASK;
index += FUTEX_INDEX_SHARED_POS; index += FUTEX_INDEX_SHARED_POS;//共享锁索引,将index锁定在 64 ~ 79号
} }
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; node->key = futexKey;//哈希key
node->index = OsFutexKeyToIndex(futexKey, flags); node->index = OsFutexKeyToIndex(futexKey, flags);//哈希桶索引
node->pid = (flags & FUTEX_PRIVATE) ? LOS_GetCurrProcessID() : OS_INVALID; node->pid = (flags & FUTEX_PRIVATE) ? LOS_GetCurrProcessID() : OS_INVALID;//获取进程ID,共享快锁时 快锁节点没有进程ID
} }
//析构参数节点
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); LOS_ListDelete(&oldHeadNode->futexList);//将旧节点从futexList链表上摘除
LOS_ListHeadInsert(futexList, &newHeadNode->futexList); LOS_ListHeadInsert(futexList, &newHeadNode->futexList);//将新节点从头部插入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;
@ -217,8 +219,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;
} }
@ -226,10 +228,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;
} }
@ -242,22 +244,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]; hashNode = &g_futexHash[index];//找到hash桶
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;
} }
@ -270,7 +272,6 @@ 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;
@ -292,7 +293,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;
@ -326,12 +327,12 @@ STATIC VOID OsFutexInsertNewFutexKeyToHash(FutexNode *node)
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;
@ -407,55 +408,54 @@ 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)); LOS_ListTailInsert(queueList, &(node->queueList));//查到queueList的尾部
OsFutexReplaceQueueListHeadNode(*firstNode, node); OsFutexReplaceQueueListHeadNode(*firstNode, node);//同时交换futexList链表上的位置
*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; return headNode;//是key和pid 一起比较,因为只有这样才能确定唯一性
}
} }
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); OsFutexSetKey(futexKey, flags, *node);//设置参数 key index pid
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); UINTPTR futexKey = OsFutexFlagsToKey(userVaddr, flags);//通过地址和flags 找到 key
UINT32 index = OsFutexKeyToIndex(futexKey, flags); UINT32 index = OsFutexKeyToIndex(futexKey, flags);//通过key找到哈希桶
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)) { if (OsFutexInsertTaskToHash(&taskCB, &node, futexKey, flags)) {// node = taskCB->futex
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) { if (absTime != LOS_WAIT_FOREVER) {//转换时间 , 内核的时间单位是 tick
timeout = OsNS2Tick((UINT64)absTime * OS_SYS_NS_PER_US); timeout = OsNS2Tick((UINT64)absTime * OS_SYS_NS_PER_US); //转成 tick
} }
return OsFutexWaitTask(userVaddr, flags, val, timeout); return OsFutexWaitTask(userVaddr, flags, val, timeout);//将任务挂起 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;
@ -673,6 +673,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,6 +709,7 @@ 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)
{ {
UINT32 intSave; UINT32 intSave;
@ -715,13 +717,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;
} }
@ -729,7 +731,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);
@ -741,7 +743,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;
@ -750,11 +752,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);
@ -762,7 +764,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;
@ -776,7 +778,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();
@ -885,7 +887,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)
{ {
@ -921,7 +923,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;
@ -930,12 +932,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;
@ -948,7 +950,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;
@ -965,12 +967,12 @@ INT32 OsFutexRequeue(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber, IN
return LOS_EINVAL; return LOS_EINVAL;
} }
oldFutexKey = OsFutexFlagsToKey(userVaddr, flags); oldFutexKey = OsFutexFlagsToKey(userVaddr, flags);//先拿key
newFutexKey = OsFutexFlagsToKey(newUserVaddr, flags); newFutexKey = OsFutexFlagsToKey(newUserVaddr, flags);
oldIndex = OsFutexKeyToIndex(oldFutexKey, flags); oldIndex = OsFutexKeyToIndex(oldFutexKey, flags);//再拿所在哈希桶位置,共有80个哈希桶
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;
} }

Loading…
Cancel
Save