diff options
-rw-r--r-- | include/lf.h | 43 | ||||
-rw-r--r-- | storage/maria/lockman.c | 8 | ||||
-rw-r--r-- | storage/maria/lockman.h | 2 | ||||
-rw-r--r-- | storage/maria/trnman.c | 147 | ||||
-rw-r--r-- | storage/maria/trnman.h | 2 | ||||
-rw-r--r-- | storage/maria/unittest/lockman-t.c | 97 | ||||
-rw-r--r-- | storage/maria/unittest/trnman-t.c | 31 |
7 files changed, 186 insertions, 144 deletions
diff --git a/include/lf.h b/include/lf.h index 45c5f109e1c..3a3b5b28ade 100644 --- a/include/lf.h +++ b/include/lf.h @@ -1,9 +1,18 @@ +/* Copyright (C) 2006 MySQL AB -/* - TODO - 1. copyright - 6. reduce the number of memory barriers -*/ + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _lf_h #define _lf_h @@ -11,7 +20,8 @@ #include <my_atomic.h> /* - Generic helpers + Helpers to define both func() and _func(), where + func() is a _func() protected by my_atomic_rwlock_wrlock() */ #define lock_wrap(f,t,proto_args, args, lock) \ @@ -49,7 +59,7 @@ static inline void f proto_args \ } /* - dynamic array + wait-free dynamic array, see lf_dynarray.c 4 levels of 256 elements each mean 4311810304 elements in an array - it should be enough for a while @@ -68,14 +78,9 @@ typedef int (*lf_dynarray_func)(void *, void *); void lf_dynarray_init(LF_DYNARRAY *array, uint element_size); void lf_dynarray_destroy(LF_DYNARRAY *array); -nolock_wrap(lf_dynarray_nr, int, - (LF_DYNARRAY *array, void *el), - (array,el)); - nolock_wrap(lf_dynarray_value, void *, (LF_DYNARRAY *array, uint idx), (array,idx)); - lock_wrap(lf_dynarray_lvalue, void *, (LF_DYNARRAY *array, uint idx), (array,idx), @@ -85,7 +90,7 @@ nolock_wrap(lf_dynarray_iterate, int, (array,func,arg)); /* - pin manager for memory allocator + pin manager for memory allocator, lf_alloc-pin.c */ #define LF_PINBOX_PINS 4 @@ -102,13 +107,13 @@ typedef struct { uint32 volatile pins_in_stack; /* number of elements in array */ } LF_PINBOX; -/* we want sizeof(LF_PINS) to be 128 to avoid false sharing */ typedef struct { void * volatile pin[LF_PINBOX_PINS]; LF_PINBOX *pinbox; void *purgatory; uint32 purgatory_count; uint32 volatile link; +/* we want sizeof(LF_PINS) to be 128 to avoid false sharing */ char pad[128-sizeof(uint32)*2 -sizeof(void *)*(LF_PINBOX_PINS+2)]; } LF_PINS; @@ -160,19 +165,13 @@ lock_wrap_void(lf_pinbox_put_pins, (LF_PINS *pins), (pins), &pins->pinbox->pinstack.lock); -#if 0 -lock_wrap_void(lf_pinbox_real_free, - (LF_PINS *pins), - (pins), - &pins->pinbox->pinstack.lock); -#endif lock_wrap_void(lf_pinbox_free, (LF_PINS *pins, void *addr), (pins,addr), &pins->pinbox->pinstack.lock); /* - memory allocator + memory allocator, lf_alloc-pin.c */ typedef struct st_lf_allocator { @@ -199,7 +198,7 @@ lock_wrap(lf_alloc_new, void *, &pins->pinbox->pinstack.lock); /* - extendible hash + extendible hash, lf_hash.c */ #include <hash.h> diff --git a/storage/maria/lockman.c b/storage/maria/lockman.c index 1712f6f2221..b37c31fb52c 100644 --- a/storage/maria/lockman.c +++ b/storage/maria/lockman.c @@ -5,7 +5,7 @@ different characteristics. long lists, few distinct resources - slow to scan, [possibly] high retry rate */ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2006 MySQL AB 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 @@ -272,7 +272,7 @@ retry: _lf_unpin(pins, 3); do { cursor->curr= PTR(*cursor->prev); - _lf_pin(pins,1,cursor->curr); + _lf_pin(pins, 1, cursor->curr); } while(*cursor->prev != (intptr)cursor->curr && LF_BACKOFF); for (;;) { @@ -507,7 +507,7 @@ static int lockdelete(LOCK * volatile *head, LOCK *node, LF_PINS *pins) void lockman_init(LOCKMAN *lm, loid_to_lo_func *func, uint timeout) { - lf_alloc_init(&lm->alloc,sizeof(LOCK), offsetof(LOCK,lonext)); + lf_alloc_init(&lm->alloc, sizeof(LOCK), offsetof(LOCK, lonext)); lf_dynarray_init(&lm->array, sizeof(LOCK **)); lm->size= 1; lm->count= 0; @@ -744,7 +744,7 @@ static char *lock2str[]= void print_lockhash(LOCKMAN *lm) { LOCK *el= *(LOCK **)_lf_dynarray_lvalue(&lm->array, 0); - printf("hash: size=%u count=%u\n", lm->size, lm->count); + printf("hash: size:%u count:%u\n", lm->size, lm->count); while (el) { intptr next= el->link; diff --git a/storage/maria/lockman.h b/storage/maria/lockman.h index 9edd79eb7f1..6577a5e80fc 100644 --- a/storage/maria/lockman.h +++ b/storage/maria/lockman.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2006 MySQL AB 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 diff --git a/storage/maria/trnman.c b/storage/maria/trnman.c index ecabf100cb8..95e5be4284a 100644 --- a/storage/maria/trnman.c +++ b/storage/maria/trnman.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2006 MySQL AB 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 @@ -20,21 +20,35 @@ #include <lf.h> #include "trnman.h" +/* status variables */ uint trnman_active_transactions, trnman_allocated_transactions; -static TRN active_list_min, active_list_max, - committed_list_min, committed_list_max, *pool; +/* list of active transactions in the trid order */ +static TRN active_list_min, active_list_max; +/* list of committed transactions in the trid order */ +static TRN committed_list_min, committed_list_max; -static pthread_mutex_t LOCK_trn_list; +/* a counter, used to generate transaction ids */ static TrID global_trid_generator; -static LF_HASH trid_to_trn; -static LOCKMAN maria_lockman; +/* the mutex for everything above */ +static pthread_mutex_t LOCK_trn_list; + +/* LIFO pool of unused TRN structured for reuse */ +static TRN *pool; + +/* a hash for committed transactions that maps trid to a TRN structure */ +static LF_HASH trid_to_committed_trn; -static TRN **short_trid_to_trn; +/* an array that maps short_trid of an active transaction to a TRN structure */ +static TRN **short_trid_to_active_trn; + +/* locks for short_trid_to_active_trn and pool */ static my_atomic_rwlock_t LOCK_short_trid_to_trn, LOCK_pool; -static byte *trn_get_hash_key(const byte *trn,uint* len, my_bool unused) +static LOCKMAN maria_lockman; + +static byte *trn_get_hash_key(const byte *trn, uint* len, my_bool unused) { *len= sizeof(TrID); return (byte *) & ((*((TRN **)trn))->trid); @@ -44,7 +58,7 @@ static LOCK_OWNER *trnman_short_trid_to_TRN(uint16 short_trid) { TRN *trn; my_atomic_rwlock_rdlock(&LOCK_short_trid_to_trn); - trn= my_atomic_loadptr((void **)&short_trid_to_trn[short_trid]); + trn= my_atomic_loadptr((void **)&short_trid_to_active_trn[short_trid]); my_atomic_rwlock_rdunlock(&LOCK_short_trid_to_trn); return (LOCK_OWNER *)trn; } @@ -52,39 +66,56 @@ static LOCK_OWNER *trnman_short_trid_to_TRN(uint16 short_trid) int trnman_init() { pthread_mutex_init(&LOCK_trn_list, MY_MUTEX_INIT_FAST); + + /* + Initialize lists. + active_list_max.min_read_from must be larger than any trid, + so that when an active list is empty we would could free + all committed list. + And committed_list_max itself can not be freed so + committed_list_max.commit_trid must not be smaller that + active_list_max.min_read_from + */ + active_list_max.trid= active_list_min.trid= 0; active_list_max.min_read_from= ~0; active_list_max.next= active_list_min.prev= 0; active_list_max.prev= &active_list_min; active_list_min.next= &active_list_max; - trnman_active_transactions= 0; - trnman_allocated_transactions= 0; committed_list_max.commit_trid= ~0; committed_list_max.next= committed_list_min.prev= 0; committed_list_max.prev= &committed_list_min; committed_list_min.next= &committed_list_max; + trnman_active_transactions= 0; + trnman_allocated_transactions= 0; + pool= 0; - global_trid_generator= 0; /* set later by recovery code */ - lf_hash_init(&trid_to_trn, sizeof(TRN*), LF_HASH_UNIQUE, + global_trid_generator= 0; /* set later by the recovery code */ + lf_hash_init(&trid_to_committed_trn, sizeof(TRN*), LF_HASH_UNIQUE, 0, 0, trn_get_hash_key, 0); my_atomic_rwlock_init(&LOCK_short_trid_to_trn); my_atomic_rwlock_init(&LOCK_pool); - short_trid_to_trn= (TRN **)my_malloc(SHORT_TRID_MAX*sizeof(TRN*), + short_trid_to_active_trn= (TRN **)my_malloc(SHORT_TRID_MAX*sizeof(TRN*), MYF(MY_WME|MY_ZEROFILL)); - if (!short_trid_to_trn) + if (!short_trid_to_active_trn) return 1; - short_trid_to_trn--; /* min short_trid is 1 */ + short_trid_to_active_trn--; /* min short_trid is 1 */ lockman_init(&maria_lockman, &trnman_short_trid_to_TRN, 10000); return 0; } +/* + NOTE + this could only be called in the "idle" state - no transaction can be + running. See asserts below. +*/ int trnman_destroy() { - DBUG_ASSERT(trid_to_trn.count == 0); + DBUG_ASSERT(trid_to_committed_trn.count == 0); DBUG_ASSERT(trnman_active_transactions == 0); DBUG_ASSERT(active_list_max.prev == &active_list_min); DBUG_ASSERT(active_list_min.next == &active_list_max); @@ -98,14 +129,20 @@ int trnman_destroy() DBUG_ASSERT(trn->locks.cond == 0); my_free((void *)trn, MYF(0)); } - lf_hash_destroy(&trid_to_trn); + lf_hash_destroy(&trid_to_committed_trn); pthread_mutex_destroy(&LOCK_trn_list); my_atomic_rwlock_destroy(&LOCK_short_trid_to_trn); my_atomic_rwlock_destroy(&LOCK_pool); - my_free((void *)(short_trid_to_trn+1), MYF(0)); + my_free((void *)(short_trid_to_active_trn+1), MYF(0)); lockman_destroy(&maria_lockman); } +/* + NOTE + TrID is limited to 6 bytes. Initial value of the generator + is set by the recovery code - being read from the last checkpoint + (or 1 on a first run). +*/ static TrID new_trid() { DBUG_ASSERT(global_trid_generator < 0xffffffffffffLL); @@ -120,8 +157,8 @@ static void set_short_trid(TRN *trn) for ( ; ; i= i % SHORT_TRID_MAX + 1) /* the range is [1..SHORT_TRID_MAX] */ { void *tmp= NULL; - if (short_trid_to_trn[i] == NULL && - my_atomic_casptr((void **)&short_trid_to_trn[i], &tmp, trn)) + if (short_trid_to_active_trn[i] == NULL && + my_atomic_casptr((void **)&short_trid_to_active_trn[i], &tmp, trn)) break; } my_atomic_rwlock_wrunlock(&LOCK_short_trid_to_trn); @@ -138,38 +175,37 @@ TRN *trnman_new_trn(pthread_mutex_t *mutex, pthread_cond_t *cond) TRN *trn; /* - see trnman_end_trn to see why we need a mutex here - - and as we have a mutex, we can as well do everything - under it - allocating a TRN, incrementing trnman_active_transactions, - setting trn->min_read_from. + we have a mutex, to do simple things under it - allocate a TRN, + increment trnman_active_transactions, set trn->min_read_from. Note that all the above is fast. generating short_trid may be slow, - as it involves scanning a big array - so it's still done - outside of the mutex. + as it involves scanning a large array - so it's done outside of the + mutex. */ pthread_mutex_lock(&LOCK_trn_list); - trnman_active_transactions++; + /* Allocating a new TRN structure */ trn= pool; - /* popping an element from a stack */ + /* Popping an unused TRN from the pool */ my_atomic_rwlock_wrlock(&LOCK_pool); while (trn && !my_atomic_casptr((void **)&pool, (void **)&trn, (void *)trn->next)) /* no-op */; my_atomic_rwlock_wrunlock(&LOCK_pool); + /* Nothing in the pool ? Allocate a new one */ if (!trn) { trn= (TRN *)my_malloc(sizeof(TRN), MYF(MY_WME)); - if (!trn) + if (unlikely(!trn)) { pthread_mutex_unlock(&LOCK_trn_list); return 0; } trnman_allocated_transactions++; } + trnman_active_transactions++; trn->min_read_from= active_list_min.next->trid; @@ -181,36 +217,31 @@ TRN *trnman_new_trn(pthread_mutex_t *mutex, pthread_cond_t *cond) active_list_max.prev= trn->prev->next= trn; pthread_mutex_unlock(&LOCK_trn_list); - trn->pins= lf_hash_get_pins(&trid_to_trn); + trn->pins= lf_hash_get_pins(&trid_to_committed_trn); - if (!trn->min_read_from) + if (unlikely(!trn->min_read_from)) trn->min_read_from= trn->trid; + trn->commit_trid= 0; + trn->locks.mutex= mutex; trn->locks.cond= cond; - trn->commit_trid= 0; trn->locks.waiting_for= 0; trn->locks.all_locks= 0; trn->locks.pins= lf_alloc_get_pins(&maria_lockman.alloc); - set_short_trid(trn); /* this must be the last! */ + /* + only after the following function TRN is considered initialized, + so it must be done the last + */ + set_short_trid(trn); return trn; } /* - remove a trn from the active list, - move to committed list, - set commit_trid - - TODO - integrate with log manager. That means: - a common "commit" mutex - forcing the log and setting commit_trid - must be done atomically (QQ how the heck it could be done with - group commit ???) XXX - why did I think it must be done atomically ? - - trid_to_trn, active_list_*, and committed_list_* can be - updated asyncronously. + remove a trn from the active list. + if necessary - move to committed list and set commit_trid */ void trnman_end_trn(TRN *trn, my_bool commit) { @@ -224,7 +255,11 @@ void trnman_end_trn(TRN *trn, my_bool commit) trn->next->prev= trn->prev; trn->prev->next= trn->next; - /* if this transaction was the oldest - clean up committed list */ + /* + if trn was the oldest active transaction, now that it goes away there + may be committed transactions in the list which no active transaction + needs to bother about - clean up the committed list + */ if (trn->prev == &active_list_min) { TRN *t; @@ -232,6 +267,7 @@ void trnman_end_trn(TRN *trn, my_bool commit) t->commit_trid < active_list_min.next->min_read_from; t= t->next) /* no-op */; + /* found transactions committed before the oldest active one */ if (t != committed_list_min.next) { free_me= committed_list_min.next; @@ -241,7 +277,10 @@ void trnman_end_trn(TRN *trn, my_bool commit) } } - /* add transaction to the committed list (for read-from relations) */ + /* + if transaction is committed and it was not the only active transaction - + add it to the committed list (which is used for read-from relation) + */ if (commit && active_list_min.next != &active_list_max) { trn->commit_trid= global_trid_generator; @@ -250,10 +289,10 @@ void trnman_end_trn(TRN *trn, my_bool commit) trn->prev= committed_list_max.prev; committed_list_max.prev= trn->prev->next= trn; - res= lf_hash_insert(&trid_to_trn, pins, &trn); + res= lf_hash_insert(&trid_to_committed_trn, pins, &trn); DBUG_ASSERT(res == 0); } - else /* or free it right away */ + else /* otherwise free it right away */ { trn->next= free_me; free_me= trn; @@ -266,7 +305,7 @@ void trnman_end_trn(TRN *trn, my_bool commit) trn->locks.mutex= 0; trn->locks.cond= 0; my_atomic_rwlock_rdlock(&LOCK_short_trid_to_trn); - my_atomic_storeptr((void **)&short_trid_to_trn[trn->locks.loid], 0); + my_atomic_storeptr((void **)&short_trid_to_active_trn[trn->locks.loid], 0); my_atomic_rwlock_rdunlock(&LOCK_short_trid_to_trn); while (free_me) // XXX send them to the purge thread @@ -275,7 +314,7 @@ void trnman_end_trn(TRN *trn, my_bool commit) TRN *t= free_me; free_me= free_me->next; - res= lf_hash_delete(&trid_to_trn, pins, &t->trid, sizeof(TrID)); + res= lf_hash_delete(&trid_to_committed_trn, pins, &t->trid, sizeof(TrID)); trnman_free_trn(t); } @@ -331,7 +370,7 @@ my_bool trnman_can_read_from(TRN *trn, TrID trid) if (trid > trn->trid) return FALSE; /* cannot read */ - found= lf_hash_search(&trid_to_trn, trn->pins, &trid, sizeof(trid)); + found= lf_hash_search(&trid_to_committed_trn, trn->pins, &trid, sizeof(trid)); if (!found) return FALSE; /* not in the hash of committed transactions = cannot read */ diff --git a/storage/maria/trnman.h b/storage/maria/trnman.h index 9470678f3b2..c059947f35c 100644 --- a/storage/maria/trnman.h +++ b/storage/maria/trnman.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2006 MySQL AB 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 diff --git a/storage/maria/unittest/lockman-t.c b/storage/maria/unittest/lockman-t.c index 638078fea65..ad382a360fb 100644 --- a/storage/maria/unittest/lockman-t.c +++ b/storage/maria/unittest/lockman-t.c @@ -42,16 +42,20 @@ LOCK_OWNER *loid2lo(uint16 loid) return loarray+loid-1; } -#define unlock_all(O) diag("lo" #O "> release all locks"); \ +#define unlock_all(O) diag("lo" #O "> release all locks"); \ lockman_release_locks(&lockman, loid2lo(O));print_lockhash(&lockman) -#define test_lock(O, R, L, S, RES) \ - ok(lockman_getlock(&lockman, loid2lo(O), R, L) == RES, \ - "lo" #O "> " S " lock resource " #R " with " #L "-lock"); \ +#define test_lock(O, R, L, S, RES) \ + ok(lockman_getlock(&lockman, loid2lo(O), R, L) == RES, \ + "lo" #O "> " S " lock resource " #R " with " #L "-lock"); \ print_lockhash(&lockman) -#define lock_ok_a(O,R,L) test_lock(O,R,L,"",GOT_THE_LOCK) -#define lock_ok_i(O,R,L) test_lock(O,R,L,"",GOT_THE_LOCK_NEED_TO_LOCK_A_SUBRESOURCE) -#define lock_ok_l(O,R,L) test_lock(O,R,L,"",GOT_THE_LOCK_NEED_TO_INSTANT_LOCK_A_SUBRESOURCE) -#define lock_conflict(O,R,L) test_lock(O,R,L,"cannot ",DIDNT_GET_THE_LOCK); +#define lock_ok_a(O, R, L) \ + test_lock(O, R, L, "", GOT_THE_LOCK) +#define lock_ok_i(O, R, L) \ + test_lock(O, R, L, "", GOT_THE_LOCK_NEED_TO_LOCK_A_SUBRESOURCE) +#define lock_ok_l(O, R, L) \ + test_lock(O, R, L, "", GOT_THE_LOCK_NEED_TO_INSTANT_LOCK_A_SUBRESOURCE) +#define lock_conflict(O, R, L) \ + test_lock(O, R, L, "cannot ", DIDNT_GET_THE_LOCK); void test_lockman_simple() { @@ -63,41 +67,41 @@ void test_lockman_simple() lock_ok_a(1, 1, X); lock_ok_i(2, 2, IX); /* failures */ - lock_conflict(2,1,X); + lock_conflict(2, 1, X); unlock_all(2); - lock_ok_a(1,2,S); - lock_ok_a(1,2,IS); - lock_ok_a(1,2,LS); - lock_ok_i(1,3,IX); - lock_ok_a(2,3,LS); - lock_ok_i(1,3,IX); - lock_ok_l(2,3,IS); + lock_ok_a(1, 2, S); + lock_ok_a(1, 2, IS); + lock_ok_a(1, 2, LS); + lock_ok_i(1, 3, IX); + lock_ok_a(2, 3, LS); + lock_ok_i(1, 3, IX); + lock_ok_l(2, 3, IS); unlock_all(1); unlock_all(2); - lock_ok_i(1,1,IX); - lock_conflict(2,1,S); - lock_ok_a(1,1,LS); + lock_ok_i(1, 1, IX); + lock_conflict(2, 1, S); + lock_ok_a(1, 1, LS); unlock_all(1); unlock_all(2); - lock_ok_i(1,1,IX); - lock_ok_a(2,1,LS); - lock_ok_a(1,1,LS); - lock_ok_i(1,1,IX); - lock_ok_i(3,1,IS); + lock_ok_i(1, 1, IX); + lock_ok_a(2, 1, LS); + lock_ok_a(1, 1, LS); + lock_ok_i(1, 1, IX); + lock_ok_i(3, 1, IS); unlock_all(1); unlock_all(2); unlock_all(3); - lock_ok_i(1,4,IS); - lock_ok_i(2,4,IS); - lock_ok_i(3,4,IS); - lock_ok_a(3,4,LS); - lock_ok_i(4,4,IS); - lock_conflict(4,4,IX); - lock_conflict(2,4,IX); - lock_ok_a(1,4,LS); + lock_ok_i(1, 4, IS); + lock_ok_i(2, 4, IS); + lock_ok_i(3, 4, IS); + lock_ok_a(3, 4, LS); + lock_ok_i(4, 4, IS); + lock_conflict(4, 4, IX); + lock_conflict(2, 4, IX); + lock_ok_a(1, 4, LS); unlock_all(1); unlock_all(2); unlock_all(3); @@ -110,7 +114,7 @@ pthread_mutex_t rt_mutex; pthread_cond_t rt_cond; int rt_num_threads; int litmus; -int thread_number= 0, timeouts=0; +int thread_number= 0, timeouts= 0; void run_test(const char *test, pthread_handler handler, int n, int m) { pthread_t t; @@ -121,7 +125,8 @@ void run_test(const char *test, pthread_handler handler, int n, int m) diag("Testing %s with %d threads, %d iterations... ", test, n, m); for (rt_num_threads= n ; n ; n--) - pthread_create(&t, &rt_attr, handler, &m); + if (pthread_create(&t, &rt_attr, handler, &m)) + abort(); pthread_mutex_lock(&rt_mutex); while (rt_num_threads) pthread_cond_wait(&rt_cond, &rt_mutex); @@ -133,9 +138,9 @@ void run_test(const char *test, pthread_handler handler, int n, int m) int Nrows= 100; int Ntables= 10; int table_lock_ratio= 10; -enum lock_type lock_array[6]={S,X,LS,LX,IS,IX}; -char *lock2str[6]={"S","X","LS","LX","IS","IX"}; -char *res2str[4]={ +enum lock_type lock_array[6]= {S, X, LS, LX, IS, IX}; +char *lock2str[6]= {"S", "X", "LS", "LX", "IS", "IX"}; +char *res2str[4]= { "DIDN'T GET THE LOCK", "GOT THE LOCK", "GOT THE LOCK NEED TO LOCK A SUBRESOURCE", @@ -160,12 +165,12 @@ pthread_handler_t test_lockman(void *arg) if (table_lock_ratio && (x/Nrows/4) % table_lock_ratio == 0) { /* table lock */ res= lockman_getlock(&lockman, lo, table, lock_array[locklevel]); - DIAG(("loid=%2d, table %d lock %s, res=%s", loid, table, + DIAG(("loid %2d, table %d, lock %s, res %s", loid, table, lock2str[locklevel], res2str[res])); if (res == DIDNT_GET_THE_LOCK) { lockman_release_locks(&lockman, lo); - DIAG(("loid=%2d, release all locks", loid)); + DIAG(("loid %2d, release all locks", loid)); timeout++; continue; } @@ -175,13 +180,13 @@ pthread_handler_t test_lockman(void *arg) { /* row lock */ locklevel&= 1; res= lockman_getlock(&lockman, lo, table, lock_array[locklevel + 4]); - DIAG(("loid=%2d, row %d lock %s, res=%s", loid, row, + DIAG(("loid %2d, row %d, lock %s, res %s", loid, row, lock2str[locklevel+4], res2str[res])); switch (res) { case DIDNT_GET_THE_LOCK: lockman_release_locks(&lockman, lo); - DIAG(("loid=%2d, release all locks", loid)); + DIAG(("loid %2d, release all locks", loid)); timeout++; continue; case GOT_THE_LOCK: @@ -190,12 +195,12 @@ pthread_handler_t test_lockman(void *arg) /* not implemented, so take a regular lock */ case GOT_THE_LOCK_NEED_TO_LOCK_A_SUBRESOURCE: res= lockman_getlock(&lockman, lo, row, lock_array[locklevel]); - DIAG(("loid=%2d, ROW %d lock %s, res=%s", loid, row, + DIAG(("loid %2d, ROW %d, lock %s, res %s", loid, row, lock2str[locklevel], res2str[res])); if (res == DIDNT_GET_THE_LOCK) { lockman_release_locks(&lockman, lo); - DIAG(("loid=%2d, release all locks", loid)); + DIAG(("loid %2d, release all locks", loid)); timeout++; continue; } @@ -234,7 +239,7 @@ int main() return exit_status(); pthread_attr_init(&rt_attr); - pthread_attr_setdetachstate(&rt_attr,PTHREAD_CREATE_DETACHED); + pthread_attr_setdetachstate(&rt_attr, PTHREAD_CREATE_DETACHED); pthread_mutex_init(&rt_mutex, 0); pthread_cond_init(&rt_cond, 0); @@ -261,13 +266,13 @@ int main() Nrows= 100; Ntables= 10; table_lock_ratio= 10; - run_test("lockman", test_lockman, THREADS,CYCLES); + run_test("lockman", test_lockman, THREADS, CYCLES); /* "real-life" simulation - many rows, no table locks */ Nrows= 1000000; Ntables= 10; table_lock_ratio= 0; - run_test("lockman", test_lockman, THREADS,10000); + run_test("lockman", test_lockman, THREADS, 10000); for (i= 0; i < Nlos; i++) { diff --git a/storage/maria/unittest/trnman-t.c b/storage/maria/unittest/trnman-t.c index 6d4b48c6d3d..7bde9f5f720 100644 --- a/storage/maria/unittest/trnman-t.c +++ b/storage/maria/unittest/trnman-t.c @@ -41,7 +41,7 @@ pthread_handler_t test_trnman(void *arg) pthread_mutex_t mutexes[MAX_ITER]; pthread_cond_t conds[MAX_ITER]; - for (i=0; i < MAX_ITER; i++) + for (i= 0; i < MAX_ITER; i++) { pthread_mutex_init(&mutexes[i], MY_MUTEX_INIT_FAST); pthread_cond_init(&conds[i], 0); @@ -60,7 +60,7 @@ pthread_handler_t test_trnman(void *arg) } } - for (i=0; i < MAX_ITER; i++) + for (i= 0; i < MAX_ITER; i++) { pthread_mutex_destroy(&mutexes[i]); pthread_cond_destroy(&conds[i]); @@ -84,7 +84,8 @@ void run_test(const char *test, pthread_handler handler, int n, int m) diag("Testing %s with %d threads, %d iterations... ", test, n, m); for (rt_num_threads= n ; n ; n--) - pthread_create(&t, &rt_attr, handler, &m); + if (pthread_create(&t, &rt_attr, handler, &m)) + abort(); pthread_mutex_lock(&rt_mutex); while (rt_num_threads) pthread_cond_wait(&rt_cond, &rt_mutex); @@ -94,11 +95,10 @@ void run_test(const char *test, pthread_handler handler, int n, int m) } #define ok_read_from(T1, T2, RES) \ - i=trnman_can_read_from(trn[T1], trid[T2]); \ + i= trnman_can_read_from(trn[T1], trn[T2]->trid); \ ok(i == RES, "trn" #T1 " %s read from trn" #T2, i ? "can" : "cannot") #define start_transaction(T) \ - trn[T]= trnman_new_trn(&mutexes[T], &conds[T]); \ - trid[T]= trn[T]->trid + trn[T]= trnman_new_trn(&mutexes[T], &conds[T]) #define commit(T) trnman_commit_trn(trn[T]) #define abort(T) trnman_abort_trn(trn[T]) @@ -106,12 +106,11 @@ void run_test(const char *test, pthread_handler handler, int n, int m) void test_trnman_read_from() { TRN *trn[Ntrns]; - TrID trid[Ntrns]; pthread_mutex_t mutexes[Ntrns]; pthread_cond_t conds[Ntrns]; int i; - for (i=0; i < Ntrns; i++) + for (i= 0; i < Ntrns; i++) { pthread_mutex_init(&mutexes[i], MY_MUTEX_INIT_FAST); pthread_cond_init(&conds[i], 0); @@ -119,19 +118,19 @@ void test_trnman_read_from() start_transaction(0); /* start trn1 */ start_transaction(1); /* start trn2 */ - ok_read_from(1,0,0); + ok_read_from(1, 0, 0); commit(0); /* commit trn1 */ start_transaction(2); /* start trn4 */ abort(2); /* abort trn4 */ start_transaction(3); /* start trn5 */ - ok_read_from(3,0,1); - ok_read_from(3,1,0); - ok_read_from(3,2,0); + ok_read_from(3, 0, 1); + ok_read_from(3, 1, 0); + ok_read_from(3, 2, 0); commit(1); /* commit trn2 */ - ok_read_from(3,1,0); + ok_read_from(3, 1, 0); commit(3); /* commit trn5 */ - for (i=0; i < Ntrns; i++) + for (i= 0; i < Ntrns; i++) { pthread_mutex_destroy(&mutexes[i]); pthread_cond_destroy(&conds[i]); @@ -148,7 +147,7 @@ int main() return exit_status(); pthread_attr_init(&rt_attr); - pthread_attr_setdetachstate(&rt_attr,PTHREAD_CREATE_DETACHED); + pthread_attr_setdetachstate(&rt_attr, PTHREAD_CREATE_DETACHED); pthread_mutex_init(&rt_mutex, 0); pthread_cond_init(&rt_cond, 0); @@ -158,7 +157,7 @@ int main() trnman_init(); test_trnman_read_from(); - run_test("trnman", test_trnman, THREADS,CYCLES); + run_test("trnman", test_trnman, THREADS, CYCLES); diag("mallocs: %d", trnman_allocated_transactions); { |