问题标签 [futex]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
93 浏览

gdb - 使用 gdb 检索地址的信息

在 Java 应用程序上运行 strace 后,我注意到系统调用很长时间(主要是 futex)。

我真的很想了解对 futex 的等待是针对这里的哪些共享资源。

但是,我不确定如何?

我做了一些谷歌搜索,发现 GDB 有助于找到上述原因。但不幸的是,我对 GDB 不太了解,因为我以前几乎没有使用过它。

有些人可以帮助我了解如何找到我正在寻找的答案。

0 投票
0 回答
984 浏览

c++ - sem_timedwait 导致“futex 工具返回了意外的错误代码”

这段代码有什么问题?当 sem 对象发布时,它很好。但是,一旦需要等待超时,我就会收到“futex 工具返回了意外的错误代码”。

0 投票
2 回答
229 浏览

linux - futex_wake 怎么会返回 0

我使用 futex 实现了信号量。以下程序经常在 sem_post() 中的断言处失败。虽然返回值应该是 1,但它有时会返回 0。这怎么会发生?

当我使用 POSIX 信号量时,程序总是成功完成。

我正在使用 Linux 2.6.32-642.6.1.el6.x86_64

0 投票
2 回答
654 浏览

linux - Intel-64 和 ia32 原子操作获取-释放语义和 GCC 5+

我正在研究我的 Haswell CPU(4/8 核 2.3-3.9ghz i7-4790M)上的 Intel CPU atomic features,并且发现很难构建例如。可靠的 mutex_lock() 和 mutex_unlock() 操作,例如 GCC 手册所建议的:

6.53 x86 特定于事务内存的内存模型扩展

x86 架构支持额外的内存排序标志来标记硬件锁省略的锁临界区。除了原子内在函数的现有内存模型之外,还必须指定这些。

当锁获取失败时,需要良好的性能来快速中止事务。这可以通过“_mm_pause”来完成

因此,阅读英特尔软件开发人员手册第 3 卷第 8.1 节“锁定原子操作”,特别是第 8.1.4 节“锁定操作对内部处理器缓存的影响”后,我实现了我的测试 mutex_lock() mutex_unlock () 起初喜欢:

... static inline attribute((always_inline,const)) bool ia64_has_clflush(void) { register unsigned int ebx=0; asm volatile ( "MOV $7, %%eax\n\t" "MOV $0, %%ecx\n\t" "CPUID\n\t" "MOV %%ebx, %0\n\t" : "=r" (ebx) : : "%eax", "%ecx", "%ebx" ); return ((ebx & (1U<<23)) ? true : false); }

现在,有趣的是,关键的 mutex_lock() 减法和 mutex_unlock() 加法操作最终成为指令:

互斥锁:

互斥锁:

但是这个实现似乎需要 LFENCE / SFENCE 可靠地运行(CLFLUSHOPT 是不够的),否则两个线程可能最终在 futex() 中死锁,锁定值相同 -1 。

从阅读英特尔文档中我看不到两个线程进入指令序列是如何发生的:

如果 *lck 为 0 ,则两者都可以在 *lck 中得到结果 '-1' ;肯定一个线程必须得到 -1 而另一个线程必须得到 -2 吗?

但 strace 说不:

这是僵局的情况。我哪里做错了 ?

请那里的任何英特尔 CPU 锁定和缓存专家解释如何在同一未缓存位置 *lck 的两个原子减量或增量都断言 #LOCK 总线信号(独占总线访问)和 XACQUIRE 最终会在 *lck 中得到相同的结果?

我认为这就是#LOCK 前缀(和 HLE)的目的?我已经尝试不使用 HLE 并且只使用 __ATOMIC_SEQ_CST 进行所有访问(这只是添加了 LOCK 前缀,而不是 XACQUIRE)但它没有区别 - 没有 {L,S}FENCE-es 仍然会导致死锁。

我已经阅读了 Ulrich Drepper 的优秀论文 [Futexes are Tricky]:http ://www.akkadia.org/drepper/futex.pdf ,但他提出了一个仅将硬编码常量写入锁定内存的互斥锁实现。我明白为什么了。很难让互斥锁在服务员计数或对锁定值上进行的任何算术运算中可靠地工作。有没有人找到方法来做可靠的锁定算法,使得结果适合 x86_64 Linux 上的锁定/信号量值?最有兴趣讨论它们...

因此,在调查了 HLE 和 CLFLUSH 的一些死胡同之后,我能够到达的唯一工作版本的锁定/解锁使用硬编码常量和 __atomic_compare_exchange_n - 测试程序的完整源代码,它增加了一个计数器(没有锁定) 直到收到 + / 退出信号,位于:

工作示例:intel_lock3.c

[]:https ://drive.google.com/open?id=1ElB0qmwcDMxy9NBYkSXVxljj5djITYxa

使用算术破解的版本:

https://drive.google.com/open?id=10yLrohdKLZT4p3G1icFHdjF5eHY68Yws

编译例如:

它不应该打印“被锁定!” 并且在几秒钟内应该超过了@ 5e8 : 5x10^8 的计数,而不是 446。

使用 strace 运行显示有两个线程正在阻塞等待 -1 的锁定值变为 0 :

$

通常, WAIT 应该在 WAKE 之前安排,但不知何故 GCC 将内存排序语义解释为意味着 WAKE 总是在任何 WAIT 之前被安排;但即使发生这种情况,代码也应该会被延迟,并且永远不会导致两个线程在进入 futex(...FUTEX_WAIT..) 时获得 -1 lck 值。

当两个线程都获得 (-1,-1) 时,几乎相同的算法在锁定值上使用算术总是死锁 - 请注意,任何线程都不会看到 -2 值:

所以,我认为如果算术运算按预期工作,即。被序列化和原子化,那么上面的代码就不会死锁;算术应该生成与工作示例中使用的 LockStatus 枚举值相同的数字。

但是算术出了点问题,现在产生了指令:

互斥锁:

互斥锁:

代码本身没有插入栅栏,但每个 __atomic_store_n(ua,...) 都会生成一个 .

AFAICS,没有导致两个线程获得相同 -1 值的代码的有效时间表。

所以我的结论是,在算术指令上使用 intel LOCK 前缀是不安全的,并且会在用户模式 ​​Linux x86_64 gcc 编译程序中引入错误行为 - 仅将常量值从文本内存写入数据内存是原子的,并且在 Intel Haswell i7 上按顺序排序-4790M 具有 gcc 和 Linux 的平台,并且这些平台上的算术不能通过使用 HLE / XACQUIRE、锁定前缀或 FENCE 指令的任何组合来进行原子和顺序排序。

我的预感是分支预测以某种方式失败并添加了额外的算术运算/无法在此平台上执行算术运算,并在不同的物理内核上声明了 LOCK 前缀和多个线程。因此,所有带有 LOCK 前缀的算术运算都是可疑的,应该避免。

0 投票
1 回答
2257 浏览

linux - 测试和设置(或其他原子 RMW 操作)是任何架构上的特权指令吗?

硬件提供原子指令,如测试和设置、比较和交换、加载链接存储条件。这些是特权指令吗?也就是说,只有操作系统才能执行它们(因此需要系统调用)?

我认为他们没有特权,可以在用户空间中调用。但http://faculty.salina.k-state.edu/tim/ossg/IPC_sync/ts.html似乎另有建议。但是,futex(7)在某些条件下,可以在没有系统调用的情况下实现锁定,这意味着它必须在没有特权的情况下执行指令(如 test-and-set)。

矛盾?如果是这样,哪个是对的?

0 投票
2 回答
2796 浏览

c - 如何找到导致 futex 设施失败的原因?

我正在尝试同步 5 个进程,它们必须由同一个父亲创建。

我尝试插入 5 个 waitpid 来等待子进程结束,但代码永远不会到达 D4 和 D5。

我希望 D4 在 D1 和 D2 之后显示,D5 最后显示(D3 独立于 D1、D2、D4)。但是我的代码永远不会到达 D4,因为 futex 工具返回了一个意外错误。

输出:

0 投票
1 回答
430 浏览

c++ - futex 等待/唤醒对是否实现获取/释放语义?

给定这个伪代码,其中全局有一个原子 inta初始化为 0:

线程 1:

线程 2:

忽略虚假唤醒的可能性;我们可以从上面的代码中推断出代码X同步Y吗?基本上,它归结为 futex 本身是否意味着在唤醒的等待中实现获取/释放语义。


一点上下文:TSAN 不理解 futex 系统调用(例如,请参见此处此处)。

现在,通常,当使用 futex 来实现互斥锁、信号量或其他同步原语时,还有一个原子变量,它通过“锁定”端加载获取排序,并通过“解锁”存储在释放排序中边。(上面,我故意使用宽松的语义。)

该获取/释放足以实现同步,形式上是正确的,并且它被 TSAN 识别(它不会报告任何以这种方式实现的锁,例如 Qt 中的 QBasicMutex)。

这个问题主要是关于上面链接的论坛帖子中提供的建议,用获取/释放语义标记 futex 操作本身。这样的标记是否正确?

(我知道 C++ 抽象机对 . 一无所知futex。它甚至对 pthreads 一无所知,但 TSAN 知道,并且知道例如发生在 apthread_create之前的代码也发生在新创建的线程中运行的代码之前。在其他话说,这不是语言律师的问题……)

0 投票
0 回答
452 浏览

c - 唤醒线程池线程的最快方法

我编写了一个线程池,其中包含尽可能多的线程(备用内核),以避免上下文切换。每当需要执行一个新任务时,该任务就会被添加到一个无锁环形缓冲区中,以供线程池的线程使用。每次添加新任务时,我当前都会调用sem_post

我的基准测试表明,sem_post当有线程等待信号量时,调用需要 10 微秒。有些调用只需要 50 ns(这可能意味着完全在用户空间中可以确定没有线程可以被唤醒),但 350 +/- 30 纳秒也是一个常见的值。

这个问题是关于一个或多个线程无事可做并正在等待信号量的情况。

在那种情况下,调用者(试图唤醒一个新线程)在sem_post.

没有更快的方法(从调用者的角度来看)唤醒睡眠线程吗?我可以忍受 10 微秒的延迟,直到新线程最终开始运行,但是唤醒的线程不应该延迟太多。

我能找到的相关问题(但不回答我的问题)是

请注意,信号量似乎是在 futex 之上实现的。我认为 futex 是 Linux 上最快的方法吗?也许使用信号或中断更快?

0 投票
1 回答
94 浏览

c - futex 手册页演示结果不正确

futex 手册页提供了一个简单的 演示,但我无法得到页面描述的结果,结果似乎是我的机器上的死锁(linux 5.2.1);父进程不会被其子进程唤醒。手册页错了吗?

我的机器上的输出示例:

我的系统:

0 投票
0 回答
1448 浏览

android - app进程在art::ConditionVariable::WaitHoldingLocks被阻塞,如何查找原因?

在 Android 8.0 上,使用 kotlin 和 kotlin 协程开发。应用程序中的所有线程都将被阻止。我曾使用 strace、gdbserver 进行分析以检查系统调用并获取堆。这样的堆:来自gdb的第一个线程的堆

或来自 gdb 的第二个线程的堆

或来自 gdb 的第三个线程的堆

这三个堆来自不同的线程。现在我的应用程序进程被阻止了。我该如何分析原因?