更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_futex_pri.h
浏览该文件的文档.
1/*!
2 * @file los_futex_pri.h
3 * @brief
4 * @link
5 @verbatim
6 FUTEX_WAIT
7 这个操作用来检测有uaddr指向的futex是否包含关心的数值val,如果是,则继续sleep直到FUTEX_WAKE操作触发。
8 加载futex的操作是原子的。这个加载,从比较关心的数值,到开始sleep,都是原子的,与另外一个对于同一个
9 futex的操作是线性的,串行的,严格按照顺序来执行的。如果线程开始sleep,就表示有一个waiter在futex上。
10 如果futex的值不匹配,回调直接返回失败,错误代码是EAGAIN。
11
12 与期望值对比的目的是为了防止丢失唤醒的操作。如果另一个线程在基于前面的数值阻塞调用之后,修改了这个值,
13 另一个线程在数值改变之后,调用FUTEX_WAIT之前执行了FUTEX_WAKE操作,这个调用的线程就会观察到数值变换并且无法唤醒。
14 这里的意思是,调用FUTEX_WAIT需要做上面的一个操作,就是检测一下这个值是不是我们需要的,如果不是就等待,
15 如果是就直接运行下去。之所以检测是为了避免丢失唤醒,也就是防止一直等待下去,比如我们在调用FUTEX_WAIT之前,
16 另一个线程已经调用了FUTEX_WAKE,那么就不会有线程调用FUTEX_WAKE,调用FUTEX_WAIT的线程就永远等不到信号了,也就永远唤醒不了了。
17
18 如果timeout不是NULL,就表示指向了一个特定的超时时钟。这个超时间隔使用系统时钟的颗粒度四舍五入,
19 可以保证触发不会比定时的时间早。默认情况通过CLOCK_MONOTONIC测量,但是从Linux 4.5开始,可以在futex_op中设置
20 FUTEX_CLOCK_REALTIME使用CLOCK_REALTIME测量。如果timeout是NULL,将会永远阻塞。
21
22 注意:对于FUTEX_WAIT,timeout是一个关联的值。与其他的futex设置不同,timeout被认为是一个绝对值。
23 使用通过FUTEX_BITSET_MATCH_ANY特殊定义的val3传入FUTEX_WAIT_BITSET可以获得附带timeout的FUTEX_WAIT的值。
24 @endverbatim
25 * @version
26 * @author weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
27 * @date 2021-11-24
28 */
29/*
30 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
31 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without modification,
34 * are permitted provided that the following conditions are met:
35 *
36 * 1. Redistributions of source code must retain the above copyright notice, this list of
37 * conditions and the following disclaimer.
38 *
39 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
40 * of conditions and the following disclaimer in the documentation and/or other materials
41 * provided with the distribution.
42 *
43 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
44 * to endorse or promote products derived from this software without specific prior written
45 * permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
48 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
49 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
50 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
51 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
52 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
53 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
54 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
55 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
56 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
57 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 */
59
60#ifndef _LOS_FUTEX_PRI_H
61#define _LOS_FUTEX_PRI_H
62#include "los_list.h"
63
64#define FUTEX_WAIT 0 ///< 原子性的检查 uaddr 中计数器的值是否为 val,如果是则让任务休眠,直到 FUTEX_WAKE 或者超时(time-out)。
65 //也就是把任务挂到 uaddr 相对应的等待队列上去。
66#define FUTEX_WAKE 1 ///< 最多唤醒 val 个等待在 uaddr 上任务。
67#define FUTEX_REQUEUE 3 ///< 调整指定锁在Futex表中的位置
68#define FUTEX_WAKE_OP 5
69#define FUTEX_LOCK_PI 6
70#define FUTEX_UNLOCK_PI 7
71#define FUTEX_TRYLOCK_PI 8
72#define FUTEX_WAIT_BITSET 9
73
74#define FUTEX_PRIVATE 128 //私有快锁(以虚拟地址进行哈希)
75#define FUTEX_MASK 0x3U
76/// 每个futex node对应一个被挂起的task ,key值唯一标识一把用户态锁,具有相同key值的node被queue_list串联起来表示被同一把锁阻塞的task队列。
77typedef struct {
78 UINTPTR key; /* private:uvaddr | 私有锁,用虚拟地址 shared:paddr | 共享锁,用物理地址*/
79 UINT32 index; /* hash bucket index | 哈希桶索引 OsFutexKeyToIndex */
80 UINT32 pid; /* private:process id shared:OS_INVALID(-1) | 私有锁:进程ID , 共享锁为 -1 */
81 LOS_DL_LIST pendList; /* point to pendList in TCB struct | 指向 TCB 结构中的 pendList, 通过它找到任务*/
82 LOS_DL_LIST queueList; /* thread list blocked by this lock | 挂等待这把锁的任务,其实这里挂到是FutexNode.queueList ,
83 通过 queueList 可以找到 pendList ,通过 pendList又可以找到真正的任务*/
84 LOS_DL_LIST futexList; /* point to the next FutexNode | 下一把Futex锁*/
85} FutexNode;
86
87extern UINT32 OsFutexInit(VOID);
88extern VOID OsFutexNodeDeleteFromFutexHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags);
89extern INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber);
90extern INT32 OsFutexWait(const UINT32 *userVaddr, UINT32 flags, UINT32 val, UINT32 absTime);
91extern INT32 OsFutexRequeue(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber,
92 INT32 count, const UINT32 *newUserVaddr);
93#endif
VOID OsFutexNodeDeleteFromFutexHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags)
从哈希桶上删除快锁
Definition: los_futex.c:302
INT32 OsFutexWait(const UINT32 *userVaddr, UINT32 flags, UINT32 val, UINT32 absTime)
设置线程等待 | 向Futex表中插入代表被阻塞的线程的node
Definition: los_futex.c:693
UINT32 OsFutexInit(VOID)
Definition: los_futex.c:144
INT32 OsFutexRequeue(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber, INT32 count, const UINT32 *newUserVaddr)
调整指定锁在Futex表中的位置
Definition: los_futex.c:1022
INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber)
唤醒一个被指定锁阻塞的线程
Definition: los_futex.c:815
双向链表由内联函数实现 http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-small-apx-dll....
signed int INT32
Definition: los_typedef.h:60
unsigned long UINTPTR
Definition: los_typedef.h:68
unsigned int UINT32
Definition: los_typedef.h:57
size_t BOOL
Definition: los_typedef.h:88
每个futex node对应一个被挂起的task ,key值唯一标识一把用户态锁,具有相同key值的node被queue_list串联起来表示被同一把锁阻塞的task队列。
Definition: los_futex_pri.h:77
LOS_DL_LIST queueList
Definition: los_futex_pri.h:82
UINTPTR key
Definition: los_futex_pri.h:78
UINT32 index
Definition: los_futex_pri.h:79
LOS_DL_LIST futexList
Definition: los_futex_pri.h:84
UINT32 pid
Definition: los_futex_pri.h:80
LOS_DL_LIST pendList
Definition: los_futex_pri.h:81