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: