summaryrefslogtreecommitdiffstatsabout
path: root/SylixOS
diff options
context:
space:
mode:
authorHanhui <hanhui@acoinfo.com>2021-01-02 12:35:19 (GMT)
committer Hanhui <hanhui@acoinfo.com>2021-01-02 12:35:19 (GMT)
commit3fa8b96ef18230811c60c686610441c52f1985c1 (patch)
treee9576e1121c21414734a1ba48c2bf73960289619 /SylixOS
parent7c54c31a534697deb2277c8f75500179829077fc (diff)
downloadlibsylixos-3fa8b96ef18230811c60c686610441c52f1985c1.zip
libsylixos-3fa8b96ef18230811c60c686610441c52f1985c1.tar.gz
libsylixos-3fa8b96ef18230811c60c686610441c52f1985c1.tar.bz2
Add fastlock library which used the VUTEX implement mutex, semaphore, pthread condition, and fastlock compatible with SylixOS standard interface.
Diffstat (limited to 'SylixOS')
-rw-r--r--SylixOS/CHANGELOG3
-rw-r--r--SylixOS/api/Lw_Api_Kernel.h6
-rw-r--r--SylixOS/debug/dtrace/dtrace.c2
-rw-r--r--SylixOS/kernel/core/_ThreadInit.c3
-rw-r--r--SylixOS/kernel/include/k_class.h11
-rw-r--r--SylixOS/kernel/include/k_internal.h7
-rw-r--r--SylixOS/kernel/include/k_kernel.h2
-rw-r--r--SylixOS/kernel/include/k_option.h20
-rw-r--r--SylixOS/kernel/show/ThreadShow.c9
-rw-r--r--SylixOS/kernel/threadext/ThreadOnce.c14
-rw-r--r--SylixOS/kernel/vutex/vutex.c168
-rw-r--r--SylixOS/kernel/vutex/vutex.h13
-rw-r--r--SylixOS/kernel/vutex/vutexLib.c211
-rw-r--r--SylixOS/kernel/vutex/vutexLib.h6
-rw-r--r--SylixOS/posix/fastlock/cond.c3
-rw-r--r--SylixOS/posix/fastlock/fastlock.h0
-rw-r--r--SylixOS/posix/fastlock/mutex.c3
-rw-r--r--SylixOS/posix/fastlock/semaphore.c3
18 files changed, 314 insertions, 170 deletions
diff --git a/SylixOS/CHANGELOG b/SylixOS/CHANGELOG
index 3ef942f..462b50e 100644
--- a/SylixOS/CHANGELOG
+++ b/SylixOS/CHANGELOG
@@ -4,6 +4,9 @@ HISTORY
++ New features:
+ 2021-01-01: han.hui
+ 加入 fastlock 库, 现实用户态非严格顺序的快速 pthread mutex cond semaphore 实现.
+
2020-12-26: han.hui
加入 Vutex 支持, 类似 Linux Futex.
diff --git a/SylixOS/api/Lw_Api_Kernel.h b/SylixOS/api/Lw_Api_Kernel.h
index c0e0a4d..91836f7 100644
--- a/SylixOS/api/Lw_Api_Kernel.h
+++ b/SylixOS/api/Lw_Api_Kernel.h
@@ -423,9 +423,15 @@
#define Lw_Vutex_Pend API_VutexPend
#define Lw_Vutex_Wait API_VutexPend
+#define Lw_Vutex_PendEx API_VutexPendEx
+#define Lw_Vutex_WaitEx API_VutexPendEx
+
#define Lw_Vutex_Post API_VutexPost
#define Lw_Vutex_Wake API_VutexPost
+#define Lw_Vutex_PostEx API_VutexPostEx
+#define Lw_Vutex_WakeEx API_VutexPostEx
+
/*********************************************************************************************************
TIME
*********************************************************************************************************/
diff --git a/SylixOS/debug/dtrace/dtrace.c b/SylixOS/debug/dtrace/dtrace.c
index a85f61b..3a7aa78 100644
--- a/SylixOS/debug/dtrace/dtrace.c
+++ b/SylixOS/debug/dtrace/dtrace.c
@@ -1236,7 +1236,7 @@ ULONG API_DtraceThreadExtraInfo (PVOID pvDtrace, LW_OBJECT_HANDLE ulThread,
pcPendType = "MSGQ";
} else if (tcbdesc.TCBD_usStatus & LW_THREAD_STATUS_VUTEX) { /* 等待变量条件 */
- pcPendType = "VUTEX";
+ pcPendType = "VUTX";
} else if (tcbdesc.TCBD_usStatus & LW_THREAD_STATUS_JOIN) { /* 等待其他线程 */
pcPendType = "JOIN";
diff --git a/SylixOS/kernel/core/_ThreadInit.c b/SylixOS/kernel/core/_ThreadInit.c
index 46cc514..6cf37df 100644
--- a/SylixOS/kernel/core/_ThreadInit.c
+++ b/SylixOS/kernel/core/_ThreadInit.c
@@ -452,8 +452,7 @@ VOID _TCBDestroyExt (PLW_CLASS_TCB ptcb)
patomic = (atomic_t *)pcur->CUO_piOnce;
__LW_ATOMIC_SET(0, patomic); /* 未完成的 once 操作 */
- API_VutexPost(pcur->CUO_piOnce,
- __ARCH_INT_MAX, LW_OPTION_VUTEX_LOCAL); /* 唤醒等待完成的任务 */
+ API_VutexPost(pcur->CUO_piOnce, __ARCH_INT_MAX); /* 唤醒等待完成的任务 */
__KHEAP_FREE(pcur); /* 释放 */
}
diff --git a/SylixOS/kernel/include/k_class.h b/SylixOS/kernel/include/k_class.h
index 7e1e4ea..45e479a 100644
--- a/SylixOS/kernel/include/k_class.h
+++ b/SylixOS/kernel/include/k_class.h
@@ -464,11 +464,12 @@ typedef LW_SHELL_CONTEXT *PLW_SHELL_CONTEXT;
*********************************************************************************************************/
typedef struct {
- LW_LIST_LINE VUTEX_lineVutex; /* 等待链 */
- INT VUTEX_iFlags; /* 等待 flags */
- INT32 VUTEX_iVutexExpect; /* 期望的数值 */
- UINT32 VUTEX_uiVutexHash; /* 等待变量 HASH index */
- phys_addr_t VUTEX_phyaddrVutex; /* 等待的变量 */
+ LW_LIST_LINE VUTEX_lineWait; /* 等待链 */
+ BOOL VUTEX_bWakeAll; /* WakeAll 唤醒 */
+ INT VUTEX_iCompare; /* 比较方法 */
+ INT32 VUTEX_iDesired; /* 期望的数值 */
+ UINT32 VUTEX_uiHash; /* 等待变量 HASH index */
+ phys_addr_t VUTEX_phyaddr; /* 等待的变量 */
} LW_VUTEX_CONTEXT;
typedef LW_VUTEX_CONTEXT *PLW_VUTEX_CONTEXT;
diff --git a/SylixOS/kernel/include/k_internal.h b/SylixOS/kernel/include/k_internal.h
index 15cdef5..500a0eb 100644
--- a/SylixOS/kernel/include/k_internal.h
+++ b/SylixOS/kernel/include/k_internal.h
@@ -400,12 +400,7 @@ VOID _MsgQueueMsgLen(PLW_CLASS_MSGQUEUE pmsgqueue, size_t *pstMsgLen
VOID _VutexInitCtx(PLW_CLASS_TCB ptcb);
VOID _VutexUnQueue(PLW_CLASS_TCB ptcb);
-/*********************************************************************************************************
- VUTEX 等待判断
-*********************************************************************************************************/
-
-#define __VUTEX_IS_GLOBAL(ptcb) (ptcb->TCB_vutex.VUTEX_iFlags & LW_OPTION_VUTEX_GLOBAL)
-#define __VUTEX_IS_WAITING(ptcb) (ptcb->TCB_vutex.VUTEX_phyaddrVutex != LW_PHY_ADDR_INVALID)
+#define __VUTEX_IS_WAITING(ptcb) ((ptcb)->TCB_vutex.VUTEX_phyaddr != LW_PHY_ADDR_INVALID)
/*********************************************************************************************************
构建句柄
diff --git a/SylixOS/kernel/include/k_kernel.h b/SylixOS/kernel/include/k_kernel.h
index cfb9362..e2ab52b 100644
--- a/SylixOS/kernel/include/k_kernel.h
+++ b/SylixOS/kernel/include/k_kernel.h
@@ -53,7 +53,7 @@
#define __SYLIXOS_MAJOR_VER 2
#define __SYLIXOS_MINOR_VER 1
-#define __SYLIXOS_PATCH_VER 2
+#define __SYLIXOS_PATCH_VER 3
#define __SYLIXOS_PATCH_PAD 0
/*********************************************************************************************************
diff --git a/SylixOS/kernel/include/k_option.h b/SylixOS/kernel/include/k_option.h
index 151e904..56ddf50 100644
--- a/SylixOS/kernel/include/k_option.h
+++ b/SylixOS/kernel/include/k_option.h
@@ -266,11 +266,21 @@
#define LW_OPTION_EVENT_ALL (0xffffffff) /* 事件集的所有事件位 */
/*********************************************************************************************************
- VUTEX FLAG
-*********************************************************************************************************/
-
-#define LW_OPTION_VUTEX_LOCAL 0x00000000 /* 进程内虚拟地址变量等待 */
-#define LW_OPTION_VUTEX_GLOBAL 0x80000000 /* 全局物理地址变量等待 */
+ VUTEX OPTIONS
+*********************************************************************************************************/
+ /* 判断条件 */
+#define LW_OPTION_VUTEX_EQU 0 /* == */
+#define LW_OPTION_VUTEX_LESS 1 /* < */
+#define LW_OPTION_VUTEX_LESS_EQU 2 /* <= */
+#define LW_OPTION_VUTEX_GREATER 3 /* > */
+#define LW_OPTION_VUTEX_GREATER_EQU 4 /* >= */
+#define LW_OPTION_VUTEX_AND 5 /* & */
+#define LW_OPTION_VUTEX_NAND 6 /* &~ */
+
+ /* PostEx Flags */
+#define LW_OPTION_VUTEX_FLAG_WAKEALL 0x0001 /* 全部唤醒 */
+#define LW_OPTION_VUTEX_FLAG_DONTSET 0x0002 /* 不设置变量值 */
+#define LW_OPTION_VUTEX_FLAG_DEEPWAKE 0x0004 /* Post 不进行相同值检查优化 */
/*********************************************************************************************************
SCHEDLER
diff --git a/SylixOS/kernel/show/ThreadShow.c b/SylixOS/kernel/show/ThreadShow.c
index 6a5456f..3fe5b69 100644
--- a/SylixOS/kernel/show/ThreadShow.c
+++ b/SylixOS/kernel/show/ThreadShow.c
@@ -121,7 +121,7 @@ VOID API_ThreadShowEx (pid_t pid)
pcPendType = "MSGQ";
} else if (tcbdesc.TCBD_usStatus & LW_THREAD_STATUS_VUTEX) { /* 等待变量条件 */
- pcPendType = "VUTEX";
+ pcPendType = "VUTX";
} else if (tcbdesc.TCBD_usStatus & LW_THREAD_STATUS_JOIN) { /* 等待其他线程 */
pcPendType = "JOIN";
@@ -285,6 +285,11 @@ VOID API_ThreadPendShowEx (pid_t pid)
break;
}
+ } else if (__VUTEX_IS_WAITING(ptcb)) { /* 等待 vutex 变量 */
+ ulEvent = ptcb->TCB_vutex.VUTEX_phyaddr;
+ lib_itoa(ptcb->TCB_vutex.VUTEX_iDesired, cEventName, 10);
+ ulOwner = LW_OBJECT_HANDLE_INVALID;
+
#if (LW_CFG_EVENTSET_EN > 0) && (LW_CFG_MAX_EVENTSETS > 0)
} else if (ptcb->TCB_pesnPtr) { /* 等待事件标志组 */
pes = (PLW_CLASS_EVENTSET)ptcb->TCB_pesnPtr->EVENTSETNODE_pesEventSet;
@@ -333,7 +338,7 @@ VOID API_ThreadPendShowEx (pid_t pid)
pcPendType = "MSGQ";
} else if (tcbdesc.TCBD_usStatus & LW_THREAD_STATUS_VUTEX) { /* 等待变量条件 */
- pcPendType = "VUTEX";
+ pcPendType = "VUTX";
} else if (tcbdesc.TCBD_usStatus & LW_THREAD_STATUS_JOIN) { /* 等待其他线程 */
pcPendType = "JOIN";
diff --git a/SylixOS/kernel/threadext/ThreadOnce.c b/SylixOS/kernel/threadext/ThreadOnce.c
index 179a667..8fbc34a 100644
--- a/SylixOS/kernel/threadext/ThreadOnce.c
+++ b/SylixOS/kernel/threadext/ThreadOnce.c
@@ -130,7 +130,6 @@ INT API_ThreadOnce (INT *piOnce, VOIDFUNCPTR pfuncRoutine)
case __THREAD_ONCE_STATUS_INIT: /* 正在被其他任务执行 */
API_VutexPend(piOnce,
__THREAD_ONCE_STATUS_DOWN,
- LW_OPTION_VUTEX_LOCAL,
LW_OPTION_WAIT_INFINITE); /* 等待初始化执行完毕 */
continue;
@@ -155,9 +154,9 @@ INT API_ThreadOnce (INT *piOnce, VOIDFUNCPTR pfuncRoutine)
__threadOnceCleanPop(); /* 删除回收点 */
}
- __LW_ATOMIC_SET(__THREAD_ONCE_STATUS_DOWN, patomic); /* 执行完毕 */
-
- API_VutexPost(piOnce, __ARCH_INT_MAX, LW_OPTION_VUTEX_LOCAL); /* 唤醒等待的任务 */
+ API_VutexPostEx(piOnce,
+ __THREAD_ONCE_STATUS_DOWN,
+ LW_OPTION_VUTEX_FLAG_WAKEALL); /* 执行完毕, 唤醒等待的任务 */
return (ERROR_NONE);
}
@@ -196,7 +195,6 @@ INT API_ThreadOnce2 (INT *piOnce, VOIDFUNCPTR pfuncRoutine, PVOID pvArg)
case __THREAD_ONCE_STATUS_INIT: /* 正在被其他任务执行 */
API_VutexPend(piOnce,
__THREAD_ONCE_STATUS_DOWN,
- LW_OPTION_VUTEX_LOCAL,
LW_OPTION_WAIT_INFINITE); /* 等待初始化执行完毕 */
continue;
@@ -221,9 +219,9 @@ INT API_ThreadOnce2 (INT *piOnce, VOIDFUNCPTR pfuncRoutine, PVOID pvArg)
__threadOnceCleanPop(); /* 删除回收点 */
}
- __LW_ATOMIC_SET(__THREAD_ONCE_STATUS_DOWN, patomic); /* 执行完毕 */
-
- API_VutexPost(piOnce, __ARCH_INT_MAX, LW_OPTION_VUTEX_LOCAL); /* 唤醒等待的任务 */
+ API_VutexPostEx(piOnce,
+ __THREAD_ONCE_STATUS_DOWN,
+ LW_OPTION_VUTEX_FLAG_WAKEALL); /* 执行完毕, 唤醒等待的任务 */
return (ERROR_NONE);
}
diff --git a/SylixOS/kernel/vutex/vutex.c b/SylixOS/kernel/vutex/vutex.c
index b0e4104..f0df9d2 100644
--- a/SylixOS/kernel/vutex/vutex.c
+++ b/SylixOS/kernel/vutex/vutex.c
@@ -22,13 +22,18 @@
#include "SylixOS.h"
#include "vutexLib.h"
/*********************************************************************************************************
-** 函数名称: API_VutexPend
-** 功能描述: 等待一个变量到达某个值
+ Post check value
+*********************************************************************************************************/
+#define LW_VUTEX_POST_CHECK_VALUE(flags) \
+ (!((flags) & LW_OPTION_VUTEX_FLAG_WAKEALL) && !((flags) & LW_OPTION_VUTEX_FLAG_DEEPWAKE))
+/*********************************************************************************************************
+** 函数名称: API_VutexPendEx
+** 功能描述: 等待一个变量到达某个值 (带有条件)
** 输 入 : piVar 等待的变量地址
-** iExpect 期望的数值
-** iFlags 操作选项
+** iDesired 期望的数值
+** iCompare 比较方法
** ulTimeout 等待时间
-** 输 出 : ERROR or OK
+** 输 出 : ERROR or 0: 被真实的等待值激活, 1: 被 WAKEALL 激活.
** 全局变量:
** 调用模块:
API 函数
@@ -36,8 +41,9 @@
(不得在中断中调用)
*********************************************************************************************************/
LW_API
-INT API_VutexPend (INT *piVar, INT iExpect, INT iFlags, ULONG ulTimeout)
+INT API_VutexPendEx (INT *piVar, INT iCompare, INT iDesired, ULONG ulTimeout)
{
+ INTREG iregInterLevel;
phys_addr_t phyaddr;
PLW_CLASS_TCB ptcbCur;
ULONG ulTimeSave; /* 系统事件记录 */
@@ -54,7 +60,7 @@ INT API_VutexPend (INT *piVar, INT iExpect, INT iFlags, ULONG ulTimeout)
}
__wait_again:
- if (*(volatile INT *)piVar == iExpect) {
+ if (_VutexWakeIsMatch(*piVar, iCompare, iDesired)) { /* 是否已经满足条件 */
return (ERROR_NONE);
} else if (ulTimeout == LW_OPTION_NOT_WAIT) { /* 不等待 */
@@ -62,31 +68,31 @@ __wait_again:
return (PX_ERROR);
}
- if (iFlags & LW_OPTION_VUTEX_GLOBAL) { /* 是否为全局地址 */
+ __KERNEL_ENTER(); /* 进入内核 */
+ if (_VutexWakeIsMatch(*piVar, iCompare, iDesired)) {
+ __KERNEL_EXIT();
+ return (ERROR_NONE);
+ }
+
#if LW_CFG_VMM_EN > 0
- if (vmmVirtualToPhysical((addr_t)piVar, &phyaddr)) { /* 转换为物理地址 */
- return (PX_ERROR);
- }
+ if (__vmmLibVirtualToPhysical((addr_t)piVar, &phyaddr)) { /* 转换为物理地址 */
+ __KERNEL_EXIT();
+ return (PX_ERROR);
+ }
#else /* LW_CFG_VMM_EN > 0 */
- phyaddr = (phys_addr_t)piVar;
+ phyaddr = (phys_addr_t)piVar;
#endif /* LW_CFG_VMM_EN == 0 */
- } else {
- phyaddr = (phys_addr_t)piVar;
- }
if (phyaddr == LW_PHY_ADDR_INVALID) { /* 地址无效 */
+ __KERNEL_EXIT();
_ErrorHandle(EFAULT);
return (PX_ERROR);
}
- __KERNEL_ENTER(); /* 进入内核 */
- if (*(volatile INT *)piVar == iExpect) {
- __KERNEL_EXIT();
- return (ERROR_NONE);
- }
-
LW_TCB_GET_CUR(ptcbCur);
+ iregInterLevel = KN_INT_DISABLE(); /* 关闭中断 */
+
ptcbCur->TCB_usStatus |= LW_THREAD_STATUS_VUTEX; /* 写状态位,开始等待 */
ptcbCur->TCB_ucWaitTimeout = LW_WAIT_TIME_CLEAR; /* 清空等待时间 */
@@ -97,44 +103,51 @@ __wait_again:
}
__KERNEL_TIME_GET_IGNIRQ(ulTimeSave, ULONG); /* 记录系统时间 */
- _VutexWaitQueue(ptcbCur, phyaddr, iExpect, iFlags); /* 加入等待表 */
-
- iSchedRet = __KERNEL_EXIT(); /* 退出内核 */
- if (*(volatile INT *)piVar == iExpect) {
- return (ERROR_NONE);
- }
+ _VutexWaitQueue(ptcbCur, phyaddr, iDesired, iCompare); /* 加入等待表 */
+ iSchedRet = __KERNEL_EXIT_IRQ(iregInterLevel); /* 退出内核 */
if (iSchedRet == LW_SIGNAL_EINTR) {
_ErrorHandle(EINTR); /* 被信号打断 */
return (PX_ERROR);
} else if (iSchedRet == LW_SIGNAL_RESTART) {
ulTimeout = _sigTimeoutRecalc(ulTimeSave, ulTimeout);
-
- } else {
- if (ptcbCur->TCB_ucWaitTimeout == LW_WAIT_TIME_OUT) { /* 被唤醒或超时了 */
- _ErrorHandle(ERROR_THREAD_WAIT_TIMEOUT); /* 等待超时 */
- return (PX_ERROR);
-
- } else {
- ulTimeout = _sigTimeoutRecalc(ulTimeSave, ulTimeout);
+ if (ulTimeout != LW_OPTION_NOT_WAIT) {
+ goto __wait_again; /* 重新等待 */
}
- }
- if (ulTimeout != LW_OPTION_NOT_WAIT) {
- goto __wait_again; /* 重新等待 */
+ } else if (ptcbCur->TCB_ucWaitTimeout == LW_WAIT_TIME_OUT) { /* 被唤醒或超时了 */
+ _ErrorHandle(ERROR_THREAD_WAIT_TIMEOUT); /* 等待超时 */
+ return (PX_ERROR);
}
- _ErrorHandle(ERROR_THREAD_WAIT_TIMEOUT); /* 等待超时 */
- return (PX_ERROR);
+ return (_VutexWakeIsAll(ptcbCur) ? 1 : 0); /* 被唤醒 */
}
/*********************************************************************************************************
-** 函数名称: API_VutexPost
-** 功能描述: 改变一个变量为某个值
+** 函数名称: API_VutexPend
+** 功能描述: 等待一个变量到达某个值
+** 输 入 : piVar 等待的变量地址
+** iDesired 期望的数值
+** ulTimeout 等待时间
+** 输 出 : ERROR or 0: 被真实的等待值激活, 1: 被 WAKEALL 激活.
+** 全局变量:
+** 调用模块:
+ API 函数
+
+ (不得在中断中调用)
+*********************************************************************************************************/
+LW_API
+INT API_VutexPend (INT *piVar, INT iDesired, ULONG ulTimeout)
+{
+ return (API_VutexPendEx(piVar, LW_OPTION_VUTEX_EQU, iDesired, ulTimeout));
+}
+/*********************************************************************************************************
+** 函数名称: API_VutexPostEx
+** 功能描述: 改变一个变量为某个值唤醒等待线程
** 输 入 : piVar 变量地址
** iValue 要设置的值
-** iFlags 操作选项
-** 输 出 : ERROR or OK
+** iFlags flags
+** 输 出 : ERROR or 唤醒的任务数
** 全局变量:
** 调用模块:
API 函数
@@ -142,10 +155,10 @@ __wait_again:
(不得在中断中调用)
*********************************************************************************************************/
LW_API
-INT API_VutexPost (INT *piVar, INT iValue, INT iFlags)
+INT API_VutexPostEx (INT *piVar, INT iValue, INT iFlags)
{
- phys_addr_t phyaddr;
- PLW_CLASS_TCB ptcbCur;
+ INT iWakeCnt;
+ phys_addr_t phyaddr;
if (!piVar) {
_ErrorHandle(EFAULT);
@@ -157,45 +170,62 @@ INT API_VutexPost (INT *piVar, INT iValue, INT iFlags)
return (PX_ERROR);
}
- if (*(volatile INT *)piVar == iValue) {
- return (ERROR_NONE);
+ if (LW_VUTEX_POST_CHECK_VALUE(iFlags)) {
+ if (*(volatile INT *)piVar == iValue) { /* 非全部唤醒且值已经相同 */
+ return (ERROR_NONE);
+ }
}
- if (iFlags & LW_OPTION_VUTEX_GLOBAL) { /* 是否为全局地址 */
-#if LW_CFG_VMM_EN > 0
- if (vmmVirtualToPhysical((addr_t)piVar, &phyaddr)) { /* 转换为物理地址 */
- return (PX_ERROR);
+ __KERNEL_ENTER(); /* 进入内核 */
+ if (LW_VUTEX_POST_CHECK_VALUE(iFlags)) {
+ if (*(volatile INT *)piVar == iValue) {
+ __KERNEL_EXIT();
+ return (ERROR_NONE); /* 非全部唤醒且值已经相同 */
}
-#else /* LW_CFG_VMM_EN > 0 */
- phyaddr = (phys_addr_t)piVar;
-#endif /* LW_CFG_VMM_EN == 0 */
- } else {
- phyaddr = (phys_addr_t)piVar;
}
- if (phyaddr == LW_PHY_ADDR_INVALID) { /* 地址无效 */
- _ErrorHandle(EFAULT);
+#if LW_CFG_VMM_EN > 0
+ if (__vmmLibVirtualToPhysical((addr_t)piVar, &phyaddr)) { /* 转换为物理地址 */
+ __KERNEL_EXIT();
return (PX_ERROR);
}
+#else /* LW_CFG_VMM_EN > 0 */
+ phyaddr = (phys_addr_t)piVar;
+#endif /* LW_CFG_VMM_EN == 0 */
- __KERNEL_ENTER(); /* 进入内核 */
- if (*(volatile INT *)piVar == iValue) {
+ if (phyaddr == LW_PHY_ADDR_INVALID) { /* 地址无效 */
__KERNEL_EXIT();
- return (ERROR_NONE);
+ _ErrorHandle(EFAULT);
+ return (PX_ERROR);
}
- if (iValue != __ARCH_INT_MAX) { /* __ARCH_INT_MAX 仅唤醒 */
- *piVar = iValue;
+ if (!(iFlags & LW_OPTION_VUTEX_FLAG_DONTSET)) { /* 仅唤醒 */
+ *(volatile INT *)piVar = iValue;
KN_SMP_WMB();
}
- LW_TCB_GET_CUR(ptcbCur);
-
- _VutexWakeQueue(ptcbCur, phyaddr, iValue, iFlags); /* 唤醒合适的任务 */
+ iWakeCnt = _VutexWakeQueue(phyaddr, iValue, iFlags); /* 唤醒合适的任务 */
__KERNEL_EXIT(); /* 退出内核 */
- return (ERROR_NONE);
+ return (iWakeCnt);
+}
+/*********************************************************************************************************
+** 函数名称: API_VutexPost
+** 功能描述: 改变一个变量为某个值
+** 输 入 : piVar 变量地址
+** iValue 要设置的值
+** 输 出 : ERROR or 唤醒的任务数
+** 全局变量:
+** 调用模块:
+ API 函数
+
+ (不得在中断中调用)
+*********************************************************************************************************/
+LW_API
+INT API_VutexPost (INT *piVar, INT iValue)
+{
+ return (API_VutexPostEx(piVar, iValue, 0));
}
/*********************************************************************************************************
END
diff --git a/SylixOS/kernel/vutex/vutex.h b/SylixOS/kernel/vutex/vutex.h
index 097509a..ca1b45c 100644
--- a/SylixOS/kernel/vutex/vutex.h
+++ b/SylixOS/kernel/vutex/vutex.h
@@ -24,14 +24,17 @@
/*********************************************************************************************************
API
+*********************************************************************************************************/
+
+LW_API INT API_VutexPend(INT *piVar, INT iDesired, ULONG ulTimeout);
+LW_API INT API_VutexPost(INT *piVar, INT iValue);
- 只有 iFlags 相同, 才表示同一变量,
- 仅对进程内多任务生效, 可以使用 LW_OPTION_VUTEX_LOCAL, Vutex 工作速度快, 不进行地址映射转换.
- 对整个系统生效, 可以使用 LW_OPTION_VUTEX_GLOBAL, Vutex 将保存对应的物理地址关系, 可跨进程等待.
+/*********************************************************************************************************
+ 带有比较条件与选项的等待与唤醒
*********************************************************************************************************/
-LW_API INT API_VutexPend(INT *piVar, INT iExpect, INT iFlags, ULONG ulTimeout);
-LW_API INT API_VutexPost(INT *piVar, INT iValue, INT iFlags);
+LW_API INT API_VutexPendEx(INT *piVar, INT iCompare, INT iDesired, ULONG ulTimeout);
+LW_API INT API_VutexPostEx(INT *piVar, INT iValue, INT iFlags);
#endif /* __VUTEX_H */
/*********************************************************************************************************
diff --git a/SylixOS/kernel/vutex/vutexLib.c b/SylixOS/kernel/vutex/vutexLib.c
index d90e510..31f951b 100644
--- a/SylixOS/kernel/vutex/vutexLib.c
+++ b/SylixOS/kernel/vutex/vutexLib.c
@@ -31,88 +31,160 @@
全局变量
*********************************************************************************************************/
static LW_LIST_LINE_HEADER _k_plineVutexHashHeader[LW_VUTEX_HASH_SIZE];
+static PLW_LIST_LINE _k_plineVutexOp;
+/*********************************************************************************************************
+** 函数名称: _VutexWakeIsMatch
+** 功能描述: 判断条件是否匹配
+** 输 入 : iValue 真实数值
+** iCompare 比较方法
+** iDesired 期望数值
+** 输 出 : 是否匹配
+** 全局变量:
+** 调用模块:
+*********************************************************************************************************/
+BOOL _VutexWakeIsMatch (INT iValue, INT iCompare, INT iDesired)
+{
+ BOOL bMatch = LW_FALSE;
+
+ switch (iCompare) {
+
+ case LW_OPTION_VUTEX_EQU:
+ if (iValue == iDesired) {
+ bMatch = LW_TRUE;
+ }
+ break;
+
+ case LW_OPTION_VUTEX_LESS:
+ if (iValue < iDesired) {
+ bMatch = LW_TRUE;
+ }
+ break;
+
+ case LW_OPTION_VUTEX_LESS_EQU:
+ if (iValue <= iDesired) {
+ bMatch = LW_TRUE;
+ }
+ break;
+
+ case LW_OPTION_VUTEX_GREATER:
+ if (iValue > iDesired) {
+ bMatch = LW_TRUE;
+ }
+ break;
+
+ case LW_OPTION_VUTEX_GREATER_EQU:
+ if (iValue >= iDesired) {
+ bMatch = LW_TRUE;
+ }
+ break;
+
+ case LW_OPTION_VUTEX_AND:
+ if (iValue & iDesired) {
+ bMatch = LW_TRUE;
+ }
+ break;
+
+ case LW_OPTION_VUTEX_NAND:
+ if (~iValue & iDesired) {
+ bMatch = LW_TRUE;
+ }
+ break;
+ }
+
+ return (bMatch);
+}
+/*********************************************************************************************************
+** 函数名称: _VutexWakeIsAll
+** 功能描述: 获得唤醒类型是否为 WAKEALL
+** 输 入 : ptcb 任务
+** 输 出 : NONE
+** 全局变量:
+** 调用模块:
+*********************************************************************************************************/
+BOOL _VutexWakeIsAll (PLW_CLASS_TCB ptcb)
+{
+ PLW_VUTEX_CONTEXT pvutex = &ptcb->TCB_vutex;
+
+ return (pvutex->VUTEX_bWakeAll);
+}
/*********************************************************************************************************
** 函数名称: _VutexWaitQueue
-** 功能描述: 将当前任务加入等待队列
+** 功能描述: 将当前任务加入等待队列 (进入内核且关中断情况被调用)
** 输 入 : ptcbCur 当前任务
** phyaddr 等待的物理地址
-** iExpect 期望的值
-** iFlags 操作选项
+** iDesired 期望的值
+** iCompare 比较方法
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
-VOID _VutexWaitQueue (PLW_CLASS_TCB ptcbCur, phys_addr_t phyaddr, INT32 iExpect, INT iFlags)
+VOID _VutexWaitQueue (PLW_CLASS_TCB ptcbCur, phys_addr_t phyaddr, INT32 iDesired, INT iCompare)
{
- REGISTER PLW_CLASS_PCB ppcb;
- LW_LIST_LINE_HEADER *pplineHeader;
- PLW_VUTEX_CONTEXT pvutex = &ptcbCur->TCB_vutex;
+ REGISTER PLW_CLASS_PCB ppcb;
+ PLW_VUTEX_CONTEXT pvutex = &ptcbCur->TCB_vutex;
- pvutex->VUTEX_phyaddrVutex = phyaddr;
+ pvutex->VUTEX_phyaddr = phyaddr;
ppcb = _GetPcb(ptcbCur);
__DEL_FROM_READY_RING(ptcbCur, ppcb); /* 从就绪队列中删除 */
- pvutex->VUTEX_iFlags = iFlags;
- pvutex->VUTEX_iVutexExpect = iExpect;
- pvutex->VUTEX_uiVutexHash = LW_VUTEX_HASH_INDEX(phyaddr);
- pplineHeader = &_k_plineVutexHashHeader[pvutex->VUTEX_uiVutexHash];
- _List_Line_Add_Ahead(&pvutex->VUTEX_lineVutex, pplineHeader); /* 加入等待队列 */
+ pvutex->VUTEX_bWakeAll = LW_FALSE;
+ pvutex->VUTEX_iCompare = iCompare;
+ pvutex->VUTEX_iDesired = iDesired;
+ pvutex->VUTEX_uiHash = LW_VUTEX_HASH_INDEX(phyaddr);
+ _List_Line_Add_Ahead(&pvutex->VUTEX_lineWait, /* 加入等待变量队列 */
+ &_k_plineVutexHashHeader[pvutex->VUTEX_uiHash]);
if (ptcbCur->TCB_ulDelay) {
- __ADD_TO_WAKEUP_LINE(ptcbCur); /* 加入等待扫描链 */
+ __ADD_TO_WAKEUP_LINE(ptcbCur); /* 加入超时扫描链 */
}
}
/*********************************************************************************************************
** 函数名称: _VutexWaitQueue
-** 功能描述: 根据地址和期望数据唤醒目标任务
-** 输 入 : ptcbCur 当前任务
-** phyaddr 物理地址
+** 功能描述: 根据地址和期望数据唤醒目标任务 (进入内核情况被调用)
+** 输 入 : phyaddr 物理地址
** iValue 写入的值
-** iFlags 操作选项
+** iFlags 唤醒选项
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
-VOID _VutexWakeQueue (PLW_CLASS_TCB ptcbCur, phys_addr_t phyaddr, INT32 iValue, INT iFlags)
+INT _VutexWakeQueue (phys_addr_t phyaddr, INT32 iValue, INT iFlags)
{
- UINT32 uiHash = LW_VUTEX_HASH_INDEX(phyaddr);
- BOOL bMatch, bGlobal = iFlags & LW_OPTION_VUTEX_GLOBAL;
- PLW_CLASS_TCB ptcb;
- PLW_CLASS_PCB ppcb;
- PLW_VUTEX_CONTEXT pvutex;
- LW_LIST_LINE_HEADER *pplineHeader;
- PLW_LIST_LINE plineTemp, plineNext;
-
- pplineHeader = &_k_plineVutexHashHeader[uiHash];
- plineTemp = *pplineHeader;
-
- while (plineTemp) {
- plineNext = _list_line_get_next(plineTemp);
-
- pvutex = _LIST_ENTRY(plineTemp, LW_VUTEX_CONTEXT, VUTEX_lineVutex);
- bMatch = LW_FALSE;
-
- if (bGlobal && (pvutex->VUTEX_iFlags & LW_OPTION_VUTEX_GLOBAL)) {
- if ((pvutex->VUTEX_phyaddrVutex == phyaddr) &&
- (pvutex->VUTEX_iVutexExpect == iValue || iValue == __ARCH_INT_MAX)) {
- ptcb = _LIST_ENTRY(pvutex, LW_CLASS_TCB, TCB_vutex);
- bMatch = LW_TRUE; /* 全局匹配 */
- }
+ INTREG iregInterLevel;
+ UINT32 uiHash = LW_VUTEX_HASH_INDEX(phyaddr);
+ INT iWakeCnt = 0;
+ BOOL bMatch;
+ PLW_CLASS_TCB ptcb;
+ PLW_CLASS_PCB ppcb;
+ PLW_VUTEX_CONTEXT pvutex;
+ PLW_LIST_LINE plineTemp;
- } else if (!(pvutex->VUTEX_iFlags & LW_OPTION_VUTEX_GLOBAL)) {
- if ((pvutex->VUTEX_phyaddrVutex == phyaddr) &&
- (pvutex->VUTEX_iVutexExpect == iValue || iValue == __ARCH_INT_MAX)) {
- ptcb = _LIST_ENTRY(pvutex, LW_CLASS_TCB, TCB_vutex);
- if (ptcbCur->TCB_pvVProcessContext == ptcb->TCB_pvVProcessContext) {
- bMatch = LW_TRUE; /* 进程内匹配 */
- }
- }
+ iregInterLevel = KN_INT_DISABLE(); /* 关闭中断 */
+
+ _k_plineVutexOp = _k_plineVutexHashHeader[uiHash];
+ while (_k_plineVutexOp) {
+ plineTemp = _k_plineVutexOp;
+ _k_plineVutexOp = _list_line_get_next(plineTemp); /* 下一个等待节点 */
+
+ pvutex = _LIST_ENTRY(plineTemp, LW_VUTEX_CONTEXT, VUTEX_lineWait);
+ if (pvutex->VUTEX_phyaddr == phyaddr) {
+ bMatch = (iFlags & LW_OPTION_VUTEX_FLAG_WAKEALL)
+ ? LW_TRUE
+ : _VutexWakeIsMatch(iValue, pvutex->VUTEX_iCompare, pvutex->VUTEX_iDesired);
+ } else {
+ bMatch = LW_FALSE;
}
if (bMatch) {
- _List_Line_Del(&pvutex->VUTEX_lineVutex, pplineHeader);
+ _List_Line_Del(&pvutex->VUTEX_lineWait,
+ &_k_plineVutexHashHeader[uiHash]); /* 退出等待变量队列 */
+ pvutex->VUTEX_phyaddr = LW_PHY_ADDR_INVALID; /* 删除等待信息 */
+ pvutex->VUTEX_bWakeAll = (iFlags & LW_OPTION_VUTEX_FLAG_WAKEALL)
+ ? LW_TRUE : LW_FALSE;
+
+ ptcb = _LIST_ENTRY(pvutex, LW_CLASS_TCB, TCB_vutex);
if (ptcb->TCB_usStatus & LW_THREAD_STATUS_DELAY) {
- __DEL_FROM_WAKEUP_LINE(ptcb); /* 退出等待队列 */
+ __DEL_FROM_WAKEUP_LINE(ptcb); /* 退出超时队列 */
ptcb->TCB_ulDelay = 0ul;
}
@@ -121,15 +193,23 @@ VOID _VutexWakeQueue (PLW_CLASS_TCB ptcbCur, phys_addr_t phyaddr, INT32 iVal
} else {
ptcb->TCB_usStatus = (UINT16)(ptcb->TCB_usStatus & ~LW_THREAD_STATUS_VUTEX);
if (__LW_THREAD_IS_READY(ptcb)) { /* 是否就绪 */
- ptcb->TCB_ucSchedActivate = LW_SCHED_ACT_OTHER; /* 调度激活方式 */
+ ptcb->TCB_ucSchedActivate = LW_SCHED_ACT_INTERRUPT; /* 调度激活方式 */
ppcb = _GetPcb(ptcb);
__ADD_TO_READY_RING(ptcb, ppcb); /* 加入到相对优先级就绪环 */
}
}
- }
- plineTemp = plineNext;
+ KN_INT_ENABLE(iregInterLevel); /* 打开中断 */
+
+ iWakeCnt++;
+
+ iregInterLevel = KN_INT_DISABLE(); /* 关闭中断 */
+ }
}
+
+ KN_INT_ENABLE(iregInterLevel); /* 打开中断 */
+
+ return (iWakeCnt);
}
/*********************************************************************************************************
** 函数名称: _VutexInitCtx
@@ -143,12 +223,12 @@ VOID _VutexInitCtx (PLW_CLASS_TCB ptcb)
{
PLW_VUTEX_CONTEXT pvutex = &ptcb->TCB_vutex;
- pvutex->VUTEX_phyaddrVutex = LW_PHY_ADDR_INVALID;
- _LIST_LINE_INIT_IN_CODE(pvutex->VUTEX_lineVutex);
+ pvutex->VUTEX_phyaddr = LW_PHY_ADDR_INVALID;
+ _LIST_LINE_INIT_IN_CODE(pvutex->VUTEX_lineWait);
}
/*********************************************************************************************************
** 函数名称: _VutexUnQueue
-** 功能描述: 将目标任务退出等待队列
+** 功能描述: 将目标任务退出等待队列 (进入内核且关中断情况被调用)
** 输 入 : ptcb 目标任务
** 输 出 : NONE
** 全局变量:
@@ -156,14 +236,17 @@ VOID _VutexInitCtx (PLW_CLASS_TCB ptcb)
*********************************************************************************************************/
VOID _VutexUnQueue (PLW_CLASS_TCB ptcb)
{
- PLW_VUTEX_CONTEXT pvutex = &ptcb->TCB_vutex;
- LW_LIST_LINE_HEADER *pplineHeader;
+ PLW_VUTEX_CONTEXT pvutex = &ptcb->TCB_vutex;
+
+ if (_k_plineVutexOp == &pvutex->VUTEX_lineWait) {
+ _k_plineVutexOp = _list_line_get_next(_k_plineVutexOp); /* 移动至下一个节点 */
+ }
- pplineHeader = &_k_plineVutexHashHeader[pvutex->VUTEX_uiVutexHash];
- _List_Line_Del(&pvutex->VUTEX_lineVutex, pplineHeader);
+ _List_Line_Del(&pvutex->VUTEX_lineWait,
+ &_k_plineVutexHashHeader[pvutex->VUTEX_uiHash]); /* 退出等待变量队列 */
- pvutex->VUTEX_uiVutexHash = 0;
- pvutex->VUTEX_phyaddrVutex = LW_PHY_ADDR_INVALID;
+ pvutex->VUTEX_uiHash = 0;
+ pvutex->VUTEX_phyaddr = LW_PHY_ADDR_INVALID;
}
/*********************************************************************************************************
END
diff --git a/SylixOS/kernel/vutex/vutexLib.h b/SylixOS/kernel/vutex/vutexLib.h
index 9beca42..9e6938d 100644
--- a/SylixOS/kernel/vutex/vutexLib.h
+++ b/SylixOS/kernel/vutex/vutexLib.h
@@ -26,8 +26,10 @@
内部函数
*********************************************************************************************************/
-VOID _VutexWaitQueue(PLW_CLASS_TCB ptcbCur, phys_addr_t phyaddr, INT32 iExpect, INT iFlags);
-VOID _VutexWakeQueue(PLW_CLASS_TCB ptcbCur, phys_addr_t phyaddr, INT32 iValue, INT iFlags);
+BOOL _VutexWakeIsAll(PLW_CLASS_TCB ptcb);
+BOOL _VutexWakeIsMatch(INT iValue, INT iCompare, INT iDesired);
+INT _VutexWakeQueue(phys_addr_t phyaddr, INT32 iValue, INT iFlags);
+VOID _VutexWaitQueue(PLW_CLASS_TCB ptcbCur, phys_addr_t phyaddr, INT32 iDesired, INT iCompare);
#endif /* __VUTEXLIB_H */
/*********************************************************************************************************
diff --git a/SylixOS/posix/fastlock/cond.c b/SylixOS/posix/fastlock/cond.c
new file mode 100644
index 0000000..15a5e57
--- /dev/null
+++ b/SylixOS/posix/fastlock/cond.c
@@ -0,0 +1,3 @@
+/*
+ * This file NOT include in open source version.
+ */
diff --git a/SylixOS/posix/fastlock/fastlock.h b/SylixOS/posix/fastlock/fastlock.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/SylixOS/posix/fastlock/fastlock.h
diff --git a/SylixOS/posix/fastlock/mutex.c b/SylixOS/posix/fastlock/mutex.c
new file mode 100644
index 0000000..15a5e57
--- /dev/null
+++ b/SylixOS/posix/fastlock/mutex.c
@@ -0,0 +1,3 @@
+/*
+ * This file NOT include in open source version.
+ */
diff --git a/SylixOS/posix/fastlock/semaphore.c b/SylixOS/posix/fastlock/semaphore.c
new file mode 100644
index 0000000..15a5e57
--- /dev/null
+++ b/SylixOS/posix/fastlock/semaphore.c
@@ -0,0 +1,3 @@
+/*
+ * This file NOT include in open source version.
+ */