On 17-Apr-06, at 2:00 PM, Ian Piumarta wrote:
Hi John,
This is a bit unclear, all this is doing is forcing a call to ioProcessEvents()
Did you read the message to David Reed that I copied you on earlier today?
Cheers, Ian
mmm
ok let me say
ioProcessEvents() is a null call on os-x.
you have some other magic you are expecting it to do?
-- ======================================================================== === John M. McIntosh johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===
John M McIntosh wrote:
ioProcessEvents() is a null call on os-x.
you have some other magic you are expecting it to do?
How do you deal with sockets? I thought you were using the Unix socket code which relies on aio* and which is commonly called in ioProcessEvents. If not there, where *do* you call it? ;-)
Cheers, - Andreas
For some reason lost in time, it's called only in
ioGetNextEvent()
I do think here if you want a specialized call to process socket events what about a flag aioPollNeeded and set that to true, then check for that in checkForInterrupts() Otherwise you end up with ioProcessEvents() being called say oh 10,000 a second if there are lots of socket events happening? and just because ioProcessEvents() handles sockets doesn't mean it might be doing other things which are assuming a low calling rate.
On 17-Apr-06, at 2:19 PM, Andreas Raab wrote:
John M McIntosh wrote:
ioProcessEvents() is a null call on os-x. you have some other magic you are expecting it to do?
How do you deal with sockets? I thought you were using the Unix socket code which relies on aio* and which is commonly called in ioProcessEvents. If not there, where *do* you call it? ;-)
Cheers,
- Andreas
-- ======================================================================== === John M. McIntosh johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===
Hi John -
I do think here if you want a specialized call to process socket events what about a flag aioPollNeeded and set that to true, then check for that in checkForInterrupts() Otherwise you end up with ioProcessEvents() being called say oh 10,000 a second if there are lots of socket events happening? and just because ioProcessEvents() handles sockets doesn't mean it might be doing other things which are assuming a low calling rate.
Yes, this could be done but the "minimally invasive" solution of resetting nextPollTick seems pretty good in my understanding. Mostly because a) a platform doesn't have to force an interrupt check if it can't handle 10k queries a second and b) if it's really that slow in a part of ioProcessEvents it could use a timer or somesuch to not overdo the polling.
If we would change that, we probably should factor this so that we have a call to ioProcessInterrupts() being called from checkForInterrupts() (instead of ioProcessEvents) so that the platform code can decide what is proper to do in an interrupt check vs. what is proper to do in a "full" event query. In practice, I'd expect the two to be the same however.
Having said that, let me add that all *I* care about right now, is VMs that pass the Croquet VM tests ;-) The first solution has already been proven to do that so I have a clear preference for having that solution *right now* simply because I've already seen it working.
Cheers, - Andreas
On Apr 17, 2006, at 2:30 PM, John M McIntosh wrote:
For some reason lost in time, it's called only in
ioGetNextEvent()
I do think here if you want a specialized call to process socket events what about a flag aioPollNeeded and set that to true, then check for that in checkForInterrupts()
One obvious condition would be to set the flag when external semaphores are registered. That might be messier than just resetting nextPollTick.
Otherwise you end up with ioProcessEvents() being called say oh 10,000 a second if there are lots of socket events happening? and just because ioProcessEvents() handles sockets doesn't mean it might be doing other things which are assuming a low calling rate.
The question is how to separate things the image/Interpreter know most about from things the support knows most about, and keeping the assumptions between them as simple as possible.
If the support is doing some expensive operation in ioProcessEvents, maybe the support should arrange to limit the frequency of these operations rather than trying to communicate something back to the Interpreter to affect the frequency indirectly. OTOH, assuming that ioProcessEvents is either (1) expensive or (2) not performing a time- critical poll of activity (in the absence of any other easy means to perform such a poll) is also a bad mistake on the part of the Interpreter.
Arranging for forceInterruptCheck to cause an ioProcessEvents at the earliest opportunity seems to me to make the fewest assumptions across the Interperter/support barrier. The support code knows what it's doing in calling forceIntrCheck, and can take steps to compensate for the frequency of ioProcessEvents if necessary. (The nextPollTick logic would, I suspect, be far better in ioProcessEvents than in checkForInterrupts.)
If you have a simpler solution I'd be eager to hear it.
Cheers, Ian
On 17-Apr-06, at 2:53 PM, Ian Piumarta wrote:
Otherwise you end up with ioProcessEvents() being called say oh 10,000 a second if there are lots of socket events happening? and just because ioProcessEvents() handles sockets doesn't mean it might be doing other things which are assuming a low calling rate.
The question is how to separate things the image/Interpreter know most about from things the support knows most about, and keeping the assumptions between them as simple as possible.
If the support is doing some expensive operation in ioProcessEvents, maybe the support should arrange to limit the frequency of these operations rather than trying to communicate something back to the Interpreter to affect the frequency indirectly. OTOH, assuming that ioProcessEvents is either (1) expensive or (2) not performing a time-critical poll of activity (in the absence of any other easy means to perform such a poll) is also a bad mistake on the part of the Interpreter.
Arranging for forceInterruptCheck to cause an ioProcessEvents at the earliest opportunity seems to me to make the fewest assumptions across the Interperter/support barrier. The support code knows what it's doing in calling forceIntrCheck, and can take steps to compensate for the frequency of ioProcessEvents if necessary. (The nextPollTick logic would, I suspect, be far better in ioProcessEvents than in checkForInterrupts.)
If you have a simpler solution I'd be eager to hear it.
ioProcessEvents had an implied expense which is why it was only checked every 500 ms, or what ever.
What I'd suggest here is setting a aioPollNeed flag
have forceaioPoll() that does set the aioPollNeed flag calls forceInterruptCheck()
in checkForInterrupts() check aioPollNeed, if true call aioPoll() and reset.
Cheers, Ian
-- ======================================================================== === John M. McIntosh johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===
Hi John -
What I'd suggest here is setting a aioPollNeed flag
have forceaioPoll() that does set the aioPollNeed flag calls forceInterruptCheck()
in checkForInterrupts() check aioPollNeed, if true call aioPoll() and reset.
What for? We can just call ioProcessInterrupts() no matter what. If you really need to have extra tests for aio you can implement them in the support code, e.g.,
ioProcessInterrupts() { if(aioPollNeeded) aioPoll(); }
and leave the main VM without further modifications (I really dislike adding such unnecessary extensions to the VM itself - it's up to the support code to behave as stated, and if the stated behavior is to get out quickly, well, then the support code should just comply).
Cheers, - Andreas
The other thing I'm confused about is that in the past ioRelinquishProcessorForMicroseconds()
where we would calculate the pending wakeup time based on my thoughts of a few years ago then we would have said aioPoll(realTimeToWait)....
and the aioPoll() logic would do it's thing for the supposed set of micro seconds.
However now I see that this has changed to:
if (!aioPoll(0)) { struct timespec rqtp= { 0, realTimeToWait * 1000*1000 }; struct timespec rmtp; while ((nanosleep(&rqtp, &rmtp) < 0) && (errno == EINTR)) rqtp= rmtp; }
so why the change not to have the select() do the sleep?
what are the conditions that would cause aioPoll() to return 0, thus invoking this nanosleep and if the nanosleep is invoked, would 16 ms pass before servicing a socket? if realTimeToWait is 16ms?
On 17-Apr-06, at 2:19 PM, Andreas Raab wrote:
John M McIntosh wrote:
ioProcessEvents() is a null call on os-x. you have some other magic you are expecting it to do?
How do you deal with sockets? I thought you were using the Unix socket code which relies on aio* and which is commonly called in ioProcessEvents. If not there, where *do* you call it? ;-)
Cheers,
- Andreas
-- ======================================================================== === John M. McIntosh johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===
On Apr 17, 2006, at 2:56 PM, John M McIntosh wrote:
However now I see that this has changed to:
if (!aioPoll(0)) { struct timespec rqtp= { 0, realTimeToWait * 1000*1000 }; struct timespec rmtp; while ((nanosleep(&rqtp, &rmtp) < 0) && (errno == EINTR)) rqtp= rmtp; }
so why the change not to have the select() do the sleep?
Because select() cannot guarantee granularity of less than a timeslice once it has decided to go to sleep (hence the test just above that code for ms < timeslice quantum). You were sitting in my office when we proved this.
what are the conditions that would cause aioPoll() to return 0
No pending i/o activity on any open descriptors.
and if the nanosleep is invoked, would 16 ms pass before servicing a socket? if realTimeToWait is 16ms?
Not necessarily. If your kernel is clever enough to return early from nanosleep when a signal is delivered then socket i/o will have minimum latency. (On OSX this appears to be the case: nanosleep can return -1 and set errno to EINTR.)
Cheers, Ian
So is aioPoll() ever called with a non-zero value?
On 17-Apr-06, at 3:04 PM, Ian Piumarta wrote:
Because select() cannot guarantee granularity of less than a timeslice once it has decided to go to sleep (hence the test just above that code for ms < timeslice quantum). You were sitting in my office when we proved this.
-- ======================================================================== === John M. McIntosh johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===
On Apr 17, 2006, at 3:08 PM, John M McIntosh wrote:
So is aioPoll() ever called with a non-zero value?
Yes. The line after the code you quoted is
dpy->ioRelinquishProcessorForMicroseconds(ms*1000);
which defers to the active display driver. When the display is X11 (for example), the above calls
static sqInt display_ioRelinquishProcessorForMicroseconds(sqInt microSeconds) { aioPoll(handleEvents() ? 0 : microSeconds); return 0; }
in sqUnixX11.c.
Cheers, Ian
Ahh?
so if next wakeup tick is less than 16ms then call aioPoll(0) then nanosleep for upto 16ms ish then call aioPoll(0) mmm I guess that services any interrupt that woke things up. and if greater than 16ms you end up sleeping in select() via callling aioPoll(waitfor).
mind I didn't look to see what handleEvents() does... Perhaps you never sleep?
Any chance you could fold the nanosleep back into the aioPoll() logic instead of making it a special case outside of select logic in aioPoll()
On 17-Apr-06, at 3:21 PM, Ian Piumarta wrote:
On Apr 17, 2006, at 3:08 PM, John M McIntosh wrote:
So is aioPoll() ever called with a non-zero value?
Yes. The line after the code you quoted is
dpy->ioRelinquishProcessorForMicroseconds(ms*1000);
which defers to the active display driver. When the display is X11 (for example), the above calls
static sqInt display_ioRelinquishProcessorForMicroseconds(sqInt microSeconds) { aioPoll(handleEvents() ? 0 : microSeconds); return 0; }
in sqUnixX11.c.
Cheers, Ian
-- ======================================================================== === John M. McIntosh johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===
On Apr 17, 2006, at 3:38 PM, John M McIntosh wrote:
so if next wakeup tick is less than 16ms then call aioPoll(0) then nanosleep for upto 16ms ish then call aioPoll(0) mmm I guess that services any interrupt that woke things up. and if greater than 16ms you end up sleeping in select() via callling aioPoll(waitfor).
I couldn't have described it better.
mind I didn't look to see what handleEvents() does... Perhaps you never sleep?
handleEvents() returns 1 if any UI events came in (or if the event buffer is not empty), otherwise 0 to indicate no UI activity to worry about.
In other words, ioRelinquishProc only sleeps if there is no UI activity and no descriptor is ready for a pending i/o operation.
Any chance you could fold the nanosleep back into the aioPoll() logic instead of making it a special case outside of select logic in aioPoll()
Would this be particularly helpful to you? I never call aioPoll() with non-zero from anywhere except relinquishProc, so for me it's better being outside aioPoll. But if you'd find it useful inside aioPoll then I don't think moving it there would break anything.
Cheers, Ian
On 17-Apr-06, at 3:47 PM, Ian Piumarta wrote:
Any chance you could fold the nanosleep back into the aioPoll() logic instead of making it a special case outside of select logic in aioPoll()
Would this be particularly helpful to you? I never call aioPoll() with non-zero from anywhere except relinquishProc, so for me it's better being outside aioPoll. But if you'd find it useful inside aioPoll then I don't think moving it there would break anything.
Cheers, Ian
That would be better, then no chance to miss a change later, so if I call aioPoll(0) you do the right thing and if I call aioPoll(timeToWait) then you wait N ms unless I guess an event comes in that needs to be processed thus terminating the wait.
-- ======================================================================== === John M. McIntosh johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===
On Apr 17, 2006, at 3:57 PM, John M McIntosh wrote:
Would this be particularly helpful to you? I never call aioPoll() with non-zero from anywhere except relinquishProc, so for me it's better being outside aioPoll. But if you'd find it useful inside aioPoll then I don't think moving it there would break anything.
That would be better, then no chance to miss a change later, so if I call aioPoll(0) you do the right thing and if I call aioPoll(timeToWait) then you wait N ms unless I guess an event comes in that needs to be processed thus terminating the wait.
Checked-in, but you'll want to call aioSleep() rather than aioPoll().
Cheers, Ian
k, thank you
On 17-Apr-06, at 5:15 PM, Ian Piumarta wrote:
On Apr 17, 2006, at 3:57 PM, John M McIntosh wrote:
Would this be particularly helpful to you? I never call aioPoll () with non-zero from anywhere except relinquishProc, so for me it's better being outside aioPoll. But if you'd find it useful inside aioPoll then I don't think moving it there would break anything.
That would be better, then no chance to miss a change later, so if I call aioPoll(0) you do the right thing and if I call aioPoll(timeToWait) then you wait N ms unless I guess an event comes in that needs to be processed thus terminating the wait.
Checked-in, but you'll want to call aioSleep() rather than aioPoll().
Cheers, Ian
-- ======================================================================== === John M. McIntosh johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===
vm-dev@lists.squeakfoundation.org