Commit aea73116 authored by unknown's avatar unknown

post-review fixes (style)


include/lf.h:
  comments
parent 12a55aea
/* 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>
......
......@@ -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;
......
/* 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
......
/* 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 */
......
/* 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
......
......@@ -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++)
{
......
......@@ -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);
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment