~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/thr_lock.cc

  • Committer: Brian Aker
  • Date: 2008-12-05 17:55:00 UTC
  • Revision ID: brian@tangent.org-20081205175500-g3ja7dl0vfgjtrob
Random cleanup, removed dead mysys call for hw address creation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
119
119
  return rhs == lhs;
120
120
}
121
121
 
122
 
#ifdef EXTRA_DEBUG
123
 
 
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;
128
 
 
129
 
static int check_lock(struct st_lock_list *list, const char* lock_type,
130
 
                      const char *where, bool same_owner, bool no_cond)
131
 
{
132
 
  THR_LOCK_DATA *data,**prev;
133
 
  uint32_t count=0;
134
 
  THR_LOCK_OWNER *first_owner;
135
 
 
136
 
  prev= &list->data;
137
 
  if (list->data)
138
 
  {
139
 
    enum thr_lock_type last_lock_type=list->data->type;
140
 
 
141
 
    if (same_owner && list->data)
142
 
      first_owner= list->data->owner;
143
 
    for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
144
 
    {
145
 
      if (data->type != last_lock_type)
146
 
        last_lock_type=TL_IGNORE;
147
 
      if (data->prev != prev)
148
 
      {
149
 
        fprintf(stderr,
150
 
                "Warning: prev link %d didn't point at previous lock at %s: %s\n",
151
 
                count, lock_type, where);
152
 
        return 1;
153
 
      }
154
 
      if (same_owner &&
155
 
          !thr_lock_owner_equal(data->owner, first_owner) &&
156
 
          last_lock_type != TL_WRITE_ALLOW_WRITE)
157
 
      {
158
 
        fprintf(stderr,
159
 
                "Warning: Found locks from different threads in %s: %s\n",
160
 
                lock_type,where);
161
 
        return 1;
162
 
      }
163
 
      if (no_cond && data->cond)
164
 
      {
165
 
        fprintf(stderr,
166
 
                "Warning: Found active lock with not reset cond %s: %s\n",
167
 
                lock_type,where);
168
 
        return 1;
169
 
      }
170
 
      prev= &data->next;
171
 
    }
172
 
    if (data)
173
 
    {
174
 
      fprintf(stderr,"Warning: found too many locks at %s: %s\n",
175
 
              lock_type,where);
176
 
      return 1;
177
 
    }
178
 
  }
179
 
  if (prev != list->last)
180
 
  {
181
 
    fprintf(stderr,"Warning: last didn't point at last lock at %s: %s\n",
182
 
            lock_type, where);
183
 
    return 1;
184
 
  }
185
 
  return 0;
186
 
}
187
 
 
188
 
 
189
 
static void check_locks(THR_LOCK *lock, const char *where,
190
 
                        bool allow_no_locks)
191
 
{
192
 
  uint32_t old_found_errors=found_errors;
193
 
 
194
 
  if (found_errors < MAX_FOUND_ERRORS)
195
 
  {
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))
200
 
      found_errors++;
201
 
 
202
 
    if (found_errors < MAX_FOUND_ERRORS)
203
 
    {
204
 
      uint32_t count=0;
205
 
      THR_LOCK_DATA *data;
206
 
      for (data=lock->read.data ; data ; data=data->next)
207
 
      {
208
 
        if ((int) data->type == (int) TL_READ_NO_INSERT)
209
 
          count++;
210
 
        /* Protect against infinite loop. */
211
 
        assert(count <= lock->read_no_write_count);
212
 
      }
213
 
      if (count != lock->read_no_write_count)
214
 
      {
215
 
        found_errors++;
216
 
        fprintf(stderr,
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);
218
 
      }      
219
 
 
220
 
      if (!lock->write.data)
221
 
      {
222
 
        if (!allow_no_locks && !lock->read.data &&
223
 
            (lock->write_wait.data || lock->read_wait.data))
224
 
        {
225
 
          found_errors++;
226
 
          fprintf(stderr,
227
 
                  "Warning at '%s': No locks in use but locks are in wait queue\n",
228
 
                  where);
229
 
        }
230
 
        if (!lock->write_wait.data)
231
 
        {
232
 
          if (!allow_no_locks && lock->read_wait.data)
233
 
          {
234
 
            found_errors++;
235
 
            fprintf(stderr,
236
 
                    "Warning at '%s': No write locks and waiting read locks\n",
237
 
                    where);
238
 
          }
239
 
        }
240
 
        else
241
 
        {
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 &&
248
 
                !lock->read.data)))
249
 
          {
250
 
            found_errors++;
251
 
            fprintf(stderr,
252
 
                    "Warning at '%s': Write lock %d waiting while no exclusive read locks\n",where,(int) lock->write_wait.data->type);
253
 
          }
254
 
        }             
255
 
      }
256
 
      else
257
 
      {                                         /* Have write lock */
258
 
        if (lock->write_wait.data)
259
 
        {
260
 
          if (!allow_no_locks && 
261
 
              lock->write.data->type == TL_WRITE_ALLOW_WRITE &&
262
 
              lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE)
263
 
          {
264
 
            found_errors++;
265
 
            fprintf(stderr,
266
 
                    "Warning at '%s': Found WRITE_ALLOW_WRITE lock waiting for WRITE_ALLOW_WRITE lock\n",
267
 
                    where);
268
 
          }
269
 
        }
270
 
        if (lock->read.data)
271
 
        {
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)))
279
 
          {
280
 
            found_errors++;
281
 
            fprintf(stderr,
282
 
                    "Warning at '%s': Found lock of type %d that is write and read locked\n",
283
 
                    where, lock->write.data->type);
284
 
          }
285
 
        }
286
 
        if (lock->read_wait.data)
287
 
        {
288
 
          if (!allow_no_locks && lock->write.data->type <= TL_WRITE_DELAYED &&
289
 
              lock->read_wait.data->type <= TL_READ_HIGH_PRIORITY)
290
 
          {
291
 
            found_errors++;
292
 
            fprintf(stderr,
293
 
                    "Warning at '%s': Found read lock of type %d waiting for write lock of type %d\n",
294
 
                    where,
295
 
                    (int) lock->read_wait.data->type,
296
 
                    (int) lock->write.data->type);
297
 
          }
298
 
        }
299
 
      }
300
 
    }
301
 
  }
302
 
  return;
303
 
}
304
 
 
305
 
#else /* EXTRA_DEBUG */
306
 
#define check_locks(A,B,C)
307
 
#endif
308
 
 
309
122
 
310
123
        /* Initialize a lock */
311
124
 
448
261
      else
449
262
        wait->last=data->prev;
450
263
      data->type= TL_UNLOCK;                    /* No lock */
451
 
      check_locks(data->lock, "killed or timed out wait_for_lock", 1);
452
264
      wake_up_waiters(data->lock);
453
265
    }
454
 
    else
455
 
    {
456
 
      check_locks(data->lock, "aborted wait_for_lock", 0);
457
 
    }
458
266
  }
459
267
  else
460
268
  {
461
269
    result= THR_LOCK_SUCCESS;
462
270
    if (data->lock->get_status)
463
271
      (*data->lock->get_status)(data->status_param, 0);
464
 
    check_locks(data->lock,"got wait_for_lock",0);
465
272
  }
466
273
  pthread_mutex_unlock(&data->lock->mutex);
467
274
 
488
295
  data->type=lock_type;
489
296
  data->owner= owner;                           /* Must be reset ! */
490
297
  pthread_mutex_lock(&lock->mutex);
491
 
  check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ?
492
 
              "enter read_lock" : "enter write_lock",0);
493
298
  if ((int) lock_type <= (int) TL_READ_NO_INSERT)
494
299
  {
495
300
    /* Request for READ lock */
515
320
        lock->read.last= &data->next;
516
321
        if (lock_type == TL_READ_NO_INSERT)
517
322
          lock->read_no_write_count++;
518
 
        check_locks(lock,"read lock with old write lock",0);
519
323
        if (lock->get_status)
520
324
          (*lock->get_status)(data->status_param, 0);
521
325
        statistic_increment(locks_immediate,&THR_LOCK_lock);
541
345
        (*lock->get_status)(data->status_param, 0);
542
346
      if (lock_type == TL_READ_NO_INSERT)
543
347
        lock->read_no_write_count++;
544
 
      check_locks(lock,"read lock with no write locks",0);
545
348
      statistic_increment(locks_immediate,&THR_LOCK_lock);
546
349
      goto end;
547
350
    }
619
422
        (*lock->write.last)=data;       /* Add to running fifo */
620
423
        data->prev=lock->write.last;
621
424
        lock->write.last= &data->next;
622
 
        check_locks(lock,"second write lock",0);
623
425
        if (data->lock->get_status)
624
426
          (*data->lock->get_status)(data->status_param, 0);
625
427
        statistic_increment(locks_immediate,&THR_LOCK_lock);
652
454
          lock->write.last= &data->next;
653
455
          if (data->lock->get_status)
654
456
            (*data->lock->get_status)(data->status_param, concurrent_insert);
655
 
          check_locks(lock,"only write lock",0);
656
457
          statistic_increment(locks_immediate,&THR_LOCK_lock);
657
458
          goto end;
658
459
        }
685
486
{
686
487
  THR_LOCK_DATA *data=lock->read_wait.data;
687
488
 
688
 
  check_locks(lock,"before freeing read locks",1);
689
 
 
690
489
  /* move all locks from read_wait list to read list */
691
490
  (*lock->read.last)=data;
692
491
  data->prev=lock->read.last;
723
522
  *lock->read_wait.last=0;
724
523
  if (!lock->read_wait.data)
725
524
    lock->write_lock_count=0;
726
 
  check_locks(lock,"after giving read locks",0);
727
525
}
728
526
 
729
527
        /* Unlock lock and free next thread on same lock */
733
531
  THR_LOCK *lock=data->lock;
734
532
  enum thr_lock_type lock_type=data->type;
735
533
  pthread_mutex_lock(&lock->mutex);
736
 
  check_locks(lock,"start of release lock",0);
737
534
 
738
535
  if (((*data->prev)=data->next))               /* remove from lock-list */
739
536
    data->next->prev= data->prev;
762
559
  if (lock_type == TL_READ_NO_INSERT)
763
560
    lock->read_no_write_count--;
764
561
  data->type=TL_UNLOCK;                         /* Mark unlocked */
765
 
  check_locks(lock,"after releasing lock",1);
766
562
  wake_up_waiters(lock);
767
563
  pthread_mutex_unlock(&lock->mutex);
768
564
  return;
878
674
      free_all_read_locks(lock,0);
879
675
  }
880
676
end:
881
 
  check_locks(lock, "after waking up waiters", 0);
882
677
  return;
883
678
}
884
679
 
928
723
      thr_multi_unlock(data,(uint) (pos-data));
929
724
      return(result);
930
725
    }
931
 
#ifdef MAIN
932
 
    printf("Thread: %s  Got lock: 0x%lx  type: %d\n",my_thread_name(),
933
 
           (long) pos[0]->lock, pos[0]->type); fflush(stdout);
934
 
#endif
935
726
  }
936
727
  /*
937
728
    Ensure that all get_locks() have the same status
991
782
 
992
783
  for (pos=data,end=data+count; pos < end ; pos++)
993
784
  {
994
 
#ifdef MAIN
995
 
    printf("Thread: %s  Rel lock: 0x%lx  type: %d\n",
996
 
           my_thread_name(), (long) pos[0]->lock, pos[0]->type);
997
 
    fflush(stdout);
998
 
#endif
999
785
    if ((*pos)->type != TL_UNLOCK)
1000
786
      thr_unlock(*pos);
1001
787
  }
1121
907
 
1122
908
  pthread_mutex_lock(&lock->mutex);
1123
909
  in_data->type= new_lock_type;
1124
 
  check_locks(lock,"after downgrading lock",0);
1125
910
 
1126
911
  pthread_mutex_unlock(&lock->mutex);
1127
912
  return;
1139
924
    pthread_mutex_unlock(&lock->mutex);
1140
925
    return(data->type == TL_UNLOCK);    /* Test if Aborted */
1141
926
  }
1142
 
  check_locks(lock,"before upgrading lock",0);
1143
927
  /* TODO:  Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */
1144
928
  data->type=TL_WRITE;                          /* Upgrade lock */
1145
929
 
1165
949
      lock->write_wait.last= &data->next;
1166
950
    data->prev= &lock->write_wait.data;
1167
951
    lock->write_wait.data=data;
1168
 
    check_locks(lock,"upgrading lock",0);
1169
 
  }
1170
 
  else
1171
 
  {
1172
 
    check_locks(lock,"waiting for lock",0);
1173
 
  }
 
952
  }
 
953
 
1174
954
  return(wait_for_lock(&lock->write_wait,data,1));
1175
955
}
1176
956
 
1208
988
  pthread_mutex_unlock(&lock->mutex);
1209
989
  return(thr_upgrade_write_delay_lock(data));
1210
990
}
1211
 
 
1212
 
 
1213
 
#include <my_sys.h>
1214
 
 
1215
 
/*****************************************************************************
1216
 
** Test of thread locks
1217
 
****************************************************************************/
1218
 
 
1219
 
#ifdef MAIN
1220
 
 
1221
 
struct st_test {
1222
 
  uint32_t lock_nr;
1223
 
  enum thr_lock_type lock_type;
1224
 
};
1225
 
 
1226
 
THR_LOCK locks[5];                      /* 4 locks */
1227
 
 
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}};
1245
 
 
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)
1266
 
};
1267
 
 
1268
 
 
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;
1273
 
 
1274
 
#define MAX_LOCK_COUNT 8
1275
 
 
1276
 
/* The following functions is for WRITE_CONCURRENT_INSERT */
1277
 
 
1278
 
static void test_get_status(void* param __attribute__((unused)),
1279
 
                            int concurrent_insert __attribute__((unused)))
1280
 
{
1281
 
}
1282
 
 
1283
 
static void test_update_status(void* param __attribute__((unused)))
1284
 
{
1285
 
}
1286
 
 
1287
 
static void test_copy_status(void* to __attribute__((unused)) ,
1288
 
                             void *from __attribute__((unused)))
1289
 
{
1290
 
}
1291
 
 
1292
 
static bool test_check_status(void* param __attribute__((unused)))
1293
 
{
1294
 
  return 0;
1295
 
}
1296
 
 
1297
 
 
1298
 
static void *test_thread(void *arg)
1299
 
{
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];
1305
 
  my_thread_init();
1306
 
 
1307
 
  printf("Thread %s (%d) started\n",my_thread_name(),param); fflush(stdout);
1308
 
 
1309
 
 
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 */
1315
 
  {
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;
1320
 
    }
1321
 
    thr_multi_lock(multi_locks, lock_counts[param], &owner);
1322
 
    pthread_mutex_lock(&LOCK_thread_count);
1323
 
    {
1324
 
      int tmp=rand() & 7;                       /* Do something from 0-2 sec */
1325
 
      if (tmp == 0)
1326
 
        sleep(1);
1327
 
      else if (tmp == 1)
1328
 
        sleep(2);
1329
 
      else
1330
 
      {
1331
 
        uint32_t k;
1332
 
        for (k=0 ; k < (uint32_t) (tmp-2)*100000L ; k++)
1333
 
          sum+=k;
1334
 
      }
1335
 
    }
1336
 
    pthread_mutex_unlock(&LOCK_thread_count);
1337
 
    thr_multi_unlock(multi_locks,lock_counts[param]);
1338
 
  }
1339
 
 
1340
 
  printf("Thread %s (%d) ended\n",my_thread_name(),param); fflush(stdout);
1341
 
  thr_print_locks();
1342
 
  pthread_mutex_lock(&LOCK_thread_count);
1343
 
  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);
1347
 
  return 0;
1348
 
}
1349
 
 
1350
 
 
1351
 
int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
1352
 
{
1353
 
  pthread_t tid;
1354
 
  pthread_attr_t thr_attr;
1355
 
  int i,*param,error;
1356
 
  MY_INIT(argv[0]);
1357
 
 
1358
 
  printf("Main thread: %s\n",my_thread_name());
1359
 
 
1360
 
  if ((error=pthread_cond_init(&COND_thread_count,NULL)))
1361
 
  {
1362
 
    fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)",
1363
 
            error,errno);
1364
 
    exit(1);
1365
 
  }
1366
 
  if ((error=pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST)))
1367
 
  {
1368
 
    fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)",
1369
 
            error,errno);
1370
 
    exit(1);
1371
 
  }
1372
 
 
1373
 
  for (i=0 ; i < (int) array_elements(locks) ; i++)
1374
 
  {
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;
1380
 
  }
1381
 
  if ((error=pthread_attr_init(&thr_attr)))
1382
 
  {
1383
 
    fprintf(stderr,"Got error: %d from pthread_attr_init (errno: %d)",
1384
 
            error,errno);
1385
 
    exit(1);
1386
 
  }
1387
 
  if ((error=pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED)))
1388
 
  {
1389
 
    fprintf(stderr,
1390
 
            "Got error: %d from pthread_attr_setdetachstate (errno: %d)",
1391
 
            error,errno);
1392
 
    exit(1);
1393
 
  }
1394
 
#ifndef pthread_attr_setstacksize               /* void return value */
1395
 
  if ((error=pthread_attr_setstacksize(&thr_attr,65536L)))
1396
 
  {
1397
 
    fprintf(stderr,"Got error: %d from pthread_attr_setstacksize (errno: %d)",
1398
 
            error,errno);
1399
 
    exit(1);
1400
 
  }
1401
 
#endif
1402
 
#ifdef HAVE_THR_SETCONCURRENCY
1403
 
  thr_setconcurrency(2);
1404
 
#endif
1405
 
  for (i=0 ; i < (int) array_elements(lock_counts) ; i++)
1406
 
  {
1407
 
    param=(int*) malloc(sizeof(int));
1408
 
    *param=i;
1409
 
 
1410
 
    if ((error=pthread_mutex_lock(&LOCK_thread_count)))
1411
 
    {
1412
 
      fprintf(stderr,"Got error: %d from pthread_mutex_lock (errno: %d)",
1413
 
              error,errno);
1414
 
      exit(1);
1415
 
    }
1416
 
    if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param)))
1417
 
    {
1418
 
      fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n",
1419
 
              error,errno);
1420
 
      pthread_mutex_unlock(&LOCK_thread_count);
1421
 
      exit(1);
1422
 
    }
1423
 
    thread_count++;
1424
 
    pthread_mutex_unlock(&LOCK_thread_count);
1425
 
  }
1426
 
 
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)
1431
 
  {
1432
 
    if ((error=pthread_cond_wait(&COND_thread_count,&LOCK_thread_count)))
1433
 
      fprintf(stderr,"Got error: %d from pthread_cond_wait\n",error);
1434
 
  }
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);
1439
 
#ifdef EXTRA_DEBUG
1440
 
  if (found_errors)
1441
 
    printf("Got %d warnings\n",found_errors);
1442
 
  else
1443
 
#endif
1444
 
    printf("Test succeeded\n");
1445
 
  return 0;
1446
 
}
1447
 
 
1448
 
#endif /* MAIN */