2010-08-31 100 views
1

我收到一個奇怪的錯誤。我實現了這兩個功能:搞砸了使用do_futex?

int flag_and_sleep(volatile unsigned int *flag) 
{ 
    int res = 0; 

    (*flag) = 1; 

    res = syscall(__NR_futex, flag, FUTEX_WAIT, 1, NULL, NULL, 0); 
    if(0 == res && (0 != (*flag))) 
     die("0 == res && (0 != (*flag))"); 
    return 0; 
} 

int wake_up_if_any(volatile unsigned int *flag) 
{ 
    if(1 == (*flag)) 
    { 
     (*flag) = 0; 
     return syscall(__NR_futex, flag, FUTEX_WAKE, 1, NULL, NULL, 0); 
    } 
    return 0; 
} 

,並測試他們通過運行兩個POSIX線程:

static void die(const char *msg) 
{ 
    fprintf(stderr, "%s %u %lu %lu\n", msg, thread1_waits, thread1_count, thread2_count); 
    _exit(1); 
} 

volatile unsigned int thread1_waits = 0; 

void* threadf1(void *p) 
{ 
    int res = 0; 
    while(1) 
    { 
     res = flag_and_sleep(&thread1_waits); 
     thread1_count++; 
    } 
    return NULL; 
} 

void* threadf2(void *p) 
{ 
    int res = 0; 
    while(1) 
    { 
     res = wake_up_if_any(&thread1_waits); 
     thread2_count++; 
    } 

    return NULL; 
} 

線程2已經有一百萬左右的迭代之後,我得到了我的斷言火:

./a.out 0 == RES & &(0!=(*標記))1 261129 1094433

這意味着系統調用 - 從而do_futex() - 返回0.人說,它應該只這樣做,如果由do_futex(WAKE)調用喚醒。但是在我進行WAKE調用之前,我將該標誌設置爲0.在此看來,標誌仍然是1.

這是Intel,意思是強大的內存模型。因此,如果在thread1中看到thread2中系統調用的結果,我還必須在調用之前看到線程2中寫入的結果。

標記和指向它的所有指針都是不穩定的,所以我看不到gcc可能無法讀取正確的值。

我很困惑。

謝謝!

+0

這可能值得在LKML上提出。 – caf 2010-09-01 00:46:13

回答

1

比賽發生在線程1變爲全週期,並重新進入等待線程時,從2

(*flag) = 0; 

return syscall(__NR_futex, flag, FUTEX_WAKE, 1, NULL, NULL, 0); 

所以測試故障調用。