#At file:///usr/home/serg/Abk/mysql/6.0-maria/
2756 Sergei Golubchik 2008-11-07 [merge]
merge
modified:
include/waiting_threads.h
mysys/lf_hash.c
mysys/waiting_threads.c
=== modified file 'include/waiting_threads.h'
--- a/include/waiting_threads.h 2008-10-27 22:23:34 +0000
+++ b/include/waiting_threads.h 2008-11-04 13:09:32 +0000
@@ -30,13 +30,11 @@ typedef struct st_wt_resource_type {
const void *(*make_key)(WT_RESOURCE_ID *id, uint *len);
} WT_RESOURCE_TYPE;
-/* we want to compare this struct with memcmp, make it packed */
-#pragma pack(1)
struct st_wt_resource_id {
ulonglong value;
WT_RESOURCE_TYPE *type;
};
-#pragma pack()
+#define sizeof_WT_RESOURCE_ID (sizeof(ulonglong)+sizeof(void*))
#define WT_WAIT_STATS 24
#define WT_CYCLE_STATS 32
@@ -82,7 +80,31 @@ typedef struct st_wt_resource {
#ifdef WT_RWLOCKS_USE_MUTEXES
/*
we need a special rwlock-like 'lock' to allow readers bypass
- waiting writers, otherwise readers can deadlock.
+ waiting writers, otherwise readers can deadlock. For example:
+
+ A waits on resource x, owned by B, B waits on resource y, owned
+ by A, we have a cycle (A->x->B->y->A)
+ Both A and B start deadlock detection:
+
+ A locks x B locks y
+ A goes deeper B goes deeper
+ A locks y B locks x
+
+ with mutexes it would deadlock. With rwlocks it won't, as long
+ as both A and B are taking read locks (and they do).
+ But other threads may take write locks. Assume there's
+ C who wants to start waiting on x, and D who wants to start
+ waiting on y.
+
+ A read-locks x B read-locks y
+ A goes deeper B goes deeper
+ => C write-locks x (to add a new edge) D write-locks y
+ .. C is blocked D is blocked
+ A read-locks y B read-locks x
+
+ Now, if a read lock can bypass a pending wrote lock request, we're fine.
+ If it can not, we have a deadlock.
+
writer starvation is technically possible, but unlikely, because
the contention is expected to be low.
*/
=== modified file 'mysys/lf_hash.c'
--- a/mysys/lf_hash.c 2008-07-29 14:10:24 +0000
+++ b/mysys/lf_hash.c 2008-11-03 19:33:34 +0000
@@ -281,8 +281,9 @@ static inline const uchar* hash_key(cons
}
/*
- compute the hash key value from the raw key.
- note, that the hash value is limited to 2^31, because we need one
+ Compute the hash key value from the raw key.
+
+ @note, that the hash value is limited to 2^31, because we need one
bit to distinguish between normal and dummy nodes.
*/
static inline uint calc_hash(LF_HASH *hash, const uchar *key, uint keylen)
@@ -300,7 +301,7 @@ static int initialize_bucket(LF_HASH *,
/*
Initializes lf_hash, the arguments are compatible with hash_init
- @@note element_size sets both the size of allocated memory block for
+ @note element_size sets both the size of allocated memory block for
lf_alloc and a size of memcpy'ed block size in lf_hash_insert. Typically
they are the same, indeed. But LF_HASH::element_size can be decreased
after lf_hash_init, and then lf_alloc will allocate larger block that
=== modified file 'mysys/waiting_threads.c'
--- a/mysys/waiting_threads.c 2008-10-24 10:34:08 +0000
+++ b/mysys/waiting_threads.c 2008-11-03 19:33:34 +0000
@@ -280,7 +280,7 @@ void wt_init()
DBUG_ENTER("wt_init");
lf_hash_init(&reshash, sizeof(WT_RESOURCE), LF_HASH_UNIQUE, 0,
- sizeof(struct st_wt_resource_id), 0, 0);
+ sizeof_WT_RESOURCE_ID, 0, 0);
reshash.alloc.constructor= wt_resource_init;
reshash.alloc.destructor= wt_resource_destroy;
/*
@@ -396,9 +396,7 @@ void wt_thd_destroy(WT_THD *thd)
*/
int wt_resource_id_memcmp(void *a, void *b)
{
- /* assert that the structure is not padded with random bytes */
- compile_time_assert(sizeof(WT_RESOURCE_ID)==sizeof(ulonglong)+sizeof(void*));
- return memcmp(a, b, sizeof(WT_RESOURCE_ID));
+ return memcmp(a, b, sizeof_WT_RESOURCE_ID);
}
/**
@@ -657,7 +655,7 @@ static int unlock_lock_and_free_resource
/* XXX if (rc->id.type->make_key) key=
rc->id.type->make_key(&rc->id, &keylen); else */
{
key= &rc->id;
- keylen= sizeof(rc->id);
+ keylen= sizeof_WT_RESOURCE_ID;
}
/*
@@ -751,7 +749,7 @@ int wt_thd_will_wait_for(WT_THD *thd, WT
/* XXX if (restype->make_key) key= restype->make_key(resid, &keylen); else
*/
{
key= resid;
- keylen= sizeof(*resid);
+ keylen= sizeof_WT_RESOURCE_ID;
}
DBUG_PRINT("wt", ("first blocker"));
| Thread |
|---|
| • bzr commit into mysql-6.0 branch (serg:2756) | Sergei Golubchik | 7 Nov |