/arch/arm/asm/include/atomic.h


/*
 * On ARM, ordinary assignment (str instruction) doesn't clear the local
 * strex/ldrex monitor on some implementations. The reason we can use it for
 * atomic_set() is the clrex or dummy strex done on every exception return.
 */
#define atomic_read(v)    (*(volatile int *)&(v)->counter)
#define atomic_set(v,i)    (((v)->counter) = (i))


2009년 부터 현재까지 ARM에서의 atomic_set과 atomic_read의 구현은 위처럼

ldrex/strex 쌍 없이 C 언어의 기본적인 대입 구문으로 되어 있습니다.


먼저, 아시다시피 volatile 키워드는 컴파일러가 이전에 가져온 counter 값을 재사용하도록 최적화하는 것을 막기 위해 사용되었습니다. 따라서 atomic_set 매크로에는 필요가 없습니다.


대입 구문은 str 명령으로 변환될 것입니다. str 명령은 이미 원자적입니다.

하지만 다른 쓰레드에서 동시에 수행중인 ldrex/strex 쌍과 동기화되어야 합니다.

여기서 ldrex/strex 쌍은 load-link/store-conditional 매커니즘을 따르는 명령으로 read-modify-write 연산으로 분류됩니다.

ARM v6 이후로 버그가 있는 swp 명령을 대체하기 위해 나왔습니다. (현재 swp는 deprecated된 명령입니다.)

또 다른 프로세서에서 동일한 공유 메모리에 접근하는 ldrex/strex 쌍과도 동기화되어야 합니다.

또 인터럽트 서비스 루틴과도 동기화되어야 합니다.


이를 위해 각 프로세서에는 local exclusive monitor가 붙어있습니다.

local exclusive monitor는 해당 프로세서가 ldrex를 수행하면 해당 메모리 주소를 배타적 상태로 태그합니다.

해당 프로세서가 태그된 메모리 주소에 새로 값을 쓰면 태그의 상태도 갱신됩니다. 즉, 오픈 상태가 됩니다.

그래서 ldrex가 수행된 이후 strexeq나 strex를 수행하면 그동안 값이 다시 쓰여졌는지 알 수 있습니다.

다시 쓰여졌다면 strex 명령은 실패 상태를 반환합니다. 상태를 보고 원자적으로 수행하려던 로직을 재수행할 수 있습니다.


이 때, local exclusive monitor는 ldrex와 strex의 쌍을 추적하기는 하지만, 문맥 변환을 인식하지는 못합니다.

따라서 동일한 프로세서에서 여러개의 쓰레드 사이에 ldrex/strex 쌍은 꼬이게 됩니다.


Thread 1

Thread 2

Thread 3

ldrex

 

 

 

ldrex

 

 

strex

 

 

 

ldrex

strex

 

 

 

 

strex


예를 들어 위와 같은 경우, local exclusvie monitor는 같은 색으로 칠한 것을 하나의 쌍으로 이해할 것입니다.

즉, 1번과 3번 쓰레드의 ldrex/strex 쌍이 잘못되었습니다. 이렇게 되면 strex 결과 상태가 사실은 실패해야 해도 성공하거나, 사실은 성공해야 해도 실패하는 경우가 발생합니다.


이를 해결하기 위해 문맥 전환을 할 때마다 clrex 명령을 수행해야 합니다.

clrex를 수행하면 해당 프로세서의 local exclusive monitor의 상태를 클리어합니다. 결과적으로 원자적인 구간을 수행하는 도중에 문맥 전환을 한다면 해당 구간은 실패하도록 합니다. ARMv6k 이전은 clrex 명령이 없으므로 dummy strex 명령으로 대체합니다.


다중 프로세서 환경에서 프로세서 간 동일한 공유 메모리 접근에 대해 동기화하기 위해서 global exclusive monitor가 제공됩니다. global exclusive monitor는 각 프로세서가 베타적으로 접근하는 주소를 태그합니다. ldrex를 통해 베타적 상태를 태그해 둔 메모리에 다른 프로세서가 단순 str 연산이나 strex를 수행하면 global exclusive monitor는 해당 태그 상태를 open으로 변경합니다. 이렇게해서 베타적 접근이 실패함을 이후에 알리게 됩니다.


인터럽트 핸들러는 다른 인터럽트를 막아두거나, 또는 nested되기 때문에, ISR 문맥 사이에 clrex가 사용될 필요가 없습니다. 모든 인터럽트 핸들러가 제대로 된 ldrex/strex 쌍을 가지고 있지 않아도 더 안전함을 보장하기 위해 넣을 수도 있습니다.


결과적으로 시그널 핸들링 경로나 모든 각 예외 루틴에 clrex를 넣음으로써 atomic_set 매크로가 단순 str 연산이어도 안전하도록 할 수 있습니다.



오류 발견하면 꼭 지적해주세요.

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 커널 스터디 관련 Q&A 게시판 입니다. [5] woos 2016.04.09 2197
1625 소스 인사이트 UTF-8 지원? 김용욱 2012.02.11 9269
1624 [알림] 스터디용 커널 1단계 준비 완료 [4] 장병남 2010.04.20 9265
1623 게시판이 썰렁하군요,,, [1] 파란피 2010.02.24 9245
1622 10월 25일 모임 [3] 조용락 2008.10.27 9238
1621 arch/x86_64/kernel/head.S 분석 자료 [1] file 맥주 2007.05.20 9232
1620 2월 21일 스터디 내용~ [3] 김다진 2009.02.25 9227
» [ARM초] atomic_set 매크로가 ldrex/strex 대신 단일 str 명령으로 구현된 이유 [7] 윤호정 2012.02.14 9207
1618 11월 22일 모임 조용락 2008.11.25 9206
1617 x86 interrupt & instruction table file 백창우 2007.02.23 9190
1616 ARM System Developer's Manual 이거 pdf 있으신분~~ [1] 윤종일 2010.04.04 9182
1615 [잡담] 이쿠 지송합니다. [1] 맥주 2008.05.14 9156
1614 살짝 덜 춥다가 다시 추워지네요 [4] 천풍 2008.12.12 9142
1613 12월20일 모임 [1] 조용락 2008.12.20 9089
1612 체감온도 영하 15도랍니다. 천풍 2008.12.26 9086
1611 오늘도 고생많으셧습니다. [3] 강진성 2010.04.04 9078
1610 3/14일 스터디 참석 확인^^ [6] 석헌영 2009.03.13 9057
1609 ARM TCM 관련 자료 [1] 홍순민 2010.04.12 9054
1608 12월 6일모임은~~ [2] 조용락 2008.12.04 9053
1607 11월 8일 모임 [2] 조용락 2008.11.11 8997
1606 커널 2.6 Makefile 분석 자료 (2nd Edition) 송형주 2007.05.28 8972
XE Login