Hi Lou,<br><br><div class="gmail_quote">On Tue, Mar 5, 2013 at 2:38 PM, Louis LaBrunda <span dir="ltr">&lt;<a href="mailto:Lou@keystone-software.com" target="_blank">Lou@keystone-software.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I will bow to your knowledge of Squeak but take a look at the code below<br>
from VA Smalltalk.<br>
<br>
Pay special attention to #resume: which looks to me like it puts the new<br>
process at the top of the queue (there are 7 queues, one for each priority)<br>
and puts the current (activeProcess) at the bottom of the same queue and<br>
then switches to the highestPriorityProcess.  Which can be another process<br>
or the new process just put in front of the current process.<br></blockquote><div><br></div><div>thanks, that&#39;s interesting, and good to know.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
Don&#39;t ask my why it works this way.  As I said, I added #forkReady which it<br>
seems works more like Squeak.  Most of the time I think it doesn&#39;t matter<br>
but sometimes it does.<br>
<br>
Lou<br>
<br>
fork<br>
        &quot;Create a new Process which is scheduled by the<br>
         ProcessScheduler. The new process executes the receiver by<br>
         sending it the message value. The new process is created<br>
         with the same prority as the activeProcess. Answer the<br>
         receiver.&quot;<br>
<br>
        ^self newProcess resume<br>
<br>
resume<br>
        &quot;Tell the process scheduler to add the process to the ready<br>
         to run queue.&quot;<br>
<br>
        self isResumable ifFalse: [^self error: (NlsCatKRN indexedMsg: 2)].<br>
&quot;$NLS$ process cannot be resumed&quot;<br>
        Processor resume: self.<br>
        ^ self<br>
<br>
resume: aProcess<br>
<br>
        | state |<br>
        state := self enableAsyncMessages: false.<br>
        (aProcess == self activeProcess or: [aProcess isDead]) ifTrue: [<br>
                self enableAsyncMessages: state.<br>
                ^self &quot;Resuming a dead process or the active process is a nop.&quot;].<br>
<br>
        aProcess isRunable ifTrue: [<br>
                (aProcess processState: ##ready) queue addFirst: aProcess].<br>
<br>
        (self activeProcess processState: ##ready) queue addLast: self<br>
activeProcess.<br>
        self activeProcess switchTo: self highestPriorityProcess.<br>
        self enableAsyncMessages: state<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
On Tue, 5 Mar 2013 13:46:13 -0800, Eliot Miranda &lt;<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>&gt;<br>
wrote:<br>
<div class="HOEnZb"><div class="h5"><br>
&gt;On Tue, Mar 5, 2013 at 1:36 PM, Louis LaBrunda &lt;<a href="mailto:Lou@keystone-software.com">Lou@keystone-software.com</a>&gt;wrote:<br>
&gt;<br>
&gt;&gt; Hi Eliot,<br>
&gt;&gt;<br>
&gt;&gt; Thanks for all the very valuable information.  I think I didn&#39;t ask my<br>
&gt;&gt; question properly but with all the answers I was able to accomplish exactly<br>
&gt;&gt; what I wanted.<br>
&gt;&gt;<br>
&gt;&gt; I do have a question about one thing you said.  See below.<br>
&gt;&gt;<br>
&gt;&gt; Lou<br>
&gt;&gt;<br>
&gt;&gt; &gt;On Thu, Feb 28, 2013 at 2:30 PM, Bert Freudenberg &lt;<a href="mailto:bert@freudenbergs.de">bert@freudenbergs.de</a><br>
&gt;&gt; &gt;wrote:<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; On 2013-02-28, at 22:38, Louis LaBrunda &lt;Lou@Keystone-Software.com&gt;<br>
&gt;&gt; wrote:<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; &gt; If a process is running when an image is saved, is the process<br>
&gt;&gt; stopped at<br>
&gt;&gt; &gt;&gt; &gt; any point in particular?<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; The active process is stopped in the snapshot primitive (a.k.a. &quot;image<br>
&gt;&gt; &gt;&gt; saving&quot;) and resumes after it on startup. All other processes are<br>
&gt;&gt; waiting<br>
&gt;&gt; &gt;&gt; on some semaphore anyway.<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;Nope.  No processes are stopped.  Processes are simply unable to run while<br>
&gt;&gt; &gt;in the snapshot.  The key to understanding this is understanding the<br>
&gt;&gt; &gt;scheduler (the Processor global, an instance of ProcessorSheduler).  It<br>
&gt;&gt; &gt;maintains an activeProcess and a set of runnable processes, implemented as<br>
&gt;&gt; &gt;an Array of lists of processes at the same priority.  A runnable process<br>
&gt;&gt; &gt;(one not sent suspend or not waiting on a semaphore) is either the<br>
&gt;&gt; &gt;activeProcess or on one of the lists.  This state is saved to the<br>
&gt;&gt; snapshot.<br>
&gt;&gt; &gt; At any time the scheduler&#39;s activeProcess is the first highest priority<br>
&gt;&gt; &gt;process in the set of runnable processes.  It will only be deposed as<br>
&gt;&gt; &gt;activeProcess when either another higher-priority process becomes runnable<br>
&gt;&gt; &gt;or it yields or suspends or waits on a semaphore.  If it suspends or waits<br>
&gt;&gt; &gt;on a semaphore it is removed from the set of runnable processes.  If it<br>
&gt;&gt; &gt;yields it gets sent to the back of its run-queue and the next process in<br>
&gt;&gt; &gt;that queue becomes the runnable process.  If it is the only runnable<br>
&gt;&gt; &gt;process at its priority yield is a noop.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;On loading the image the VM activates the activeProcess; the activeProcess<br>
&gt;&gt; &gt;will typically be in a method that has called the snapshot primitive and<br>
&gt;&gt; &gt;the system will continue, with the snapshot primitive answering true.  All<br>
&gt;&gt; &gt;the other processes in the run queues are runnable but, just as before the<br>
&gt;&gt; &gt;snapshot, can&#39;t be run because the activeProcess is still runnable.  But<br>
&gt;&gt; as<br>
&gt;&gt; &gt;soon as the activeProcess suspends, waits or yields, one of these<br>
&gt;&gt; processes<br>
&gt;&gt; &gt;may run.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;Several processes are terminated (terminate is suspend + run unwinds) on<br>
&gt;&gt; &gt;resuming the image.  This is done to inform the VM of additional state to<br>
&gt;&gt; &gt;make these processes run.  For example, the Delay process needs to tell<br>
&gt;&gt; the<br>
&gt;&gt; &gt;VM what the next delay expiry is on start-up.  The delay semaphore (the<br>
&gt;&gt; &gt;semaphore the VM signals when the current active delay expires) is saved<br>
&gt;&gt; in<br>
&gt;&gt; &gt;the image in the specialObjects array, so it persists across a snapshot,<br>
&gt;&gt; &gt;but the VM doesn&#39;t persist the current delay expiry time.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;So any long-running process which doesn&#39;t need to inform the VM of<br>
&gt;&gt; anything<br>
&gt;&gt; &gt;special at start-up will just keep truckin&#39; along, and nothing need be<br>
&gt;&gt; &gt;done.  A snapshot really is like a fermata, a pause.  It is not some kind<br>
&gt;&gt; &gt;of shut-down.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;As a side-note what happens if one does<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;     [Semaphore new wait] fork.<br>
&gt;&gt; &gt;    Processor activeProcess yield.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;?<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;This creates a new process and adds it to the Processor&#39;s run queue.  Once<br>
&gt;&gt; &gt;the process has been sent fork the current process doesn&#39;t reference it<br>
&gt;&gt; &gt;since it has been popped from the current process&#39;s stack, and so the only<br>
&gt;&gt; &gt;reference to the new process is from one of the Processors&#39; run queues,<br>
&gt;&gt; but<br>
&gt;&gt; &gt;it isn&#39;t running yet because the activeProcess (the one that sent fork) is<br>
&gt;&gt; &gt;running.  When the activeProcess yields the new process gets to run.  Once<br>
&gt;&gt; &gt;it has created the new semaphore it sends wait to it.  At this point it is<br>
&gt;&gt; &gt;removed from the Processor&#39;s run-queue and added to the semaphore&#39;s queue.<br>
&gt;&gt; &gt; So now there is a circular reference between the process and the<br>
&gt;&gt; semaphore<br>
&gt;&gt; &gt;and these are the only references to the process and the semaphore, and so<br>
&gt;&gt; &gt;both get garbage collected.<br>
&gt;&gt;<br>
&gt;&gt; I think the forked process gets to run before the processor returns to the<br>
&gt;&gt; yield line.  This is the way it works in VA Smalltalk and from looking at<br>
&gt;&gt; the implementers of #fork, I think it is the way it works in Squeak.  I<br>
&gt;&gt; could be wrong, if so please be kind, I have been following the news group<br>
&gt;&gt; for a while but I&#39;m new to playing with Squeak.<br>
&gt;&gt;<br>
&gt;<br>
&gt;No.  In Smalltalk-80 (VisualWorks, Squeak etc) fork creates a new process<br>
&gt;with the same priority as the current process and then resumes it (resume<br>
&gt;is the primitive that adds the process to the run queue).  So the new<br>
&gt;process is effectively behind the activeProcess in the run-queue.  e.g.<br>
&gt;<br>
&gt;| who |<br>
&gt;who := #me.<br>
&gt;[who := #him. Semaphore new wait] fork.<br>
&gt;who<br>
&gt;=&gt; #me<br>
&gt;<br>
&gt;<br>
&gt;| who |<br>
&gt;who := #me.<br>
&gt;[who := #him. Semaphore new wait] fork.<br>
&gt;Processor yield.<br>
&gt;who<br>
&gt;=&gt; #him<br>
&gt;<br>
&gt;I can&#39;t speak for VA, but I doubt you;re right.  I expect VA to have the<br>
&gt;same behaviour as the above.<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;&gt; There were times when I wanted to create a new fork but didn&#39;t want it to<br>
&gt;&gt; run until the method creating it finished.  So, I added #forkReady (and<br>
&gt;&gt; friends) that would create the process but not run it right away.<br>
&gt;&gt;<br>
&gt;<br>
&gt;there&#39;s also forkAt: Processor activePriority - 1, or<br>
&gt;<br>
&gt;| gate result |<br>
&gt;gate := Semaphore new.<br>
&gt;[gate wait.<br>
&gt; self doStuff] fork.<br>
&gt;result := self getResult.<br>
&gt;gate signal.<br>
&gt;^result<br>
&gt;<br>
&gt;<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; &gt; If the saved image is started, is there any way the process can tell?<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; Not the process itself. But you surely keep the process in a class<br>
&gt;&gt; &gt;&gt; somewhere, and the class can arrange to get notified on startup by<br>
&gt;&gt; adding<br>
&gt;&gt; &gt;&gt; itself to the startup list. See addToStartUpList:.<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;exactly. one could also e.g. poll OSProcess to get the process ID of the<br>
&gt;&gt; VM<br>
&gt;&gt; &gt;process and see if that changes, but that&#39;s a horrible hack, and once in a<br>
&gt;&gt; &gt;blue moon will fail (cuz process ids are not unique and get reused).<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; I&#39;m running a process that keeps running for a look time.  It loops<br>
&gt;&gt; with a<br>
&gt;&gt; &gt;&gt; &gt; delay and in the loop gets the date and time.  If the date and time<br>
&gt;&gt; were<br>
&gt;&gt; &gt;&gt; &gt; obtained just before the save, they would be old at the time of the<br>
&gt;&gt; image<br>
&gt;&gt; &gt;&gt; &gt; restart and need to be refreshed.<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; Delays get adjusted after resuming from snapshot. So it should just<br>
&gt;&gt; work.<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;exactly.  the snapshot will look just like a long time on the run-queue<br>
&gt;&gt; &gt;whole the process is preempted by higher-priroity processes,<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; - Bert -<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; -----------------------------------------------------------<br>
&gt;&gt; Louis LaBrunda<br>
&gt;&gt; Keystone Software Corp.<br>
&gt;&gt; SkypeMe callto://PhotonDemon<br>
&gt;&gt; mailto:<a href="mailto:Lou@Keystone-Software.com">Lou@Keystone-Software.com</a> <a href="http://www.Keystone-Software.com" target="_blank">http://www.Keystone-Software.com</a><br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
-----------------------------------------------------------<br>
Louis LaBrunda<br>
Keystone Software Corp.<br>
SkypeMe callto://PhotonDemon<br>
mailto:<a href="mailto:Lou@Keystone-Software.com">Lou@Keystone-Software.com</a> <a href="http://www.Keystone-Software.com" target="_blank">http://www.Keystone-Software.com</a><br>
<br>
<br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div>