110
119
return rhs == lhs;
114
#define MAX_FOUND_ERRORS 10 /* Report 10 first errors */
115
static uint32_t found_errors=0;
117
static int check_lock(struct st_lock_list *list, const char* lock_type,
118
const char *where, bool same_owner, bool no_cond)
120
THR_LOCK_DATA *data,**prev;
122
THR_LOCK_OWNER *first_owner;
127
enum thr_lock_type last_lock_type=list->data->type;
129
if (same_owner && list->data)
130
first_owner= list->data->owner;
131
for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
133
if (data->type != last_lock_type)
134
last_lock_type=TL_IGNORE;
135
if (data->prev != prev)
138
"Warning: prev link %d didn't point at previous lock at %s: %s\n",
139
count, lock_type, where);
143
!thr_lock_owner_equal(data->owner, first_owner) &&
144
last_lock_type != TL_WRITE_ALLOW_WRITE)
147
"Warning: Found locks from different threads in %s: %s\n",
151
if (no_cond && data->cond)
154
"Warning: Found active lock with not reset cond %s: %s\n",
162
fprintf(stderr,"Warning: found too many locks at %s: %s\n",
167
if (prev != list->last)
169
fprintf(stderr,"Warning: last didn't point at last lock at %s: %s\n",
177
static void check_locks(THR_LOCK *lock, const char *where,
180
uint32_t old_found_errors=found_errors;
182
if (found_errors < MAX_FOUND_ERRORS)
184
if (check_lock(&lock->write,"write",where,1,1) |
185
check_lock(&lock->write_wait,"write_wait",where,0,0) |
186
check_lock(&lock->read,"read",where,0,1) |
187
check_lock(&lock->read_wait,"read_wait",where,0,0))
190
if (found_errors < MAX_FOUND_ERRORS)
194
for (data=lock->read.data ; data ; data=data->next)
196
if ((int) data->type == (int) TL_READ_NO_INSERT)
198
/* Protect against infinite loop. */
199
assert(count <= lock->read_no_write_count);
201
if (count != lock->read_no_write_count)
205
"Warning at '%s': Locks read_no_write_count was %u when it should have been %u\n", where, lock->read_no_write_count,count);
208
if (!lock->write.data)
210
if (!allow_no_locks && !lock->read.data &&
211
(lock->write_wait.data || lock->read_wait.data))
215
"Warning at '%s': No locks in use but locks are in wait queue\n",
218
if (!lock->write_wait.data)
220
if (!allow_no_locks && lock->read_wait.data)
224
"Warning at '%s': No write locks and waiting read locks\n",
230
if (!allow_no_locks &&
231
(((lock->write_wait.data->type == TL_WRITE_CONCURRENT_INSERT ||
232
lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) &&
233
!lock->read_no_write_count) ||
234
lock->write_wait.data->type == TL_WRITE_ALLOW_READ ||
235
(lock->write_wait.data->type == TL_WRITE_DELAYED &&
240
"Warning at '%s': Write lock %d waiting while no exclusive read locks\n",where,(int) lock->write_wait.data->type);
245
{ /* Have write lock */
246
if (lock->write_wait.data)
248
if (!allow_no_locks &&
249
lock->write.data->type == TL_WRITE_ALLOW_WRITE &&
250
lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE)
254
"Warning at '%s': Found WRITE_ALLOW_WRITE lock waiting for WRITE_ALLOW_WRITE lock\n",
260
if (!thr_lock_owner_equal(lock->write.data->owner,
261
lock->read.data->owner) &&
262
((lock->write.data->type > TL_WRITE_DELAYED &&
263
lock->write.data->type != TL_WRITE_ONLY) ||
264
((lock->write.data->type == TL_WRITE_CONCURRENT_INSERT ||
265
lock->write.data->type == TL_WRITE_ALLOW_WRITE) &&
266
lock->read_no_write_count)))
270
"Warning at '%s': Found lock of type %d that is write and read locked\n",
271
where, lock->write.data->type);
274
if (lock->read_wait.data)
276
if (!allow_no_locks && lock->write.data->type <= TL_WRITE_DELAYED &&
277
lock->read_wait.data->type <= TL_READ_HIGH_PRIORITY)
281
"Warning at '%s': Found read lock of type %d waiting for write lock of type %d\n",
283
(int) lock->read_wait.data->type,
284
(int) lock->write.data->type);
293
#else /* EXTRA_DEBUG */
294
#define check_locks(A,B,C)
298
123
/* Initialize a lock */
1196
988
pthread_mutex_unlock(&lock->mutex);
1197
989
return(thr_upgrade_write_delay_lock(data));
1203
/*****************************************************************************
1204
** Test of thread locks
1205
****************************************************************************/
1211
enum thr_lock_type lock_type;
1214
THR_LOCK locks[5]; /* 4 locks */
1216
struct st_test test_0[] = {{0,TL_READ}}; /* One lock */
1217
struct st_test test_1[] = {{0,TL_READ},{0,TL_WRITE}}; /* Read and write lock of lock 0 */
1218
struct st_test test_2[] = {{1,TL_WRITE},{0,TL_READ},{2,TL_READ}};
1219
struct st_test test_3[] = {{2,TL_WRITE},{1,TL_READ},{0,TL_READ}}; /* Deadlock with test_2 ? */
1220
struct st_test test_4[] = {{0,TL_WRITE},{0,TL_READ},{0,TL_WRITE},{0,TL_READ}};
1221
struct st_test test_5[] = {{0,TL_READ},{1,TL_READ},{2,TL_READ},{3,TL_READ}}; /* Many reads */
1222
struct st_test test_6[] = {{0,TL_WRITE},{1,TL_WRITE},{2,TL_WRITE},{3,TL_WRITE}}; /* Many writes */
1223
struct st_test test_7[] = {{3,TL_READ}};
1224
struct st_test test_8[] = {{1,TL_READ_NO_INSERT},{2,TL_READ_NO_INSERT},{3,TL_READ_NO_INSERT}}; /* Should be quick */
1225
struct st_test test_9[] = {{4,TL_READ_HIGH_PRIORITY}};
1226
struct st_test test_10[] ={{4,TL_WRITE}};
1227
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 */
1228
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 */
1229
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}};
1230
struct st_test test_14[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_READ}};
1231
struct st_test test_15[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_READ}};
1232
struct st_test test_16[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_WRITE_ALLOW_WRITE}};
1234
struct st_test *tests[] = {test_0,test_1,test_2,test_3,test_4,test_5,test_6,
1235
test_7,test_8,test_9,test_10,test_11,test_12,
1236
test_13,test_14,test_15,test_16};
1237
int lock_counts[]= {sizeof(test_0)/sizeof(struct st_test),
1238
sizeof(test_1)/sizeof(struct st_test),
1239
sizeof(test_2)/sizeof(struct st_test),
1240
sizeof(test_3)/sizeof(struct st_test),
1241
sizeof(test_4)/sizeof(struct st_test),
1242
sizeof(test_5)/sizeof(struct st_test),
1243
sizeof(test_6)/sizeof(struct st_test),
1244
sizeof(test_7)/sizeof(struct st_test),
1245
sizeof(test_8)/sizeof(struct st_test),
1246
sizeof(test_9)/sizeof(struct st_test),
1247
sizeof(test_10)/sizeof(struct st_test),
1248
sizeof(test_11)/sizeof(struct st_test),
1249
sizeof(test_12)/sizeof(struct st_test),
1250
sizeof(test_13)/sizeof(struct st_test),
1251
sizeof(test_14)/sizeof(struct st_test),
1252
sizeof(test_15)/sizeof(struct st_test),
1253
sizeof(test_16)/sizeof(struct st_test)
1257
static pthread_cond_t COND_thread_count;
1258
static pthread_mutex_t LOCK_thread_count;
1259
static uint32_t thread_count;
1260
static uint32_t sum=0;
1262
#define MAX_LOCK_COUNT 8
1264
/* The following functions is for WRITE_CONCURRENT_INSERT */
1266
static void test_get_status(void* param __attribute__((unused)),
1267
int concurrent_insert __attribute__((unused)))
1271
static void test_update_status(void* param __attribute__((unused)))
1275
static void test_copy_status(void* to __attribute__((unused)) ,
1276
void *from __attribute__((unused)))
1280
static bool test_check_status(void* param __attribute__((unused)))
1286
static void *test_thread(void *arg)
1288
int i,j,param=*((int*) arg);
1289
THR_LOCK_DATA data[MAX_LOCK_COUNT];
1290
THR_LOCK_OWNER owner;
1291
THR_LOCK_INFO lock_info;
1292
THR_LOCK_DATA *multi_locks[MAX_LOCK_COUNT];
1295
printf("Thread %s (%d) started\n",my_thread_name(),param); fflush(stdout);
1298
thr_lock_info_init(&lock_info);
1299
thr_lock_owner_init(&owner, &lock_info);
1300
for (i=0; i < lock_counts[param] ; i++)
1301
thr_lock_data_init(locks+tests[param][i].lock_nr,data+i,NULL);
1302
for (j=1 ; j < 10 ; j++) /* try locking 10 times */
1304
for (i=0; i < lock_counts[param] ; i++)
1305
{ /* Init multi locks */
1306
multi_locks[i]= &data[i];
1307
data[i].type= tests[param][i].lock_type;
1309
thr_multi_lock(multi_locks, lock_counts[param], &owner);
1310
pthread_mutex_lock(&LOCK_thread_count);
1312
int tmp=rand() & 7; /* Do something from 0-2 sec */
1320
for (k=0 ; k < (uint32_t) (tmp-2)*100000L ; k++)
1324
pthread_mutex_unlock(&LOCK_thread_count);
1325
thr_multi_unlock(multi_locks,lock_counts[param]);
1328
printf("Thread %s (%d) ended\n",my_thread_name(),param); fflush(stdout);
1330
pthread_mutex_lock(&LOCK_thread_count);
1332
pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */
1333
pthread_mutex_unlock(&LOCK_thread_count);
1334
free((unsigned char*) arg);
1339
int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
1342
pthread_attr_t thr_attr;
1346
printf("Main thread: %s\n",my_thread_name());
1348
if ((error=pthread_cond_init(&COND_thread_count,NULL)))
1350
fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)",
1354
if ((error=pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST)))
1356
fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)",
1361
for (i=0 ; i < (int) array_elements(locks) ; i++)
1363
thr_lock_init(locks+i);
1364
locks[i].check_status= test_check_status;
1365
locks[i].update_status=test_update_status;
1366
locks[i].copy_status= test_copy_status;
1367
locks[i].get_status= test_get_status;
1369
if ((error=pthread_attr_init(&thr_attr)))
1371
fprintf(stderr,"Got error: %d from pthread_attr_init (errno: %d)",
1375
if ((error=pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED)))
1378
"Got error: %d from pthread_attr_setdetachstate (errno: %d)",
1382
#ifndef pthread_attr_setstacksize /* void return value */
1383
if ((error=pthread_attr_setstacksize(&thr_attr,65536L)))
1385
fprintf(stderr,"Got error: %d from pthread_attr_setstacksize (errno: %d)",
1390
#ifdef HAVE_THR_SETCONCURRENCY
1391
thr_setconcurrency(2);
1393
for (i=0 ; i < (int) array_elements(lock_counts) ; i++)
1395
param=(int*) malloc(sizeof(int));
1398
if ((error=pthread_mutex_lock(&LOCK_thread_count)))
1400
fprintf(stderr,"Got error: %d from pthread_mutex_lock (errno: %d)",
1404
if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param)))
1406
fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n",
1408
pthread_mutex_unlock(&LOCK_thread_count);
1412
pthread_mutex_unlock(&LOCK_thread_count);
1415
pthread_attr_destroy(&thr_attr);
1416
if ((error=pthread_mutex_lock(&LOCK_thread_count)))
1417
fprintf(stderr,"Got error: %d from pthread_mutex_lock\n",error);
1418
while (thread_count)
1420
if ((error=pthread_cond_wait(&COND_thread_count,&LOCK_thread_count)))
1421
fprintf(stderr,"Got error: %d from pthread_cond_wait\n",error);
1423
if ((error=pthread_mutex_unlock(&LOCK_thread_count)))
1424
fprintf(stderr,"Got error: %d from pthread_mutex_unlock\n",error);
1425
for (i=0 ; i < (int) array_elements(locks) ; i++)
1426
thr_lock_delete(locks+i);
1429
printf("Got %d warnings\n",found_errors);
1432
printf("Test succeeded\n");