[fpc-pascal] Semaphore problems
Burkhard Carstens
fpc at bcsoft.de
Tue Jul 25 11:00:25 CEST 2006
Am Montag, 24. Juli 2006 23:38 schrieb Vinzent Höfler:
> Vinzent Höfler wrote:
> > 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. ;)
>
> I knew it. Of course this is wrong. We can only lock the mutex once,
> because we assume it's non-recursive, that was the whole point. So we
> should *first* check the count and then may lock/unlock the mutex
> accordingly.
* It's early, and I didn't dink enough coffee yet, so excuse me, if I
overlook something ;-)
some points:
* In windows, I never used mutexes, as I didn't see the point. Usually,
CriticalSections do what I want, except for IPC ... So I don't know if
windows mutexes are recursive.
However, IMO a CriticalSection should be recursive, so I stick to it
here
* pthread-Mutexes may not be used asynchronously (signal handlers are
mentioned in the man page), so if we take that as basic rule, things
get pretty simple: the same code is never executed simultanously from
the same thread.
* rtleventStartWait should have a counterpart rtlEventDoneWait, which
unlocks the internal mutex of a rtlevent.
* rtlWaitEvent should get a parameter telling it whether to call
rtlEventDoneWait or not. (currently, it simply does it)
* protect any method of a TCriticalSection with a internal critical
section (a simple, non-recursive form should do the job)
TCriticalSection.Enter;
procedure internalEnter;
begin
OwnerThread:=GetCurrentThreadID;
fLockCount:=1;
ExternelLock.lock;
end;
begin
internal.lock;
if OwnerThread = 0 then begin //not locked yet
internalEnter;
end
else begin //allready locked
if OwnerThread=GetCurrentThreadID then //we are the owner
inc(fLockCount)
else begin //other thread owns the cs
rtlEventStartWait(fExternalLock);
internallock.unlock;
rtlEventWaitFor(fExternalLock,DontAutoReleaseRTLEventMutex);
internalLock.lock;
rtlEventDoneWait(fExternalLock);
internalEnter;
end;
end;
internal.unlock;
end;
TCriticalSection.Leave;
procedure internalEnter;
begin
OwnerThread:=GetCurrentThreadID;
fLockCount:=1;
ExternelLock.lock;
end;
begin
internal.lock;
try
if OwnerThread <> GetCurrentThreadID then begin //we are not allowed
//to leave, because we don't own it!not locked yet
raise exception.create('leave on a foreign critical section');
end
else begin //we are the owner
if fLockCount = 0 then begin
raise exception.create('leave on a unlocked section');
end
else begin
dec(fLockCount);
if fLockCount=0 then rtlSetEvent(fExternalLock);
end;
end;
finally
internal.unlock;
end;
end;
* just a quick draft. This one should be pretty much the same as a
recursive mutex, i think ..
* have to leave now, bbl. Maybe we meet in IRC later and/or setup a wiki
page about this topic to collect and discuss proposals
Regards,
Burkhard
More information about the fpc-pascal
mailing list