[fpc-pascal] Semaphore problems

Vinzent Höfler JeLlyFish.software at gmx.net
Mon Jul 24 23:33:53 CEST 2006


Burkhard Carstens wrote:
> Am Montag, 24. Juli 2006 22:05 schrieb Vinzent Höfler:
>> Burkhard Carstens wrote:
>>> Am Montag, 24. Juli 2006 20:33 schrieb Vinzent Höfler:
>>>> Burkhard Carstens wrote:
>>>>> [..]
>>
>>> btw. this is not TEvent, we are talking about, it's rtlevent ..
>>> TEvent (in synconjs) is implemented differently, and should work
>>> like delphi/ windows TEvent, except that it is not capable of
>>> timedwait ..
>> Well, if I'm looking at it correctly that's only because its
>> implementation is based on the POSIX semaphore. It could be using the
>> phtread_mutex stuff instead. The pthread-primitives are used anyway,
>> so I don't see problems with dependencies on  libpthread/libc or
>> so...
> 
> My idea was to use a rtlevent additionally and only when waitfor is 
> called with timeout AND event is not signalled yet.

Why additionally? Do I miss something here? If done the proper way, 
everything in SyncObjs should be based on the basic RTL stuff. This 
would make the SyncObjs unit system independent with clearly defined 
semantics on all targets.

Of course, the original implementation (I suppose it came from Delphi?) 
was very windows-centric and made use of the available 
Windows-primitives directly. So maybe for Win32 it should even be kept 
this way, if not for anything else, somebody may say, for performance 
reasons at least.

>> Hmm, *looking closer* ... are there any differences between
>> Darwin/BSD/Linux/Solaris code at all? AFAICS, all these
>> implementations could be merged into a single one for Unix/POSIX
>> targets.
> 
> Don't know, maybe. However, we use PTHREAD_MUTEX_RECURSIVE_NP, where NP 
> stands for NotPortable.. don't know which platforms support it and 
> which not.

Well, those flags are somhow there, but there marked "XSI" in the 
OpenGroup's current specification, so probably most of our targets 
implement it - but it's still an extension.

> That's why I voted for implementing most of the functionality in pascal 
> and use pthread primitives only in their basic (i.e. mutex in 
> non-recursive) form.

Hmm. So we'd need a mutex inside a mutex. Now I know why they call it 
recursive. ;) So it'll be something like that:

function Recursive_Mutex.Lock : ...;
begin
    // Lock mutex inside mutex.
    self.Owner_Check_Lock.Lock;

    // Owned by current thread?
    if CurrentThreadId <> self.ThreadId then
    begin
       // Nope! Get the hell outta here.
       self.Owner_Check_Lock.Unlock;
       exit (NOT_OWNED);
    end {if};

    // Now try locking the real mutex.
    if pthread_mutex_lock (self...) = 0 then
    begin
       self.Count := self.Count + 1;
       self.Owner_Check.Unlock;
       exit (SUCCESS);
    end {if};

    self.Owner_Check.Unlock;
    exit (FAILURE);
end {Mutex.Lock};

Something like that. Don't nail me on that, it's quite late and the heat 
  is still killing me. ;)

Well, a simple spinlock would even be better here for performance 
reasons, because first the locking time should be quite small, and 
second usually this code will be called in a sequential manner from 
within the same thread anyway. This would make the lock always being in 
an unlocked state under all sane circumstances.

Maybe even some overflow check in case someone tries to lock the mutex 
more than 2**32 times in a row? ;)

Same for unlock etc.


Vinzent.




More information about the fpc-pascal mailing list