在 Linux 中存在系统调用之前futex,线程库使用哪些底层系统调用来pthreads阻塞/休眠线程并随后从用户空间唤醒这些线程?
例如,如果一个线程尝试获取互斥锁,用户态实现将阻止该线程(可能在很短的旋转间隔之后),但我找不到用于此目的的系统调用(除了相对较新的创建的系统调用之外futex) )。
也许这只是我,但man 2页面中的例子membarrier似乎毫无意义.
基本上,membarrier()是一个异步内存屏障,给定两个协调的代码段(让我们调用然后快速路径和慢速路径)允许您将屏障的所有硬件成本移动到慢速路径,并且只保留快速路径编译屏障1.有几种不同的方法可以完成这种membarrier行为,例如向每个涉及的处理器发送IPI或等待每个处理器上运行的代码被取消调度 - 但具体的实现细节在这里并不重要.
现在,这是手册页中给出的示例转换:
static volatile int a, b;
static void
fast_path(void)
{
int read_a, read_b;
read_b = b;
asm volatile ("mfence" : : : "memory");
read_a = a;
/* read_b == 1 implies read_a == 1. */
if (read_b == 1 && read_a == 0)
abort();
}
static void
slow_path(void)
{
a = 1;
asm volatile …Run Code Online (Sandbox Code Playgroud) 从最新消息来看,新的苹果处理器A11 Bionic在Geekbench基准测试中比移动英特尔酷睿i7得分更高。
据我了解,该基准测试中有很多不同的测试。这些测试模拟了不同的负载,包括日常使用中可能发生的负载。
有人指出,这些结果无法与x86结果进行比较。他们说x86能够执行“更复杂的任务”。例如,他们领导Photoshop,视频转换,科学计算。我同意ARM的软件通常只是台式机软件的“轻量级”版本。但是在我看来,这种限制是由移动操作系统的格式(移动中完成工作,没有鼠标等)引起的,而不是由ARM的性能引起的。
作为相反的示例,让我们看一下Safari。浏览器是一个复杂的程序。Safari在iPad上的工作原理与Mac一样。此外,如果我们采用Sunspider(JS基准测试)的结果,事实证明iPad上的Safari得分更高。
我认为在日常任务(Web,Office,音乐/电影)中,ARM(A10X,A11)和x86(双核移动英特尔i7)的性能是可比的和相等的。
ARM真的有远远落后于x86的任何类型的任务吗?如果是这样,原因是什么?是什么阻止了Apple在ARM上发布笔记本电脑?从POWER迁移到x86,他们已经做了同样的事情。这是技术限制,还是营销?
我相信这是一个常见问题,但有些谷歌搜索不会返回匹配项,因此请在这里询问。
所以我有以下课程:
class A {
public:
A(const A &rhs) { m_a = rhs.m_a; }
private:
int m_a;
};
Run Code Online (Sandbox Code Playgroud)
一切都很酷,直到一段时间后,可能是一年后,我添加了一个新属性m_bto class A,但我忘记更新复制构造函数。
需要进行痛苦的调试才能找到不同步的位置。
有没有办法避免这样的问题,最好是在构建时?
是的,我可以编写单元测试来覆盖该复制构造函数,但是当我忘记更新复制构造函数时,很可能我也忘记了该单元测试。
我正在编写C,C++和汇编的混合编程,我希望从代码的任何部分获得可靠的回溯.
这主要工作正常的C和C++代码,因为我可以生成调试与信息-g,这对于现代的x86编译器和平台生成DWARF调试信息,这意味着最终的二进制包括CFI(调用帧信息).此信息允许通过当前调用堆栈中的函数向后移动.它可以支持复杂的场景,例如没有基指针的函数以及rsp动态方式的变化.对于C和C++代码,我不必关心:即使对于优化的代码,编译器也会生成正确的CFI.
对于我在nasm中编写的x86汇编代码,CFI是个问题.nasm和语法兼容的竞争对手yasm对生成DWARF信息有一些有限的支持,但它主要涉及指向行映射的指令指针,并且不包括任何CFI 1(实际上,即使它集合也无法真正生成它因为程序集太低而无法明确表达调用/返回语义,所以需要.
我想为程序集生成的例程添加CFI,但我不需要CFI的完全灵活性来根据指令细化更改识别CFA rsp等等:我非常乐意设置标准框架-pointer in rbpfor each assembly function并保持整个函数的完整性.DWARF3是否通过一小段CFI信息支持这种情况,希望我能用汇编器宏生成一个?
1 yasm 的实验性"nextgen" 版本确实支持CFI指令,但该项目尚未在5年内更新.有一个未解决的问题是将此支持移回yasm的主线版本.
GCC 支持-march允许您指定目标架构的开关 - 允许它调整该平台的指令序列以及使用该平台上可能可用但在“默认”或基本版本上不可用的指令架构。
例如,-march=skylake将告诉编译器以 Skylake CPU 为目标,包括使用 Skylake 上可用的指令集,例如 AVX2。
如何判断-march本地版本gcc支持的值?当传递无效参数时,较新版本有助于列出有效参数,但较旧版本不会。
当不存在这样的重载时,是否允许重载运算符,例如operator+标准库类型和内置类型的组合?
例如,在默认命名空间或用户定义的命名空间中实现以下运算符是否合法:
std::string operator+(const std::string& s, int right) { ... }
Run Code Online (Sandbox Code Playgroud)
我知道在命名空间中实现事物有各种限制std::,但我不清楚是否有任何规则违反上述规定(当然这是否是一个好主意是完全不同的事情!)。
我的gcc版本(5.4)警告未使用的static函数,即使在使用时的头文件中-Wall也是如此.如果定义相同的功能static inline或简单,它不会抱怨inline.
例如,文件中的以下函数unused.h:
static void foo() {}
Run Code Online (Sandbox Code Playgroud)
...当包含在test.cpp文件中时如下:
#include "unused.h"
Run Code Online (Sandbox Code Playgroud)
编译时使用以下命令生成以下编译器诊断-Wall:
In file included from test.cpp:11:0:
unused.h: At global scope:
unused.h:9:13: warning: ‘void foo()’ defined but not used [-Wunused-function]
static void foo() {}
^
Run Code Online (Sandbox Code Playgroud)
据我所知,通常的做法是包含具有许多实用程序功能的标头,在任何给定的源文件中只能使用少数几个.这种行为意味着我得到了我不使用的任何仅声明的函数的警告static.
作为一个实际问题,我可以简单地改变这些以static inline消除警告(或完全关闭特定警告,但我确实发现它不时有用),但似乎大型实用功能不会从中受益内联1更逻辑地声明为static2.
据我所知,在编译翻译单元时,gcc会简单地删除未使用的static函数(就像static inline),因此它们根本不会产生二进制大小或链接时间开销.
我在这里错过了什么吗?是否有充分的理由认为未使用的static功能比问题更多static inline?
1是的,我知道这只是一个暗示,但gcc在很多情况下实际上都是暗示.
2或者更好,只在头文件中声明并在文件中的其他位置定义 …
在Intel x86上,Linux使用事件l1d.replacements来实现其事件。L1-dcache-load-misses事件。
此事件的定义如下:
计算L1D数据线的替换量,包括机会性替换,以及需要停顿替换的替换或需要替换块的替换。
也许天真地,我希望perf使用像这样的东西mem_load_retired.l1_miss,它支持PEBS,并且定义为:
用至少一个在L1高速缓存中未命中的uop计数退休的加载指令。(支持PEBS)
事件值通常不是非常接近,有时会发生巨大变化。例如:
$ocperf stat -e mem_inst_retired.all_loads,l1d.replacement,mem_load_retired.l1_hit,mem_load_retired.l1_miss,mem_load_retired_fb_hit head -c100M /dev/urandom > /dev/null
Performance counter stats for 'head -c100M /dev/urandom':
445,662,315 mem_inst_retired_all_loads
92,968 l1d_replacement
443,864,439 mem_load_retired_l1_hit
1,694,671 mem_load_retired_l1_miss
28,080 mem_load_retired_fb_hit
Run Code Online (Sandbox Code Playgroud)
与相比,“ L1未命中”的数量多于17 倍。相反,您也可以找到比计数器高得多的示例。mem_load_retired.l1_missl1d.replacementl1d.replacementmem_load_retired
到底在l1d.replacement测量什么,为什么要在内核中选择它,并且它比L1 d缓存未命中更好的代理mem_load_retired.l1_miss?