~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/thr_lock.cc

  • Committer: Brian Aker
  • Date: 2009-05-11 17:50:22 UTC
  • Revision ID: brian@gaz-20090511175022-y35q9ky6uh9ldcjt
Replacing Sun employee copyright headers (aka... anything done by a Sun
employee is copyright by Sun).

Show diffs side-by-side

added added

removed removed

Lines of Context:
70
70
 
71
71
*/
72
72
 
73
 
#include "mysys_priv.h"
 
73
#include "mysys/mysys_priv.h"
74
74
 
75
75
#include "thr_lock.h"
76
76
#include <mystrings/m_string.h>
77
77
#include <errno.h>
 
78
#include <list>
 
79
 
 
80
#if TIME_WITH_SYS_TIME
 
81
# include <sys/time.h>
 
82
# include <time.h>
 
83
#else
 
84
# if HAVE_SYS_TIME_H
 
85
#  include <sys/time.h>
 
86
# else
 
87
#  include <time.h>
 
88
# endif
 
89
#endif
 
90
 
 
91
#include <drizzled/util/test.h>
 
92
 
 
93
using namespace std;
78
94
 
79
95
bool thr_lock_inited=0;
80
96
uint32_t locks_immediate = 0L, locks_waited = 0L;
81
 
ulong table_lock_wait_timeout;
 
97
uint64_t table_lock_wait_timeout;
82
98
enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE;
83
99
 
84
 
/* The following constants are only for debug output */
85
 
#define MAX_THREADS 100
86
 
#define MAX_LOCKS   100
87
 
 
88
 
 
89
 
LIST *thr_lock_thread_list;                     /* List of threads in use */
90
 
ulong max_write_lock_count= ~(ulong) 0L;
 
100
 
 
101
static list<THR_LOCK *> thr_lock_thread_list;          /* List of threads in use */
 
102
 
 
103
uint64_t max_write_lock_count= ~(uint64_t) 0L;
91
104
 
92
105
static inline pthread_cond_t *get_cond(void)
93
106
{
110
123
  return rhs == lhs;
111
124
}
112
125
 
113
 
#ifdef EXTRA_DEBUG
114
 
#define MAX_FOUND_ERRORS        10              /* Report 10 first errors */
115
 
static uint32_t found_errors=0;
116
 
 
117
 
static int check_lock(struct st_lock_list *list, const char* lock_type,
118
 
                      const char *where, bool same_owner, bool no_cond)
119
 
{
120
 
  THR_LOCK_DATA *data,**prev;
121
 
  uint32_t count=0;
122
 
  THR_LOCK_OWNER *first_owner;
123
 
 
124
 
  prev= &list->data;
125
 
  if (list->data)
126
 
  {
127
 
    enum thr_lock_type last_lock_type=list->data->type;
128
 
 
129
 
    if (same_owner && list->data)
130
 
      first_owner= list->data->owner;
131
 
    for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
132
 
    {
133
 
      if (data->type != last_lock_type)
134
 
        last_lock_type=TL_IGNORE;
135
 
      if (data->prev != prev)
136
 
      {
137
 
        fprintf(stderr,
138
 
                "Warning: prev link %d didn't point at previous lock at %s: %s\n",
139
 
                count, lock_type, where);
140
 
        return 1;
141
 
      }
142
 
      if (same_owner &&
143
 
          !thr_lock_owner_equal(data->owner, first_owner) &&
144
 
          last_lock_type != TL_WRITE_ALLOW_WRITE)
145
 
      {
146
 
        fprintf(stderr,
147
 
                "Warning: Found locks from different threads in %s: %s\n",
148
 
                lock_type,where);
149
 
        return 1;
150
 
      }
151
 
      if (no_cond && data->cond)
152
 
      {
153
 
        fprintf(stderr,
154
 
                "Warning: Found active lock with not reset cond %s: %s\n",
155
 
                lock_type,where);
156
 
        return 1;
157
 
      }
158
 
      prev= &data->next;
159
 
    }
160
 
    if (data)
161
 
    {
162
 
      fprintf(stderr,"Warning: found too many locks at %s: %s\n",
163
 
              lock_type,where);
164
 
      return 1;
165
 
    }
166
 
  }
167
 
  if (prev != list->last)
168
 
  {
169
 
    fprintf(stderr,"Warning: last didn't point at last lock at %s: %s\n",
170
 
            lock_type, where);
171
 
    return 1;
172
 
  }
173
 
  return 0;
174
 
}
175
 
 
176
 
 
177
 
static void check_locks(THR_LOCK *lock, const char *where,
178
 
                        bool allow_no_locks)
179
 
{
180
 
  uint32_t old_found_errors=found_errors;
181
 
 
182
 
  if (found_errors < MAX_FOUND_ERRORS)
183
 
  {
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))
188
 
      found_errors++;
189
 
 
190
 
    if (found_errors < MAX_FOUND_ERRORS)
191
 
    {
192
 
      uint32_t count=0;
193
 
      THR_LOCK_DATA *data;
194
 
      for (data=lock->read.data ; data ; data=data->next)
195
 
      {
196
 
        if ((int) data->type == (int) TL_READ_NO_INSERT)
197
 
          count++;
198
 
        /* Protect against infinite loop. */
199
 
        assert(count <= lock->read_no_write_count);
200
 
      }
201
 
      if (count != lock->read_no_write_count)
202
 
      {
203
 
        found_errors++;
204
 
        fprintf(stderr,
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);
206
 
      }      
207
 
 
208
 
      if (!lock->write.data)
209
 
      {
210
 
        if (!allow_no_locks && !lock->read.data &&
211
 
            (lock->write_wait.data || lock->read_wait.data))
212
 
        {
213
 
          found_errors++;
214
 
          fprintf(stderr,
215
 
                  "Warning at '%s': No locks in use but locks are in wait queue\n",
216
 
                  where);
217
 
        }
218
 
        if (!lock->write_wait.data)
219
 
        {
220
 
          if (!allow_no_locks && lock->read_wait.data)
221
 
          {
222
 
            found_errors++;
223
 
            fprintf(stderr,
224
 
                    "Warning at '%s': No write locks and waiting read locks\n",
225
 
                    where);
226
 
          }
227
 
        }
228
 
        else
229
 
        {
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 &&
236
 
                !lock->read.data)))
237
 
          {
238
 
            found_errors++;
239
 
            fprintf(stderr,
240
 
                    "Warning at '%s': Write lock %d waiting while no exclusive read locks\n",where,(int) lock->write_wait.data->type);
241
 
          }
242
 
        }             
243
 
      }
244
 
      else
245
 
      {                                         /* Have write lock */
246
 
        if (lock->write_wait.data)
247
 
        {
248
 
          if (!allow_no_locks && 
249
 
              lock->write.data->type == TL_WRITE_ALLOW_WRITE &&
250
 
              lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE)
251
 
          {
252
 
            found_errors++;
253
 
            fprintf(stderr,
254
 
                    "Warning at '%s': Found WRITE_ALLOW_WRITE lock waiting for WRITE_ALLOW_WRITE lock\n",
255
 
                    where);
256
 
          }
257
 
        }
258
 
        if (lock->read.data)
259
 
        {
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)))
267
 
          {
268
 
            found_errors++;
269
 
            fprintf(stderr,
270
 
                    "Warning at '%s': Found lock of type %d that is write and read locked\n",
271
 
                    where, lock->write.data->type);
272
 
          }
273
 
        }
274
 
        if (lock->read_wait.data)
275
 
        {
276
 
          if (!allow_no_locks && lock->write.data->type <= TL_WRITE_DELAYED &&
277
 
              lock->read_wait.data->type <= TL_READ_HIGH_PRIORITY)
278
 
          {
279
 
            found_errors++;
280
 
            fprintf(stderr,
281
 
                    "Warning at '%s': Found read lock of type %d waiting for write lock of type %d\n",
282
 
                    where,
283
 
                    (int) lock->read_wait.data->type,
284
 
                    (int) lock->write.data->type);
285
 
          }
286
 
        }
287
 
      }
288
 
    }
289
 
  }
290
 
  return;
291
 
}
292
 
 
293
 
#else /* EXTRA_DEBUG */
294
 
#define check_locks(A,B,C)
295
 
#endif
296
 
 
297
126
 
298
127
        /* Initialize a lock */
299
128
 
307
136
  lock->write.last= &lock->write.data;
308
137
 
309
138
  pthread_mutex_lock(&THR_LOCK_lock);           /* Add to locks in use */
310
 
  lock->list.data=(void*) lock;
311
 
  thr_lock_thread_list=list_add(thr_lock_thread_list,&lock->list);
 
139
  thr_lock_thread_list.push_front(lock);
312
140
  pthread_mutex_unlock(&THR_LOCK_lock);
313
141
  return;
314
142
}
318
146
{
319
147
  pthread_mutex_destroy(&lock->mutex);
320
148
  pthread_mutex_lock(&THR_LOCK_lock);
321
 
  thr_lock_thread_list=list_delete(thr_lock_thread_list,&lock->list);
 
149
  thr_lock_thread_list.remove(lock);
322
150
  pthread_mutex_unlock(&THR_LOCK_lock);
323
151
  return;
324
152
}
436
264
      else
437
265
        wait->last=data->prev;
438
266
      data->type= TL_UNLOCK;                    /* No lock */
439
 
      check_locks(data->lock, "killed or timed out wait_for_lock", 1);
440
267
      wake_up_waiters(data->lock);
441
268
    }
442
 
    else
443
 
    {
444
 
      check_locks(data->lock, "aborted wait_for_lock", 0);
445
 
    }
446
269
  }
447
270
  else
448
271
  {
449
272
    result= THR_LOCK_SUCCESS;
450
273
    if (data->lock->get_status)
451
274
      (*data->lock->get_status)(data->status_param, 0);
452
 
    check_locks(data->lock,"got wait_for_lock",0);
453
275
  }
454
276
  pthread_mutex_unlock(&data->lock->mutex);
455
277
 
476
298
  data->type=lock_type;
477
299
  data->owner= owner;                           /* Must be reset ! */
478
300
  pthread_mutex_lock(&lock->mutex);
479
 
  check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ?
480
 
              "enter read_lock" : "enter write_lock",0);
481
301
  if ((int) lock_type <= (int) TL_READ_NO_INSERT)
482
302
  {
483
303
    /* Request for READ lock */
503
323
        lock->read.last= &data->next;
504
324
        if (lock_type == TL_READ_NO_INSERT)
505
325
          lock->read_no_write_count++;
506
 
        check_locks(lock,"read lock with old write lock",0);
507
326
        if (lock->get_status)
508
327
          (*lock->get_status)(data->status_param, 0);
509
328
        statistic_increment(locks_immediate,&THR_LOCK_lock);
529
348
        (*lock->get_status)(data->status_param, 0);
530
349
      if (lock_type == TL_READ_NO_INSERT)
531
350
        lock->read_no_write_count++;
532
 
      check_locks(lock,"read lock with no write locks",0);
533
351
      statistic_increment(locks_immediate,&THR_LOCK_lock);
534
352
      goto end;
535
353
    }
607
425
        (*lock->write.last)=data;       /* Add to running fifo */
608
426
        data->prev=lock->write.last;
609
427
        lock->write.last= &data->next;
610
 
        check_locks(lock,"second write lock",0);
611
428
        if (data->lock->get_status)
612
429
          (*data->lock->get_status)(data->status_param, 0);
613
430
        statistic_increment(locks_immediate,&THR_LOCK_lock);
640
457
          lock->write.last= &data->next;
641
458
          if (data->lock->get_status)
642
459
            (*data->lock->get_status)(data->status_param, concurrent_insert);
643
 
          check_locks(lock,"only write lock",0);
644
460
          statistic_increment(locks_immediate,&THR_LOCK_lock);
645
461
          goto end;
646
462
        }
673
489
{
674
490
  THR_LOCK_DATA *data=lock->read_wait.data;
675
491
 
676
 
  check_locks(lock,"before freeing read locks",1);
677
 
 
678
492
  /* move all locks from read_wait list to read list */
679
493
  (*lock->read.last)=data;
680
494
  data->prev=lock->read.last;
691
505
      if (using_concurrent_insert)
692
506
      {
693
507
        /*
694
 
          We can't free this lock; 
 
508
          We can't free this lock;
695
509
          Link lock away from read chain back into read_wait chain
696
510
        */
697
511
        if (((*data->prev)=data->next))
704
518
        continue;
705
519
      }
706
520
      lock->read_no_write_count++;
707
 
    }      
 
521
    }
708
522
    data->cond=0;                               /* Mark thread free */
709
523
    pthread_cond_signal(cond);
710
524
  } while ((data=data->next));
711
525
  *lock->read_wait.last=0;
712
526
  if (!lock->read_wait.data)
713
527
    lock->write_lock_count=0;
714
 
  check_locks(lock,"after giving read locks",0);
715
528
}
716
529
 
717
530
        /* Unlock lock and free next thread on same lock */
721
534
  THR_LOCK *lock=data->lock;
722
535
  enum thr_lock_type lock_type=data->type;
723
536
  pthread_mutex_lock(&lock->mutex);
724
 
  check_locks(lock,"start of release lock",0);
725
537
 
726
538
  if (((*data->prev)=data->next))               /* remove from lock-list */
727
539
    data->next->prev= data->prev;
730
542
  else if (lock_type == TL_WRITE_DELAYED && data->cond)
731
543
  {
732
544
    /*
733
 
      This only happens in extreme circumstances when a 
 
545
      This only happens in extreme circumstances when a
734
546
      write delayed lock that is waiting for a lock
735
547
    */
736
548
    lock->write_wait.last=data->prev;           /* Put it on wait queue */
750
562
  if (lock_type == TL_READ_NO_INSERT)
751
563
    lock->read_no_write_count--;
752
564
  data->type=TL_UNLOCK;                         /* Mark unlocked */
753
 
  check_locks(lock,"after releasing lock",1);
754
565
  wake_up_waiters(lock);
755
566
  pthread_mutex_unlock(&lock->mutex);
756
567
  return;
866
677
      free_all_read_locks(lock,0);
867
678
  }
868
679
end:
869
 
  check_locks(lock, "after waking up waiters", 0);
870
680
  return;
871
681
}
872
682
 
878
688
*/
879
689
 
880
690
 
881
 
#define LOCK_CMP(A,B) ((unsigned char*) (A->lock) - (uint) ((A)->type) < (unsigned char*) (B->lock)- (uint) ((B)->type))
 
691
#define LOCK_CMP(A,B) ((unsigned char*) (A->lock) - (uint32_t) ((A)->type) < (unsigned char*) (B->lock)- (uint32_t) ((B)->type))
882
692
 
883
693
static void sort_locks(THR_LOCK_DATA **data,uint32_t count)
884
694
{
913
723
    enum enum_thr_lock_result result= thr_lock(*pos, owner, (*pos)->type);
914
724
    if (result != THR_LOCK_SUCCESS)
915
725
    {                                           /* Aborted */
916
 
      thr_multi_unlock(data,(uint) (pos-data));
 
726
      thr_multi_unlock(data,(uint32_t) (pos-data));
917
727
      return(result);
918
728
    }
919
 
#ifdef MAIN
920
 
    printf("Thread: %s  Got lock: 0x%lx  type: %d\n",my_thread_name(),
921
 
           (long) pos[0]->lock, pos[0]->type); fflush(stdout);
922
 
#endif
923
729
  }
924
730
  /*
925
731
    Ensure that all get_locks() have the same status
979
785
 
980
786
  for (pos=data,end=data+count; pos < end ; pos++)
981
787
  {
982
 
#ifdef MAIN
983
 
    printf("Thread: %s  Rel lock: 0x%lx  type: %d\n",
984
 
           my_thread_name(), (long) pos[0]->lock, pos[0]->type);
985
 
    fflush(stdout);
986
 
#endif
987
788
    if ((*pos)->type != TL_UNLOCK)
988
789
      thr_unlock(*pos);
989
790
  }
1109
910
 
1110
911
  pthread_mutex_lock(&lock->mutex);
1111
912
  in_data->type= new_lock_type;
1112
 
  check_locks(lock,"after downgrading lock",0);
1113
913
 
1114
914
  pthread_mutex_unlock(&lock->mutex);
1115
915
  return;
1127
927
    pthread_mutex_unlock(&lock->mutex);
1128
928
    return(data->type == TL_UNLOCK);    /* Test if Aborted */
1129
929
  }
1130
 
  check_locks(lock,"before upgrading lock",0);
1131
930
  /* TODO:  Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */
1132
931
  data->type=TL_WRITE;                          /* Upgrade lock */
1133
932
 
1153
952
      lock->write_wait.last= &data->next;
1154
953
    data->prev= &lock->write_wait.data;
1155
954
    lock->write_wait.data=data;
1156
 
    check_locks(lock,"upgrading lock",0);
1157
 
  }
1158
 
  else
1159
 
  {
1160
 
    check_locks(lock,"waiting for lock",0);
1161
 
  }
 
955
  }
 
956
 
1162
957
  return(wait_for_lock(&lock->write_wait,data,1));
1163
958
}
1164
959
 
1196
991
  pthread_mutex_unlock(&lock->mutex);
1197
992
  return(thr_upgrade_write_delay_lock(data));
1198
993
}
1199
 
 
1200
 
 
1201
 
#include <my_sys.h>
1202
 
 
1203
 
/*****************************************************************************
1204
 
** Test of thread locks
1205
 
****************************************************************************/
1206
 
 
1207
 
#ifdef MAIN
1208
 
 
1209
 
struct st_test {
1210
 
  uint32_t lock_nr;
1211
 
  enum thr_lock_type lock_type;
1212
 
};
1213
 
 
1214
 
THR_LOCK locks[5];                      /* 4 locks */
1215
 
 
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}};
1233
 
 
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)
1254
 
};
1255
 
 
1256
 
 
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;
1261
 
 
1262
 
#define MAX_LOCK_COUNT 8
1263
 
 
1264
 
/* The following functions is for WRITE_CONCURRENT_INSERT */
1265
 
 
1266
 
static void test_get_status(void* param __attribute__((unused)),
1267
 
                            int concurrent_insert __attribute__((unused)))
1268
 
{
1269
 
}
1270
 
 
1271
 
static void test_update_status(void* param __attribute__((unused)))
1272
 
{
1273
 
}
1274
 
 
1275
 
static void test_copy_status(void* to __attribute__((unused)) ,
1276
 
                             void *from __attribute__((unused)))
1277
 
{
1278
 
}
1279
 
 
1280
 
static bool test_check_status(void* param __attribute__((unused)))
1281
 
{
1282
 
  return 0;
1283
 
}
1284
 
 
1285
 
 
1286
 
static void *test_thread(void *arg)
1287
 
{
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];
1293
 
  my_thread_init();
1294
 
 
1295
 
  printf("Thread %s (%d) started\n",my_thread_name(),param); fflush(stdout);
1296
 
 
1297
 
 
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 */
1303
 
  {
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;
1308
 
    }
1309
 
    thr_multi_lock(multi_locks, lock_counts[param], &owner);
1310
 
    pthread_mutex_lock(&LOCK_thread_count);
1311
 
    {
1312
 
      int tmp=rand() & 7;                       /* Do something from 0-2 sec */
1313
 
      if (tmp == 0)
1314
 
        sleep(1);
1315
 
      else if (tmp == 1)
1316
 
        sleep(2);
1317
 
      else
1318
 
      {
1319
 
        uint32_t k;
1320
 
        for (k=0 ; k < (uint32_t) (tmp-2)*100000L ; k++)
1321
 
          sum+=k;
1322
 
      }
1323
 
    }
1324
 
    pthread_mutex_unlock(&LOCK_thread_count);
1325
 
    thr_multi_unlock(multi_locks,lock_counts[param]);
1326
 
  }
1327
 
 
1328
 
  printf("Thread %s (%d) ended\n",my_thread_name(),param); fflush(stdout);
1329
 
  thr_print_locks();
1330
 
  pthread_mutex_lock(&LOCK_thread_count);
1331
 
  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);
1335
 
  return 0;
1336
 
}
1337
 
 
1338
 
 
1339
 
int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
1340
 
{
1341
 
  pthread_t tid;
1342
 
  pthread_attr_t thr_attr;
1343
 
  int i,*param,error;
1344
 
  MY_INIT(argv[0]);
1345
 
 
1346
 
  printf("Main thread: %s\n",my_thread_name());
1347
 
 
1348
 
  if ((error=pthread_cond_init(&COND_thread_count,NULL)))
1349
 
  {
1350
 
    fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)",
1351
 
            error,errno);
1352
 
    exit(1);
1353
 
  }
1354
 
  if ((error=pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST)))
1355
 
  {
1356
 
    fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)",
1357
 
            error,errno);
1358
 
    exit(1);
1359
 
  }
1360
 
 
1361
 
  for (i=0 ; i < (int) array_elements(locks) ; i++)
1362
 
  {
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;
1368
 
  }
1369
 
  if ((error=pthread_attr_init(&thr_attr)))
1370
 
  {
1371
 
    fprintf(stderr,"Got error: %d from pthread_attr_init (errno: %d)",
1372
 
            error,errno);
1373
 
    exit(1);
1374
 
  }
1375
 
  if ((error=pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED)))
1376
 
  {
1377
 
    fprintf(stderr,
1378
 
            "Got error: %d from pthread_attr_setdetachstate (errno: %d)",
1379
 
            error,errno);
1380
 
    exit(1);
1381
 
  }
1382
 
#ifndef pthread_attr_setstacksize               /* void return value */
1383
 
  if ((error=pthread_attr_setstacksize(&thr_attr,65536L)))
1384
 
  {
1385
 
    fprintf(stderr,"Got error: %d from pthread_attr_setstacksize (errno: %d)",
1386
 
            error,errno);
1387
 
    exit(1);
1388
 
  }
1389
 
#endif
1390
 
#ifdef HAVE_THR_SETCONCURRENCY
1391
 
  thr_setconcurrency(2);
1392
 
#endif
1393
 
  for (i=0 ; i < (int) array_elements(lock_counts) ; i++)
1394
 
  {
1395
 
    param=(int*) malloc(sizeof(int));
1396
 
    *param=i;
1397
 
 
1398
 
    if ((error=pthread_mutex_lock(&LOCK_thread_count)))
1399
 
    {
1400
 
      fprintf(stderr,"Got error: %d from pthread_mutex_lock (errno: %d)",
1401
 
              error,errno);
1402
 
      exit(1);
1403
 
    }
1404
 
    if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param)))
1405
 
    {
1406
 
      fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n",
1407
 
              error,errno);
1408
 
      pthread_mutex_unlock(&LOCK_thread_count);
1409
 
      exit(1);
1410
 
    }
1411
 
    thread_count++;
1412
 
    pthread_mutex_unlock(&LOCK_thread_count);
1413
 
  }
1414
 
 
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)
1419
 
  {
1420
 
    if ((error=pthread_cond_wait(&COND_thread_count,&LOCK_thread_count)))
1421
 
      fprintf(stderr,"Got error: %d from pthread_cond_wait\n",error);
1422
 
  }
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);
1427
 
#ifdef EXTRA_DEBUG
1428
 
  if (found_errors)
1429
 
    printf("Got %d warnings\n",found_errors);
1430
 
  else
1431
 
#endif
1432
 
    printf("Test succeeded\n");
1433
 
  return 0;
1434
 
}
1435
 
 
1436
 
#endif /* MAIN */