[squeak-dev] Problem with fork

Eliot Miranda eliot.miranda at gmail.com
Wed Jul 1 18:40:20 UTC 2009


On Wed, Jul 1, 2009 at 10:55 AM, Mariano Martinez Peck <
marianopeck at gmail.com> wrote:

>
>
> On Wed, Jul 1, 2009 at 3:10 PM, Eliot Miranda <eliot.miranda at gmail.com>wrote:
>
>> Hi Mariano,
>>     Smalltalk'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't preempt the first process and so they don'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'll be able to get your desired
>> behaviour.
>>
>
> 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'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.
>
> My real code (of the benchmark) is something like this:
>
> collect: aBlock
>
> |semaphores|
> semaphores := Array new: self amountOfForks.
> 1 to: self amountOfForks do: [ :index | semaphores at: index put: Semaphore
> new ].
>
>     1 to: self amountOfForks do: [:i |
>         [
>         mutex critical: [ times add: (MessageTally time: aBlock) ].
>         (semaphores at: i) signal.
>         ] forkAt: self benchPriority
>     ].
>
>     semaphores do: [:each | each wait ].
>
> In this case, aBlock is a piece of code that does a big select.
>
> 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:
>
> (Delay forMilliseconds: 1000) wait
>
> This piece of code will free that process and pass to another? if not, I
> must add a yield ?
>

Yes it will pass to another and no you don'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.

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:

     oldSlowLetsCreateLotsOfObjectsButNotRequireVMModificationsYield
        | sem |
        sem := Semaphore new.
        [sem signal] fork.
        sem wait

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's runnable process queue.

I was going to suggest that you read the class comments of
ProcessorScheduler, Process, Semaphore, Mutex and Delay, but they're pretty
simplistic.  Better to read the blue book chapters on the scheduler either
here
http://web.archive.org/web/20060615014524/http://users.ipa.net/~dwighth/smalltalk/bluebook/bluebook_chapter29.html#ControlPrimitives29
or
here: http://stephane.ducasse.free.fr/FreeBooks/BlueBook/

I'm sure others will have better reference material to suggest.

cheers
e.


>
> Thanks a lot for the help!
>
> Mariano
>
>
>
>>
>>
>> On Wed, Jul 1, 2009 at 7:41 AM, Mariano Martinez Peck <
>> marianopeck at gmail.com> wrote:
>>
>>> Hi folks! I am doing some benchmarks and I having problems with fork (I
>>> think).
>>>
>>> I have this method collect:
>>>
>>> collect
>>> |semaphores tr|
>>> semaphores := Array new: 10.
>>> tr := ThreadSafeTranscript new.
>>> tr open.
>>> 1 to: 10 do: [ :index | semaphores at: index put: Semaphore
>>> forMutualExclusion ].
>>>
>>>     1 to: 10 do: [:i |
>>>         [
>>>         tr show: 'one fork'; cr.
>>>         (semaphores at: i) signal.
>>>         ] fork
>>>     ].
>>>
>>>     semaphores do: [:each | each wait ].
>>>     tr show: 'all forks proccesed'; cr.
>>>
>>>
>>> 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't do a
>>> transcript show: but another thing.
>>>
>>> I would expect something like this:
>>>
>>> one fork
>>> one fork
>>> one fork
>>> one fork
>>> one fork
>>> one fork
>>> one fork
>>> one fork
>>> one fork
>>> one fork
>>> all forks proccesed
>>>
>>> But the output is:
>>>
>>>
>>> all forks proccesed
>>> one fork
>>> one fork
>>> one fork
>>> one forkone fork
>>> one fork
>>> one fork
>>> one forkone fork
>>> one fork
>>> one fork
>>> one forkone fork
>>>
>>> So, I guess it isn't working :(   I don't know too much about forks so
>>> any help is welcome!
>>>
>>> can be a problem with  ThreadSafeTranscript  ? If so, how could I test if
>>> my code is working as expected ?
>>>
>>> Thanks,
>>>
>>> Mariano
>>>
>>>
>>>
>>>
>>>
>>
>>
>>
>>
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20090701/c210b810/attachment.htm


More information about the Squeak-dev mailing list