Squeak SmalltalkJoker Squeak Smalltalk : System : prevnext Serial Port Reading Semaphore Timer Accuracy

I compared with Jon Hylands and discovered a big difference between my Ubuntu 
and his Windows results.

Time millisecondsToRun: [10 timesRepeat: [(Delay forMilliseconds: 1000) wait]] 
10015

Time millisecondsToRun: [100 timesRepeat: [(Delay forMilliseconds: 100) wait]] 
 10015

Time millisecondsToRun: [1000 timesRepeat: [(Delay forMilliseconds: 10) wait]] 
 13405

Time millisecondsToRun: [10000 timesRepeat: [(Delay forMilliseconds: 1) wait]] 
 45728

He did the third test and got something like 10250 instead of my 13405.

Is this behavior well-known and understood or is there something wrong with my 
install?

---

This is a very well known issue. Different operating systems have very 
different minimal timer resolutions. Generally speaking, on Windows and 
Mac OS the timer resolution is very close to 1ms whereas most Linux 
kernels have *awful* timer resolutions. I have been told that you can 
recompile your kernel to fix it but I'm not sure how. The classic 
benchmark to verify your timer accuracy is to do something like here:

	delay := Delay forMilliseconds: 1.
	bag := Bag new.
	1000 timesRepeat:[bag add: [delay wait] timeToRun].
	bag sortedCounts

On my box it yields "a SortedCollection(941->1 51->2 8->3)" which means 
that 94.1% of the delays are true 1msec delays.

---

What you want is the ability for a serial port
to issue an interrupt / signal a semaphore so that your waiting process
gets woken up when something happens. The way to do this is by fixing
the (very, very naive) serial port primitives to add something that
allows you to signal a semaphore upon data availability. There are
examples for this kind of thing in other plugins (like the socket or
async file plugin).

Also, I vaguely remember that John had built a better serial port plugin
(don't remember where I saw this but I'm sure he'll chime in) which may
very well support this out of the box.

> I probably don't understand the primitive serial methods well enough.
> They seem not to block while awaiting input so that requires
> continuously looping to read.  Is there a blocking method?

There isn't. Since Squeak doesn't use native threads internally (instead
it uses so-called "green threads") a blocking read would block the
entire VM and completely defeat the purpose of a blocking read. That's
why all such primitives are designed to simply signal a semaphore so
that the process in squeak just sits there doing something like:

   dataArrived := Semaphore new.
   self registerSemaphoreForSignallingData: dataArrived.
   [true] whileTrue:[
      dataArrived wait.
      self processData.
   ].

etc.

Cheers,

   - Andreas