Semaphore problems

classic Classic list List threaded Threaded
43 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Semaphore problems

Graeme Geldenhuys-2
Hi,

I am having troubles with porting Semaphores in a project under Linux.
 Under Windows everything works fine, but under Linux my app keeps
freezing.

The project is tiOPF v2 (TechInsite Object Persistent Framework).
There is a class called TtiPool, that handles a pool of database
connections.

When I run the Unit Tests and create a single Lock and the Unlock it,
all works fine.  If I then iterrate that test by creating 10 locks and
then call unlock 10 times, the Unit Tests freeze on the following line
with the second iteration:

  if sem_wait(FSemaphore) <> 0 then
    raise EtiOPFInternalException.Create(cErrorTimedOutWaitingForSemaphore);

* Under Linux, I am using the "pthreads" unit.  What is the difference
between the cthreads and pthreads unit?
* The calls I am using from pthreads are:
  * sem_init() to create a semaphore
  * sem_wait() to lock the semaphore
  * sem_post() to unlock the semaphore
  All the above with a variable of type TSemaphore.


Now, I have to admit, I don't know much about Semaphore's... Anybody
know of some good documentation or tutorial on the net?
Anything obvious I could be doing wrong?

Regards,
  Graeme.

--
There's no place like 127.0.0.1
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Graeme Geldenhuys-2
Looking at my code, I might have initialized my semaphore incorrectly.

The Windows portion works, and I tried to port it to Linux as follows...

procedure TtiPool.CreatePoolSemaphore;
begin
  {$IFDEF MSWINDOWS}
  if FSemaphore <> 0 then
    CloseHandle( FSemaphore ) ;
  FSemaphore := CreateSemaphore( nil, FiMaxPoolSize, FiMaxPoolSize, nil );
  {$ENDIF MSWINDOWS}
  {$IFDEF LINUX}
  sem_destroy( FSemaphore );

  if sem_init(FSemaphore, 0, 1) <> 0 then
    raise Exception.Create('Failed to create the semaphore');
  {$ENDIF LINUX}
end;


Regards,
  Graeme.


On 7/24/06, Graeme Geldenhuys <[hidden email]> wrote:

> Hi,
>
> I am having troubles with porting Semaphores in a project under Linux.
>  Under Windows everything works fine, but under Linux my app keeps
> freezing.
>
> The project is tiOPF v2 (TechInsite Object Persistent Framework).
> There is a class called TtiPool, that handles a pool of database
> connections.
>
> When I run the Unit Tests and create a single Lock and the Unlock it,
> all works fine.  If I then iterrate that test by creating 10 locks and
> then call unlock 10 times, the Unit Tests freeze on the following line
> with the second iteration:
>
>   if sem_wait(FSemaphore) <> 0 then
>     raise EtiOPFInternalException.Create(cErrorTimedOutWaitingForSemaphore);
>
> * Under Linux, I am using the "pthreads" unit.  What is the difference
> between the cthreads and pthreads unit?
> * The calls I am using from pthreads are:
>   * sem_init() to create a semaphore
>   * sem_wait() to lock the semaphore
>   * sem_post() to unlock the semaphore
>   All the above with a variable of type TSemaphore.
>
>
> Now, I have to admit, I don't know much about Semaphore's... Anybody
> know of some good documentation or tutorial on the net?
> Anything obvious I could be doing wrong?
>
> Regards,
>   Graeme.
>
> --
> There's no place like 127.0.0.1
>


--
There's no place like 127.0.0.1
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Marco van de Voort
In reply to this post by Graeme Geldenhuys-2
> When I run the Unit Tests and create a single Lock and the Unlock it,
> all works fine.  If I then iterrate that test by creating 10 locks and
> then call unlock 10 times, the Unit Tests freeze on the following line
> with the second iteration:

Sounds like some recursion property is not set.
 
>   if sem_wait(FSemaphore) <> 0 then
>     raise EtiOPFInternalException.Create(cErrorTimedOutWaitingForSemaphore);
>
> * Under Linux, I am using the "pthreads" unit.  What is the difference
> between the cthreads and pthreads unit?

pthreads is a straight header to the platforms POSIX pthreads library. It is
as native to the pthreads lib on that platform as possible, so not 100%
portable.

Cthreads is a bit more complicated; Deep in the RTL/FCL and even the
compiler we need threading primitives on *nix, but we don't want to import
library pthread always, even if we don't use threading.

So we defined a subset of pthreads with uniform typing, and programmed the
RTL/FCL against an empty implementation of this interface that is always
linked in.

Cthreads is the _full_ implementation (that actually pulls in library
pthreads) that is a unit on which no other units have any dependancy. By
adding it to the project, the threading support is "armed". The Windows
platform doesn't need this construct, since linking to the thread functions
is not as potentially problematic, so thread support is installed always.

So language threading, TCriticalSection and syncobjs are mostly
built on top of this interface.

Third, there is also the unit IPC, which is more an interface to kernel
level IPC.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: Semaphore problems

Marco van de Voort
In reply to this post by Graeme Geldenhuys-2
> Looking at my code, I might have initialized my semaphore incorrectly.
>
> The Windows portion works, and I tried to port it to Linux as follows...
>
> procedure TtiPool.CreatePoolSemaphore;
> begin
>   {$IFDEF MSWINDOWS}
>   if FSemaphore <> 0 then
>     CloseHandle( FSemaphore ) ;
>   FSemaphore := CreateSemaphore( nil, FiMaxPoolSize, FiMaxPoolSize, nil );
>   {$ENDIF MSWINDOWS}
>   {$IFDEF LINUX}
>   sem_destroy( FSemaphore );
>
>   if sem_init(FSemaphore, 0, 1) <> 0 then
>     raise Exception.Create('Failed to create the semaphore');
>   {$ENDIF LINUX}
> end;

Looking at unit syncobjs might save you some ifdefs and trouble.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: Semaphore problems

Vinzent Höfler
In reply to this post by Graeme Geldenhuys-2
On Monday 24 July 2006 10:21, Graeme Geldenhuys wrote:

> procedure TtiPool.CreatePoolSemaphore;
> begin
>   {$IFDEF MSWINDOWS}
>   if FSemaphore <> 0 then
>     CloseHandle( FSemaphore ) ;
>   FSemaphore := CreateSemaphore( nil, FiMaxPoolSize, FiMaxPoolSize,
> nil ); {$ENDIF MSWINDOWS}
>   {$IFDEF LINUX}
>   sem_destroy( FSemaphore );
>
>   if sem_init(FSemaphore, 0, 1) <> 0 then
>     raise Exception.Create('Failed to create the semaphore');
>   {$ENDIF LINUX}
> end;

What is FiMaxPoolSize? I assume, it's something like a number of request
being allowed inside the semaphore-protected region at once?

So in the linux version only one thread is allowed being there.

I suppose you wrote something like

|for i := 0 to 9 do
|begin
|   Lock;
|   WriteLn ('Ping');
|end {for};
|
|for i := 0 to 9 do
|begin
|   WriteLn ('Pong');
|   Unlock;
|end {for};

In that case you're experiencing the lock-up when the semaphore is being
"entered"/locked the second time inside your loop. The counter is zero
after the first sem_wait and remains that way, because there's nobody
there to call the sem_post() operation. Well, it may seen as a kind of
a classical deadlock situation, although there's nothing classical in
here. ;)

That's what you're experiencing. Although it might appear similar, a
semaphore is *not* a mutex.

What I don't understand is why you don't use the "SyncObjs" unit where
almost all the stuff someone ever needs is nicely laid out in a
portable and object-oriented way.


> >   if sem_wait(FSemaphore) <> 0 then
> >     raise
> > EtiOPFInternalException.Create(cErrorTimedOutWaitingForSemaphore);

BTW, sem_wait() never returns anything else than zero, so checking is
sort of useless here. There's sem_trywait() for that, if you really
need to go so low-level.

To the question, what are semaphores. It's quite easily explained:
Atomic counters, you can only get past if they're non-zero and in that
case the counter is decremented.


Vinzent.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Vinzent Höfler
In reply to this post by Marco van de Voort
On Monday 24 July 2006 13:34, Marco van de Voort wrote:
> > When I run the Unit Tests and create a single Lock and the Unlock
> > it, all works fine.  If I then iterrate that test by creating 10
> > locks and then call unlock 10 times, the Unit Tests freeze on the
> > following line with the second iteration:
>
> Sounds like some recursion property is not set.

I don't think, semaphores have recursion properties.


Vinzent.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Michael Van Canneyt


On Mon, 24 Jul 2006, Vinzent Hoefler wrote:

> On Monday 24 July 2006 13:34, Marco van de Voort wrote:
>>> When I run the Unit Tests and create a single Lock and the Unlock
>>> it, all works fine.  If I then iterrate that test by creating 10
>>> locks and then call unlock 10 times, the Unit Tests freeze on the
>>> following line with the second iteration:
>>
>> Sounds like some recursion property is not set.
>
> I don't think, semaphores have recursion properties.

They do, in some implementations.

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Vinzent Höfler
On Monday 24 July 2006 14:09, Michael Van Canneyt wrote:

> On Mon, 24 Jul 2006, Vinzent Hoefler wrote:
> > On Monday 24 July 2006 13:34, Marco van de Voort wrote:
> >>> When I run the Unit Tests and create a single Lock and the Unlock
> >>> it, all works fine.  If I then iterrate that test by creating 10
> >>> locks and then call unlock 10 times, the Unit Tests freeze on the
> >>> following line with the second iteration:
> >>
> >> Sounds like some recursion property is not set.
> >
> > I don't think, semaphores have recursion properties.
>
> They do, in some implementations.

Ok, granted. :) But not in POSIX, AFAICS.

And they were never designed that way. I think, that's why someone
invented the mutex. ;)


Vinzent.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: Semaphore problems

Graeme Geldenhuys-2
In reply to this post by Vinzent Höfler
Hi Vinzent,

You got me one the right track, I think... :-)

I thought the counter in Semaphores get incremented, but as you stated
(and reading some Man Pages), they get decremented.

I then change my code from:

> >   if sem_init(FSemaphore, 0, 1) <> 0 then
> >     raise Exception.Create('Failed to create the semaphore');

to ...

> >   if sem_init(FSemaphore, 0, FiMaxPoolSize) <> 0 then
> >     raise Exception.Create('Failed to create the semaphore');

Which makes more sense now...  FiMaxPoolSize is the maximum number of
requests being allow.  Having it set to 1, I was only allowed 1, so
after the first Lock, the others ended in a deadlock type situation.
Hence the second iteration freezing the app.


> What I don't understand is why you don't use the "SyncObjs" unit where
> almost all the stuff someone ever needs is nicely laid out in a
> portable and object-oriented way.

I didn't write the original Windows code, just tried to port it as is
to FPC and get the Unit Tests to pass.  I will speak to the original
author and see what he thinks of you idea. As long as the code can
still compile under Delphi and FPC, I am sure everything should be
fine.


> > >   if sem_wait(FSemaphore) <> 0 then
> > >     raise
> > > EtiOPFInternalException.Create(cErrorTimedOutWaitingForSemaphore);
>
> BTW, sem_wait() never returns anything else than zero, so checking is
> sort of useless here. There's sem_trywait() for that, if you really
> need to go so low-level.

I changed it to sem_trywait() which pretty made all my tiPool unit
tests pass.  For some strange reason I still get a lock-up, but much
less now.  Say once every 5 iterations of the complete test suite
where-as before it was every time on a specific test case.  I will now
try and implement the timeout work-around as suggested in the IBM
article below.

I found the IBM article very handy to explain some information.
  http://tinyurl.com/n8jq9


Thanks for you time!

Regards,
  Graeme.


--
There's no place like 127.0.0.1
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: Semaphore problems

Graeme Geldenhuys-2
In reply to this post by Marco van de Voort
> Looking at unit syncobjs might save you some ifdefs and trouble.

Thanks for the tip.  I always get hassled about keeping the IFDEF's as
little as possible. I will go browse the SyncObjs unit now.


Regards,
  Graeme.


--
There's no place like 127.0.0.1
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Burkhard Carstens-3
In reply to this post by Vinzent Höfler
Am Montag, 24. Juli 2006 16:19 schrieb Vinzent Hoefler:

> On Monday 24 July 2006 14:09, Michael Van Canneyt wrote:
> > On Mon, 24 Jul 2006, Vinzent Hoefler wrote:
> > > On Monday 24 July 2006 13:34, Marco van de Voort wrote:
> > >>> When I run the Unit Tests and create a single Lock and the
> > >>> Unlock it, all works fine.  If I then iterrate that test by
> > >>> creating 10 locks and then call unlock 10 times, the Unit Tests
> > >>> freeze on the following line with the second iteration:
> > >>
> > >> Sounds like some recursion property is not set.
> > >
> > > I don't think, semaphores have recursion properties.
> >
> > They do, in some implementations.
>
> Ok, granted. :) But not in POSIX, AFAICS.
>
> And they were never designed that way. I think, that's why someone
> invented the mutex. ;)

hmm, so a mutex can be recursive, if the type is set correctly, which is
not supportet on all platforms implementing pthread (man-pages of
pthread).

I vote for more pascal based versions of TMutex, TSemaphore and TEvent,
that behaves just like the ones in Delphi and use the system specific
functions (like pthread stuff) only internally in their simplest/most
portable form.

Currently, I have the problem to get a working TEvent:
- The one in syncobjs returns wrError, when it's waitfor is called with
anything else tah infinite timeout
- same goes for rtlbasicevent (cthreads)
- the rtlEvent works even with timeout (with my patch posted on mantis),
but this one clears the signaled state, when wait is called. IOW. if I
call waitfor on the allready signalled event, it won't return before
timeout. Also it doesn't inform the caller, wheter it returnt due to
signalled or to timeout ..

regards
 Burkhard

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Vinzent Höfler
On Monday 24 July 2006 14:57, Burkhard Carstens wrote:

> I vote for more pascal based versions of TMutex, TSemaphore and
> TEvent, that behaves just like the ones in Delphi and use the system
> specific functions (like pthread stuff) only internally in their
> simplest/most portable form.

I'd vote for a more abstract version. :) The more or less basic things
needed in multi-threaded programing are

- semaphore
- persistent signal
- transient signal ("pulse")
- event

There's some more higher level stuff (like broadcasts, for example), but
that's about all you usually need. Currently we have the semaphore
(more or less as SyncObjs.tCriticalSection), the persistent and the
transient signal (SyncObjs.tEvent), although without timeouts (at least
when trying to be portable), the event is somewhat implemented, but
IIRC it misses a "Toggle" property, which can be used for simple
intertask communication ("Now I'm blocking, you're on.").

> Currently, I have the problem to get a working TEvent:
> - The one in syncobjs returns wrError, when it's waitfor is called
> with anything else tah infinite timeout

Yes, that's not implemented, although it should be easily added by using
condition variables of pthreads.

> - the rtlEvent works even with timeout (with my patch posted on
> mantis), but this one clears the signaled state, when wait is called.

*oh* Before the wait? That's not good. This cries for race conditions
and subtle deadlock situations.


Vinzent.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Burkhard Carstens-3
Am Montag, 24. Juli 2006 17:27 schrieb Vinzent Hoefler:

> On Monday 24 July 2006 14:57, Burkhard Carstens wrote:
> > I vote for more pascal based versions of TMutex, TSemaphore and
> > TEvent, that behaves just like the ones in Delphi and use the
> > system specific functions (like pthread stuff) only internally in
> > their simplest/most portable form.
>
> I'd vote for a more abstract version. :) The more or less basic
> things needed in multi-threaded programing are
>
> - semaphore
> - persistent signal
> - transient signal ("pulse")
> - event
>
> There's some more higher level stuff (like broadcasts, for example),
> but that's about all you usually need. Currently we have the
> semaphore (more or less as SyncObjs.tCriticalSection), the persistent
> and the transient signal (SyncObjs.tEvent), although without timeouts
> (at least when trying to be portable), the event is somewhat
> implemented, but IIRC it misses a "Toggle" property, which can be
> used for simple intertask communication ("Now I'm blocking, you're
> on.").
>
> > Currently, I have the problem to get a working TEvent:
> > - The one in syncobjs returns wrError, when it's waitfor is called
> > with anything else tah infinite timeout
>
> Yes, that's not implemented, although it should be easily added by
> using condition variables of pthreads.

..which currently doesn't work, unless someone applies my patch (or a
better one) ..

>
> > - the rtlEvent works even with timeout (with my patch posted on
> > mantis), but this one clears the signaled state, when wait is
> > called.
>
> *oh* Before the wait? That's not good. This cries for race conditions
> and subtle deadlock situations.

thread synchronization uses this and takes care of it by calling
RTLeventstartwait which locks the associated mutex. So I don't expect a
race condition there, but don't know about other places.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Vinzent Höfler
Burkhard Carstens wrote:
> Am Montag, 24. Juli 2006 17:27 schrieb Vinzent Hoefler:
>
>>> - the rtlEvent works even with timeout (with my patch posted on
>>> mantis), but this one clears the signaled state, when wait is
>>> called.
 >>
>> *oh* Before the wait? That's not good. This cries for race conditions
>> and subtle deadlock situations.
>
> thread synchronization uses this and takes care of it by calling
> RTLeventstartwait which locks the associated mutex.

As far as I just read code and comments, it does it for Windows to get
Unix behaviour, although I don't see the point here, because this just
forces the race condition the POSIX-Threads implementation actually
tries to circumvent with this associated mutex.

I'm not even sure, if Unix actually clears the event. The man-pages
don't seem to indicate so.


Vinzent.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Burkhard Carstens-3
Am Montag, 24. Juli 2006 19:22 schrieb Vinzent Höfler:

> Burkhard Carstens wrote:
> > Am Montag, 24. Juli 2006 17:27 schrieb Vinzent Hoefler:
> >>> - the rtlEvent works even with timeout (with my patch posted on
> >>> mantis), but this one clears the signaled state, when wait is
> >>> called.
> >>
> >> *oh* Before the wait? That's not good. This cries for race
> >> conditions and subtle deadlock situations.
> >
> > thread synchronization uses this and takes care of it by calling
> > RTLeventstartwait which locks the associated mutex.
>
> As far as I just read code and comments, it does it for Windows to
> get Unix behaviour, although I don't see the point here, because this
> just forces the race condition the POSIX-Threads implementation
> actually tries to circumvent with this associated mutex.
I don't think so. In unix, the mutex is locked, which ensures, there is
not setevent between startwait and actual call to wait, because the
call to wait seems to reset the cond, then releases the mutex and
starts waiting. In windows, this doesn't matter (resetting the event on
startwait), because it preserves the signaled state of the event. The
wait call just returns immediately, if the event is allready signaled.
To me, this is fine. As long as rtlevent is used with this in mind, it
should give a consistent behaviour on windows and linux. (see
classes.inc thread synchronization)

> I'm not even sure, if Unix actually clears the event. The man-pages
> don't seem to indicate so.

It does, at least with the timedwait. I tested that extensively.

Burkhard

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Burkhard Carstens-3
[..]
> ... As long as rtlevent is used with this
> in mind, it should give a consistent behaviour on windows and linux.

"this in mind" means: The only way how rtlevent should be used is:
1. call rtlstartwait
2. start the code (e.g. start/resume a thread), that signals the event.
3. call rtlwaitevent



_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Vinzent Höfler
In reply to this post by Burkhard Carstens-3
Burkhard Carstens wrote:

> Am Montag, 24. Juli 2006 19:22 schrieb Vinzent Höfler:
>> Burkhard Carstens wrote:
>>> Am Montag, 24. Juli 2006 17:27 schrieb Vinzent Hoefler:
>>>>> - the rtlEvent works even with timeout (with my patch posted on
>>>>> mantis), but this one clears the signaled state, when wait is
>>>>> called.
>>>> *oh* Before the wait? That's not good. This cries for race
>>>> conditions and subtle deadlock situations.
>>> thread synchronization uses this and takes care of it by calling
>>> RTLeventstartwait which locks the associated mutex.
>> As far as I just read code and comments, it does it for Windows to
>> get Unix behaviour, although I don't see the point here, because this
>> just forces the race condition the POSIX-Threads implementation
>> actually tries to circumvent with this associated mutex.
 >
> I don't think so.

Well, in that case either I am totally stupid (won't be news, anyway) or
I must have different source code:

 From "rtl/unix/cthreads.inc":

|procedure intRTLEventStartWait(AEvent: PRTLEvent);
|var p:pintrtlevent;
|
|begin
|  p:=pintrtlevent(aevent);
|  pthread_mutex_lock(@p^.mutex);
|end;
|
|procedure intRTLEventWaitFor(AEvent: PRTLEvent);
|var p:pintrtlevent;
|
|begin
|  p:=pintrtlevent(aevent);
|  pthread_cond_wait(@p^.condvar, @p^.mutex);
|  pthread_mutex_unlock(@p^.mutex);
|end;

Which is pretty much what you described and if pthread_cond_wait() works
as described, there's no race condition here.

But now "rtl/win/systhrd.inc":

|procedure intRTLEventStartWait(AEvent: PRTLEvent);
|begin
|  { this is to get at least some common behaviour on unix and win32:
|    events before startwait are lost on unix, so reset the event on
|    win32 as well }
|  ResetEvent(THANDLE(AEvent));
|end;
|
|procedure intRTLEventWaitFor(AEvent: PRTLEvent);
|const
|  INFINITE=dword(-1);
|begin
|  WaitForSingleObject(THANDLE(AEvent), INFINITE);
|end;

I don't see any locking in intRTLEventStartWait(), but I see the signal
being cleared in an unprotected way. So the signal can still get set
between the calls to intRTLStartWait() and intRTLEventWaitFor() which
makes the clearing quite useless.

> In unix, the mutex is locked, which ensures, there is
> not setevent between startwait and actual call to wait, because the
> call to wait seems to reset the cond, then releases the mutex and
> starts waiting.

Yes, and now I seem to understand why. Unix only implements transient
signals. So if there's noone waiting on the signal, it gets lost.
Windows OTOH seems to implement persistent signals. That's all the
difference.

 > In windows, this doesn't matter (resetting the event on
> startwait), because it preserves the signaled state of the event.

It preserves the signalled state? By resetting it? I don't think so.

AFAICS, it resets the signal before actually starting to wait for it. So
it still can sneak in if the timing is right. That's what I'd call a
race condition.

 > The wait call just returns immediately, if the event is allready
signaled.
> To me, this is fine. As long as rtlevent is used with this in mind, it
> should give a consistent behaviour on windows and linux. (see
> classes.inc thread synchronization)

You mean code like:

|if timeout>0 then
|  begin
|    RtlEventStartWait(SynchronizeTimeoutEvent);
|    RtlEventWaitFor(SynchronizeTimeoutEvent,timeout);
|  end
|  else
|    RtlEventResetEvent(SynchronizeTimeoutEvent);

So where's the code that makes sure that the thread signalling the event
is (only) resumed between the two calls?

>> I'm not even sure, if Unix actually clears the event. The man-pages
>> don't seem to indicate so.
>
> It does, at least with the timedwait. I tested that extensively.

Yes, and now I think we both know why. I seem to repeat myself, but it
might be important: The difference is all between implementing transient
and persistent signals.


Vinzent.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Vinzent Höfler
In reply to this post by Burkhard Carstens-3
Burkhard Carstens wrote:

> [..]
>> ... As long as rtlevent is used with this
>> in mind, it should give a consistent behaviour on windows and linux.
>
> "this in mind" means: The only way how rtlevent should be used is:
> 1. call rtlstartwait
> 2. start the code (e.g. start/resume a thread), that signals the event.
> 3. call rtlwaitevent

Great. ;( But there's a flaw in this: If I'd actually know that thread A
had been executed rtlstartwait() before thread B tries signalling the
condition, I wouldn't need the whole synchronization at all.


Vinzent.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Florian Klaempfl
Vinzent Höfler wrote:

I didn't understand and follow the whole thread but please submit a bug
report if something in FPC needs to be fixed :)
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore problems

Vinzent Höfler
Florian Klaempfl wrote:

> I didn't understand and follow the whole thread but please submit a bug
> report if something in FPC needs to be fixed :)

Well, I'll do as soon as I'm sure if there's a bug. :)

Currently all I see is a subtle semantic difference between Windows- and
Unix-Event's implementation.

So for now all I can say is that this should either

a) be documented,
b) changed to a common semantic behaviour, or
c) ignored, because I'm just too stupid.


Vinzent.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
123