Subj : Re: recursive mutexes To : comp.programming.threads From : doug Date : Mon May 16 2005 03:51 pm "Uenal Mutlu" <520001085531-0001@t-online.de> wrote in message news:d69n7p$on9$04$1@news.t-online.com... > "doug" wrote >> >> > You seem to not understand what I'm talking about. >> > Do you understand this fact: "Recursive locking is defined for the >> > current >> > lock owning thread only"? >> > Since you already have the lock you can do what ever you want since >> > nobody >> > else can change anything, but you can do! You simply increment it in >> > Lock() >> > and decrement it in Unlock(). Because it is safe because you already >> > have >> > it locked. >> > >> Think carefully. How is this possible? > > It is really basic stuff. Ask yourself how you would extend a > non-recursive > locking method to make it recursive? Recursivity starts with the 2nd > Lock() > call on the same object within the same thread, true? So, after the 1st > you > already have the lock, don't you? From then on just use a simple > unprotected counter. > It is intended for the current _lock owning thread_ only. It is irrelevant > for all > other threads because they don't have the lock. > Let me know if this makes sense to you. > You're missing the point of the question. If you have the lock, yes, you can increment a counter. But you need to check if you own the lock first, don't you? Your description above sounds like you're saying: - use a lock for the first time you grab the counter - use a counter thereafter. But then your thread needs to know if already owns the lock. So this isn't a recursive semaphore at all. Let's start again. Here is some pseudocode for a recursive Lock() routine. A recursive lock consists of a mutex (lock control), a signal var (condivar), a counter, and a thread identifier. Lock() { acquire_lock_control if (lock.owner == me) } lock.counter++; } else { while (lock.counter > 0) { release_lock_control wait_for_condivar acquire_lock_control } lock.counter = 1; lock.owner = me; } release_lock_control } The above is portable, and SMP safe. Can you write us a recursive Lock() using psuedocode that shows what you mean? The people reading this don't believe it can be done without syncronisation (i.e. without those acquire/release_lock_control calls). >> It is possible if you store 'have I got this lock?' in thread local >> storage. >> So yes, by keeping a counter here, you don't need a memory barrier in >> recursive Lock()/Unlock() *. However, when you find that you don't have >> the >> semaphore, you still need synchronisation between threads so that the >> sema4 >> is acquired safely. >> What you've ended up doing here is accessing TLS for *every* acquire - >> thus >> making the common case of 'semaphore not acquired' slower. >> >> (* not true on certain SMP architectures. Without a memory barrier in >> Lock()/Unlock(), a thread rescheduled on a different CPU may mis-read the >> recursive counter (depending on how TLS is implemented).) > > I think I now know what the reason of these misunderstandings are: > You and some others seem to see a lock as a property of a thread, > and by this you do "lock the thread". I on the other hand see a lock as > a property of the shared object. > I don't use any TLS, I use just the usual sharing mechanism of threads; > ie. all objects in a program can be accessed by all threads. > By this, I put locks on objects, not threads. > Each such shared object has its own mutex, and not one mutex per thread, > and of course also not one mutex for all threads (which IMO is nonsense). > > No, I think of a lock as related to one or more pieces of data, not a thread. Threads acquire the lock to access the data. Recursive locks, IMO, are used to 'convenience' of coding, where it's easier and/or faster to use a recursive lock than get your locking design completely correct. If you're writing an API, recursive locks are a bad idea. If you're writing a self-contained piece of code and maintainability isn't the be-all-and-end-all, recursive locks are acceptable. The TLS was an idea here to implement recursive locking without syncronisation when you already own the sema4, but as I pointed out, it a) won't work on all SMP machines, and b) will run slower. Again, you've not actually answered any of my questions. You've pointed out that I'm wrong, and you're right, but not why. .