atomic_set 연산에 대하여

start_kernel() -> cgroup_init_early 함수를 보면 아래와 같은 코드가 있습니다.

atomic_set(&init_css_set.refcount, 1);

그런데, atomic_set 매크로는 아래와 같이 되어있군요.

#define atomic_set(v,i) (((v)->counter) = (i))

왜 그냥 init_css_set.refcount = 1 과 같이 하면 될 것을 굳이 이렇게 한꺼풀을 씌워서 어려워보이게 해두었을까요?
Patch History 를 보니 원래 atomic_set 은 아래와 같이 구현되어 있었네요.
http://lists.infradead.org

static inline void atomic_set(atomic_t *v, int i)
{
unsigned long tmp;
__asm__ __volatile__("@ atomic_set\n"
    "1: ldrex %0, [%1]\n"
    " strex %0, %2, [%1]\n"
    " teq %0, #0\n"
    " bne 1b"
    : "=&r" (tmp)
    : "r" (&v->counter), "r" (i)
    : "cc");
}

즉, 다른 atomic_add 나 atomic_sub 처럼 ldrex 와 strex 를 함께 사용하는 방식으로 구현되어 있었습니다.
이를 str 연산 하나로 대체해버린 주요한 원인은 아래의 문구에서 보듯이 store 연산도 Global exclusive monitor 를 clear 해줄 수 있게 되었기 때문인 것 같습니다.

With this patch, the atomic_set() operation can be a simple STR instruction (on SMP systems, the global exclusive monitor is cleared by STR anyway). Clearing the exclusive monitor during context switch is no longer needed as this is handled by the exception return path anyway.

즉, atomic_set 연산을 제대로 atomic 하게 구현하려면, store 하는 자신의 연산 뿐 아니라 자신의 연산을 다른 atomic 연산이 알아챌 수 있어야 합니다. 그런데, 만약 store 연산이 exclusive monitor 를 clear 하지 않는다면 이를 다른 연산이 알아챌 수 없을겁니다.
예를 들어, 아래 상황에서 store 연산이 exclusive monitor 를 clear 하지 않으면 ?.

  • 1 번 코어의 프로그램이 ldrex 를 수행한다. (local, global monitor 설정 - tag memory, exclusive 상태)
  • 2 번 코어의 프로그램이 str 연산 수행 (global monitor clear X)
  • 1 번 코어의 프로그램이 정상적으로 strex 수행

아마도 위와 같이 1 번 코어에서 수행되는 프로그램은 중간에 변경된 것을 눈치채지 못하고 이전에 로드한 값을 변경한 결과를 저장해 버릴 것입니다.
이는 store 연산이 다른 atomic 연산을 비정상적으로 만드는 상황이 됩니다. 이 때문에 이전에는 atomic_set 도 ldrex 와 strex 연산을 이용했었던 것 같습니다. (exclusive monitor 를 변경할 수 있는 명령)
그러다가,store 연산도 global exclusive monitor 를 clear 하도록 변경이 되었고, 이렇게 되면 다른 atomic 연산들은 monitor 가 변경되었을 때 status 값을 검사하여 변경 여부를 감지할 수 있습니다.
결국, atomic_set 연산 자체는 store 연산 하나만으로도 충분하게 된 것이므로, 성능 안좋게 굳이 ldrex 와 strex 를 함께 사용할 필요가 없게 된 것입니다. 이러한 atomic_set 에 대한 inline assembly 코드는 없어지고 결국 = (store) 만 남게 된 것입니다.


References:
1. http://www.iamroot.org/xe/Kernel_8_ARM/66152
2. linux-3.12.20/arch/arm/include/asm/atomic.h
3. linux-3.12.20/Document/atomic_ops.txt
4. http://lists.infradead.org

You may also like...

0 0 votes
Article Rating
Subscribe
Notify of
guest
4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
김칫찌개

안녕하세요~ 김칫찌개 입니다. 러브커널에서 만나니 더 반갑네요 ^^
좋은 내용 잘 봤습니다(Very nice homepage!! ㅡ.,ㅡb ).
질문이 있어서 댓글 남기는데요~
With this patch, the atomic_set() operation can be a simple STR instruction (on SMP systems, the global exclusive monitor is cleared by STR anyway). Clearing the exclusive monitor during context switch is no longer needed as this is handled by the exception return path anyway.
여기에서 이야기하는 exception return path 는 어떤걸 말하는 것일까요?

김칫찌ᄶ

안녕하세요~ 김칫찌개 입니다. 러브커널에서 만나니 더 반갑네요 ^^
좋은 내용 잘 봤습니다(Very nice homepage!! ㅡ.,ㅡb ).
질문이 있어서 댓글 남기는데요~
With this patch, the atomic_set() operation can be a simple STR instruction (on SMP systems, the global exclusive monitor is cleared by STR anyway). Clearing the exclusive monitor during context switch is no longer needed as this is handled by the exception return path anyway.
여기에서 이야기하는 exception return path 는 어떤걸 말하는 것일까요?

cloudrain21

exception 은 말그대로 page fault 같은 exception 을 말합니다.
arch/arm/kernel/entry-header.S 파일을 보시면 ARMv7-M 의 exception entry 들의 각종 macro 구현들을 보실 수 있습니다.
그런데, macro 들의 중간 중간을 보시면 clrex나 strex 명령어가 있을겁니다.
http://lxr.free-electrons.com/source/arch/arm/kernel/entry-header.S
http://lists.infradead.org/pipermail/linux-arm-kernel/2009-September/000665.html
이러한 clrex 와 strex 가 exception 에서 돌아오는 과정(exception return path)중에 exclusive monitor 를 clear 해줍니다. 즉, 이쪽에 exclusive monitor 를 clear 하는 과정이 들어가 있으니 이제 더이상 context switching 하는 동안 명시적으로 exclusive monitor 를 clear 해주는 작업들이 불필요하게 되었다는 말 같습니다.

4
0
Would love your thoughts, please comment.x
()
x