.

익명 사용자의 이미지

삭제합니다. 더이상 글 안올리겠습니다.

Forums: 
pynoos의 이미지

좋은 예제군요.

8 byte 의 unsigned long long type에

0x00000000ffffffff
0xffffffff00000000

두 값을 번갈아 써넣을 뿐인데..

0x0000000000000000
또는
0xffffffffffffffff

일 수 있는 상황이 연출되는 것은 대입 문에 대한 원자성이 보장되지 않기 때문이다.. 군요.

단, 조건은 대입중간에 쓰레드 문맥 전환이 일어나야하므로, kernel thread 이어야할 것 같은데요.

익명 사용자의 이미지

pynoos wrote:
좋은 예제군요.

8 byte 의 unsigned long long type에

0x00000000ffffffff
0xffffffff00000000

두 값을 번갈아 써넣을 뿐인데..

0x0000000000000000
또는
0xffffffffffffffff

일 수 있는 상황이 연출되는 것은 대입 문에 대한 원자성이 보장되지 않기 때문이다.. 군요.

단, 조건은 대입중간에 쓰레드 문맥 전환이 일어나야하므로, kernel thread 이어야할 것 같은데요.

우선 Kernel thread일 필요는 없습니다.
오히려 Kernel thread는 원자적 보장이 더 쉽게 됩니다. (CPU한개일때)

원자적 보장의 한계인 원자단위 즉, 32bit이상의 크기를 다룰때
발생하는 총체적인 경쟁조건을 예로 들기 위한 단편적인 부분입니다.
여기서는 unsigned long long 을 예로 들어서 64비트를 예로 한것이지만
실제 실무에서는 이것이 구조체가 많을겁니다.
제가 설명하고픈 것은 바로 그것입니다.

unsigned long long에 대입하는 부분을 역 어셈블 해보세요.
그러면 그 원인이 쉽게 이해가실거라 사료됩니다.

shkwon81의 이미지

Quote:
우선 Kernel thread일 필요는 없습니다.
오히려 Kernel thread는 원자적 보장이 더 쉽게 됩니다. (CPU한개일때)

원자적 보장의 한계인 원자단위 즉, 32bit이상의 크기를 다룰때
발생하는 총체적인 경쟁조건을 예로 들기 위한 단편적인 부분입니다.
여기서는 unsigned long long 을 예로 들어서 64비트를 예로 한것이지만
실제 실무에서는 이것이 구조체가 많을겁니다.
제가 설명하고픈 것은 바로 그것입니다.

Kernel thread가 원자적 보장이 더 쉽게 된다는 건 어떤 근거인가요?
잘 이해가 안 가네요?

그리고, 워드 단위(예를 들어 32bit)의 크기를 다룬다고 해서 원자성이 보장된다는 것은 항상 옳은 것은 아닙니다.
임의의 주소(4의 배수가 아닌)로의 접근이 가능한 플랫폼의 경우(머신 자체에서 지원 or OS의 트랩 기능을 이용한 지원)는 실제로는 32bit의 자료형일지라도 워드의 경계에 걸쳐 있을 가능성이 있죠..
그런 경우라면 실제로 메모리 읽기는 두 번이 필요합니다. 즉, 그 사이에 쓰레드가 선점되고 다른 쓰레드가 동일 메모리 주소를 접근할 가능성이 있죠..
물론 위에서 제시하신 경우보다 확률은 더더욱 희박합니다.

errai의 이미지

main의 do while 루프안의 대입 부분을 역어셈 하면 대략 다음과
같이 표현 할 수 있겠군요.

s_qword = 0xffffffffllu;

 
movl    $-1, -16(%ebp)
movl    $0, -12(%ebp)

s_qword = 0xffffffff00000000llu;

movl    $0, -16(%ebp)
movl    $-1, -12(%ebp

두개의 mov 명령으로 실행된다는게 문제인것 같습니다.
movl 한개만 실행되었을때 쓰레드에서 if 문을 실행시킨다면
바로 종료 되는군요. minzkn님께서 말씀해주셨다 시피 실제 구조체
등에서 이런 상황이 발생할 수 있을 것 같습니다.

그렇다면 이를 막을 수 있는 방법은 뭐가 있을까요.

익명 사용자의 이미지

삭제합니다. 더이상 글 안올리겠습니다.

pynoos의 이미지

pynoos wrote:
단, 조건은 대입중간에 쓰레드 문맥 전환이 일어나야하므로, kernel thread 이어야할 것 같은데요.

minzkn wrote:
우선 Kernel thread는 비선점형 이라는 점을 예기하겠습니다.

^^ 저의 질문이 모호하게 해석되어서 그런 것 같습니다.
저는 pthread 구현이 kernel thread 를 기반으로 구현되어야한다고 생각했던 것이고, 만일 user thread 라면 오히려 중간에 context switching이 안될 것이다라는 생각으로 말한 것이었습니다.
즉, pthread가 kernel thread 기반일 경우 사용자의 thread context가 커널의 선점된 스케쥴을 따르기 때문에 위와 같은 상황이 잘 연출 될 것이라는 말을 한 것이었습니다.

minzkn 님께서는 "kernel thread 내부에서"로 해석하여 답하신 것 같네요.
저도 shkwon81님과 비슷한 질문을 하려고 했는데..

둘다 비선점상황에서는 원자성이 대체로 선점상황보다 더 보장된다는 생각으로 의견을 교환한 것 같습니다. :)

datamind의 이미지

간단하게 수정하면 될것 같은데요...
음... 하루 정도 돌려보기는 힘들것 같네요.. -_-;;;

int main(void) 
{ 
pthread_t s_Thread; 
unsigned long long s_qword = 0xffffffffllu; 

/* ----- 추가 ------ */
int policy = SCHED_RR; 
struct sched_param param;

    param.sched_priority = sched_get_priority_min( policy );
    if( sched_setscheduler( getpid(), policy, & param  ) )
    {
        perror("schedure error");
        return 0;
    }
/* ---  추가 끝 ---- */
pthread_create(&s_Thread, NULL, ThreadPrint, &s_qword); 
pthread_detach(s_Thread); 
do 
{ 
  if(s_qword == 0xffffffff00000000llu)s_qword = 0xffffffffllu; 
  else s_qword = 0xffffffff00000000llu; 
/* --- 수정 --- */
  usleep( 10000 );   // usleep(0); 
/* 10000 이하로 주면 다운됩니다. 주의하시길 */ 
  // fprintf(stdout, "0x%016llx\n", s_qword); 
}while(1); 
return(0); 
} 
익명 사용자의 이미지

x86이라면 cmpxchg8b를 써서 다음과 같이 하는 건 어떨까요?

/*
 * ULONGLONG InterlockedCompareExchange8Bytes(
 *	LPULONGLONG volatile Destination,
 *	ULONGLONG Exchange,
 *	ULONGLONG Comperand);
 */
	pushl	%ebp
	movl	%esp,%ebp
	pushl	%esi
	pushl	%ebx

	movl	8(%ebp),%esi

	movl	12(%ebp),%ecx
	movl	16(%ebp),%ebx

	movl	20(%ebp),%edx
	movl	24(%ebp),%eax

1:	lock cmpxchg8b (%esi)
	jz	2f

	movl	20(%ebp),%ecx
	movl	24(%ebp),%ebx
	jmp	1b

2:	popl	%ebx
	popl	%esi
	popl	%ebp
	ret

즉 다음과 같이 된 것을
  if(s_qword == 0xffffffff00000000llu)s_qword = 0xffffffffllu; 
  else s_qword = 0xffffffff00000000llu;

이렇게 바꿉니다:
InterlockedCompareExchange8Bytes(&s_qword, 0xffffffffllu, 0xffffffff00000000llu);
Destination 위치에 있는 64비트 값을 Comperand와 비교하여 같으면 Exchange를, 다르면 Comperand를 Destination에 대입합니다.

단, 실제로 돌려보지 않고 생각나는대로 짠 것이니 동작이 될지 안될지는 모르겠습니다. 8)

익명 사용자의 이미지

삭제합니다. 더이상 글 안올리겠습니다.

익명 사용자의 이미지

cmpxchg8b는 %edx:%eax 값을 피연산자가 가리키는 메모리상의 64비트 값과 비교해서 같으면 그곳에 %ecx:%ebx 값을 저장하고(ZF=1), 다르면 거꾸로 메모리에 있던 값을 %edx:%eax에 저장합니다(ZF=0).

펜티엄에서 버그가 있다는 얘기는 사실인지 아닌지 잘 모르겠습니다. 언제 도입된 명령어인지도 기억이 확실치 않아서... 8)

댓글 달기

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