[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#919019: Interval timers with CLOCK_*_CPUTIME_ID fail to reschedule with 4.19.13-1



Package: linux-image-4.19.0-1-amd64
Version: 4.19.13-1

The attached test program should print about 100 lines each for "Hit
CLOCK_MONOTONIC!", "Hit CLOCK_PROCESS_CPUTIME_ID!", and "Hit
CLOCK_THREAD_CPUTIME_ID!".

On my laptop running kernel linux-image-4.19.0-1-amd64 version
4.19.13-1, however, it prints the ~100 for CLOCK_MONOTONIC but only one
each for CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID.

On a VirtualBox virtual machine, freshly installed and dist-upgraded to
sid, I see the same thing. Downgrading to version 4.19.12-1 from
https://snapshot.debian.org/package/linux-signed-amd64/4.19.12%2B1/#linux-image-4.19.0-1-amd64_4.19.12-1
(and rebooting, of course) causes the test program to give the expected
output.

I don't know if this was something broken upstream or if it's something
specific to Debian's kernel package. Please forward upstream if
appropriate. Thanks!
/* Compile:
   gcc foo.c -o foo -lrt
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <time.h>

void handle_event( union sigval sv ) {
    printf( "Hit %s!\n", (const char *)sv.sival_ptr );
}

void test( const char *name, clockid_t clock_id ) {
    timer_t timer;
    struct sigevent ev;
    struct itimerspec start = { { 0, 20000000 }, { 0, 20000000 } };
    struct itimerspec zero = { { 0, 0 }, { 0, 0 } };
    struct timespec ts0, ts1;

    printf( "Testing %s...\n", name );

    memset( &ev, 0, sizeof(ev) );
    ev.sigev_notify = SIGEV_THREAD;
    ev.sigev_notify_function = handle_event;
    ev.sigev_value.sival_ptr = (void *)name;

    if ( timer_create( clock_id, &ev, &timer ) != 0 ) {
        fprintf( stderr, "Failed to create %s timer: %s\n", name, strerror( errno ) );
        return;
    }
    if ( timer_settime( timer, 0, &start, NULL ) != 0 ) {
        fprintf( stderr, "Failed to start %s timer: %s\n", name, strerror( errno ) );
        return;
    }

    clock_gettime( clock_id, &ts0 );
    ts1 = ts0;
    ts0.tv_sec += 2;
    while ( ts1.tv_sec < ts0.tv_sec || ts1.tv_sec == ts0.tv_sec && ts1.tv_nsec < ts0.tv_nsec ) {
        clock_gettime( clock_id, &ts1 );
    }

    if ( timer_settime( timer, 0, &zero, NULL ) != 0 ) {
        fprintf( stderr, "Failed to stop %s timer: %s\n", name, strerror( errno ) );
    }
    if ( timer_delete( timer ) != 0 ) {
        fprintf( stderr, "Failed to delete %s timer: %s\n", name, strerror( errno ) );
    }
    printf( "Done testing %s\n", name );
}

int main( void ) {
    test( "CLOCK_MONOTONIC", CLOCK_MONOTONIC );
    test( "CLOCK_PROCESS_CPUTIME_ID", CLOCK_PROCESS_CPUTIME_ID );
    test( "CLOCK_THREAD_CPUTIME_ID", CLOCK_THREAD_CPUTIME_ID );
    return 0;
}

Reply to: