119
119
return rhs == lhs;
124
#define MAX_THREADS 100
125
#define MAX_LOCKS 100
126
#define MAX_FOUND_ERRORS 10 /* Report 10 first errors */
127
static uint32_t found_errors=0;
129
static int check_lock(struct st_lock_list *list, const char* lock_type,
130
const char *where, bool same_owner, bool no_cond)
132
THR_LOCK_DATA *data,**prev;
134
THR_LOCK_OWNER *first_owner;
139
enum thr_lock_type last_lock_type=list->data->type;
141
if (same_owner && list->data)
142
first_owner= list->data->owner;
143
for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
145
if (data->type != last_lock_type)
146
last_lock_type=TL_IGNORE;
147
if (data->prev != prev)
150
"Warning: prev link %d didn't point at previous lock at %s: %s\n",
151
count, lock_type, where);
155
!thr_lock_owner_equal(data->owner, first_owner) &&
156
last_lock_type != TL_WRITE_ALLOW_WRITE)
159
"Warning: Found locks from different threads in %s: %s\n",
163
if (no_cond && data->cond)
166
"Warning: Found active lock with not reset cond %s: %s\n",
174
fprintf(stderr,"Warning: found too many locks at %s: %s\n",
179
if (prev != list->last)
181
fprintf(stderr,"Warning: last didn't point at last lock at %s: %s\n",
189
static void check_locks(THR_LOCK *lock, const char *where,
192
uint32_t old_found_errors=found_errors;
194
if (found_errors < MAX_FOUND_ERRORS)
196
if (check_lock(&lock->write,"write",where,1,1) |
197
check_lock(&lock->write_wait,"write_wait",where,0,0) |
198
check_lock(&lock->read,"read",where,0,1) |
199
check_lock(&lock->read_wait,"read_wait",where,0,0))
202
if (found_errors < MAX_FOUND_ERRORS)
206
for (data=lock->read.data ; data ; data=data->next)
208
if ((int) data->type == (int) TL_READ_NO_INSERT)
210
/* Protect against infinite loop. */
211
assert(count <= lock->read_no_write_count);
213
if (count != lock->read_no_write_count)
217
"Warning at '%s': Locks read_no_write_count was %u when it should have been %u\n", where, lock->read_no_write_count,count);
220
if (!lock->write.data)
222
if (!allow_no_locks && !lock->read.data &&
223
(lock->write_wait.data || lock->read_wait.data))
227
"Warning at '%s': No locks in use but locks are in wait queue\n",
230
if (!lock->write_wait.data)
232
if (!allow_no_locks && lock->read_wait.data)
236
"Warning at '%s': No write locks and waiting read locks\n",
242
if (!allow_no_locks &&
243
(((lock->write_wait.data->type == TL_WRITE_CONCURRENT_INSERT ||
244
lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) &&
245
!lock->read_no_write_count) ||
246
lock->write_wait.data->type == TL_WRITE_ALLOW_READ ||
247
(lock->write_wait.data->type == TL_WRITE_DELAYED &&
252
"Warning at '%s': Write lock %d waiting while no exclusive read locks\n",where,(int) lock->write_wait.data->type);
257
{ /* Have write lock */
258
if (lock->write_wait.data)
260
if (!allow_no_locks &&
261
lock->write.data->type == TL_WRITE_ALLOW_WRITE &&
262
lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE)
266
"Warning at '%s': Found WRITE_ALLOW_WRITE lock waiting for WRITE_ALLOW_WRITE lock\n",
272
if (!thr_lock_owner_equal(lock->write.data->owner,
273
lock->read.data->owner) &&
274
((lock->write.data->type > TL_WRITE_DELAYED &&
275
lock->write.data->type != TL_WRITE_ONLY) ||
276
((lock->write.data->type == TL_WRITE_CONCURRENT_INSERT ||
277
lock->write.data->type == TL_WRITE_ALLOW_WRITE) &&
278
lock->read_no_write_count)))
282
"Warning at '%s': Found lock of type %d that is write and read locked\n",
283
where, lock->write.data->type);
286
if (lock->read_wait.data)
288
if (!allow_no_locks && lock->write.data->type <= TL_WRITE_DELAYED &&
289
lock->read_wait.data->type <= TL_READ_HIGH_PRIORITY)
293
"Warning at '%s': Found read lock of type %d waiting for write lock of type %d\n",
295
(int) lock->read_wait.data->type,
296
(int) lock->write.data->type);
305
#else /* EXTRA_DEBUG */
306
#define check_locks(A,B,C)
310
123
/* Initialize a lock */
1208
988
pthread_mutex_unlock(&lock->mutex);
1209
989
return(thr_upgrade_write_delay_lock(data));
1215
/*****************************************************************************
1216
** Test of thread locks
1217
****************************************************************************/
1223
enum thr_lock_type lock_type;
1226
THR_LOCK locks[5]; /* 4 locks */
1228
struct st_test test_0[] = {{0,TL_READ}}; /* One lock */
1229
struct st_test test_1[] = {{0,TL_READ},{0,TL_WRITE}}; /* Read and write lock of lock 0 */
1230
struct st_test test_2[] = {{1,TL_WRITE},{0,TL_READ},{2,TL_READ}};
1231
struct st_test test_3[] = {{2,TL_WRITE},{1,TL_READ},{0,TL_READ}}; /* Deadlock with test_2 ? */
1232
struct st_test test_4[] = {{0,TL_WRITE},{0,TL_READ},{0,TL_WRITE},{0,TL_READ}};
1233
struct st_test test_5[] = {{0,TL_READ},{1,TL_READ},{2,TL_READ},{3,TL_READ}}; /* Many reads */
1234
struct st_test test_6[] = {{0,TL_WRITE},{1,TL_WRITE},{2,TL_WRITE},{3,TL_WRITE}}; /* Many writes */
1235
struct st_test test_7[] = {{3,TL_READ}};
1236
struct st_test test_8[] = {{1,TL_READ_NO_INSERT},{2,TL_READ_NO_INSERT},{3,TL_READ_NO_INSERT}}; /* Should be quick */
1237
struct st_test test_9[] = {{4,TL_READ_HIGH_PRIORITY}};
1238
struct st_test test_10[] ={{4,TL_WRITE}};
1239
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 */
1240
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 */
1241
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}};
1242
struct st_test test_14[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_READ}};
1243
struct st_test test_15[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_READ}};
1244
struct st_test test_16[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_WRITE_ALLOW_WRITE}};
1246
struct st_test *tests[] = {test_0,test_1,test_2,test_3,test_4,test_5,test_6,
1247
test_7,test_8,test_9,test_10,test_11,test_12,
1248
test_13,test_14,test_15,test_16};
1249
int lock_counts[]= {sizeof(test_0)/sizeof(struct st_test),
1250
sizeof(test_1)/sizeof(struct st_test),
1251
sizeof(test_2)/sizeof(struct st_test),
1252
sizeof(test_3)/sizeof(struct st_test),
1253
sizeof(test_4)/sizeof(struct st_test),
1254
sizeof(test_5)/sizeof(struct st_test),
1255
sizeof(test_6)/sizeof(struct st_test),
1256
sizeof(test_7)/sizeof(struct st_test),
1257
sizeof(test_8)/sizeof(struct st_test),
1258
sizeof(test_9)/sizeof(struct st_test),
1259
sizeof(test_10)/sizeof(struct st_test),
1260
sizeof(test_11)/sizeof(struct st_test),
1261
sizeof(test_12)/sizeof(struct st_test),
1262
sizeof(test_13)/sizeof(struct st_test),
1263
sizeof(test_14)/sizeof(struct st_test),
1264
sizeof(test_15)/sizeof(struct st_test),
1265
sizeof(test_16)/sizeof(struct st_test)
1269
static pthread_cond_t COND_thread_count;
1270
static pthread_mutex_t LOCK_thread_count;
1271
static uint32_t thread_count;
1272
static uint32_t sum=0;
1274
#define MAX_LOCK_COUNT 8
1276
/* The following functions is for WRITE_CONCURRENT_INSERT */
1278
static void test_get_status(void* param __attribute__((unused)),
1279
int concurrent_insert __attribute__((unused)))
1283
static void test_update_status(void* param __attribute__((unused)))
1287
static void test_copy_status(void* to __attribute__((unused)) ,
1288
void *from __attribute__((unused)))
1292
static bool test_check_status(void* param __attribute__((unused)))
1298
static void *test_thread(void *arg)
1300
int i,j,param=*((int*) arg);
1301
THR_LOCK_DATA data[MAX_LOCK_COUNT];
1302
THR_LOCK_OWNER owner;
1303
THR_LOCK_INFO lock_info;
1304
THR_LOCK_DATA *multi_locks[MAX_LOCK_COUNT];
1307
printf("Thread %s (%d) started\n",my_thread_name(),param); fflush(stdout);
1310
thr_lock_info_init(&lock_info);
1311
thr_lock_owner_init(&owner, &lock_info);
1312
for (i=0; i < lock_counts[param] ; i++)
1313
thr_lock_data_init(locks+tests[param][i].lock_nr,data+i,NULL);
1314
for (j=1 ; j < 10 ; j++) /* try locking 10 times */
1316
for (i=0; i < lock_counts[param] ; i++)
1317
{ /* Init multi locks */
1318
multi_locks[i]= &data[i];
1319
data[i].type= tests[param][i].lock_type;
1321
thr_multi_lock(multi_locks, lock_counts[param], &owner);
1322
pthread_mutex_lock(&LOCK_thread_count);
1324
int tmp=rand() & 7; /* Do something from 0-2 sec */
1332
for (k=0 ; k < (uint32_t) (tmp-2)*100000L ; k++)
1336
pthread_mutex_unlock(&LOCK_thread_count);
1337
thr_multi_unlock(multi_locks,lock_counts[param]);
1340
printf("Thread %s (%d) ended\n",my_thread_name(),param); fflush(stdout);
1342
pthread_mutex_lock(&LOCK_thread_count);
1344
pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */
1345
pthread_mutex_unlock(&LOCK_thread_count);
1346
free((unsigned char*) arg);
1351
int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
1354
pthread_attr_t thr_attr;
1358
printf("Main thread: %s\n",my_thread_name());
1360
if ((error=pthread_cond_init(&COND_thread_count,NULL)))
1362
fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)",
1366
if ((error=pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST)))
1368
fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)",
1373
for (i=0 ; i < (int) array_elements(locks) ; i++)
1375
thr_lock_init(locks+i);
1376
locks[i].check_status= test_check_status;
1377
locks[i].update_status=test_update_status;
1378
locks[i].copy_status= test_copy_status;
1379
locks[i].get_status= test_get_status;
1381
if ((error=pthread_attr_init(&thr_attr)))
1383
fprintf(stderr,"Got error: %d from pthread_attr_init (errno: %d)",
1387
if ((error=pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED)))
1390
"Got error: %d from pthread_attr_setdetachstate (errno: %d)",
1394
#ifndef pthread_attr_setstacksize /* void return value */
1395
if ((error=pthread_attr_setstacksize(&thr_attr,65536L)))
1397
fprintf(stderr,"Got error: %d from pthread_attr_setstacksize (errno: %d)",
1402
#ifdef HAVE_THR_SETCONCURRENCY
1403
thr_setconcurrency(2);
1405
for (i=0 ; i < (int) array_elements(lock_counts) ; i++)
1407
param=(int*) malloc(sizeof(int));
1410
if ((error=pthread_mutex_lock(&LOCK_thread_count)))
1412
fprintf(stderr,"Got error: %d from pthread_mutex_lock (errno: %d)",
1416
if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param)))
1418
fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n",
1420
pthread_mutex_unlock(&LOCK_thread_count);
1424
pthread_mutex_unlock(&LOCK_thread_count);
1427
pthread_attr_destroy(&thr_attr);
1428
if ((error=pthread_mutex_lock(&LOCK_thread_count)))
1429
fprintf(stderr,"Got error: %d from pthread_mutex_lock\n",error);
1430
while (thread_count)
1432
if ((error=pthread_cond_wait(&COND_thread_count,&LOCK_thread_count)))
1433
fprintf(stderr,"Got error: %d from pthread_cond_wait\n",error);
1435
if ((error=pthread_mutex_unlock(&LOCK_thread_count)))
1436
fprintf(stderr,"Got error: %d from pthread_mutex_unlock\n",error);
1437
for (i=0 ; i < (int) array_elements(locks) ; i++)
1438
thr_lock_delete(locks+i);
1441
printf("Got %d warnings\n",found_errors);
1444
printf("Test succeeded\n");