voltile에 관한 질문...

psjcap의 이미지

밑에 4개에 차이가 뭘까요..??

1) volatile int a
2) int volatile b
3) volatile int* c
4) int* volatile d

그리고 thread 종료 flag로 volatile을 사용하려고하는데..
전역변수로 사용하기가 어려워서.. 포인터를 이용하려고 하거든요..
그럴 경우 위 네가지 중 변수 선언을 어떻게 해야하나요..??

처음 변수선언하는 부분이랑 포인터르 받는 부분이랑 둘다요..
무지 헛갈리네요..ㅠㅠ

서지훈의 이미지

1), 2)이 차이점은 별로 잘 모르겠구...
3), 4)은 확연한 차이가...

3) volatile int* c 이건 아마도 c가 가리키는 곳의 값을 lock 시키는거 같고요..

4) int* volatile d 이놈은 d pointer 를 lock 시키는것 같은뎅...-_-ㅋ

저도 한 번 확인을 해봐야 겠네요...
좀 오래전에 본 내용이라...

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

yielding의 이미지

volatile 키워드는 lock과는 상관없고 컴파일러가 이 키워드를 사용해서
선언한 변수를 optimize하지 말라는 거지요..

멀티쓰레드 프로그램에서 한 쓰레드가 공유되는 flag 변수를 변경시켜도 이 flag 변수가 volatile로 선언되어 있지 않으면 register에 cache만 되어있고 메모리에 반영이 안되는 경우가 있어서(컴파일러의 optimization때문에) 다른 쓰레드는 변경된 flag값을 읽어도 변경되지 않은 값을(메모리에는 반영이 안되었으므로) 읽는 경우가 생길 수 있습니다. 결과는 뭐 thread race condition 발생 등...

그리고 1 == 2, 3 == 4 인듯합니다. 자기의 개성대로 쓰면 될듯.

Life rushes on, we are distracted

서지훈의 이미지

yielding wrote:
volatile 키워드는 lock과는 상관없고 컴파일러가 이 키워드를 사용해서
선언한 변수를 optimize하지 말라는 거지요..

멀티쓰레드 프로그램에서 한 쓰레드가 공유되는 flag 변수를 변경시켜도 이 flag 변수가 volatile로 선언되어 있지 않으면 register에 cache만 되어있고 메모리에 반영이 안되는 경우가 있어서(컴파일러의 optimization때문에) 다른 쓰레드는 변경된 flag값을 읽어도 변경되지 않은 값을(메모리에는 반영이 안되었으므로) 읽는 경우가 생길 수 있습니다. 결과는 뭐 thread race condition 발생 등...

그리고 1 == 2, 3 == 4 인듯합니다. 자기의 개성대로 쓰면 될듯.


제가 lock 라고 쓴것도 같은 의미에서 였는데... ㅋㅋㅋ

그리고 제가 언젠가... 3), 4) 의 차이점에 대한 글을 본적이 있습니다...
어떤 분이 정리를 해서 올려 주신 거였는데...-_-ㅋ
그럼 그분이 틀렸다는?

이놈은 쉽게 test 하기도 어렵고...-_-ㅋ

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

jqka1의 이미지

저도 그런 글을 본적이 있구요..
3 == 4 는 분명 아닙니다... 차이는 서지훈님의 말대로이구요..

그리고.. lock 이 걸려서 레지스터 캐쉬가 안된다는 건.. 좋은 생각의 전환이네요..

방준영의 이미지

volatile의 용법은 const와 같습니다.

volatile char *p; /* p는 volatile char에 대한 포인터 */
char * volatile p; /* p는 char에 대한 volatile 포인터 */

그러므로 3) != 4) 입니다.

Quote:
lock 이 걸려서 레지스터 캐쉬가 안된다는 건.. 좋은 생각의 전환이네요..

lock은 전혀 다른 뜻으로 사용되는 용어입니다.
aqwerf의 이미지

psjcap wrote:
전역변수로 사용하기가 어려워서.. 포인터를 이용하려고 하거든요..
그럴 경우 위 네가지 중 변수 선언을 어떻게 해야하나요..??

3번이 맞습니다.
3) volatile int* c
위처럼 pointer가 가르키는 값이 volatile이라고 명시를 하여야 합니다.
4번은 해당 번지를 저장하고 있는 pointer값이 volatile이라고 명시를 하는 것이고요. 위에서 설명한 것 처럼 volatile이 가리키는 것이 어떤 것인지는 const와 동일합니다.

CPU 입장에서 보면 메모리에 있는 값을 참조하려면
- 직접 메모리를 참조하는 연산을 사용 하거나,
- 메모리 값을 먼저 CPU register로 읽어 온후에 연산을 하거나
둘 중 하나 입니다. 물론 쓰는 동작도 마찬가지 입니다. 둘 중 어떤 식으로 될 지는 CPU, compiler마다 다릅니다.

Compiler는 두번 째와 같이 한번 register로 읽어온 경우이고 그 변수를 다시 참조하게 되는 경우라면, 다시 메모리 값을 참조하지 않고 register에 이미 읽어온 값을 참조하도록 합니다. 일반적인 경우에는 이와 같은 방법이 속도면에서도 바람직하겠죠.. 하지만 thread sync. 를 위한 용도라면 이와 같은 방법이 문제가 될 수 있습니다.

이런 경우 volatile로 선언이 되어 있다면 매번 다시 memory에 있는 값을 다시 참조하게 됩니다.

CPU마다 다를 수 있지만 보통 아래와 같이 전역변수인 flag가 있고, 이를 1로 설정하는 것이 다른 thread나 ISR이라면 아래 함수는 영원히 무한 loop를 돌 수 있습니다.

flag = 0; 
...
while (flag == 0);

위의 flag라는 값이 어찌어찌 해서 register에 load된 상태라면 compiler는 reigster에 load된 값을 계속 참조하기 때문에 다른 thread에서 flag값을 바꾸어 준다 해도(메모리에 있는 값이 바뀌는 것이겠죠) 이 루틴을 빠져나가지 못하게 됩니다. (물론 CPU, compiler에 따라서 이렇게 될수도 있고 않될수도 있습니다)

위와 같은 문제를 막기위하여 volatile을 정의를 하게 되면 compiler는 매번 직접 메모리를 직접 참조하거나 다시 register로 다시 읽어오도록 합니다. Write도 마찬가지죠.

http://gcc.gnu.org/onlinedocs/gcc-3.4.1/gcc/Volatiles.html#Volatiles

참고로 thread synchronization을 위한 경우라면 어떤 연산을 하느냐에 따라 volatile만 사용한다고 문제가 모두 해결되지는 않습니다.
반드시 연산이 atomic operation이 되어야 합니다. 간단하게 말하면 1 cpu instruction에 실행되는 명령을 말합니다. 이것이 상황을 설명하기가 좀 애매한데, 한 변수를 두 thread에서 값을 변경하는 경우 이와 같이 atomic operation이 아니라면 volatile로 선언을 한다고 하여도 문제가 해결되지 않을 수 있기 때문에 mutex등으로 lock을 걸거나 inline assembler로 명시적으로 atomic operation이 되도록 만들어 주어야 합니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.