futex() 라는 것이 왜 system call() 로 되어 있는지 궁금합니다.

trymp의 이미지

linux 의 futex() 에 대해서 공부하고 있는데요.

도입목적이 효율성이라고 들었습니다.

아주 간단한 critical section 때문에 많은 cpu clock 을 소모하지 않고자

sleep 이나 스케쥴링이 안 일어나도록 user space 에서 작업하는 것이 목적이라고 들었습니다.

근데 실제로는 system call() 을 호출하던데요.

그러면 커널모드로 진입하게 되고 경우에 따라서는 스케쥴링도 될텐데

그럼 말짱 꽝 아닌가요???

제가 잘못 이해하고 있는지 모르겠지만 뭔가 모순된 부분이 있는 것 같아서

질문드립니다.

고수님들의 조언 부탁드립니다.

익명 사용자의 이미지

종래의 Mutex 는 반드시 시스템 콜을 호출하여야 커널 내에서 Lock 을 걸든, Unlock 하든
할 수 있습니다. 즉 구현된 유저레벨 함수를 호출하면 내부 구현에선 별 다른 핵심 작업 없이
무조건 시스템 콜을 호출해야 한다는 얘기입니다.

그러나 Futex 는 이름 그대로 Fast Userspace muTEX 입니다.
이 말의 의미는 부분적으로 유저 레벨에서 Lock/Unlock 처리를 할 수 있는 인터페이스를 제공한다는 의미입니다.

간단한 예로 glibc 의 pthread_mutex_lock / pthread_mutex_unlock 등의 함수 구현을 봅시다.
(Intel TSX 의 Lock Elision 때문에 코드 보기가 상당히 더러워졌습니다.. x86 기준으로 보겠습니다.)

다른건 제쳐놓고, futex_wait 만 보면 어떤식으로 사용이 되는지 한 번 확인해 봅니다.
먼저 nptl/pthread_mutex_lock.c 를 보면 lll_lock 을 여러 곳에서 호출하고 있습니다.

이는 sysdeps/unix/sysv/linux/i386/lowlevellock.h 을 보면 인라인 어셈블리로 되어 있습니다.
여기서는 대략 아래처럼 되어 있습니다.

#define lll_lock(futex, private) \
(void) \
({ int ignore1, ignore2; \
if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \
__asm __volatile (__lll_lock_asm_start \
"jz 18f\n\t" \
"1:\tleal %2, %%ecx\n" \
"2:\tcall __lll_lock_wait_private\n" \
"18:" \
: "=a" (ignore1), "=c" (ignore2), "=m" (futex) \
: "0" (0), "1" (1), "m" (futex), \
"i" (MULTIPLE_THREADS_OFFSET) \
: "memory"); \
else \
{ \
int ignore3; \
__asm __volatile (__lll_lock_asm_start \
"jz 18f\n\t" \
"1:\tleal %2, %%edx\n" \
"0:\tmovl %8, %%ecx\n" \
"2:\tcall __lll_lock_wait\n" \
"18:" \
: "=a" (ignore1), "=c" (ignore2), \
"=m" (futex), "=&d" (ignore3) \
: "1" (1), "m" (futex), \
"i" (MULTIPLE_THREADS_OFFSET), "0" (0), \
"g" ((int) (private)) \
: "memory"); \
} \
})

__lll_lock_asm_start 는 아래와 같습니다.

# define __lll_lock_asm_start LOCK_INSTR "cmpxchgl %1, %2\n\t"

락에서 흔히 볼 수 있는 핵심 연산인 CAS 입니다. 이 연산은 아시다시피 atomic 입니다.
다음 call __lll_lock_wait (또는 __lll_lock_wait_private) 명령으로 또 다른 함수를 호출합니다.

이는 sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S 에 정의되어 있습니다.
쓸데없는 코드때문에 복잡하니 핵심만 간추려서 보면 아래와 같습니다.

__lll_lock_wait:
pushl %edx
pushl %ebx
pushl %esi

movl %edx, %ebx
movl $2, %edx
xorl %esi, %esi /* No timeout. */
LOAD_FUTEX_WAIT (%ecx)

cmpl %edx, %eax /* NB: %edx == 2 */
jne 2f

1: movl $SYS_futex, %eax
ENTER_KERNEL

2: movl %edx, %eax
xchgl %eax, (%ebx) /* NB: lock is implied */

testl %eax, %eax
jnz 1b

popl %esi
popl %ebx
popl %edx
ret

사실 길지도 않고 매우 단순한 형태인데, 저기서 핵심은 1: 과 2: 부분입니다.
옆에 주석으로 설명되어 있듯이 일단 1: 은 딱 봐도 아시겠지만 futex syscall 호출 루틴입니다.
그런데 앞에서 eax 가 2가 아닌 경우는 2: 로 점프합니다. 이 경우는 뒤에서 xchg 연산을 해주고 있습니다.
즉, 이미 lock 이 걸린 리소스에 대해서 lock 을 시도하는 경우 syscall 을 호출하여 wait 합니다.
이 체크를 유저 레벨에서 하고 있습니다. 시스템 콜이 호출되면 말씀하신 대로 스케줄링이 일어납니다.(아예 큐에서 빠집니다.)
저 메모리 값의 의미나 자세한 건 futex 의 구현에 따른 definition 이니 따로 참조하시면 됩니다.

만약 락 연산 자체를 시스템 콜에서 수행한다면, 이러한 작업은 필요가 없습니다.
단순히 락을 구분할 수 있는 메모리 값 정도만 시스템 콜로 넘겨주면 될 것입니다.

그러나 futex 는 받은 인자(eax) 의 주소에 있는 값을 통해 유저 레벨에서 처리합니다.
이로 인해 시스템 콜을 호출할 일이 줄어듭니다. 락이 걸려있지 않은 상태에서 락을 처음으로
걸려고 하는 상황에서는 굳이 커널 진입을 할 필요가 없는 것이죠.

ddoman의 이미지

trymp의 이미지

^^

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.