<br><div class="gmail_quote">On Wed, Jul 1, 2009 at 5:40 PM, Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br><br><div class="gmail_quote"><div class="im">On Wed, Jul 1, 2009 at 10:55 AM, Mariano Martinez Peck <span dir="ltr">&lt;<a href="mailto:marianopeck@gmail.com" target="_blank">marianopeck@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">

<br><br><div class="gmail_quote"><div>On Wed, Jul 1, 2009 at 3:10 PM, Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">


Hi Mariano,<div><br></div><div>    Smalltalk&#39;s scheduler is preemptive across priorities and co-operative within priorities, which is a well-chosen real-time scheduling policy giving precise control over processes.  Because all your processes have the same priority they don&#39;t preempt the first process and so they don&#39;t get to run until after the doit has executed and the system has returned to some idle loop state.  If instead you change your code to either use a higher priority, e.g. [...] forkAt: Processor activePriority + 1, or to use yield, e.g. [....] fork. Processor yield, then you&#39;ll be able to get your desired behaviour. <div>





<div></div><div></div></div></div></blockquote></div><div><br>Eliot: Thanks for the reply. I think I am understanding a bit more. Let me explain myself a bit more what I am actually trying to do. I have SqueakDBX which uses FFI to call external functions of OpenDBX and do queries to databases. If you use SqueakDBX in a webapplication, like seaside, you will have like several forks using SqueakDBX. And that&#39;s exactly what I am trying to simulate: multiples forks (in a webapp they would be users connected). I am doing some benchmarks as I have some things to define (timeouts) and see how they affect this situation.<br>





<br>My real code (of the benchmark) is something like this:<br><br>collect: aBlock<br><br>|semaphores|<br>semaphores := Array new: self amountOfForks.<br>1 to: self amountOfForks do: [ :index | semaphores at: index put: Semaphore new ].<br>





<br>    1 to: self amountOfForks do: [:i |<br>        [<br>        mutex critical: [ times add: (MessageTally time: aBlock) ].<br>        (semaphores at: i) signal.<br>        ] forkAt: self benchPriority        <br><div>


    ].<br>


<br>    semaphores do: [:each | each wait ].<br><br></div>In this case, aBlock is a piece of code that does a big select.<br><br>During all the methods which are called in aBlock (SqueakDBX methods) there are for example, FFI calls and several things more. Suppose all the forks are with the same priority. My question is now when would the scheduler take another one?  As OpenDBX supports Asynchronous queries I just ask using FFI is the query if done or not and the function returns immediately. But, in order to let another connection to do another query, what I do, in case the query is not finished is:<br>



<br>(Delay forMilliseconds: 1000) wait<br><br>
This piece of code will free that process and pass to another? if not, I must add a yield ?</div></div></blockquote><div><br></div></div><div>Yes it will pass to another and no you don&#39;t need a yield.  Internal to a delay there is a semaphore and when the program does aDelay wait the active process waits on that semaphore.  The scheduler then switches to the first highest priority process.  The Delay class maintains a process that uses a VM primitive primSignal:atMilliseconds: to start a timer in the VM that will signal the semaphore supplied to the primitive when the timer expires.  The class side process then wakes (preempting the current process if the delay process is of higher priority, which it very likely is), checks the set of waiting delays and signals the semaphores of those that should be woken up, which will make those processes runnable.</div>


<div><br></div><div>You only need to do a yield when a process wants to allow a process at the same priority a chance to run but the yielding process has work to do.  If instead the process waits on a semaphore (in a Delay or explicitly) it will effectively yield.  Also note that the yield primitive is only a space efficient version of the following Smalltalk code:</div>


<div><br></div><div>     oldSlowLetsCreateLotsOfObjectsButNotRequireVMModificationsYield</div><div>        | sem |</div><div>        sem := Semaphore new.</div><div>        [sem signal] fork.</div><div>        sem wait</div>


<div><br></div><div>which is a real waste if there are no processes at the current priority level waiting to run, hence the VM primitive which avoids all this work by simply inspecting teh current priority level&#39;s runnable process queue.</div>


<div><br></div><div>I was going to suggest that you read the class comments of ProcessorScheduler, Process, Semaphore, Mutex and Delay, but they&#39;re pretty simplistic.  Better to read the blue book chapters on the scheduler either here <a href="http://web.archive.org/web/20060615014524/http://users.ipa.net/%7Edwighth/smalltalk/bluebook/bluebook_chapter29.html#ControlPrimitives29" target="_blank">http://web.archive.org/web/20060615014524/http://users.ipa.net/~dwighth/smalltalk/bluebook/bluebook_chapter29.html#ControlPrimitives29</a> or here: <a href="http://stephane.ducasse.free.fr/FreeBooks/BlueBook/" target="_blank">http://stephane.ducasse.free.fr/FreeBooks/BlueBook/</a></div>


<div></div></div></blockquote><div><br><br>Henrik:   thanks for your explanation!!<br><br>Eliot: IDEM. And thanks for the references!<br><br>Mariano<br>
<br> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div class="gmail_quote"><div><br></div><div>I&#39;m sure others will have better reference material to suggest.</div>
<div><br></div><div>cheers</div><div>e.</div><div><div></div><div class="h5"><div><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">

<div class="gmail_quote"><div><br><br>Thanks a lot for the help!<br><font color="#888888"><br>
Mariano<br><br> </font></div><div><div></div><div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div><div><div>
<br>
<br><div class="gmail_quote">On Wed, Jul 1, 2009 at 7:41 AM, Mariano Martinez Peck <span dir="ltr">&lt;<a href="mailto:marianopeck@gmail.com" target="_blank">marianopeck@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">






Hi folks! I am doing some benchmarks and I having problems with fork (I think).<br><br>I have this method collect:<br><br>collect<br>|semaphores tr|<br>semaphores := Array new: 10.<br>tr := ThreadSafeTranscript new.<br>tr open.<br>







1 to: 10 do: [ :index | semaphores at: index put: Semaphore forMutualExclusion ].<br><br>    1 to: 10 do: [:i |<br>        [<br>        tr show: &#39;one fork&#39;; cr.<br>        (semaphores at: i) signal.<br>        ] fork      <br>







    ].<br><br>    semaphores do: [:each | each wait ].<br>    tr show: &#39;all forks proccesed&#39;; cr.<br>    <br><br>What I want is that the method collect returns when ALL of the forks created inside, are finished. Obviously in my real code, I don&#39;t do a transcript show: but another thing. <br>







<br>I would expect something like this:<br><br>
one fork<br>one fork<br>
one fork<br>
one fork<br>
one fork<br>one fork<br>
one fork<br>
one fork<br>
one fork<br>one fork<br>all forks proccesed<br><br>But the output is:<br><br><br>all forks proccesed<br>one fork<br>one fork<br>one fork<br>one forkone fork<br>one fork<br>one fork<br>one forkone fork<br>one fork<br>one fork<br>







one forkone fork<br><br>So, I guess it isn&#39;t working :(   I don&#39;t know too much about forks so any help is welcome!<br><br>can be a problem with  ThreadSafeTranscript  ? If so, how could I test if my code is working as expected ?<br>







<br>Thanks,<br><font color="#888888"><br>Mariano<br><br>
</font><br><br>
<br></blockquote></div><br></div></div></div>
<br><br>
<br></blockquote></div></div></div><br>
<br><br>
<br></blockquote></div></div></div><br>
<br><br>
<br></blockquote></div><br>