diff options
author | Sergei Golubchik <serg@mysql.com> | 2009-01-15 22:27:36 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mysql.com> | 2009-01-15 22:27:36 +0100 |
commit | 9c96fde1206f254d0dd25dbe2cc1706c44e4bdea (patch) | |
tree | fdc0957f7f6b91f43a88bc18e6c37c7fd94fa911 /include/waiting_threads.h | |
parent | e01f6c8971c5598ea4868bb62bf6eb81a3bab945 (diff) | |
download | mariadb-git-9c96fde1206f254d0dd25dbe2cc1706c44e4bdea.tar.gz |
post-review fixes
include/atomic/generic-msvc.h:
prevent possible compiler warnings
include/lf.h:
comments, better definition for LF_HASH_OVERHEAD
include/maria.h:
define MARIA_CANNOT_ROLLBACK here
include/my_pthread.h:
avoid possible name clash
include/waiting_threads.h:
comments, const, move WT_RESOURCE to waiting_threads.c
mysql-test/suite/maria/r/maria_notembedded.result:
new test
mysql-test/suite/maria/t/maria_notembedded.test:
new test - 5-way deadlock
mysys/lf_hash.c:
better definition for LF_HASH_OVERHEAD
mysys/my_static.c:
comment
mysys/my_thr_init.c:
casts
mysys/waiting_threads.c:
comments, asserts, etc
server-tools/instance-manager/parse.cc:
fix my_init_dynamic_array() to follow new calling conventions
sql/mysqld.cc:
call wt_init after set_proper_floating_point_mode
sql/sql_class.h:
comment
storage/maria/ha_maria.cc:
move MARIA_CANNOT_ROLLBACK to a common header
storage/maria/ma_commit.c:
comment
storage/maria/ma_write.c:
comments, check for HA_ERR_FOUND_DUPP_KEY
storage/maria/trnman.c:
comments, assert
storage/maria/trnman.h:
comments
storage/maria/unittest/trnman-t.c:
be paranoid
unittest/mysys/lf-t.c:
comments
unittest/mysys/waiting_threads-t.c:
comments, safety, memory leak
Diffstat (limited to 'include/waiting_threads.h')
-rw-r--r-- | include/waiting_threads.h | 122 |
1 files changed, 25 insertions, 97 deletions
diff --git a/include/waiting_threads.h b/include/waiting_threads.h index c4e5b24fe43..45c3b140915 100644 --- a/include/waiting_threads.h +++ b/include/waiting_threads.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008 MySQL AB +/* Copyright (C) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,16 +24,18 @@ C_MODE_START typedef struct st_wt_resource_id WT_RESOURCE_ID; +typedef struct st_wt_resource WT_RESOURCE; typedef struct st_wt_resource_type { - int (*compare)(void *a, void *b); - const void *(*make_key)(WT_RESOURCE_ID *id, uint *len); + my_bool (*compare)(const void *a, const void *b); + const void *(*make_key)(const WT_RESOURCE_ID *id, uint *len); /* not used */ } WT_RESOURCE_TYPE; struct st_wt_resource_id { ulonglong value; - WT_RESOURCE_TYPE *type; + const WT_RESOURCE_TYPE *type; }; +/* the below differs from sizeof(WT_RESOURCE_ID) by the amount of padding */ #define sizeof_WT_RESOURCE_ID (sizeof(ulonglong)+sizeof(void*)) #define WT_WAIT_STATS 24 @@ -43,93 +45,17 @@ extern uint32 wt_wait_stats[WT_WAIT_STATS+1]; extern uint32 wt_cycle_stats[2][WT_CYCLE_STATS+1]; extern uint32 wt_success_stats; -/* - 'lock' protects 'owners', 'state', and 'waiter_count' - 'id' is read-only - - a resource is picked up from a hash in a lock-free manner - it's returned pinned, so it cannot be freed at once - but it may be freed right after the pin is removed - to free a resource it should be - 1. have no owners - 2. have no waiters - - two ways to access a resource: - 1. find it in a hash - - it's returned pinned. - a) take a lock in exclusive mode - b) check the state, it should be ACTIVE - c) unpin - 2. by a direct reference - - could only used if a resource cannot be freed - e.g. accessing a resource by thd->waiting_for is safe, - a resource cannot be freed as there's a thread waiting for it -*/ -typedef struct st_wt_resource { - WT_RESOURCE_ID id; - uint waiter_count; - enum { ACTIVE, FREE } state; -#ifndef DBUG_OFF - pthread_mutex_t *mutex; -#endif - /* - before the 'lock' all elements are mutable, after (and including) - - immutable in the sense that lf_hash_insert() won't memcpy() over them. - See wt_init(). - */ -#ifdef WT_RWLOCKS_USE_MUTEXES - /* - we need a special rwlock-like 'lock' to allow readers bypass - 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. - */ - struct { - pthread_cond_t cond; - pthread_mutex_t mutex; - uint readers: 16; - uint pending_writers: 15; - uint write_locked: 1; - } lock; -#else - rw_lock_t lock; -#endif - pthread_cond_t cond; - DYNAMIC_ARRAY owners; -} WT_RESOURCE; - typedef struct st_wt_thd { /* XXX - there's no protection (mutex) against concurrent access of - the dynarray below. it is assumed that a caller will have it - automatically (not to protect this array but to protect its - own - caller's - data structures, and we'll get it for free. - If not, we'll need to add a mutex + there's no protection (mutex) against concurrent access of the + dynarray below. it is assumed that a caller will have it anyway + (not to protect this array but to protect its own - caller's - + data structures), and we'll get it for free. A caller needs to + ensure that a blocker won't release a resource before a blocked + thread starts waiting, which is usually done with a mutex. + + If the above assumption is wrong, we'll need to add a mutex here. */ DYNAMIC_ARRAY my_resources; /* @@ -141,8 +67,10 @@ typedef struct st_wt_thd { LF_PINS *pins; /* pointers to values */ - ulong *timeout_short, *deadlock_search_depth_short; - ulong *timeout_long, *deadlock_search_depth_long; + const ulong *timeout_short; + const ulong *deadlock_search_depth_short; + const ulong *timeout_long; + const ulong *deadlock_search_depth_long; /* weight relates to the desirability of a transaction being killed if it's @@ -169,13 +97,13 @@ typedef struct st_wt_thd { */ ulong volatile weight; /* - 'killed' is indirectly protected by waiting_for->lock - - a killed thread needs to clear its 'waiting_for', and thus needs a lock. + 'killed' is indirectly protected by waiting_for->lock because + a killed thread needs to clear its 'waiting_for' and thus needs a lock. That is a thread needs an exclusive lock to read 'killed' reliably. But other threads may change 'killed' from 0 to 1, a shared lock is enough for that. */ - my_bool volatile killed; + my_bool killed; #ifndef DBUG_OFF const char *name; #endif @@ -189,13 +117,13 @@ typedef struct st_wt_thd { void wt_init(void); void wt_end(void); -void wt_thd_lazy_init(WT_THD *, ulong *, ulong *, ulong *, ulong *); +void wt_thd_lazy_init(WT_THD *, const ulong *, const ulong *, const ulong *, const ulong *); void wt_thd_destroy(WT_THD *); -int wt_thd_will_wait_for(WT_THD *, WT_THD *, WT_RESOURCE_ID *); +int wt_thd_will_wait_for(WT_THD *, WT_THD *, const WT_RESOURCE_ID *); int wt_thd_cond_timedwait(WT_THD *, pthread_mutex_t *); -void wt_thd_release(WT_THD *, WT_RESOURCE_ID *); +void wt_thd_release(WT_THD *, const WT_RESOURCE_ID *); #define wt_thd_release_all(THD) wt_thd_release((THD), 0) -int wt_resource_id_memcmp(void *, void *); +int wt_resource_id_memcmp(const void *, const void *); C_MODE_END |