I'm using pthread for a program used both in Windows and Linux environments. For windows I am using pthread for Win 32 ver 2.9.1 (latest).
I need to use pthread_cond_timedwait to wait for a time in microsecond resolution. On linux everything works fine, but on windows, despite my efforts, I can not go below the resolution of the seconds.
This is the way I use the pthread function:
int PTMon::wait(time_t sec, long nsec)
{
timespec abstime;
struct timeval tp;
gettimeofday(&tp, NULL);
abstime.tv_sec = tp.tv_sec + sec;
abstime.tv_nsec = tp.tv_usec * 1000 + nsec;
long sc;
if((sc = abstime.tv_nsec / 1000000000L) != 0){
abstime.tv_sec += sc;
abstime.tv_nsec %= 1000000000L;
}
return pthread_cond_timedwait(&cv_, &mutex_, &abstime);
}
this is the implementation of gettimeofday() I used:
if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#define DELTA_EPOCH_IN_MICROSECS10 116444736000000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#define DELTA_EPOCH_IN_MICROSECS10 116444736000000000ULL
#endif
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
unsigned __int64 tmpres = 0;
static int tzflag = 0;
if (NULL != tv)
{
GetSystemTimeAsFileTime(&ft);
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
tmpres /= 10; /*convert into microseconds*/
/*converting file time to unix epoch*/
tmpres -= DELTA_EPOCH_IN_MICROSECS;
tv->tv_sec = (long)(tmpres / 1000000UL);
tv->tv_usec = (long)(tmpres % 1000000UL);
}
if (NULL != tz)
{
if (!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}
I used this simple test program:
char tbuf[128];
int main(int argc, char* argv[]){
CYG_InitTimers();
cyg_tim_t t1, t2, dt;
int i = 0;
int wres = 0;
while(i++ < 100){
CYGMARK1(&t1);
wres = mon.wait(3, 50*MSEC_F); //this should wait for 3 sec and 50 msec
CYGMARK1(&t2);
dt = DIFFT(t1, t2);
memset(tbuf, 0, sizeof(tbuf));
sprintf(tbuf, "S%03llu - MS%03llu - US%03llu",
(dt / CYG_ONEBILLION),
(dt / CYG_ONEMILLION) % CYG_ONEKAPPA,
(dt / CYG_ONEKAPPA) % CYG_ONEKAPPA);
printf(" wt(%d): %s\n",wres, tbuf);
}
return 0;
}
LINUX OUTPUT:
devel@thor:/mnt/D/prjs/cr_prj/src/test$ ./test
wt(110): S003 - MS050 - US634
wt(110): S003 - MS051 - US386
wt(110): S003 - MS050 - US380
wt(110): S003 - MS051 - US765
wt(110): S003 - MS050 - US470
wt(110): S003 - MS051 - US520
wt(110): S003 - MS050 - US573
wt(110): S003 - MS050 - US498
wt(110): S003 - MS051 - US459
wt(110): S003 - MS050 - US665
wt(110): S003 - MS051 - US563
wt(110): S003 - MS051 - US564
wt(110): S003 - MS050 - US481
wt(110): S003 - MS051 - US650
wt(110): S003 - MS050 - US463
wt(110): S003 - MS050 - US616
wt(110): S003 - MS050 - US947
wt(110): S003 - MS050 - US570
wt(110): S003 - MS050 - US508
wt(110): S003 - MS050 - US565
wt(110): S003 - MS050 - US549
....
WIN OUTPUT:
wt(10060): S002 - MS629 - US885
wt(10060): S002 - MS998 - US859
wt(10060): S003 - MS000 - US007
wt(10060): S003 - MS000 - US013
wt(10060): S003 - MS000 - US029
wt(10060): S003 - MS023 - US701
wt(10060): S003 - MS023 - US245
wt(10060): S003 - MS023 - US697
wt(10060): S003 - MS023 - US225
wt(10060): S002 - MS999 - US730
wt(10060): S003 - MS002 - US711
wt(10060): S003 - MS010 - US663
wt(10060): S002 - MS999 - US226
wt(10060): S003 - MS000 - US214
wt(10060): S002 - MS999 - US698
wt(10060): S003 - MS000 - US215
wt(10060): S003 - MS000 - US233
wt(10060): S002 - MS999 - US210
wt(10060): S003 - MS000 - US215
wt(10060): S002 - MS999 - US215
wt(10060): S003 - MS000 - US237
wt(10060): S003 - MS000 - US205
wt(10060): S002 - MS999 - US218
wt(10060): S003 - MS000 - US223
wt(10060): S003 - MS000 - US228
wt(10060): S002 - MS999 - US210
wt(10060): S003 - MS000 - US216
wt(10060): S002 - MS999 - US097
wt(10060): S003 - MS000 - US197
wt(10060): S003 - MS000 - US210
...
Where am I wrong?