diff options
author | unknown <serg@janus.mylan> | 2006-11-19 21:32:16 +0100 |
---|---|---|
committer | unknown <serg@janus.mylan> | 2006-11-19 21:32:16 +0100 |
commit | 4b10971a3a887c176e3e71d092dd4cf4b4f68f3b (patch) | |
tree | 97b5ca197daad58db818a8764519e30e0193763a /storage/maria/tablockman.c | |
parent | 3f4aa5f7073ef6553ddacb9d3356fc88eb647657 (diff) | |
download | mariadb-git-4b10971a3a887c176e3e71d092dd4cf4b4f68f3b.tar.gz |
post-review fixes
Diffstat (limited to 'storage/maria/tablockman.c')
-rw-r--r-- | storage/maria/tablockman.c | 73 |
1 files changed, 43 insertions, 30 deletions
diff --git a/storage/maria/tablockman.c b/storage/maria/tablockman.c index b4cf77401bb..d8dffa09a5e 100644 --- a/storage/maria/tablockman.c +++ b/storage/maria/tablockman.c @@ -229,7 +229,7 @@ struct st_table_lock { #define hash_insert my_hash_insert /* for consistency :) */ static inline -TABLE_LOCK *find_loid(LOCKED_TABLE *table, uint16 loid) +TABLE_LOCK *find_by_loid(LOCKED_TABLE *table, uint16 loid) { return (TABLE_LOCK *)hash_search(& table->latest_locks, (byte *)& loid, sizeof(loid)); @@ -286,7 +286,7 @@ tablockman_getlock(TABLOCKMAN *lm, TABLE_LOCK_OWNER *lo, pthread_mutex_lock(& table->mutex); /* do we already have a lock on this resource ? */ - old= find_loid(table, lo->loid); + old= find_by_loid(table, lo->loid); /* calculate the level of the upgraded lock, if yes */ new_lock= old ? lock_combining_matrix[old->lock_type][lock] : lock; @@ -340,37 +340,50 @@ tablockman_getlock(TABLOCKMAN *lm, TABLE_LOCK_OWNER *lo, { /* found! */ wait_for= tmp; + break; } - else - { - /* - hmm, the lock before doesn't block us, let's look one step further. - the condition below means: - - if we never waited on a condition yet - OR - the lock before ours (blocker) waits on a lock (blocker2) that is - present in the hash AND and conflicts with 'blocker' - the condition after OR may fail if 'blocker2' was removed from - the hash, its signal woke us up, but 'blocker' itself didn't see - the signal yet. - */ - if (!lo->waiting_lock || - ((blocker2= find_loid(table, tmp->waiting_for_loid)) && - !lock_compatibility_matrix[blocker2->lock_type] - [blocker->lock_type])) - { - /* but it's waiting for a real lock. we'll wait for the same lock */ - wait_for= tmp->waiting_for; - } + /* + hmm, the lock before doesn't block us, let's look one step further. + the condition below means: + + if we never waited on a condition yet + OR + the lock before ours (blocker) waits on a lock (blocker2) that is + present in the hash AND and conflicts with 'blocker' + + the condition after OR may fail if 'blocker2' was removed from + the hash, its signal woke us up, but 'blocker' itself didn't see + the signal yet. + */ + if (!lo->waiting_lock || + ((blocker2= find_by_loid(table, tmp->waiting_for_loid)) && + !lock_compatibility_matrix[blocker2->lock_type] + [blocker->lock_type])) + { + /* but it's waiting for a real lock. we'll wait for the same lock */ + wait_for= tmp->waiting_for; /* - otherwise - a lock it's waiting for doesn't exist. - We've no choice but to scan the wait queue backwards, looking - for a conflicting lock or a lock waiting for a real lock. - QQ is there a way to avoid this scanning ? + We don't really need tmp->waiting_for, as tmp->waiting_for_loid + is enough. waiting_for is just a local cache to avoid calling + loid_to_tlo(). + But it's essensial that tmp->waiting_for pointer can ONLY + be dereferenced if find_by_loid() above returns a non-null + pointer, because a TABLE_LOCK_OWNER object that it points to + may've been freed when we come here after a signal. + In particular tmp->waiting_for_loid cannot be replaced + with tmp->waiting_for->loid. */ + DBUG_ASSERT(wait_for == lm->loid_to_tlo(tmp->waiting_for_loid)); + break; } + + /* + otherwise - a lock it's waiting for doesn't exist. + We've no choice but to scan the wait queue backwards, looking + for a conflicting lock or a lock waiting for a real lock. + QQ is there a way to avoid this scanning ? + */ } } @@ -531,8 +544,8 @@ void tablockman_release_locks(TABLOCKMAN *lm, TABLE_LOCK_OWNER *lo) transactions are awaken. But if trn2 times out, trn3 must be notified too (as IS and S locks are compatible). So trn2 must signal trn1->cond. */ - if (lock->prev && - lock_compatibility_matrix[lock->prev->lock_type][lock->lock_type]) + if (lock->next && + lock_compatibility_matrix[lock->next->lock_type][lock->lock_type]) { pthread_mutex_lock(lo->waiting_for->mutex); pthread_cond_broadcast(lo->waiting_for->cond); |