0

以下のプログラムは、この出力を生成します。

$ ./test_condvar 9000
1343868189.623067126 1343868198.623067126 FIRST
1343868197.623132345 1343868206.623132345 TIMEOUT
1343868205.623190120 1343868214.623190120 TIMEOUT
1343868213.623248184 1343868222.623248184 TIMEOUT
1343868221.623311549 1343868230.623311549 TIMEOUT
1343868229.623369718 1343868238.623369718 TIMEOUT
1343868237.623428856 1343868246.623428856 TIMEOUT

行全体を読み取ると、意図した9秒の時間デルタが表示されますが、列をpthread_cond_timedwait読み取ると、8秒でETIMEDOUTが返されることが示されていることに注意してください。

pthreadlibはglibc2.12です。RedHatEL6を実行しています。uname -aショー2.6.32-131.12.1.el6.x86_64 #1 SMP Tue Aug 23 11:13:45 CDT 2011 x86_64 x86_64 x86_64 GNU/Linux

タイムアウト動作にpthread_cond_timedwait依存しているようです。lll_futex_timed_wait

説明を検索する他の場所に関するアイデアはありますか?

#include <time.h>
#include <sys/time.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

int main ( int argc, char *argv[] )
{
    pthread_mutexattr_t mtx_attr;
    pthread_mutex_t mtx;
    pthread_condattr_t cond_attr;
    pthread_cond_t cond;

    int milliseconds;
    const char *res = "FIRST";

    if ( argc < 2 )
    {
        fputs ( "must specify interval in milliseconds", stderr );
        exit ( EXIT_FAILURE );
    }

    milliseconds = atoi ( argv[1] );

    pthread_mutexattr_init ( &mtx_attr );
    pthread_mutexattr_settype ( &mtx_attr, PTHREAD_MUTEX_NORMAL );
    pthread_mutexattr_setpshared ( &mtx_attr, PTHREAD_PROCESS_PRIVATE );

    pthread_mutex_init ( &mtx, &mtx_attr );
    pthread_mutexattr_destroy ( &mtx_attr );

#ifdef USE_CONDATTR
    pthread_condattr_init ( &cond_attr );
    if ( pthread_condattr_setclock ( &cond_attr, CLOCK_REALTIME ) != 0 )
    {
        fputs ( "pthread_condattr_setclock failed", stderr );
        exit ( EXIT_FAILURE );
    }

    pthread_cond_init ( &cond, &cond_attr );
    pthread_condattr_destroy ( &cond_attr );
#else
    pthread_cond_init ( &cond, NULL );
#endif

    for (;;)
    {
        struct timespec now, ts;
            clock_gettime ( CLOCK_REALTIME, &now );

        ts.tv_sec = now.tv_sec + milliseconds / 1000;
            ts.tv_nsec = now.tv_nsec + (milliseconds % 1000) * 1000000;
        if (ts.tv_nsec > 1000000000)
        {
            ts.tv_nsec -= 1000000000;
            ++ts.tv_sec;
        }

        printf ( "%ld.%09ld %ld.%09ld %s\n", now.tv_sec, now.tv_nsec,
                 ts.tv_sec, ts.tv_nsec, res );

        pthread_mutex_lock ( &mtx );
        if ( pthread_cond_timedwait ( &cond, &mtx, &ts ) == ETIMEDOUT )
            res = "TIMEOUT";
        else
            res = "OTHER";
        pthread_mutex_unlock ( &mtx );
    }
}
4

2 に答える 2

7

今年の7月1日にうるう秒が挿入されたためにLinuxカーネルのバグが発生しました。その結果、マシンが再起動されるか、回避策を実行するまで、futexの有効期限が1秒早くなりました。

# date -s "`date`"

噛まれたようですね。

于 2012-08-03T05:15:26.010 に答える
0

これが特定の問題に関連しているのかどうかはわかりませんが、あなたの行は次のとおりです。

if (ts.tv_nsec > 1000000000)

本当にあるべきです:

if (ts.tv_nsec >= 1000000000)

そして、実際、予期しないことをして10000を渡す場合(たとえば)、それを作成することを検討することをお勧めします。

while (ts.tv_nsec >= 1000000000)

ただし、ループが長時間実行されないように、ある時点でモジュラス演算を使用する方がおそらく良いでしょう。

それ以外は、これはあなたの環境に何らかの問題があるようです。コードはDebianの下で私にとってうまく機能しますLinux MYBOX 2.6.32-5-686 #1 SMP Sun May 6 04:01:19 UTC 2012 i686 GNU/Linux

1343871427.442705862 1343871436.442705862 FIRST
1343871436.442773672 1343871445.442773672 TIMEOUT
1343871445.442832158 1343871454.442832158 TIMEOUT
:

1つの可能性は、システムクロックが神聖なものではないという事実です。これは、NTPまたはその他の時刻同期プロセスによって定期的に変更される可能性があります。可能性としては申し上げますが、タイムアウトから現在時刻を取得するまでの短い時間で発生するのは少し奇妙に思えます。

1つのテストは、異なるタイムアウト(7秒と13秒を交互に繰り返すなど)を使用して、効果が同じであるかどうかを確認することです(これらの数値は素数として選択され、システム上の他のアクティビティの倍数になる可能性は低いです。

于 2012-08-02T01:17:18.507 に答える