[Vm-dev] Unix heartbeat thread vs itimer

Ben Coman btc at openinworld.com
Mon Mar 20 16:43:21 UTC 2017


On Sat, Jan 7, 2017 at 3:23 AM, Eliot Miranda <eliot.miranda at gmail.com>
wrote:

> First of all, for the heartbeat thread to work reliably it must run at
> higher priority than the thread running Smalltalk code.
>

After reading pages 11-14 of [1] , page 11 of [2] , and then [3] I was
wondering if the dynamic priorities of the Linux 2.6 scheduler would cause
a sleeping heartbeat thread to *effectively* remain a higher priority than
the Smalltalk execution thread.

[1] http://www.isical.ac.in/~mandar/os/scheduling-linux.pdf
[2] https://www.cs.columbia.edu/~smb/classes/s06-4118/l13.pdf
[3]
http://stackoverflow.com/questions/25577403/how-are-dynamic-priorities-of-threads-computed-in-linux-2-6-x


> This is because its job is to cause Smalltalk code to break out at regular
> intervals to check for events.  If the Smalltalk code is compute-intensive
> then it will prevent the heartbeat thread from running unless the
> heartbeat thread is running at a higher priority, and so it will be
> impossible to receive input keys, etc. (Note that if event collection was
> in a separate thread it would suffer the same issue; compute intensive
> code would block the event collection thread unless it was running at
> higher priority).
>

So I contrived the experiment below.  I'm not sure it properly represents
what is happening with the threaded heartbeat, but it still may make
interesting discussion.


$vi dynamicPriorityHeartbeat.c

#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

struct timespec programStartTime;
int heartbeat, heartbeatCount;


double elapsed(struct timespec start, struct timespec end)
{
        struct timespec temp;
        double elapsed;
        temp.tv_sec = end.tv_sec-start.tv_sec;
        temp.tv_nsec = end.tv_nsec-start.tv_nsec;
        if (temp.tv_nsec < 0)
        {       temp.tv_nsec += 1000 * 1000 * 1000;
                temp.tv_sec -= 1;
        }
        elapsed = temp.tv_nsec / 1000 / 1000 ;
        elapsed = temp.tv_sec + elapsed / 1000;
        return elapsed;
}


void *heart()
{
    int i;
    for(i=0; i<=heartbeatCount; i++)
    {
        printf("Heartbeat %02d ", i);
        heartbeat=1;
        usleep(500000);
    }
    heartbeat=0;
    exit(0);
}


void runSmalltalk()
{
    struct timespec heartbeatTime;
    double intenseComputation;

    intenseComputation=0;
    while(1)
    {
        if(!heartbeat)
        {
            intenseComputation += 1;
        }
        else
        {
            heartbeat=0;
            clock_gettime(CLOCK_REALTIME, &heartbeatTime);
            printf("woke at time %f ",
elapsed(programStartTime,heartbeatTime));
            printf("intenseComputation=%f\n", intenseComputation);
        }
    }
}


int main(int argc, char *argv[])
{
    clock_gettime( CLOCK_REALTIME, &programStartTime);
    if(argc<2)
    {       printf("Usage: %s heartbeatCount\n", argv[0]);
            exit(1);
    }
    heartbeatCount = atoi(argv[1]);
    heartbeat=0;

    pthread_t heartbeatThread;
    if(pthread_create(&heartbeatThread, NULL, heart, NULL))
    {
        fprintf(stderr, "Error creating thread\n");
        return 1;
    }

    runSmalltalk();
}
/////////////////////////////////////////


$ gcc dynamicPriorityHeartbeat.c -lpthread && ./a.out 50

Heartbeat 00 woke at time 0.000000 intenseComputation=19006.000000
Heartbeat 01 woke at time 0.500000 intenseComputation=124465517.000000
Heartbeat 02 woke at time 1.000000 intenseComputation=248758350.000000
Heartbeat 03 woke at time 1.500000 intenseComputation=373112100.000000
Heartbeat 04 woke at time 2.000000 intenseComputation=495566843.000000
Heartbeat 05 woke at time 2.500000 intenseComputation=619276640.000000
....
Heartbeat 45 woke at time 22.503000 intenseComputation=5583834266.000000
Heartbeat 46 woke at time 23.003000 intenseComputation=5708079390.000000
Heartbeat 47 woke at time 23.503000 intenseComputation=5831910783.000000
Heartbeat 48 woke at time 24.003000 intenseComputation=5955439495.000000
Heartbeat 49 woke at time 24.503000 intenseComputation=6078752118.000000
Heartbeat 50 woke at time 25.003000 intenseComputation=6202527610.000000


Those times a quite regular. A drift of 3 milliseconds over 25 seconds
(0.012%).
It seems the intense computation in the main thread does not block timely
events in the heatbeat thread.

Perhaps the heatbeat thread needed it static priority managed manually
for with Linux 2.4,
but maybe that is not required in 2.6 ??

cheers -ben
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20170321/7f6e65ac/attachment-0001.html>


More information about the Vm-dev mailing list