~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/thr_lock.cc

enable remaining subselect tests, merge with latest from the trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
76
76
#include <mystrings/m_string.h>
77
77
#include <errno.h>
78
78
 
 
79
#if TIME_WITH_SYS_TIME
 
80
# include <sys/time.h>
 
81
# include <time.h>
 
82
#else
 
83
# if HAVE_SYS_TIME_H
 
84
#  include <sys/time.h>
 
85
# else
 
86
#  include <time.h>
 
87
# endif
 
88
#endif
 
89
 
 
90
#include <drizzled/util/test.h>
 
91
 
79
92
bool thr_lock_inited=0;
80
93
uint32_t locks_immediate = 0L, locks_waited = 0L;
81
 
ulong table_lock_wait_timeout;
 
94
uint64_t table_lock_wait_timeout;
82
95
enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE;
83
96
 
84
 
/* The following constants are only for debug output */
85
 
#define MAX_THREADS 100
86
 
#define MAX_LOCKS   100
87
 
 
88
97
 
89
98
LIST *thr_lock_thread_list;                     /* List of threads in use */
90
 
ulong max_write_lock_count= ~(ulong) 0L;
 
99
uint64_t max_write_lock_count= ~(uint64_t) 0L;
91
100
 
92
101
static inline pthread_cond_t *get_cond(void)
93
102
{
110
119
  return rhs == lhs;
111
120
}
112
121
 
113
 
#ifdef EXTRA_DEBUG
114
 
#define MAX_FOUND_ERRORS        10              /* Report 10 first errors */
115
 
static uint 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
 
  uint 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
 
  uint 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
 
      uint 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
122
 
298
123
        /* Initialize a lock */
299
124
 
300
125
void thr_lock_init(THR_LOCK *lock)
301
126
{
302
127
  memset(lock, 0, sizeof(*lock));
303
 
  VOID(pthread_mutex_init(&lock->mutex,MY_MUTEX_INIT_FAST));
 
128
  pthread_mutex_init(&lock->mutex,MY_MUTEX_INIT_FAST);
304
129
  lock->read.last= &lock->read.data;
305
130
  lock->read_wait.last= &lock->read_wait.data;
306
131
  lock->write_wait.last= &lock->write_wait.data;
316
141
 
317
142
void thr_lock_delete(THR_LOCK *lock)
318
143
{
319
 
  VOID(pthread_mutex_destroy(&lock->mutex));
 
144
  pthread_mutex_destroy(&lock->mutex);
320
145
  pthread_mutex_lock(&THR_LOCK_lock);
321
146
  thr_lock_thread_list=list_delete(thr_lock_thread_list,&lock->list);
322
147
  pthread_mutex_unlock(&THR_LOCK_lock);
436
261
      else
437
262
        wait->last=data->prev;
438
263
      data->type= TL_UNLOCK;                    /* No lock */
439
 
      check_locks(data->lock, "killed or timed out wait_for_lock", 1);
440
264
      wake_up_waiters(data->lock);
441
265
    }
442
 
    else
443
 
    {
444
 
      check_locks(data->lock, "aborted wait_for_lock", 0);
445
 
    }
446
266
  }
447
267
  else
448
268
  {
449
269
    result= THR_LOCK_SUCCESS;
450
270
    if (data->lock->get_status)
451
271
      (*data->lock->get_status)(data->status_param, 0);
452
 
    check_locks(data->lock,"got wait_for_lock",0);
453
272
  }
454
273
  pthread_mutex_unlock(&data->lock->mutex);
455
274
 
475
294
  data->cond=0;                                 /* safety */
476
295
  data->type=lock_type;
477
296
  data->owner= owner;                           /* Must be reset ! */
478
 
  VOID(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);
 
297
  pthread_mutex_lock(&lock->mutex);
481
298
  if ((int) lock_type <= (int) TL_READ_NO_INSERT)
482
299
  {
483
300
    /* Request for READ lock */
503
320
        lock->read.last= &data->next;
504
321
        if (lock_type == TL_READ_NO_INSERT)
505
322
          lock->read_no_write_count++;
506
 
        check_locks(lock,"read lock with old write lock",0);
507
323
        if (lock->get_status)
508
324
          (*lock->get_status)(data->status_param, 0);
509
325
        statistic_increment(locks_immediate,&THR_LOCK_lock);
529
345
        (*lock->get_status)(data->status_param, 0);
530
346
      if (lock_type == TL_READ_NO_INSERT)
531
347
        lock->read_no_write_count++;
532
 
      check_locks(lock,"read lock with no write locks",0);
533
348
      statistic_increment(locks_immediate,&THR_LOCK_lock);
534
349
      goto end;
535
350
    }
607
422
        (*lock->write.last)=data;       /* Add to running fifo */
608
423
        data->prev=lock->write.last;
609
424
        lock->write.last= &data->next;
610
 
        check_locks(lock,"second write lock",0);
611
425
        if (data->lock->get_status)
612
426
          (*data->lock->get_status)(data->status_param, 0);
613
427
        statistic_increment(locks_immediate,&THR_LOCK_lock);
640
454
          lock->write.last= &data->next;
641
455
          if (data->lock->get_status)
642
456
            (*data->lock->get_status)(data->status_param, concurrent_insert);
643
 
          check_locks(lock,"only write lock",0);
644
457
          statistic_increment(locks_immediate,&THR_LOCK_lock);
645
458
          goto end;
646
459
        }
673
486
{
674
487
  THR_LOCK_DATA *data=lock->read_wait.data;
675
488
 
676
 
  check_locks(lock,"before freeing read locks",1);
677
 
 
678
489
  /* move all locks from read_wait list to read list */
679
490
  (*lock->read.last)=data;
680
491
  data->prev=lock->read.last;
691
502
      if (using_concurrent_insert)
692
503
      {
693
504
        /*
694
 
          We can't free this lock; 
 
505
          We can't free this lock;
695
506
          Link lock away from read chain back into read_wait chain
696
507
        */
697
508
        if (((*data->prev)=data->next))
704
515
        continue;
705
516
      }
706
517
      lock->read_no_write_count++;
707
 
    }      
 
518
    }
708
519
    data->cond=0;                               /* Mark thread free */
709
 
    VOID(pthread_cond_signal(cond));
 
520
    pthread_cond_signal(cond);
710
521
  } while ((data=data->next));
711
522
  *lock->read_wait.last=0;
712
523
  if (!lock->read_wait.data)
713
524
    lock->write_lock_count=0;
714
 
  check_locks(lock,"after giving read locks",0);
715
525
}
716
526
 
717
527
        /* Unlock lock and free next thread on same lock */
721
531
  THR_LOCK *lock=data->lock;
722
532
  enum thr_lock_type lock_type=data->type;
723
533
  pthread_mutex_lock(&lock->mutex);
724
 
  check_locks(lock,"start of release lock",0);
725
534
 
726
535
  if (((*data->prev)=data->next))               /* remove from lock-list */
727
536
    data->next->prev= data->prev;
730
539
  else if (lock_type == TL_WRITE_DELAYED && data->cond)
731
540
  {
732
541
    /*
733
 
      This only happens in extreme circumstances when a 
 
542
      This only happens in extreme circumstances when a
734
543
      write delayed lock that is waiting for a lock
735
544
    */
736
545
    lock->write_wait.last=data->prev;           /* Put it on wait queue */
750
559
  if (lock_type == TL_READ_NO_INSERT)
751
560
    lock->read_no_write_count--;
752
561
  data->type=TL_UNLOCK;                         /* Mark unlocked */
753
 
  check_locks(lock,"after releasing lock",1);
754
562
  wake_up_waiters(lock);
755
563
  pthread_mutex_unlock(&lock->mutex);
756
564
  return;
806
614
          {
807
615
            pthread_cond_t *cond=data->cond;
808
616
            data->cond=0;                               /* Mark thread free */
809
 
            VOID(pthread_cond_signal(cond));    /* Start waiting thread */
 
617
            pthread_cond_signal(cond);  /* Start waiting thread */
810
618
          }
811
619
          if (data->type != TL_WRITE_ALLOW_WRITE ||
812
620
              !lock->write_wait.data ||
853
661
        lock->write.last= &data->next;
854
662
        data->next=0;                           /* Only one write lock */
855
663
        data->cond=0;                           /* Mark thread free */
856
 
        VOID(pthread_cond_signal(cond));        /* Start waiting thread */
 
664
        pthread_cond_signal(cond);      /* Start waiting thread */
857
665
      } while (lock_type == TL_WRITE_ALLOW_WRITE &&
858
666
               (data=lock->write_wait.data) &&
859
667
               data->type == TL_WRITE_ALLOW_WRITE);
866
674
      free_all_read_locks(lock,0);
867
675
  }
868
676
end:
869
 
  check_locks(lock, "after waking up waiters", 0);
870
677
  return;
871
678
}
872
679
 
878
685
*/
879
686
 
880
687
 
881
 
#define LOCK_CMP(A,B) ((uchar*) (A->lock) - (uint) ((A)->type) < (uchar*) (B->lock)- (uint) ((B)->type))
 
688
#define LOCK_CMP(A,B) ((unsigned char*) (A->lock) - (uint) ((A)->type) < (unsigned char*) (B->lock)- (uint) ((B)->type))
882
689
 
883
 
static void sort_locks(THR_LOCK_DATA **data,uint count)
 
690
static void sort_locks(THR_LOCK_DATA **data,uint32_t count)
884
691
{
885
692
  THR_LOCK_DATA **pos,**end,**prev,*tmp;
886
693
 
902
709
 
903
710
 
904
711
enum enum_thr_lock_result
905
 
thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner)
 
712
thr_multi_lock(THR_LOCK_DATA **data, uint32_t count, THR_LOCK_OWNER *owner)
906
713
{
907
714
  THR_LOCK_DATA **pos,**end;
908
715
  if (count > 1)
916
723
      thr_multi_unlock(data,(uint) (pos-data));
917
724
      return(result);
918
725
    }
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
726
  }
924
727
  /*
925
728
    Ensure that all get_locks() have the same status
973
776
 
974
777
  /* free all locks */
975
778
 
976
 
void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
 
779
void thr_multi_unlock(THR_LOCK_DATA **data,uint32_t count)
977
780
{
978
781
  THR_LOCK_DATA **pos,**end;
979
782
 
980
783
  for (pos=data,end=data+count; pos < end ; pos++)
981
784
  {
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
785
    if ((*pos)->type != TL_UNLOCK)
988
786
      thr_unlock(*pos);
989
787
  }
1109
907
 
1110
908
  pthread_mutex_lock(&lock->mutex);
1111
909
  in_data->type= new_lock_type;
1112
 
  check_locks(lock,"after downgrading lock",0);
1113
910
 
1114
911
  pthread_mutex_unlock(&lock->mutex);
1115
912
  return;
1127
924
    pthread_mutex_unlock(&lock->mutex);
1128
925
    return(data->type == TL_UNLOCK);    /* Test if Aborted */
1129
926
  }
1130
 
  check_locks(lock,"before upgrading lock",0);
1131
927
  /* TODO:  Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */
1132
928
  data->type=TL_WRITE;                          /* Upgrade lock */
1133
929
 
1153
949
      lock->write_wait.last= &data->next;
1154
950
    data->prev= &lock->write_wait.data;
1155
951
    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
 
  }
 
952
  }
 
953
 
1162
954
  return(wait_for_lock(&lock->write_wait,data,1));
1163
955
}
1164
956
 
1196
988
  pthread_mutex_unlock(&lock->mutex);
1197
989
  return(thr_upgrade_write_delay_lock(data));
1198
990
}
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
 
  uint 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 uint 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
 
  VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
1333
 
  pthread_mutex_unlock(&LOCK_thread_count);
1334
 
  free((uchar*) 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
 
  VOID(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 */