小编Ine*_*ion的帖子

使用std :: atomic和std :: condition_variable,Sync是不可靠的

在用C++ 11编写的分布式作业系统中,我使用以下结构实现了一个fence(即工作线程池外部的线程可能会要求阻塞,直到完成所有当前计划的作业):

struct fence
{
    std::atomic<size_t>                     counter;
    std::mutex                              resume_mutex;
    std::condition_variable                 resume;

    fence(size_t num_threads)
        : counter(num_threads)
    {}
};
Run Code Online (Sandbox Code Playgroud)

实现fence的代码如下所示:

void task_pool::fence_impl(void *arg)
{
    auto f = (fence *)arg;
    if (--f->counter == 0)      // (1)
        // we have zeroed this fence's counter, wake up everyone that waits
        f->resume.notify_all(); // (2)
    else
    {
        unique_lock<mutex> lock(f->resume_mutex);
        f->resume.wait(lock);   // (3)
    }
}
Run Code Online (Sandbox Code Playgroud)

如果线程在一段时间内进入围栏,这种方法非常有效.然而,如果他们几乎同时尝试这样做,似乎有时会发生在原子递减(1)和开始条件var(3)的等待之间,线程产生CPU时间而另一个线程将计数器递减到零( 1)并解雇cond.var(2).这导致前一个线程在(3)中永远等待,因为它已经被通知后开始等待它.

让事情变得可行的黑客就是在(2)之前进行10毫秒的睡眠,但这显然是不可接受的.

有关如何以高效的方式解决这个问题的任何建议?

c++ multithreading stl c++11

11
推荐指数
1
解决办法
2651
查看次数

强制G ++(GCC)到特定的libstdc ++版本(GLIBCXX_*)

我正在尝试使用GCC 4.9.0构建一个向后兼容的二进制文件libstdc++.根据GCC的ABI策略和指南以及控制C++方言的选项,命令行选项-fabi-version应该可以解决问题; 但是,无论我设置哪个版本,我仍然可以从更新的版本导入符号,如下所示:

$ objdump -T binary | grep GLIBCXX_3.4.20
00000000      DF *UND*  00000000  GLIBCXX_3.4.20 _ZSt24__throw_out_of_range_fmtPKcz
Run Code Online (Sandbox Code Playgroud)

我试图-fabi-version=1-fabi-version=5(ABI版本5个对应于GCC 4.6,这是保证是存在于目标系统上),但这些进口保持在所得到的文件卷绕.

我该如何解决?由于其他原因,回到旧的GCC版本不是我的选择.

gcc g++ libstdc++

7
推荐指数
1
解决办法
1437
查看次数

在NASM中声明恒定的64位地址

我需要在自修改程序的代码中声明一个伪绝对地址.此指针的作用类似于链接器的重定位 - 它仅在指令中保留适当的空间,并在运行时稍后使用有效地址进行更新.这在x86-32上对我来说很好用:

movups xmm0, [0xDEADBEEF]
Run Code Online (Sandbox Code Playgroud)

这会在运行时按预期进行组装和工作.但是,当我尝试在x86-64代码中执行此操作时:

movups xmm0, [0xDEADC0DEDEADBEEF]
Run Code Online (Sandbox Code Playgroud)

它汇编了以下警告:

warning: dword data exceeds bounds
Run Code Online (Sandbox Code Playgroud)

并在运行时迅速崩溃,因为下一条指令被地址的其余部分覆盖,这恰好是垃圾指令.

任何超过32位的地址都无法在没有警告的情况下进行汇编,即使是比32位更短的地址:

movups xmm0, [0xADEADBEEF] ; 36-bit address
Run Code Online (Sandbox Code Playgroud)

我应该如何声明一个恒定的,绝对的64位指针?或者是没有办法解决它,我需要在那里删除一个RIP相对的32位指针?

64-bit assembly x86-64 nasm 32bit-64bit

5
推荐指数
1
解决办法
1525
查看次数

从内联汇编访问结构成员?

我正在尝试使用内联汇编将一堆结构成员(Particle是指向此类结构的指针)加载到某些寄存器中。这是我最初的解决方案:

asm("mov    %1(%0), %%edx\n"
    "fld    %2(%0)\n"
    "fld    %3(%0)\n"
    "fld    %4(%0)\n"
    "fld    %5(%0)\n"
    "movups %6(%0), %%xmm1\n"
    "movups %7(%0), %%xmm2\n"
    "movups %8(%0), %%xmm3\n"
    "movups %9(%0), %%xmm4\n"
    :
    : "r" (Particle),
        "n" (offsetof(ptcParticle, Active)),
        "n" (offsetof(ptcParticle, Size)),
        "n" (offsetof(ptcParticle, Rotation)),
        "n" (offsetof(ptcParticle, Time)),
        "n" (offsetof(ptcParticle, TimeScale)),
        "n" (offsetof(ptcParticle, Colour)),
        "n" (offsetof(ptcParticle, Location)),
        "n" (offsetof(ptcParticle, Velocity)),
        "n" (offsetof(ptcParticle, Accel))
    : "%edx", "%st", "%st(1)", "%st(2)", "%st(3)", "%xmm1", "%xmm2",
        "%xmm3", "%xmm4"
);
Run Code Online (Sandbox Code Playgroud)

但它不起作用,因为 GCC 将这些偏移量输出为立即数字文字,如下所示:

mov     $0(%eax), %edx
fld     $44(%eax)
fld     $40(%eax)
fld     $8(%eax) …
Run Code Online (Sandbox Code Playgroud)

gcc gnu-assembler inline-assembly

5
推荐指数
1
解决办法
2597
查看次数