Web lists-archives.com

pthread_cond_timedwait with setclock(CLOCK_MONOTONIC) times out early




I have isolated a problem in pthread_cond_timedwait when the condattr
is used to set the clock type to CLOCK_MONOTONIC.  In this case even
though a target time point in the future is specified, the call
returns ETIMEDOUT but a subsequent call to
clock_gettime(CLOCK_MONOTONIC) shows the desired time point was not
reached.

$ gcc timed_wait_short.c -o timed_wait_short
$ ./timed_wait_short.exe
 begin:     521036s  122315900n
target:     521036s  172315900n
   end:     521036s  173293100n
    ok: true
 begin:     521036s  174872400n
target:     521036s  224872400n
   end:     521036s  224378900n
    ok: false
Jim@pulsar /cygdrive/c/users/jim/desktop
$ ./timed_wait_short.exe
 begin:     521052s   95953200n
target:     521052s  145953200n
   end:     521052s  145284000n
    ok: false
Jim@pulsar /cygdrive/c/users/jim/desktop
$ ./timed_wait_short.exe
 begin:     521056s  396277200n
target:     521056s  446277200n
   end:     521056s  446664700n
    ok: true
 begin:     521056s  454535100n
target:     521056s  504535100n
   end:     521056s  504567000n
    ok: true
 begin:     521056s  510360800n
target:     521056s  560360800n
   end:     521056s  560555600n
    ok: true
 begin:     521056s  566604400n
target:     521056s  616604400n
   end:     521056s  616622800n
    ok: true
 begin:     521056s  619277800n
target:     521056s  669277800n
   end:     521056s  669646400n
    ok: true
 begin:     521056s  671907500n
target:     521056s  721907500n
   end:     521056s  721578000n
    ok: false

I have attached the source code.

Cygwin DLL version info:
        DLL version: 2.11.2
        DLL epoch: 19
        DLL old termios: 5
        DLL malloc env: 28
        Cygwin conv: 181
        API major: 0
        API minor: 329
        Shared data: 5
        DLL identifier: cygwin1
        Mount registry: 3
        Cygwin registry name: Cygwin
        Installations name: Installations
        Cygdrive default prefix:
        Build date:
        Shared id: cygwin1S5
/*
 * Copyright (C) 2018 James E. King III
 * 
 * This test exposes a problem in cygwin's condition variable clock
 * handling when setclock(CLOCK_MONOTONIC) is used on the attribute.
 *
 * Although ETIMEDOUT is being returned by pthread_cond_timedwait,
 * a subsequent fetch of the clock shows that the time point was not
 * reached.
 */

#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <time.h>

int main()
{
    int ok;
    pthread_cond_t cv;
    pthread_condattr_t attr;
    pthread_mutex_t m;
    
    assert(!pthread_condattr_init(&attr));
    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
    assert(!pthread_mutex_init(&m, NULL));
    assert(!pthread_cond_init(&cv, &attr));
    pthread_condattr_destroy(&attr);
    assert(!pthread_mutex_lock(&m));
    
    do
    {
        struct timespec ts_begin;
        struct timespec ts_target;
        struct timespec ts_end;
    
        assert(!clock_gettime(CLOCK_MONOTONIC, &ts_begin));

        ts_target = ts_begin;
        ts_target.tv_nsec += 50000000; // add 50ms
        if (ts_target.tv_nsec >= 1000000000)
        {
            ++ts_target.tv_sec;
            ts_target.tv_nsec -= 1000000000;
        }
        assert(ETIMEDOUT == pthread_cond_timedwait(&cv, &m, &ts_target));

        assert(!clock_gettime(CLOCK_MONOTONIC, &ts_end));
    
        ok = ts_end.tv_sec > ts_target.tv_sec ||
            (ts_end.tv_sec == ts_target.tv_sec && ts_end.tv_nsec >= ts_target.tv_nsec);
    
        printf(" begin: %10us %10un\n",  ts_begin.tv_sec,  ts_begin.tv_nsec);
        printf("target: %10us %10un\n", ts_target.tv_sec, ts_target.tv_nsec);
        printf("   end: %10us %10un\n",    ts_end.tv_sec,    ts_end.tv_nsec);
        printf("    ok: %s\n", ok ? "true" : "false");
    
    } while (ok);

    pthread_mutex_unlock(&m);
    pthread_mutex_destroy(&m);
    pthread_cond_destroy(&cv);

    return !ok;
}

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple