【问题标题】:std::mutex::lock() produces weird (and unnecessary) asm codestd::mutex::lock() 产生奇怪的(和不必要的)asm 代码
【发布时间】:2020-03-29 16:40:33
【问题描述】:

我正在为我的一些代码检查生成的 asm,我注意到了一些 interesting stuff:

#include <mutex>

std::mutex m;

void foo()
{
    m.lock();
}

生成的 asm 代码(x86-64 gcc 9.2,-std=c++11 -O2):

foo():
        mov     eax, OFFSET FLAT:_ZL28__gthrw___pthread_key_createPjPFvPvE
        test    rax, rax
        je      .L10                  // (1) we can simply bypass lock() call?
        sub     rsp, 8
        mov     edi, OFFSET FLAT:m
        call    __gthrw_pthread_mutex_lock(pthread_mutex_t*)
        test    eax, eax
        jne     .L14                  // (2) waste of space that will never be executed
        add     rsp, 8
        ret
.L10:
        ret
.L14:
        mov     edi, eax
        call    std::__throw_system_error(int)
m:
        .zero   40

问题:

  • 第 (1) 部分 -- gcc 特定:
    • 它在做什么? (分配 TLS 条目?)
    • 该操作失败如何让我们静默绕过lock() 呼叫?
  • 第 (2) 部分——看起来每个编译器都受到了影响:
    • std::mutex::lock()can throw按标准
    • ...但它永远不会使用正确的代码(如相关 SO 帖子中所述),出于所有意图和目的,std::mutex::lock() 始终是正确代码中的noexcept
    • 是否可以让编译器知道,以便它停止发出不必要的测试和指令块(如上面的.L14)?

注意:我看不出std::mutex::lock() 的投掷比简单的abort()ing 更好。在这两种情况下,您的程序都被搞砸了(没有人期望它会失败),但至少在后一种情况下,您最终得到的 asm 代码要小得多(“只为您使用的东西付费”,记得吗?)。

【问题讨论】:

标签: c++ c++11 gcc


【解决方案1】:

您似乎误解了 asm 输出。你看到的不是 foo 的代码,而是 mutex::lock 的内联代码。

来自https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/mutex

void lock() // in class mutex
{
    int __e = __gthread_recursive_mutex_lock(&_M_mutex);

    // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
    if (__e)
        __throw_system_error(__e);
}

来自https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.0/gthr-default_8h-source.html

static inline int __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
{
    return __gthread_mutex_lock (mutex);
}

static inline int __gthread_mutex_lock (__gthread_mutex_t *mutex)
{
    if (__gthread_active_p ())
        return pthread_mutex_lock (mutex);
    else
        return 0;
}

名称与您的 asm 代码不完全匹配,因此我可能查看了不同的 libstdc++ 源代码,但对我来说,编译器似乎将 mutex::lock 内联到您的函数 foo 中,并且它还内联了 @987654328 的函数@正在打电话。

【讨论】:

  • 有道理...谢谢。
猜你喜欢
  • 1970-01-01
  • 2017-03-28
  • 2015-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-11
  • 2021-09-20
相关资源
最近更新 更多