C언어 volatile keyword
C언어에서 volatile을 변수에 적용하면 컴파일러가 최적화를 하지 않고 항상 해당 메모리에 접근한다. volatile의 사전적인 의미는 "변할 수 있는" 정도의 뜻이며, 변할 수 있는 값이기 때문에 컴파일러가 최적화를 할 수 없다. volatile은 HW 접근 시에 보통 사용한다. 아래의 예제를 보자.
* target CPU는 RISC-V이며 컴파일 조건은 아래와 같다.
포스팅 ▶ 테스트 조건 및 성능 / 메모리 사용량 비교 방법
* RISC-V 명령어 설명은 아래를 참조하자.
포스팅 ▶ RISC-V 어셈블리 명령어 설명
<C 코드>
#define HW_QUEUE_POP (*(int*)0x20000000)
int first_value;
int second_value;
void get_two_values(void)
{
first_value = HW_QUEUE_POP;
second_value = HW_QUEUE_POP;
}
<어셈블리 코드>
00000000 <get_two_values>:
0: 200007b7 lui a5,0x20000
4: 0007a783 lw a5,0(a5) # a5 = 20000000번지의 값
8: 10000737 lui a4,0x10000
c: 00f72223 sw a5,4(a4) # 10000004번지(first_value) = a5
10: 10000737 lui a4,0x10000
14: 00f72023 sw a5,0(a4) # 10000000번지(second_vaule) = a5
18: 00008067 ret
Disassembly of section .sbss:
10000000 <second_value>:
10000000: 0000 unimp
...
10000004 <first_value>:
10000004: 0000 unimp
위의 예제에서 0x2000_0000번지는 read 하면 HW QUEUE에서 값이 하나씩 pop 되는 HW address이다.
프로그램을 작성한 사람은 0x2000_0000번지 read 한 값이 first_value에 대입되고, 다시 0x2000_0000번지 read 한 값이 second_value에 대입되길 기대했을 것이다. 하지만 어셈블리를 보면 0x2000_0000번지를 한 번만 read 해서 그 값을 first_value, second_value에 똑같이 대입했다. 컴파일러는 같은 메모리 위치의 값이니 여러 번 read 해도 같은 값일 것으로 생각하여 한 번만 read하고 같은 값을 first_value, second_value에 대입했다.
이런 경우에 volatile keyword가 필요하다. 아래에는 HW_QUEUE_POP define에 volatile을 적용했다.
<C 코드>
#define HW_QUEUE_POP (*(volatile int*)0x20000000)
int first_value;
int second_value;
void get_two_values(void)
{
first_value = HW_QUEUE_POP;
second_value = HW_QUEUE_POP;
}
<어셈블리 코드>
00000000 <get_two_values>:
0: 200007b7 lui a5,0x20000
4: 0007a683 lw a3,0(a5) # a3 = 20000000번지의 값
8: 10000737 lui a4,0x10000
c: 00d72223 sw a3,4(a4) # 10000004번지(first_value) = a3
10: 0007a703 lw a4,0(a5) # a4 = 20000000번지의 값
14: 100007b7 lui a5,0x10000
18: 00e7a023 sw a4,0(a5) # 10000000번지(second_value) = a4
1c: 00008067 ret
Disassembly of section .sbss:
10000000 <second_value>:
10000000: 0000 unimp
...
10000004 <first_value>:
10000004: 0000 unimp
이번에는 0x2000_0000번지에서 read 해서 fisrt_value에 대입하고 다시 0x2000_0000번지에서 read 해서 second_value에 대입했다. 컴파일러가 volatile이 있어서 최적화를 하지 않고 매번 메모리에서 값을 읽었다.
위와 같이 컴파일러 최적화가 되지 않아야 하는 변수에는 volatile keyword를 사용해야 한다.
* Feedback은 언제나 환영합니다.
Comments
Post a Comment