等待变量锁 (vutex)

更新时间:
2024-05-29
下载文档

等待变量锁 (vutex)

SylixOS 引入了与 Linux futex 类似的用户快速锁 vutex(vitual user mutex)(SylixOS 习惯称为“等待变量锁”);vutex 包括两个操作:pend 和 post,pend 操作用于等待期望值得到满足,post 操作用于设置期望值,并唤醒等待的线程。

vutex 通过一个变量地址(整形变量)管理线程间的“锁”,该变量地址为用户空间地址,因此在同一个进程中,vutex 的 pend 与 post 操作使用同一个虚拟地址(内核通过该虚拟地址对应的物理地址进行期望值的管理);在两个不同的进程之间,则需要建立一个共享内存,实现使用同一个物理地址的目的。

vutex pend 操作

vutex pend 用于线程/进程等待一个期望的值,pend 操作可以设置线程/进程的等待方式(等待指定的时间、永久等待、不等待),如果等待方式设置为等待指定的时间(单位为 TICK),当时间超时后,期望的值仍然未满足,则 pend 函数返回错误并设置错误号(ERROR_THREAD_WAIT_TIMEOUT);如果等待方式为永久等待,则等待线程的期望值未满足之前将永远陷入等待,直到期望值满足或线程被删除;特殊地,如果等待方式设置为不等待,则 pend 函数仅尝试一次查询期望值,如果期望值不满足,pend 函数返回错误并设置错误号(ERROR_THREAD_WAIT_TIMEOUT)。

vutex pend 接口详细描述如下:

#include <SylixOS.h>
INT  Lw_Vutex_Pend(INT  *piVar, INT  iDesired, ULONG  ulTimeout)
INT  Lw_Vutex_PendEx(INT  *piVar, INT  iCompare, INT  iDesired, ULONG  ulTimeout)

函数原型分析:

  • 函数成功返回 0,失败返回-1 并设置错误号。
  • 参数 piVar 是变量地址。
  • 参数 iCompare 是比较方法,如下表所示。
  • 参数 iDesired 是期待的值。
  • 参数 ulTimeout 是等待的超时时间(单位为 TICK)。

参数 iCompare 指定了设置值与期望值得比较策略,这些比较策略拓宽了 pend 函数的使用场景,例如 GREATER_EQU 策略,允许在设置值大于期望值得时候满足条件,而不仅仅是必须等于期望值。

vutex 比较方法说明
LW_OPTION_VUTEX_EQU设置值与期望值相同
LW_OPTION_VUTEX_NOT_EQU设置值与期望值不相同
LW_OPTION_VUTEX_LESS设置值小于期望值
LW_OPTION_VUTEX_LESS_EQU设置值小于等于期望值
LW_OPTION_VUTEX_GREATER设置值大于期望值
LW_OPTION_VUTEX_GREATER_EQU设置值大于等于期望值
LW_OPTION_VUTEX_AND设置值完全包含期望值
LW_OPTION_VUTEX_NOT设置值不包含期望值
LW_OPTION_VUTEX_OR设置值部分包含期望值

vutex post 操作

vutex post 是 vutex pend 的反操作,post 将满足期望的值设置到变量地址(参数 piVar 指定的地址),post 设置完期望值后会唤醒被阻塞的线程,根据不同的使用场景,post 包括以下三种设置方式:

  • 全部唤醒并阻塞的线程。
  • 仅唤醒被阻塞的线程不设置期望值。
  • 深度唤醒(设置期望值并唤醒单个线程)。
#include <SylixOS.h>
INT  Lw_Vutex_Post(INT  *piVar, INT  iValue)
INT  Lw_Vutex_PostEx(INT  *piVar, INT  iValue, INT  iFlags)

函数原型分析:

  • 函数成功返回 0,失败返回-1 并设置错误号。
  • 参数 piVar 是变量地址。
  • 参数 iValue 是要设置的值。
  • 参数 iFlags 是 vutex 标志,如下表所示。
vutex 标志说明
LW_OPTION_VUTEX_FLAG_WAKEALL全部唤醒
LW_OPTION_VUTEX_FLAG_DONTSET不设置变量值
LW_OPTION_VUTEX_FLAG_DEEPWAKEPost 不进行相同值检查优化

下面程序展示了 vutex 在两个线程间实现的同步作用。

#include <SylixOS.h>
#include <pthread.h>

static  int  *pvar = NULL;

static void *t_vpend (void *arg)
{
    int  ret;

    printf("vutex start pend, expect value == 1\n");
    ret = API_VutexPend(pvar, 1, LW_OPTION_WAIT_INFINITE);
    printf("vutex pend return: %d\n", ret);
    return (NULL);
}

static void *t_vpost (void *arg)
{
    sleep(1);
    printf("vutex post expect 1\n");
    API_VutexPost(pvar, 1);
    return  (NULL);
}

int main (int argc, char **argv)
{
    pthread_t   tid0, tid1;

    pthread_create(&tid0, NULL, t_vpend, NULL);
    pthread_create(&tid1, NULL, t_vpost, NULL);
    pthread_join(tid0, NULL);
    pthread_join(tid1, NULL);
    return  (0);
}

在 SylixOS Shell 下运行程序:

# ./vutex_use
vutex start pend, expect value == 1
vutex post expect 1
vutex pend return: 0
文档内容是否对您有所帮助?
有帮助
没帮助