Am Dienstag, 25. Juli 2006 11:59 schrieb Vinzent Hoefler: > On Tuesday 25 July 2006 09:04, Burkhard Carstens wrote: > > Am Dienstag, 25. Juli 2006 10:46 schrieb Micha Nelissen: > > > function Recursive_Mutex.Lock:...; > > > begin > > > // Owned by current thread? > > > if CurrentThreadId <> self.ThreadId then > > > begin > > > result := pthread_mutex_lock (self...); > > > if result <> 0 then exit; > > > self.ThreadId := CurrentThreadId; > > > self.Count := 1; > > > end else begin > > > Inc(self.Count); > > > end; > > > result := SUCCESS; > > > end {Mutex.Lock}; > > > > > > function Recursive_Mutex.Unlock: ...; > > > begin > > > if CurrentThreadId <> self.ThreadId then > > > exit(ENOTOWN); > > > assert(self.Count > 0); > > > dec(self.Count); > > > if self.Count = 0 then > > > begin > > > self.ThreadId := 0; // a threadid that does not occur in > > > system pthread_mutex_unlock(self...); > > > end; > > > result := SUCCESS; > > > end; > > > > > > I don't see the need for Owner_Check_Lock anymore ? :-) > > > > You have to prevent that 2 concurrent threads call lock > > simultanously, > > No. That's not a problem. See the explanation below. > > Perhaps the line "if result <> 0 then exit;" may be kind of > superfluous, or even dangerous, because it would return from the lock > operation without actually locking it, but well - if it goes wrong > here, we're screwed anyway. At least the caller could check, if it > did. > > > so you have to take an internal lock before touching > > internal vars like self.ThreadID ? > > First I thought that, too. But after looking at and thinking about it > a while, the race you mention could only occur if the *same* thread > would call Lock() simultaneously, and that can't happen. > > In the case two different threads enter here, they may both still see > "0" and are trying to continue then, but only one of them will > acquire the mutex sucessfully, leaving the other suspended. Once the > suspended thread continues, it actually owns the mutex, so > everything's ok then. > > Ok, there's a glitch: The read and write of self.ThreadId is required > to be atomic, so that a thread entering may either see "0" or the > owner's thread id when checking, otherwise it could be possible, it > sees its own thread_id due to a partial update and *then* it goes > really wrong.
To prevent this very rare but indeed possible case, just use interlockedexchange to assign anything to self.threadid ? Beside this, I like this implementation! This way, we have a recursive mutex, without depending on pthread recursive extension. Burkhard _______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal