On Tue, 17 Feb 2009, Maurilio Longo wrote:

Hi Maurilio,

> > Without such condition the above peace of code may never wake up all
> > threads. But there is other problem and as I can see it exists also
> > in xHarbour. It's still possible that signal will be lost and waiting
> > thread will never be woken up due to hb_threadCondWait() implementation.
> > It needs multistate semaphore like in Windows to be sure that we do not
> > lost posted event.
> > F.e. 1-st thread is waiting on some results calculated by 2-nd thread
> > in code like:
> > 
> >    hb_threadEnterCriticalSection( mutex );
> >    while( result == 0 )
> >       hb_threadCondWait( cond, mutex );
> >    hb_threadLeaveCriticalSection( mutex );
> > 
> > The second thread is making:
> >    hb_threadEnterCriticalSection( mutex );
> >    result += nDone;
> >    hb_threadLeaveCriticalSection( mutex );
> >    hb_threadCondSignal( cond );
> > 
> > in hb_threadCondWait() the mutex should be unlocked and process suspended
> > in one atomic operation. OS2 API does not give us such functionality and
> > the code like above can freeze 1-st thread forever. It may happen if
> > inside hb_threadCondWait() it executes:
> >    DosReleaseMutexSem( mutex );
> > and OS suspend the thread before executing:
> >    DosWaitEventSem( cond );
> > activating 2-nd thread. Which can lock unlocked mutex set result and
> > send signal which will be ignored because the 1-st thread has not
> > entered DosWaitEventSem() yet. The second thread finish its job and
> > terminates and the 1-st one is never woken up so our application
> > hangups. The above now can happen in xHarbour.
> I see these two comments on OS/2 sdk:
> -------------------8<-----------------
> If the semaphore is already posted when DosWaitEventSem is called, the
> function returns immediately, and the thread continues to run. Otherwise, the
> thread is blocked until the semaphore is posted.
> ------------------->8-----------------

Yes I know but the semaphor won't be posted
because inside hb_threadCondSignal() xHarbour has:

   DosPostEventSem( cond ); // it does nothing because 1-st thread
                            // haven't reached DosWaitEventSem() yet
   DosResetEventSem( cond, &ulPostCount ); // it reset the posted even't
                                           // so the event semaphore is
                                           // still close

> -------------------8<-----------------
> Unlike multiple event semaphores in a muxwait list, which are level-triggered,
> single event semaphores are edge-triggered. This means that if an event
> semaphore is posted and then reset before a waiting thread gets a chance to
> run, the semaphore is considered to be posted for the rest of that thread's
> waiting period; the thread does not have to wait for the semaphore to be
> posted again.
> ------------------->8-----------------

Yes, this is the condtion I said is necessary to be sure that all threads
waiting on even semaphore will be woken up even if other thread execute
   DosPostEventSem( cond );
   DosResetEventSem( cond, &ulPostCount );
before they start execution. The above confirms it. Thank you.

> So the thread should not block and the event does not get lost.

Unfortunately not because the 1-st thread haven't reached DosWaitEventSem()
function and when it's resumed the semaphore is already reset by the same
thread which also called DosPostEventSem() so it enters not posted event
semaphore and is blocked.

> Do you think this answers your questions?

See above. Such code potentially causes that signal will be lost and
waiting thread will be frozen forever. It's not good solution. In general
such API is not good solution because it always causes race condition so
can be used only in places where such race condition is unimportant.
The problem is caused by the fact that there is not good place to execute
DosResetEventSem().
It's a serious problem for us because to resolve it well I should implement
full waiting queue or at least introduce few additional semaphores.
replicating the OS job. It may cause serious performance overhead.
I can also try introduce additional counters with posted events and
reset semaphore when such counter reach 0 but as I can see it only
reduce the problem (in our case seems that it may be enough for HVM
code) but it also isn't good solution because it does not eliminate
starvation effect which can be exploited by the fact that DosPostEventSem()
works like a broadcast signal waking up all threads. With such solution
it's still possible that only one thread will "eat" all posted events
and reset the semaphore before some threads like the 1-st one in the
example above will be resumed. But here we are sure that at least one
thread will be woken up so if all threads are waiting with the same
condition nothing wrong will happen. The problem appears only when
the conditions are different and threads which can continue execution
will not be woken up. The only one solution I see here is introducing
second event semaphore and maybe also event queue if it will not be
enough. I have to rethink it yet and build a model to not miss sth
important.
Meanwhile I can commit modification which will introduce simple counters
to reduce the problem from dead lock to starvation effect.

best regards,
Przemek
_______________________________________________
Harbour mailing list
[email protected]
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to