Messages in this thread | | | Date | Fri, 24 Sep 1999 05:41:40 +0530 (IST) | From | Sushil Agarwal <> | Subject | recursive locks in kernel? |
| |
Hi,
Do we have recursive locks (like the one described in the book "Unix Internals" by Uresh Vahalia (Section 7.10.2) in linux 2.2.9 kernel (or any later kernel)?
Recursive locks are useful when we have a lower level function which is called by many higher level functions with some of them locking some data before calling this function and some of them not. Now the problem arises if this lower level function also wants to lock the same data because it does not know whether the data is already locked by some higher level function or not. If it just locks it blindly then this could lead to a deadlock.
For example:
The function f3 might get called via two diffrent call sequences like shown below: In the second sequence, the caller f1 locks X and in the first it doesn't. Since f3 does not know whether X is locked or not, it tries to lock it (in second sequence) resulting in deadlock.
calls calls f1 -----> f2 -----> f3, f3 locks X successfully.
calls calls f1A(locks X) -----> f2 -----> f3, f3 tries to lock X resulting in deadlock.
One solution to above probelm is to pass an argument to f3 via f2 which will hint f3 on whether to lock or not. But this is awkward and also what if there are more than one locks to consider. Here recursive locks will be a better solution.
One implementation of recursive locks: --------------------------------------
typedef struct recursive_lock { int data_to_lock; /* 1 means locked, 0 means free */ pid_t owner_pid; /* owner process of the lock */ int lock_count; /* no. of recursive instances of the lock held by the owner */ }recursive_lock_t;
get_recursive_lock(recursive_lock_t *r) { if(atomic_test_and_set(&r->data_to_lock) == 0) { /* if lock is free */ r->data_to_lock = 1; /* lock it */ r->owner_pid = current->pid; /* make ourself as the owner */ r->lock_count = 1; /* first instance of this lock */ return; } /* data is locked ; check if we are already the owner */ if(r->owner_pid == current->pid) { /* if held by the same process */ r->lock_count ++; /* return with success */ return; } /* lock is owned by some other process. So busy wait */ while(atomic_test_and_set(&r->data_to_lock) != 0) { /* if already locked */ while(r->data_to_lock != 0) /* busy wait till unlocked */ ; } r->owner_pid = current->pid; /* make ourself as the owner */ r->lock_count = 1; /* first instance of this lock */ }
release_recursive_lock(recursive_lock_t *r) { r->lock_count --; if(r->lock_count == 0) { /* last lock */ r->owner_pid = -1; /* no one owns this lock */ r->data_to_lock = 0; /* free the lock */ } }
expecting comments from you , - Sushil.
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |