summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/lf.h43
-rw-r--r--storage/maria/lockman.c8
-rw-r--r--storage/maria/lockman.h2
-rw-r--r--storage/maria/trnman.c147
-rw-r--r--storage/maria/trnman.h2
-rw-r--r--storage/maria/unittest/lockman-t.c97
-rw-r--r--storage/maria/unittest/trnman-t.c31
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);
{