2012-11-24 1 views
2

AFAIK 메모리 장벽 역할을하는 pthread 함수가 있습니다 (예 : clarifications-on-full-memory-barriers-involved-by-pthread-mutexes). 그러나 컴파일 타임 장벽은 컴파일러 (특히 gcc)가 이것을 알고 있습니까? 다른 말로 - 예를 들어. - pthread_create()가 gcc가 재정렬을 수행하지 않는 이유는 무엇입니까?컴파일 시간 장벽 - 컴파일러 코드 재정렬 - gcc 및 pthreads

코드의 예를 들면 다음과 같습니다

a = 1; 
pthread_create(...); 

그것은 재정렬이 발생하지 것이라고 확신인가?
어떤 다른 기능의 호출에 대한 :

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

a = 1; 
fun(); 

() 또한 시간의 장벽을 컴파일 재미 (가정에서는 pthread_create()이다)?
다른 번역 단위의 기능은 무엇입니까?

일반적인 gcc 및 pthreads 동작 scpecification에 관심이 있습니다. x86 관련 (다양한 임베디드 플랫폼에 중점을두고 있음) 일 필요는 없습니다.
다른 컴파일러/스레드 라이브러리 동작에도 관심이 없습니다.

답변

3

pthread_create()과 같은 함수는 외부 함수이므로 컴파일러는 함수를 호출하기 전에 외부 함수에서 볼 수있는 부작용 (예 : 전역 변수에 대한 쓰기)을 수행해야합니다. 컴파일은 a이 첫 번째 경우에 함수 호출 이후까지 a에 대한 쓰기를 재정렬 할 수 없었습니다. 즉, a이 전역 적이거나 외부에서 잠재적으로 액세스 할 수 있다고 가정).

이것은 모든 C 컴파일러에서 필요하며 실제로 스레드와 관련이없는 동작입니다.

그러나 변수 a이 로컬 변수 인 경우 컴파일러는 함수 호출 (a이 메모리에서 전혀 끝나지 않을 수도 있음)이 발생할 때까지 재정렬 할 수 있습니다. a을 가져 와서 어떻게 든 외부에서 사용할 수있게되었습니다 (thread 매개 변수로 전달하는 것과 같습니다). 예를 들어

: -이 규칙 '처럼'C의에 의해 크게 덮여 자세한 내용이 간략하게 설명 문서가 있다면

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); 
} 

잘 모르겠어요. C99에서는 5.1.2.3/3 "프로그램 실행"에 있습니다. C는 부작용이 완료되어야하는 시퀀스 포인트가있는 추상 기계에 의해 지정되며 컴파일러가 부작용이 필요 없다고 추론 할 수있는 경우를 제외하고 프로그램은 해당 추상 기계 모델을 따라야합니다. 내 foo() 예에서

위, 컴파일러는 일반적으로 a = 1;를 설정하는 것은 pthread_create()에 의해 필요하지 않은 것을 추론 할 수 없을 것입니다, 그래서 값 1a 설정의 부작용 pthread_create()를 호출하기 전에 완료해야합니다. a이 다른 곳에서 사용되지 않는다고 추측 할 수있는 전역 최적화를 수행하는 컴파일러가있는 경우 할당을 지연 시키거나 삭제할 수 있습니다. 그러나, 그 경우에는 다른 어떤 것도 부작용을 사용하지 않으므로 아무런 문제가 없습니다.

+0

변수에 내부 또는 외부 연결 (정적 대 외부)이있는 경우 중요합니까? – Andy

+1

내부 연결 고리가있는 주요 변수는 지역 주민과 유사하게 취급 될 수 있습니다.그러나 간접적으로 외부에 액세스 할 수 있다면 컴파일러는 전역 변수와 유사하게 처리해야합니다. 예를 들어,'static' 변수가 쓰레드 함수에 의해 사용된다면, 쓰레드 함수가 '외부'에서 호출되기 때문에 외부 적으로 간접적으로 접근 할 수 있습니다 (이것은 쓰레드 함수에 대한 포인터가 외부 기능). –

+0

나는 당신의 마지막 코멘트를 얻지 못했다. IMHO 정적 변수는 스레드가 다른 외부 함수 (thread가 생성되기 전에 정적 a에 대한 포인터를 얻음)를 통해 간접적으로 사용될 수 있습니다. 그러나 내가 무엇을 찾고 있는지는 순서 변경이 발생할 수있는 경우 규칙을 설명하는 공식적인 설명 (예 : gcc 문서, 메일 링리스트 게시물 링크)입니다. – Andy