以下程序产生此输出:
$ ./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。
pthread lib是glibc 2.12。运行Red Hat EL6。 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 );
}
}
答案 0 :(得分:7)
答案 1 :(得分: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
:
一个可能性是系统时钟不是神圣不可侵犯的事实 - 它可以通过NTP或其他时间同步过程定期修改。我提到这是一种可能性,但似乎有点奇怪,它会在超时和获取当前时间之间的短时间内发生。
一个测试是使用不同的超时(例如交替七秒和十三秒)来查看效果是否相同(这些数字被选择为素数并且不太可能是系统上任何其他活动的倍数)