Andreas,
Thank you for the explanation. I was wondering a few things.
why do scripts have to run in the wild? you provide an initial moment when the script is running to initialize itself and schedule. Is it needed? why not run your own scheduling script at a higher priority? It would grab any newScript requests and schedule them..resuming the suspended script.
what am I missing?
cheers, rob
On Sunday, February 16, 2003, at 05:00 PM, Andreas Raab wrote:
Rob,
The most important thing first:
Ok, that works, but how is that guaranteed?
Yes, yes, and yes. It is THE fundamental invariant. Scripts are only interrupted if they block. #startScript: is non-blocking. Period. What follows are mere details of how this is implemented ;-)
[Note: Read up to the end of the message before replying - various questions might be answered further down the line]
I have a few questions. I don't think this is a good thing for the eventual event-loop. This is interrupting the current script and I don't think there are any guarantees that the currentScript will be the first script resumed after the new script is scheduled. Is there?
As far as the "user script" (namely: the payload of the process) is concerned, #startScript: is immediate (non-blocking). It is the implementation of the synchronization semantics which will temporarily suspend the invoking user script but do so in a way that it is invisible from the client. The implementation essentially does:
- script1 issues #startScript:
===== system level ==== this is where the synchronization semantics starts. in order to preserve ordering of scripts the following happens:
- #startScript: creates a new script (script2) with a higher(!)
priority than script1 (Processor>>initialScriptPriority)
- script2 preempts script1
- script2 schedules itself with the scheduler
- script2 suspends itself (in scheduler's activeList)
===== user level =====
- script1 continues happily as if never interrupted
[... some time later ...]
- script2 gets its slot
===== system level ====
- script2 resets its priority down(!) to regular user script priority
===== user level ====
- script2 delivers payload
To get the scheduling semantics right, I am playing with process priorities. As long as scripts are "out in the wild" (that is: not controlled by the script processor) they run at higher priority. This happens only in two places: Immediately after their creation (in which case they need to schedule themselves) or inside "primitive waits". In both cases the priority is bumped up in order to ensure that there can be only a single script "out in the wild" and that this script reschedules itself as quickly as it can with the script scheduler. [Slight OT: There *is* a chance that two scripts are "in the wild" if both get released after waiting on a semaphore. However, in this case the user code cannot decide "which one was first" so ordering does not matter. For issuing #startScript: however, this will never happen, since #startScript: is only issued from scripts which aren't "out in the wild"].
There are many, many subtleties in this regime. I went to great length to make this work "just right".
There may be a third script which is scheduled ahead of the currentScript.
No. There is no way that this can happen. Literally. The scheduler process even runs at a lower priority than the script processes (once more: priorities are our friends ;) in order to ensure that a new script is only scheduled if the current script is blocking or completed. Using priorities ensures this invariant primitively and avoids needless synchronization of script/processor.
How does the suspension of a script schedule the script for resumption?
The script reschedules itself. When a script blocks, it always waits on some semaphore (this is the only way any process in Squeak can block). When this happens, the hooks within #beginWaitOn: and #endWaitOn: kick in. They provide the appropriate rescheduling semantics by bumping the priority up for the wait (the script is now "in the wild" since we don't know when it will become resumed primitively) and rescheduling itself (and reducing the priority) once it wakes up again.
One exception: Scripts inside critical sections *must* be run in the wild. The reason being that we would deadlock otherwise (I tried it ;)
Is there no way to schedule the new script without making it the activeScript?
You never schedule a new script and "automatically" make it the active script. When you schedule a script then (as the name "scheduling" says) its get added to the list of scripts that may be run as soon as the current one completes. Or do you mean "without adding it to the activeList"?!
Cheers,
- Andreas
Squeak-e mailing list Squeak-e@lists.squeakfoundation.org http://lists.squeakfoundation.org/listinfo/squeak-e