<div dir="ltr">Hi Ben,<div class="gmail_extra"><br><div class="gmail_quote">On Mon, Mar 20, 2017 at 9:43 AM, Ben Coman <span dir="ltr"><<a href="mailto:btc@openinworld.com" target="_blank">btc@openinworld.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> <br><div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Jan 7, 2017 at 3:23 AM, Eliot Miranda <span dir="ltr"><<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div>First of all, for the <span class="m_5992679420728115648gmail-il">heartbeat</span> <span class="m_5992679420728115648gmail-il">thread</span> to work reliably it must run at higher priority than the <span class="m_5992679420728115648gmail-il">thread</span> running Smalltalk code.  </div></blockquote><div><br></div><div><div class="gmail_extra">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. </div></div><div class="gmail_extra"><br></div><div class="gmail_extra">[1] <a href="http://www.isical.ac.in/~mandar/os/scheduling-linux.pdf" target="_blank">http://www.isical.ac.in/~<wbr>mandar/os/scheduling-linux.pdf</a></div><div class="gmail_extra">[2] <a href="https://www.cs.columbia.edu/~smb/classes/s06-4118/l13.pdf" target="_blank">https://www.cs.columbia.<wbr>edu/~smb/classes/s06-4118/l13.<wbr>pdf</a></div><div class="gmail_extra">[3] <a href="http://stackoverflow.com/questions/25577403/how-are-dynamic-priorities-of-threads-computed-in-linux-2-6-x" target="_blank">http://stackoverflow.com/<wbr>questions/25577403/how-are-<wbr>dynamic-priorities-of-threads-<wbr>computed-in-linux-2-6-x</a><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div>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 <span class="m_5992679420728115648gmail-il">heartbeat</span> <span class="m_5992679420728115648gmail-il">thread</span> from running unless the <span class="m_5992679420728115648gmail-il">heartbeat</span> <span class="m_5992679420728115648gmail-il">thread</span> 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 <span class="m_5992679420728115648gmail-il">thread</span> it would suffer the same issue; compute intensive code would block the event collection <span class="m_5992679420728115648gmail-il">thread</span> unless it was running at higher priority).</div></blockquote></div><div class="gmail_extra"><br></div><div class="gmail_extra">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.   </div><div class="gmail_extra"><br></div><div class="gmail_extra"><br></div><div class="gmail_extra">$vi dynamicPriorityHeartbeat.c</div><div class="gmail_extra"><br></div><div class="gmail_extra"><div class="gmail_extra">#include <stdio.h></div><div class="gmail_extra">#include <sys/time.h></div><div class="gmail_extra">#include <stdlib.h></div><div class="gmail_extra">#include <time.h></div><div class="gmail_extra">#include <pthread.h></div><div class="gmail_extra"><br></div><div class="gmail_extra">struct timespec programStartTime;</div><div class="gmail_extra">int heartbeat, heartbeatCount;</div><div class="gmail_extra"><br></div><div class="gmail_extra"><br></div><div class="gmail_extra">double elapsed(struct timespec start, struct timespec end)</div><div class="gmail_extra">{</div><div class="gmail_extra">        struct timespec temp;</div><div class="gmail_extra">        double elapsed;</div><div class="gmail_extra">        temp.tv_sec = end.tv_sec-start.tv_sec;</div><div class="gmail_extra">        temp.tv_nsec = end.tv_nsec-start.tv_nsec;</div><div class="gmail_extra">        if (temp.tv_nsec < 0)</div><div class="gmail_extra">        {       temp.tv_nsec += 1000 * 1000 * 1000;</div><div class="gmail_extra">                temp.tv_sec -= 1;</div><div class="gmail_extra">        }</div><div class="gmail_extra">        elapsed = temp.tv_nsec / 1000 / 1000 ;</div><div class="gmail_extra">        elapsed = temp.tv_sec + elapsed / 1000;</div><div class="gmail_extra">        return elapsed;</div><div class="gmail_extra">}</div><div><br></div><div><br></div></div></div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra">void *heart()</div><div class="gmail_extra">{</div><div class="gmail_extra">    int i;</div><div class="gmail_extra">    for(i=0; i<=heartbeatCount; i++)</div><div class="gmail_extra">    {</div><div class="gmail_extra">        printf("Heartbeat %02d ", i);</div><div class="gmail_extra">        heartbeat=1;</div><div class="gmail_extra">        usleep(500000);</div><div class="gmail_extra">    }</div><div class="gmail_extra">    heartbeat=0;</div><div class="gmail_extra">    exit(0);</div><div class="gmail_extra">}</div><div><br></div><div><br></div><div><div>void runSmalltalk()</div><div>{</div><div>    struct timespec heartbeatTime;</div><div>    double intenseComputation;</div><div><br></div><div>    intenseComputation=0;</div><div>    while(1)</div><div>    {</div><div>        if(!heartbeat)</div><div>        {</div><div>            intenseComputation += 1;</div><div>        }</div><div>        else</div><div>        {</div><div>            heartbeat=0;</div><div>            clock_gettime(CLOCK_REALTIME, &heartbeatTime);</div><div>            printf("woke at time %f ", elapsed(programStartTime,<wbr>heartbeatTime));</div><div>            printf("intenseComputation=%f\<wbr>n", intenseComputation);</div><div>        }</div><div>    }</div><div>}</div></div><div><br></div><div><br></div><div><div>int main(int argc, char *argv[])</div><div>{</div><div>    clock_gettime( CLOCK_REALTIME, &programStartTime);</div><div>    if(argc<2)</div><div>    {       printf("Usage: %s heartbeatCount\n", argv[0]);</div><div>            exit(1);</div><div>    }</div><div>    heartbeatCount = atoi(argv[1]);</div><div>    heartbeat=0;</div><div><br></div><div>    pthread_t heartbeatThread;</div><div>    if(pthread_create(&<wbr>heartbeatThread, NULL, heart, NULL))</div><div>    {</div><div>        fprintf(stderr, "Error creating thread\n");</div><div>        return 1;</div><div>    }</div><div><br></div><div>    runSmalltalk();</div><div>}</div></div><div>//////////////////////////////<wbr>///////////</div><div><br></div><div><br></div><div>$ gcc dynamicPriorityHeartbeat.c -lpthread && ./a.out 50</div><div><br></div><div><div>Heartbeat 00 woke at time 0.000000 intenseComputation=19006.<wbr>000000</div><div>Heartbeat 01 woke at time 0.500000 intenseComputation=124465517.<wbr>000000</div><div>Heartbeat 02 woke at time 1.000000 intenseComputation=248758350.<wbr>000000</div><div>Heartbeat 03 woke at time 1.500000 intenseComputation=373112100.<wbr>000000</div><div>Heartbeat 04 woke at time 2.000000 intenseComputation=495566843.<wbr>000000</div><div>Heartbeat 05 woke at time 2.500000 intenseComputation=619276640.<wbr>000000</div></div><div>....</div><div><div>Heartbeat 45 woke at time 22.503000 intenseComputation=5583834266.<wbr>000000</div><div>Heartbeat 46 woke at time 23.003000 intenseComputation=<a href="tel:(570)%20807-9390" value="+15708079390" target="_blank">5708079390</a>.<wbr>000000</div><div>Heartbeat 47 woke at time 23.503000 intenseComputation=5831910783.<wbr>000000</div><div>Heartbeat 48 woke at time 24.003000 intenseComputation=5955439495.<wbr>000000</div><div>Heartbeat 49 woke at time 24.503000 intenseComputation=<a href="tel:(607)%20875-2118" value="+16078752118" target="_blank">6078752118</a>.<wbr>000000</div><div>Heartbeat 50 woke at time 25.003000 intenseComputation=<a href="tel:(620)%20252-7610" value="+16202527610" target="_blank">6202527610</a>.<wbr>000000</div></div><div><br></div><div><br></div><div>Those times a quite regular. A drift of 3 milliseconds over 25 seconds (0.012%).  </div><div>It seems the intense computation in the main thread does not block timely events in the heatbeat thread.<br></div><div><div><br></div></div><div>Perhaps the heatbeat thread needed it static priority managed manually for with Linux 2.4,</div><div>but maybe that is not required in 2.6 ??</div></div></div></div></blockquote><div><br></div><div>I wonder what happens if and when the main thread starts idling?  Then there's the concern that while it *may* just happen to work in particular schedulers it won't work if there's a scheduler change.  It seems to me that the safe thing is to use priorities and be sure.  But you should easily be able to test the scheme above by modifying the VM to create a heartbeat thread at the same priority as the main thread and then give it some effectively infinite computation that won't cause an interrupt by itself and see if you can interrupt it.  e.g.</div><div><br></div><div>SmallInteger minVal to: SmallInteger maxVal do:</div><div>    [:i| | sum |</div><div>     sum := 0.</div><div>     0 to: SmallInteger maxVal // 2 do:</div><div>        [:j|</div><div>         sum := j even ifTrue: [sum + j] ifFalse: [sum - j]]]</div><div><br></div><div>This loop shouldn't do any allocations so shouldn't cause a scavenging GC, which would cause an interrupt check.  So if you can break into this one in your modified VM then I'd say it was worth experimenting further with your scheme.</div><div>  </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_extra"><div>cheers -ben</div></div></div></div></blockquote><div><br></div></div><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div></div>