107
102
** For the future (now the thread specific cond is alloced by my_pthread.c)
105
my_bool init_thr_lock()
112
107
thr_lock_inited=1;
111
static inline my_bool
117
112
thr_lock_owner_equal(THR_LOCK_OWNER *rhs, THR_LOCK_OWNER *lhs)
119
114
return rhs == lhs;
119
#define MAX_FOUND_ERRORS 10 /* Report 10 first errors */
120
static uint found_errors=0;
122
static int check_lock(struct st_lock_list *list, const char* lock_type,
123
const char *where, my_bool same_owner, my_bool no_cond)
125
THR_LOCK_DATA *data,**prev;
127
THR_LOCK_OWNER *first_owner;
132
enum thr_lock_type last_lock_type=list->data->type;
134
if (same_owner && list->data)
135
first_owner= list->data->owner;
136
for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
138
if (data->type != last_lock_type)
139
last_lock_type=TL_IGNORE;
140
if (data->prev != prev)
143
"Warning: prev link %d didn't point at previous lock at %s: %s\n",
144
count, lock_type, where);
148
!thr_lock_owner_equal(data->owner, first_owner) &&
149
last_lock_type != TL_WRITE_ALLOW_WRITE)
152
"Warning: Found locks from different threads in %s: %s\n",
156
if (no_cond && data->cond)
159
"Warning: Found active lock with not reset cond %s: %s\n",
167
fprintf(stderr,"Warning: found too many locks at %s: %s\n",
172
if (prev != list->last)
174
fprintf(stderr,"Warning: last didn't point at last lock at %s: %s\n",
182
static void check_locks(THR_LOCK *lock, const char *where,
183
my_bool allow_no_locks)
185
uint old_found_errors=found_errors;
186
DBUG_ENTER("check_locks");
188
if (found_errors < MAX_FOUND_ERRORS)
190
if (check_lock(&lock->write,"write",where,1,1) |
191
check_lock(&lock->write_wait,"write_wait",where,0,0) |
192
check_lock(&lock->read,"read",where,0,1) |
193
check_lock(&lock->read_wait,"read_wait",where,0,0))
196
if (found_errors < MAX_FOUND_ERRORS)
200
for (data=lock->read.data ; data ; data=data->next)
202
if ((int) data->type == (int) TL_READ_NO_INSERT)
204
/* Protect against infinite loop. */
205
DBUG_ASSERT(count <= lock->read_no_write_count);
207
if (count != lock->read_no_write_count)
211
"Warning at '%s': Locks read_no_write_count was %u when it should have been %u\n", where, lock->read_no_write_count,count);
214
if (!lock->write.data)
216
if (!allow_no_locks && !lock->read.data &&
217
(lock->write_wait.data || lock->read_wait.data))
221
"Warning at '%s': No locks in use but locks are in wait queue\n",
224
if (!lock->write_wait.data)
226
if (!allow_no_locks && lock->read_wait.data)
230
"Warning at '%s': No write locks and waiting read locks\n",
236
if (!allow_no_locks &&
237
(((lock->write_wait.data->type == TL_WRITE_CONCURRENT_INSERT ||
238
lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) &&
239
!lock->read_no_write_count) ||
240
lock->write_wait.data->type == TL_WRITE_ALLOW_READ ||
241
(lock->write_wait.data->type == TL_WRITE_DELAYED &&
246
"Warning at '%s': Write lock %d waiting while no exclusive read locks\n",where,(int) lock->write_wait.data->type);
251
{ /* Have write lock */
252
if (lock->write_wait.data)
254
if (!allow_no_locks &&
255
lock->write.data->type == TL_WRITE_ALLOW_WRITE &&
256
lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE)
260
"Warning at '%s': Found WRITE_ALLOW_WRITE lock waiting for WRITE_ALLOW_WRITE lock\n",
266
if (!thr_lock_owner_equal(lock->write.data->owner,
267
lock->read.data->owner) &&
268
((lock->write.data->type > TL_WRITE_DELAYED &&
269
lock->write.data->type != TL_WRITE_ONLY) ||
270
((lock->write.data->type == TL_WRITE_CONCURRENT_INSERT ||
271
lock->write.data->type == TL_WRITE_ALLOW_WRITE) &&
272
lock->read_no_write_count)))
276
"Warning at '%s': Found lock of type %d that is write and read locked\n",
277
where, lock->write.data->type);
278
DBUG_PRINT("warning",("At '%s': Found lock of type %d that is write and read locked\n",
279
where, lock->write.data->type));
283
if (lock->read_wait.data)
285
if (!allow_no_locks && lock->write.data->type <= TL_WRITE_DELAYED &&
286
lock->read_wait.data->type <= TL_READ_HIGH_PRIORITY)
290
"Warning at '%s': Found read lock of type %d waiting for write lock of type %d\n",
292
(int) lock->read_wait.data->type,
293
(int) lock->write.data->type);
298
if (found_errors != old_found_errors)
300
DBUG_PRINT("error",("Found wrong lock"));
306
#else /* EXTRA_DEBUG */
307
#define check_locks(A,B,C)
123
311
/* Initialize a lock */
125
313
void thr_lock_init(THR_LOCK *lock)
127
memset(lock, 0, sizeof(*lock));
128
pthread_mutex_init(&lock->mutex,MY_MUTEX_INIT_FAST);
315
DBUG_ENTER("thr_lock_init");
316
bzero((char*) lock,sizeof(*lock));
317
VOID(pthread_mutex_init(&lock->mutex,MY_MUTEX_INIT_FAST));
129
318
lock->read.last= &lock->read.data;
130
319
lock->read_wait.last= &lock->read_wait.data;
131
320
lock->write_wait.last= &lock->write_wait.data;
986
1272
free_all_read_locks(lock,0);
988
1274
pthread_mutex_unlock(&lock->mutex);
989
return(thr_upgrade_write_delay_lock(data));
1275
DBUG_RETURN(thr_upgrade_write_delay_lock(data));
1281
static void thr_print_lock(const char* name,struct st_lock_list *list)
1283
THR_LOCK_DATA *data,**prev;
1288
printf("%-10s: ",name);
1290
for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
1292
printf("0x%lx (%lu:%d); ", (ulong) data, data->owner->info->thread_id,
1294
if (data->prev != prev)
1295
printf("\nWarning: prev didn't point at previous lock\n");
1299
if (prev != list->last)
1300
printf("Warning: last didn't point at last lock\n");
1304
void thr_print_locks(void)
1309
pthread_mutex_lock(&THR_LOCK_lock);
1310
puts("Current locks:");
1311
for (list= thr_lock_thread_list; list && count++ < MAX_THREADS;
1312
list= list_rest(list))
1314
THR_LOCK *lock=(THR_LOCK*) list->data;
1315
VOID(pthread_mutex_lock(&lock->mutex));
1316
printf("lock: 0x%lx:",(ulong) lock);
1317
if ((lock->write_wait.data || lock->read_wait.data) &&
1318
(! lock->read.data && ! lock->write.data))
1319
printf(" WARNING: ");
1320
if (lock->write.data)
1322
if (lock->write_wait.data)
1323
printf(" write_wait");
1324
if (lock->read.data)
1326
if (lock->read_wait.data)
1327
printf(" read_wait");
1329
thr_print_lock("write",&lock->write);
1330
thr_print_lock("write_wait",&lock->write_wait);
1331
thr_print_lock("read",&lock->read);
1332
thr_print_lock("read_wait",&lock->read_wait);
1333
VOID(pthread_mutex_unlock(&lock->mutex));
1337
pthread_mutex_unlock(&THR_LOCK_lock);
1340
/*****************************************************************************
1341
** Test of thread locks
1342
****************************************************************************/
1348
enum thr_lock_type lock_type;
1351
THR_LOCK locks[5]; /* 4 locks */
1353
struct st_test test_0[] = {{0,TL_READ}}; /* One lock */
1354
struct st_test test_1[] = {{0,TL_READ},{0,TL_WRITE}}; /* Read and write lock of lock 0 */
1355
struct st_test test_2[] = {{1,TL_WRITE},{0,TL_READ},{2,TL_READ}};
1356
struct st_test test_3[] = {{2,TL_WRITE},{1,TL_READ},{0,TL_READ}}; /* Deadlock with test_2 ? */
1357
struct st_test test_4[] = {{0,TL_WRITE},{0,TL_READ},{0,TL_WRITE},{0,TL_READ}};
1358
struct st_test test_5[] = {{0,TL_READ},{1,TL_READ},{2,TL_READ},{3,TL_READ}}; /* Many reads */
1359
struct st_test test_6[] = {{0,TL_WRITE},{1,TL_WRITE},{2,TL_WRITE},{3,TL_WRITE}}; /* Many writes */
1360
struct st_test test_7[] = {{3,TL_READ}};
1361
struct st_test test_8[] = {{1,TL_READ_NO_INSERT},{2,TL_READ_NO_INSERT},{3,TL_READ_NO_INSERT}}; /* Should be quick */
1362
struct st_test test_9[] = {{4,TL_READ_HIGH_PRIORITY}};
1363
struct st_test test_10[] ={{4,TL_WRITE}};
1364
struct st_test test_11[] = {{0,TL_WRITE_LOW_PRIORITY},{1,TL_WRITE_LOW_PRIORITY},{2,TL_WRITE_LOW_PRIORITY},{3,TL_WRITE_LOW_PRIORITY}}; /* Many writes */
1365
struct st_test test_12[] = {{0,TL_WRITE_ALLOW_READ},{1,TL_WRITE_ALLOW_READ},{2,TL_WRITE_ALLOW_READ},{3,TL_WRITE_ALLOW_READ}}; /* Many writes */
1366
struct st_test test_13[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_WRITE_CONCURRENT_INSERT},{2,TL_WRITE_CONCURRENT_INSERT},{3,TL_WRITE_CONCURRENT_INSERT}};
1367
struct st_test test_14[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_READ}};
1368
struct st_test test_15[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_READ}};
1369
struct st_test test_16[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_WRITE_ALLOW_WRITE}};
1371
struct st_test *tests[] = {test_0,test_1,test_2,test_3,test_4,test_5,test_6,
1372
test_7,test_8,test_9,test_10,test_11,test_12,
1373
test_13,test_14,test_15,test_16};
1374
int lock_counts[]= {sizeof(test_0)/sizeof(struct st_test),
1375
sizeof(test_1)/sizeof(struct st_test),
1376
sizeof(test_2)/sizeof(struct st_test),
1377
sizeof(test_3)/sizeof(struct st_test),
1378
sizeof(test_4)/sizeof(struct st_test),
1379
sizeof(test_5)/sizeof(struct st_test),
1380
sizeof(test_6)/sizeof(struct st_test),
1381
sizeof(test_7)/sizeof(struct st_test),
1382
sizeof(test_8)/sizeof(struct st_test),
1383
sizeof(test_9)/sizeof(struct st_test),
1384
sizeof(test_10)/sizeof(struct st_test),
1385
sizeof(test_11)/sizeof(struct st_test),
1386
sizeof(test_12)/sizeof(struct st_test),
1387
sizeof(test_13)/sizeof(struct st_test),
1388
sizeof(test_14)/sizeof(struct st_test),
1389
sizeof(test_15)/sizeof(struct st_test),
1390
sizeof(test_16)/sizeof(struct st_test)
1394
static pthread_cond_t COND_thread_count;
1395
static pthread_mutex_t LOCK_thread_count;
1396
static uint thread_count;
1399
#define MAX_LOCK_COUNT 8
1401
/* The following functions is for WRITE_CONCURRENT_INSERT */
1403
static void test_get_status(void* param __attribute__((unused)),
1404
int concurrent_insert __attribute__((unused)))
1408
static void test_update_status(void* param __attribute__((unused)))
1412
static void test_copy_status(void* to __attribute__((unused)) ,
1413
void *from __attribute__((unused)))
1417
static my_bool test_check_status(void* param __attribute__((unused)))
1423
static void *test_thread(void *arg)
1425
int i,j,param=*((int*) arg);
1426
THR_LOCK_DATA data[MAX_LOCK_COUNT];
1427
THR_LOCK_OWNER owner;
1428
THR_LOCK_INFO lock_info;
1429
THR_LOCK_DATA *multi_locks[MAX_LOCK_COUNT];
1432
printf("Thread %s (%d) started\n",my_thread_name(),param); fflush(stdout);
1435
thr_lock_info_init(&lock_info);
1436
thr_lock_owner_init(&owner, &lock_info);
1437
for (i=0; i < lock_counts[param] ; i++)
1438
thr_lock_data_init(locks+tests[param][i].lock_nr,data+i,NULL);
1439
for (j=1 ; j < 10 ; j++) /* try locking 10 times */
1441
for (i=0; i < lock_counts[param] ; i++)
1442
{ /* Init multi locks */
1443
multi_locks[i]= &data[i];
1444
data[i].type= tests[param][i].lock_type;
1446
thr_multi_lock(multi_locks, lock_counts[param], &owner);
1447
pthread_mutex_lock(&LOCK_thread_count);
1449
int tmp=rand() & 7; /* Do something from 0-2 sec */
1457
for (k=0 ; k < (ulong) (tmp-2)*100000L ; k++)
1461
pthread_mutex_unlock(&LOCK_thread_count);
1462
thr_multi_unlock(multi_locks,lock_counts[param]);
1465
printf("Thread %s (%d) ended\n",my_thread_name(),param); fflush(stdout);
1467
pthread_mutex_lock(&LOCK_thread_count);
1469
VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
1470
pthread_mutex_unlock(&LOCK_thread_count);
1476
int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
1479
pthread_attr_t thr_attr;
1482
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#')
1483
DBUG_PUSH(argv[1]+2);
1485
printf("Main thread: %s\n",my_thread_name());
1487
if ((error=pthread_cond_init(&COND_thread_count,NULL)))
1489
fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)",
1493
if ((error=pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST)))
1495
fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)",
1500
for (i=0 ; i < (int) array_elements(locks) ; i++)
1502
thr_lock_init(locks+i);
1503
locks[i].check_status= test_check_status;
1504
locks[i].update_status=test_update_status;
1505
locks[i].copy_status= test_copy_status;
1506
locks[i].get_status= test_get_status;
1508
if ((error=pthread_attr_init(&thr_attr)))
1510
fprintf(stderr,"Got error: %d from pthread_attr_init (errno: %d)",
1514
if ((error=pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED)))
1517
"Got error: %d from pthread_attr_setdetachstate (errno: %d)",
1521
#ifndef pthread_attr_setstacksize /* void return value */
1522
if ((error=pthread_attr_setstacksize(&thr_attr,65536L)))
1524
fprintf(stderr,"Got error: %d from pthread_attr_setstacksize (errno: %d)",
1529
#ifdef HAVE_THR_SETCONCURRENCY
1530
VOID(thr_setconcurrency(2));
1532
for (i=0 ; i < (int) array_elements(lock_counts) ; i++)
1534
param=(int*) malloc(sizeof(int));
1537
if ((error=pthread_mutex_lock(&LOCK_thread_count)))
1539
fprintf(stderr,"Got error: %d from pthread_mutex_lock (errno: %d)",
1543
if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param)))
1545
fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n",
1547
pthread_mutex_unlock(&LOCK_thread_count);
1551
pthread_mutex_unlock(&LOCK_thread_count);
1554
pthread_attr_destroy(&thr_attr);
1555
if ((error=pthread_mutex_lock(&LOCK_thread_count)))
1556
fprintf(stderr,"Got error: %d from pthread_mutex_lock\n",error);
1557
while (thread_count)
1559
if ((error=pthread_cond_wait(&COND_thread_count,&LOCK_thread_count)))
1560
fprintf(stderr,"Got error: %d from pthread_cond_wait\n",error);
1562
if ((error=pthread_mutex_unlock(&LOCK_thread_count)))
1563
fprintf(stderr,"Got error: %d from pthread_mutex_unlock\n",error);
1564
for (i=0 ; i < (int) array_elements(locks) ; i++)
1565
thr_lock_delete(locks+i);
1568
printf("Got %d warnings\n",found_errors);
1571
printf("Test succeeded\n");