SqNOS: interpreterProxy signalSemaphoreWithIndex:

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

SqNOS: interpreterProxy signalSemaphoreWithIndex:

Gerardo Richarte
John M McIntosh said:
> Likely I should point out this code is not 100% percent thread safe.
>
> People doing thousands of signal events per second from an async  
> thread should think carefully about the code.
        I'm really interested in this problem, as SqueakNOS relies 100% on signalSemaphoreWithIndex() to handle IRQs properly (see http://minnow.cc.gatech.edu/squeak/1762 for more detailed info).
However, after reading Andreas' comment in Win32 sources I think this problem is only present when the underlying native code is multithreaded, what doesn't apply to SqueakNOS... however, what I think will present a similar situation is if two IRQs (different or not) arrive in a very short period of time, both of them signaling Semaphores (same for same IRQs, different for different IRQs).
What do you think?

Where can I read an explanation of this problem to see if it applies and if we can somehow solve it? I guess we'll need to implement some type of locking mechanism, even when the underlying code is single threaded.

        thanks a lot
        gera


Reply | Threaded
Open this post in threaded view
|

Re: SqNOS: interpreterProxy signalSemaphoreWithIndex:

johnmci
Well having written these two routines 6 or 7 years ago, let me  
comment if I can remember.

The two routines of interest are:

signalSemaphoreWithIndex: index
        "Record the given semaphore index in the double buffer semaphores  
array to be signaled at the next convenient moment. Force a real  
interrupt check as soon as possible."

        index <= 0 ifTrue: [^ nil].  "bad index; ignore it"

        semaphoresUseBufferA
                ifTrue: [semaphoresToSignalCountA < SemaphoresToSignalSize
                        ifTrue: [ semaphoresToSignalCountA := semaphoresToSignalCountA + 1.
                                semaphoresToSignalA at: semaphoresToSignalCountA put: index]]
                ifFalse: [semaphoresToSignalCountB < SemaphoresToSignalSize
                        ifTrue: [ semaphoresToSignalCountB := semaphoresToSignalCountB + 1.
                                semaphoresToSignalB at: semaphoresToSignalCountB put: index]].
        self forceInterruptCheck

and the one below which is called from checkForInterrupts and happens  
every 1-2 milliseconds or as soon as possible via being triggered by  
the forceInterruptCheck call.
Thus on a signalSemaphoreWithIndex: we should call  
signalExternalSemaphores fairly soon, that 'nots' the  
semaphoresUseBufferA which flips the buffers to allow
the checkForInterrupts logic to process the semaphores in buffer 'A'  
as an interrupt driven processes fill buffer 'B'.   Of course if you  
don't have any process threads calling signalSemaphoreWithIndex: we  
don't have a problem because normally this code is only processed by  
the single squeak thread.

The risks is on dual processor machines  such that decisions based on  
semaphoresUseBufferA collide between the main squeak thread running  
signalExternalSemaphores, and
an other thread pounding on signalSemaphoreWithIndex: and we miss a  
semaphoresToSignalCountX increment.

signalExternalSemaphores
        "Signal all requested semaphores"
        | xArray xSize index sema |
        semaphoresUseBufferA := semaphoresUseBufferA not.
        xArray := self splObj: ExternalObjectsArray.
        xSize := self stSizeOf: xArray.
        semaphoresUseBufferA
                ifTrue: ["use opposite buffer during read"
                        1 to: semaphoresToSignalCountB do: [:i |
                                        index := semaphoresToSignalB at: i.
                                        index <= xSize
                                                ifTrue: [sema := self fetchPointer: index - 1 ofObject: xArray.
                                                        "Note: semaphore indices are 1-based"
                                                        (self fetchClassOf: sema) = (self splObj: ClassSemaphore)
                                                                ifTrue: [self synchronousSignal: sema]]].
                        semaphoresToSignalCountB := 0]
                ifFalse: [1 to: semaphoresToSignalCountA do: [:i |
                                        index := semaphoresToSignalA at: i.
                                        index <= xSize
                                                ifTrue: [sema := self fetchPointer: index - 1 ofObject: xArray.
                                                        "Note: semaphore indices are 1-based"
                                                        (self fetchClassOf: sema) = (self splObj: ClassSemaphore)
                                                                ifTrue: [self synchronousSignal: sema]]].
                        semaphoresToSignalCountA := 0]



On 9-Jun-06, at 7:29 PM, Gerardo Richarte wrote:

> John M McIntosh said:
>> Likely I should point out this code is not 100% percent thread safe.
>>
>> People doing thousands of signal events per second from an async
>> thread should think carefully about the code.
> I'm really interested in this problem, as SqueakNOS relies 100% on  
> signalSemaphoreWithIndex() to handle IRQs properly (see http://
> minnow.cc.gatech.edu/squeak/1762 for more detailed info).
> However, after reading Andreas' comment in Win32 sources I think  
> this problem is only present when the underlying native code is  
> multithreaded, what doesn't apply to SqueakNOS... however, what I  
> think will present a similar situation is if two IRQs (different or  
> not) arrive in a very short period of time, both of them signaling  
> Semaphores (same for same IRQs, different for different IRQs).
> What do you think?
>
> Where can I read an explanation of this problem to see if it  
> applies and if we can somehow solve it? I guess we'll need to  
> implement some type of locking mechanism, even when the underlying  
> code is single threaded.
>
> thanks a lot
> gera
>
>

--
========================================================================
===
John M. McIntosh <[hidden email]> 1-800-477-2659
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
========================================================================
===