编译时间障碍 - 编译器代码重新排序 - gcc和pthreads [英] Compile time barriers - compiler code reordering - gcc and pthreads

查看:222
本文介绍了编译时间障碍 - 编译器代码重新排序 - gcc和pthreads的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

AFAIK有pthread函数作为内存屏障(例如,这里澄清-上全存储器屏障参与的逐并行线程-互斥)。但编译时障碍,即编译器(特别是gcc)是否意识到这一点?

换句话说 - 例如 - 是pthread_create()gcc不执行重新排序的原因?



例如在代码中:

  a = 1; 
pthread_create(...);

确定重新排序不会发生?

如何调用不同的功能:

  void fun(void){
pthread_create(...);
...
}

a = 1;
fun();

fun()也编译时间障碍(假设pthread_create()是)?

在不同翻译单元中的函数怎么样?



请注意,我对一般的gcc和pthreads行为规范感兴趣,不一定是x86特定的(各种不同的嵌入式平台焦点)。
我也对其他编译器/线程库行为不感兴趣。 解决方案

例如 pthread_create()是外部函数,编译器必须确保必须完成外部函数可以看到的任何副作用(例如写入全局变量)在调用函数之前。假设 a 是全局的,则编译无法将写入操作重新排序至 a ,直到第一种情况下的函数调用之后)或其他可能的外部访问)。

这是任何C编译器所必需的行为,并且与线程无关。



然而,如果变量 a 是一个局部变量,编译器可能会重新排序它直到函数调用( a 可能根本就不会在内存中结束),除非像 a 的地址被获取并且以某种方式在外部可用(如将它作为线程参数传递)。



例如:

  int a; 

void foo(void)
{
a = 1;
pthread_create(...); //编译器无法将写入重新排序到`a`过去
//调用`pthread_create()`

// ...
}


void bar(void)
{
int b;
b = 1;
pthread_create(...);调用`pthread_create()`后,可以初始化``b``
//`b`可能永远不会存在,除非作为
//在堆栈或寄存器中传递给`printf ()`

printf(%d\\\
,b);
}

我不确定是否有文档详细描述了这一点 - 这在很大程度上由C的'好像'规则所覆盖。在5.1.2.3/3程序执行中的C99中。 C由具有序列点的抽象机器指定,副作用必须完整,程序必须遵循抽象机器模型,除非编译器可以推断不需要副作用。



在我上面的 foo()例子中,编译器通常不能推断出 a = 1; pthread_create()不需要c $ c>,所以将 a 设置为值 1 必须在调用 pthread_create()之前完成。请注意,如果执行全局优化的编译器可以推断出 a 未在其他地方使用,则它们可能会延迟或延迟赋值。但是,在这种情况下,没有其他人使用副作用了,所以没有问题。


AFAIK there are pthread functions that acts as memory barriers (e.g. here clarifications-on-full-memory-barriers-involved-by-pthread-mutexes). But what about compile-time barrier, i.e. is compiler (especially gcc) aware of this?
In other words - e.g. - is pthread_create() reason for gcc not to perform reordering?

For example in code:

a = 1;
pthread_create(...);

Is it certain that reordering will not take place?
What about invocations from different functions:

void fun(void) {
    pthread_create(...);
    ...
}

a = 1;
fun();

Is fun() also compile time barrier (assuming pthread_create() is)?
What about functions in different translation units?

Please note that I am interested in general gcc and pthreads behavior scpecification, not necessarily x86-specific (various different embedded platforms in focus).
I am also not interested in other compilers/thread libraries behavior.

解决方案

Because functions such as pthread_create() are external functions the compiler must ensure that any side effects that could be visible to an external function (such as a write to a global variable) must be done before calling the function. The compile couldn't reorder the write to a until after the function call in the first case) assuming a was global or otherwise potentially accessible externally).

This is behavior that is necessary for any C compiler, and really has little to do with threads.

However, if the variable a was a local variable, the compiler might be able to reorder it until after the function call (a might not even end up in memory at all for that matter), unless something like the address of a was taken and made available externally somehow (like passing it as the thread parameter).

For example:

int a;

void foo(void)
{
    a = 1;
    pthread_create(...);    // the compiler can't reorder the write to `a` past 
                            //  the call to `pthread_create()`

    // ...
}


void bar(void)
{
    int b;
    b = 1;
    pthread_create(...);    // `b` can be initialized after calling `pthread_create()`
                            // `b` might not ever even exist except as a something
                            //  passed on the stack or in a register to `printf()`

    printf( "%d\n", b);
}

I'm not sure if there's a document that outlines this in more detail - this is covered largely by C's 'as if' rule. In C99 that's in 5.1.2.3/3 "Program execution". C is specified by an abstract machine with sequence points where side effects must be complete, and programs must follow that abstract machine model except where the compiler can deduce that the side effects aren't needed.

In my foo() example above, the compiler would generally not be able to deduce that setting a = 1; isn't needed by pthread_create(), so the side effect of setting a to the value 1 must be completed before calling pthread_create(). Note that if there are compilers that perform global optimizations that can deduce that a isn't used elsewhere, they could delay or elide the assignment. However, in that case nothing else is using the side effect, so there would be no problem with that.

这篇关于编译时间障碍 - 编译器代码重新排序 - gcc和pthreads的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆