Multithreading
John M McIntosh
johnmci at smalltalkconsulting.com
Mon Mar 28 08:14:03 UTC 2005
I'll comment on how the current implementation works, hah I hope I get
most of it correct. I know other on the list are actually responsible
for it's creation.
If you load the vmmaker squeak map package you will find.
Interpreter>>transferTo: aProc
Is the method that actually transfer control between active process to
another, outside of direct control of any Smalltalk code.
This method is called via
Interpreter>>primitiveSuspend
Interpreter>>primitiveWait
Interpreter>>primitiveYield
Interpreter>>resume:
On Wait and Yield we add the current process to the end of a linked
list based on it's priority, then we wake the first runnable process
based on looking from highest to lowest priority.
If there is no runnable process the VM will quit, with 'scheduler
could not find a runnable process', readers of the list are welcome to
read the list archives to find the change set I managed to get into the
update stream which led to that condition for the first few early
adopters one weekend many years ago.
For Resume: we put the active process to sleep and run the indicated
process if the indicated process has a higher priority.
Suspend is used mostly in the interface by the debugger and
ProcessBrower to control the runability of an indicated process.
This algorithm ensures:
a) high priority processes will run first.
b) all process at a given priority level will run in round robin
fashion if process switching occurs.
When a process is resumed depends on what it is doing. It could be
waiting on a semaphore, or on a delay. Because of how resume: works a
process can become runnable but not run if a higher priority task can
run. This means of course a higher priority process that does not yield
control it will block runnable lower priority processes, or processes
at the same priority.
But if for example you have a server application that accepts incoming
requests then forks off work at a lower priority this allows the
higher priority listeners to
accept work, then lower priority tasks perform the actual work, but are
prevented from blocking higher priority process from accepting work. I
think someone earlier
commented on forking work at the user background priority to prevent
the UI from locking up.
In general most usages of yield I have seen are in endless while loops
where one polls for work churning CPU cycles as a side effect and
without the yield blocking any other runable processes. For the most
part usage of yield in the image follow this pattern.
"In Theory" there is nothing to prevent you from creating a processor
scheduler that wakes up every N milli-seconds and decides to suspend or
change the priority of the running process and picking a different
process to resume. There would be some question if this is 'safe',
however I do recall in VisualWorks at some point there was an optional
changeset to provide this functionality. 'Safe' here means when does a
process lose control and what does that mean for multi-threading. That
I can't answer, mind if someone could point to a Use case that would be
a plausible failure condition that would be interesting.
When processing switching can occur is of course a question to ask.
This occurs.
when a method send is made or
when a long unconditionalJump bytecode is executed in the backwards
direction. > 9 bytecodes?
on a primitive call if when the call takes > 1 or perhaps 17ms
depending on platform.
The checks are in Interpreter>>checkForInterrupts
I'll note we don't attempt to make decisions every time we encounter
these three conditions, rather we attempt to limit our checking every
2-3 milliseconds with some other
decision making to ensure we make the objective of giving Delay
accuracy a ms or less degree of error. This routine does things like
check for the low space, finalization, polling, interrupt key semaphore
and attempt to wake the waiting processes semaphores if required.
Usually one of the three conditions above occur within a 1 ms
timeframe.
I will note because Morphic polls for user UI events every 20 or so
milliseconds at a high priority, this ensures if you run things below
Processor lowIOPriority that a keyboard interrupt will be serviced,
this enables the stopping of most runaway processes.
Killing runaway process that have consumed all the existing memory is
another issue for another day, those become unkillable because the VM
can't service enough bytecodes fast enough to trigger the debugger.
On Mar 27, 2005, at 9:05 PM, Daniel Salama wrote:
> Ross,
>
> I asked myself the same questions. As I am new to Smalltalk, one of
> the things that attracted me to Smalltalk was that it's been around
> for so many decades. I would have assumed that this "limitation" in
> its libraries (or image(s)) as far as concurrency would have been
> resolved by now. I guess I got spoiled with some of the facilities
> available in Java.
>
> Yielding control to other processes without any guarantees that
> control will come back in a correspondingly mutual manner makes me
> just want to not even try developing anything multi-threaded friendly.
>
> As far as Seaside behavior in, I posted a similar question in
> Seaside's list
> (http://lists.squeakfoundation.org/pipermail/seaside/2005-March/
> 004685.html) but didn't really get an answer for it. I thank Avi for
> letting me know that Transcript>>show is just about the worst thing I
> could use to show status progress but no one really addressed my
> question about Seaside/Squeak/GOODS performance (even though it's all
> relative to application needs and application design).
>
> Thanks,
> Daniel
>
> On Mar 27, 2005, at 9:44 PM, Ross Boylan wrote:
>
>> This has been a very interesting thread for me. I thought squeak did
>> time-slicing. Are other smalltalks the same in not doing timeslicing?
>>
>> On Sat, Mar 26, 2005 at 08:50:46AM -0800, Tim Rowledge wrote:
>>> Daniel Salama <dsalama at user.net> wrote:
>>>
>>>> Karl,
>>>>
>>>> The problem I encountered is that while this method was executing,
>>>> Squeak was completely unresponsive. I could not open the Process
>>>> Browser, I could not do anything whatsoever in Squeak.
>>> Of course it was; there should be no surprise there at all. There is
>>> a
>>> single active process and it runs until it stops. You can make it
>>> stop
>>> temporarily by deliberately yielding occasioanlly which will give
>>
>> What actions, or types of actions, are necessary to yield control?
>>
>>> other processes a chance to hog the cpu for themselves - but if that
>>> other process doesn't play nice and yield occasionally you will still
>>> feel locked out.
>>>
>>> There is not any round-robin or timeslicing scheduling done by
>>> default.
>>> You can implement it fairly simply (google is your friend and can
>>> find
>>> many news postings on the subject over many years) if you really need
>>> it. The potential danger with using such a modifed scheduling setup
>>> is
>>> that most of the image is not multi-thread safe.
>>
>> Sounds as if it would take a big overhaul to get reliable
>> multi-threading.
>>
>>>
>>>
>>> tim
>>
>> I had understood that squeak was being used (via seaside) for web
>> servers. How do they manage to deal with processing many things at
>> once (I'm assuming they do)?
>>
>> Ross Boylan
>>
>>
>
>
>
--
========================================================================
===
John M. McIntosh <johnmci at smalltalkconsulting.com> 1-800-477-2659
Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com
========================================================================
===
More information about the Squeak-dev
mailing list
|