~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/thr_lock.c

  • Committer: Monty Taylor
  • Date: 2008-07-05 18:10:38 UTC
  • mto: This revision was merged to the branch mainline in revision 63.
  • Revision ID: monty@inaugust.com-20080705181038-0ih0nnamu5qrut0y
Fixed prototypes. Cleaned define a little bit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
70
70
 
71
71
*/
72
72
 
 
73
#if !defined(MAIN) && !defined(DBUG_OFF) && !defined(EXTRA_DEBUG)
 
74
#define FORCE_DBUG_OFF
 
75
#endif
 
76
 
73
77
#include "mysys_priv.h"
74
78
 
75
79
#include "thr_lock.h"
76
 
#include <mystrings/m_string.h>
 
80
#include <m_string.h>
77
81
#include <errno.h>
78
82
 
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
 
 
92
 
bool thr_lock_inited=0;
93
 
uint32_t locks_immediate = 0L, locks_waited = 0L;
 
83
my_bool thr_lock_inited=0;
 
84
ulong locks_immediate = 0L, locks_waited = 0L;
94
85
ulong table_lock_wait_timeout;
95
86
enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE;
96
87
 
111
102
** For the future (now the thread specific cond is alloced by my_pthread.c)
112
103
*/
113
104
 
114
 
bool init_thr_lock()
 
105
my_bool init_thr_lock()
115
106
{
116
107
  thr_lock_inited=1;
117
108
  return 0;
118
109
}
119
110
 
120
 
static inline bool
 
111
static inline my_bool
121
112
thr_lock_owner_equal(THR_LOCK_OWNER *rhs, THR_LOCK_OWNER *lhs)
122
113
{
123
114
  return rhs == lhs;
124
115
}
125
116
 
 
117
 
126
118
#ifdef EXTRA_DEBUG
127
119
#define MAX_FOUND_ERRORS        10              /* Report 10 first errors */
128
 
static uint32_t found_errors=0;
 
120
static uint found_errors=0;
129
121
 
130
122
static int check_lock(struct st_lock_list *list, const char* lock_type,
131
 
                      const char *where, bool same_owner, bool no_cond)
 
123
                      const char *where, my_bool same_owner, my_bool no_cond)
132
124
{
133
125
  THR_LOCK_DATA *data,**prev;
134
 
  uint32_t count=0;
 
126
  uint count=0;
135
127
  THR_LOCK_OWNER *first_owner;
136
128
 
137
129
  prev= &list->data;
188
180
 
189
181
 
190
182
static void check_locks(THR_LOCK *lock, const char *where,
191
 
                        bool allow_no_locks)
 
183
                        my_bool allow_no_locks)
192
184
{
193
 
  uint32_t old_found_errors=found_errors;
 
185
  uint old_found_errors=found_errors;
 
186
  DBUG_ENTER("check_locks");
194
187
 
195
188
  if (found_errors < MAX_FOUND_ERRORS)
196
189
  {
202
195
 
203
196
    if (found_errors < MAX_FOUND_ERRORS)
204
197
    {
205
 
      uint32_t count=0;
 
198
      uint count=0;
206
199
      THR_LOCK_DATA *data;
207
200
      for (data=lock->read.data ; data ; data=data->next)
208
201
      {
209
202
        if ((int) data->type == (int) TL_READ_NO_INSERT)
210
203
          count++;
211
204
        /* Protect against infinite loop. */
212
 
        assert(count <= lock->read_no_write_count);
 
205
        DBUG_ASSERT(count <= lock->read_no_write_count);
213
206
      }
214
207
      if (count != lock->read_no_write_count)
215
208
      {
282
275
            fprintf(stderr,
283
276
                    "Warning at '%s': Found lock of type %d that is write and read locked\n",
284
277
                    where, lock->write.data->type);
 
278
            DBUG_PRINT("warning",("At '%s': Found lock of type %d that is write and read locked\n",
 
279
                    where, lock->write.data->type));
 
280
 
285
281
          }
286
282
        }
287
283
        if (lock->read_wait.data)
299
295
        }
300
296
      }
301
297
    }
 
298
    if (found_errors != old_found_errors)
 
299
    {
 
300
      DBUG_PRINT("error",("Found wrong lock"));
 
301
    }
302
302
  }
303
 
  return;
 
303
  DBUG_VOID_RETURN;
304
304
}
305
305
 
306
306
#else /* EXTRA_DEBUG */
312
312
 
313
313
void thr_lock_init(THR_LOCK *lock)
314
314
{
315
 
  memset(lock, 0, sizeof(*lock));
316
 
  pthread_mutex_init(&lock->mutex,MY_MUTEX_INIT_FAST);
 
315
  DBUG_ENTER("thr_lock_init");
 
316
  bzero((char*) lock,sizeof(*lock));
 
317
  VOID(pthread_mutex_init(&lock->mutex,MY_MUTEX_INIT_FAST));
317
318
  lock->read.last= &lock->read.data;
318
319
  lock->read_wait.last= &lock->read_wait.data;
319
320
  lock->write_wait.last= &lock->write_wait.data;
323
324
  lock->list.data=(void*) lock;
324
325
  thr_lock_thread_list=list_add(thr_lock_thread_list,&lock->list);
325
326
  pthread_mutex_unlock(&THR_LOCK_lock);
326
 
  return;
 
327
  DBUG_VOID_RETURN;
327
328
}
328
329
 
329
330
 
330
331
void thr_lock_delete(THR_LOCK *lock)
331
332
{
332
 
  pthread_mutex_destroy(&lock->mutex);
 
333
  DBUG_ENTER("thr_lock_delete");
 
334
  VOID(pthread_mutex_destroy(&lock->mutex));
333
335
  pthread_mutex_lock(&THR_LOCK_lock);
334
336
  thr_lock_thread_list=list_delete(thr_lock_thread_list,&lock->list);
335
337
  pthread_mutex_unlock(&THR_LOCK_lock);
336
 
  return;
 
338
  DBUG_VOID_RETURN;
337
339
}
338
340
 
339
341
 
357
359
}
358
360
 
359
361
 
360
 
static inline bool
 
362
static inline my_bool
361
363
have_old_read_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner)
362
364
{
363
365
  for ( ; data ; data=data->next)
368
370
  return 0;
369
371
}
370
372
 
371
 
static inline bool have_specific_lock(THR_LOCK_DATA *data,
 
373
static inline my_bool have_specific_lock(THR_LOCK_DATA *data,
372
374
                                         enum thr_lock_type type)
373
375
{
374
376
  for ( ; data ; data=data->next)
385
387
 
386
388
static enum enum_thr_lock_result
387
389
wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
388
 
              bool in_wait_list)
 
390
              my_bool in_wait_list)
389
391
{
390
392
  struct st_my_thread_var *thread_var= my_thread_var;
391
393
  pthread_cond_t *cond= &thread_var->suspend;
392
394
  struct timespec wait_timeout;
393
395
  enum enum_thr_lock_result result= THR_LOCK_ABORTED;
394
 
  bool can_deadlock= test(data->owner->info->n_cursors);
 
396
  my_bool can_deadlock= test(data->owner->info->n_cursors);
 
397
  DBUG_ENTER("wait_for_lock");
395
398
 
396
399
  if (!in_wait_list)
397
400
  {
430
433
    */
431
434
    if (data->cond == 0)
432
435
    {
 
436
      DBUG_PRINT("thr_lock", ("lock granted/aborted"));
433
437
      break;
434
438
    }
435
439
    if (rc == ETIMEDOUT || rc == ETIME)
436
440
    {
437
441
      /* purecov: begin inspected */
 
442
      DBUG_PRINT("thr_lock", ("lock timed out"));
438
443
      result= THR_LOCK_WAIT_TIMEOUT;
439
444
      break;
440
445
      /* purecov: end */
441
446
    }
442
447
  }
 
448
  DBUG_PRINT("thr_lock", ("aborted: %d  in_wait_list: %d",
 
449
                          thread_var->abort, in_wait_list));
 
450
 
443
451
  if (data->cond || data->type == TL_UNLOCK)
444
452
  {
445
453
    if (data->cond)                             /* aborted or timed out */
454
462
    }
455
463
    else
456
464
    {
 
465
      DBUG_PRINT("thr_lock", ("lock aborted"));
457
466
      check_locks(data->lock, "aborted wait_for_lock", 0);
458
467
    }
459
468
  }
471
480
  thread_var->current_mutex= 0;
472
481
  thread_var->current_cond=  0;
473
482
  pthread_mutex_unlock(&thread_var->mutex);
474
 
  return(result);
 
483
  DBUG_RETURN(result);
475
484
}
476
485
 
477
486
 
483
492
  enum enum_thr_lock_result result= THR_LOCK_SUCCESS;
484
493
  struct st_lock_list *wait_queue;
485
494
  THR_LOCK_DATA *lock_owner;
 
495
  DBUG_ENTER("thr_lock");
486
496
 
487
497
  data->next=0;
488
498
  data->cond=0;                                 /* safety */
489
499
  data->type=lock_type;
490
500
  data->owner= owner;                           /* Must be reset ! */
491
 
  pthread_mutex_lock(&lock->mutex);
 
501
  VOID(pthread_mutex_lock(&lock->mutex));
 
502
  DBUG_PRINT("lock",("data: 0x%lx  thread: 0x%lx  lock: 0x%lx  type: %d",
 
503
                     (long) data, data->owner->info->thread_id,
 
504
                     (long) lock, (int) lock_type));
492
505
  check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ?
493
506
              "enter read_lock" : "enter write_lock",0);
494
507
  if ((int) lock_type <= (int) TL_READ_NO_INSERT)
505
518
           and the read lock is not TL_READ_NO_INSERT
506
519
      */
507
520
 
 
521
      DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx",
 
522
                         lock->write.data->owner->info->thread_id));
508
523
      if (thr_lock_owner_equal(data->owner, lock->write.data->owner) ||
509
524
          (lock->write.data->type <= TL_WRITE_DELAYED &&
510
525
           (((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) ||
616
631
          We have already got a write lock or all locks are
617
632
          TL_WRITE_ALLOW_WRITE
618
633
        */
 
634
        DBUG_PRINT("info", ("write_wait.data: 0x%lx  old_type: %d",
 
635
                            (ulong) lock->write_wait.data,
 
636
                            lock->write.data->type));
619
637
 
620
638
        (*lock->write.last)=data;       /* Add to running fifo */
621
639
        data->prev=lock->write.last;
626
644
        statistic_increment(locks_immediate,&THR_LOCK_lock);
627
645
        goto end;
628
646
      }
 
647
      DBUG_PRINT("lock",("write locked 2 by thread: 0x%lx",
 
648
                         lock->write.data->owner->info->thread_id));
629
649
    }
630
650
    else
631
651
    {
 
652
      DBUG_PRINT("info", ("write_wait.data: 0x%lx",
 
653
                          (ulong) lock->write_wait.data));
632
654
      if (!lock->write_wait.data)
633
655
      {                                         /* no scheduled write locks */
634
 
        bool concurrent_insert= 0;
 
656
        my_bool concurrent_insert= 0;
635
657
        if (lock_type == TL_WRITE_CONCURRENT_INSERT)
636
658
        {
637
659
          concurrent_insert= 1;
658
680
          goto end;
659
681
        }
660
682
      }
 
683
      DBUG_PRINT("lock",("write locked 3 by thread: 0x%lx  type: %d",
 
684
                         lock->read.data->owner->info->thread_id, data->type));
661
685
    }
662
686
    wait_queue= &lock->write_wait;
663
687
  }
670
694
  lock_owner= lock->read.data ? lock->read.data : lock->write.data;
671
695
  if (lock_owner && lock_owner->owner->info == owner->info)
672
696
  {
 
697
    DBUG_PRINT("lock",("deadlock"));
673
698
    result= THR_LOCK_DEADLOCK;
674
699
    goto end;
675
700
  }
676
701
  /* Can't get lock yet;  Wait for it */
677
 
  return(wait_for_lock(wait_queue, data, 0));
 
702
  DBUG_RETURN(wait_for_lock(wait_queue, data, 0));
678
703
end:
679
704
  pthread_mutex_unlock(&lock->mutex);
680
 
  return(result);
 
705
  DBUG_RETURN(result);
681
706
}
682
707
 
683
708
 
684
709
static inline void free_all_read_locks(THR_LOCK *lock,
685
 
                                       bool using_concurrent_insert)
 
710
                                       my_bool using_concurrent_insert)
686
711
{
687
712
  THR_LOCK_DATA *data=lock->read_wait.data;
688
713
 
718
743
      }
719
744
      lock->read_no_write_count++;
720
745
    }      
 
746
    /* purecov: begin inspected */
 
747
    DBUG_PRINT("lock",("giving read lock to thread: 0x%lx",
 
748
                       data->owner->info->thread_id));
 
749
    /* purecov: end */
721
750
    data->cond=0;                               /* Mark thread free */
722
 
    pthread_cond_signal(cond);
 
751
    VOID(pthread_cond_signal(cond));
723
752
  } while ((data=data->next));
724
753
  *lock->read_wait.last=0;
725
754
  if (!lock->read_wait.data)
733
762
{
734
763
  THR_LOCK *lock=data->lock;
735
764
  enum thr_lock_type lock_type=data->type;
 
765
  DBUG_ENTER("thr_unlock");
 
766
  DBUG_PRINT("lock",("data: 0x%lx  thread: 0x%lx  lock: 0x%lx",
 
767
                     (long) data, data->owner->info->thread_id, (long) lock));
736
768
  pthread_mutex_lock(&lock->mutex);
737
769
  check_locks(lock,"start of release lock",0);
738
770
 
766
798
  check_locks(lock,"after releasing lock",1);
767
799
  wake_up_waiters(lock);
768
800
  pthread_mutex_unlock(&lock->mutex);
769
 
  return;
 
801
  DBUG_VOID_RETURN;
770
802
}
771
803
 
772
804
 
783
815
  THR_LOCK_DATA *data;
784
816
  enum thr_lock_type lock_type;
785
817
 
 
818
  DBUG_ENTER("wake_up_waiters");
 
819
 
786
820
  if (!lock->write.data)                        /* If no active write locks */
787
821
  {
788
822
    data=lock->write_wait.data;
799
833
          lock->write_lock_count=0;
800
834
          if (lock->read_wait.data)
801
835
          {
 
836
            DBUG_PRINT("info",("Freeing all read_locks because of max_write_lock_count"));
802
837
            free_all_read_locks(lock,0);
803
838
            goto end;
804
839
          }
816
851
          if (data->type == TL_WRITE_CONCURRENT_INSERT &&
817
852
              (*lock->check_status)(data->status_param))
818
853
            data->type=TL_WRITE;                        /* Upgrade lock */
 
854
          /* purecov: begin inspected */
 
855
          DBUG_PRINT("lock",("giving write lock of type %d to thread: 0x%lx",
 
856
                             data->type, data->owner->info->thread_id));
 
857
          /* purecov: end */
819
858
          {
820
859
            pthread_cond_t *cond=data->cond;
821
860
            data->cond=0;                               /* Mark thread free */
822
 
            pthread_cond_signal(cond);  /* Start waiting thread */
 
861
            VOID(pthread_cond_signal(cond));    /* Start waiting thread */
823
862
          }
824
863
          if (data->type != TL_WRITE_ALLOW_WRITE ||
825
864
              !lock->write_wait.data ||
836
875
                            data &&
837
876
                            (data->type == TL_WRITE_CONCURRENT_INSERT ||
838
877
                             data->type == TL_WRITE_ALLOW_WRITE));
 
878
      else
 
879
      {
 
880
        DBUG_PRINT("lock",("No waiting read locks to free"));
 
881
      }
839
882
    }
840
883
    else if (data &&
841
884
             (lock_type=data->type) <= TL_WRITE_DELAYED &&
866
909
        lock->write.last= &data->next;
867
910
        data->next=0;                           /* Only one write lock */
868
911
        data->cond=0;                           /* Mark thread free */
869
 
        pthread_cond_signal(cond);      /* Start waiting thread */
 
912
        VOID(pthread_cond_signal(cond));        /* Start waiting thread */
870
913
      } while (lock_type == TL_WRITE_ALLOW_WRITE &&
871
914
               (data=lock->write_wait.data) &&
872
915
               data->type == TL_WRITE_ALLOW_WRITE);
880
923
  }
881
924
end:
882
925
  check_locks(lock, "after waking up waiters", 0);
883
 
  return;
 
926
  DBUG_VOID_RETURN;
884
927
}
885
928
 
886
929
 
891
934
*/
892
935
 
893
936
 
894
 
#define LOCK_CMP(A,B) ((unsigned char*) (A->lock) - (uint) ((A)->type) < (unsigned char*) (B->lock)- (uint) ((B)->type))
 
937
#define LOCK_CMP(A,B) ((uchar*) (A->lock) - (uint) ((A)->type) < (uchar*) (B->lock)- (uint) ((B)->type))
895
938
 
896
 
static void sort_locks(THR_LOCK_DATA **data,uint32_t count)
 
939
static void sort_locks(THR_LOCK_DATA **data,uint count)
897
940
{
898
941
  THR_LOCK_DATA **pos,**end,**prev,*tmp;
899
942
 
915
958
 
916
959
 
917
960
enum enum_thr_lock_result
918
 
thr_multi_lock(THR_LOCK_DATA **data, uint32_t count, THR_LOCK_OWNER *owner)
 
961
thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner)
919
962
{
920
963
  THR_LOCK_DATA **pos,**end;
 
964
  DBUG_ENTER("thr_multi_lock");
 
965
  DBUG_PRINT("lock",("data: 0x%lx  count: %d", (long) data, count));
921
966
  if (count > 1)
922
967
    sort_locks(data,count);
923
968
  /* lock everything */
927
972
    if (result != THR_LOCK_SUCCESS)
928
973
    {                                           /* Aborted */
929
974
      thr_multi_unlock(data,(uint) (pos-data));
930
 
      return(result);
 
975
      DBUG_RETURN(result);
931
976
    }
932
977
#ifdef MAIN
933
978
    printf("Thread: %s  Got lock: 0x%lx  type: %d\n",my_thread_name(),
981
1026
    } while (pos != data);
982
1027
  }
983
1028
#endif
984
 
  return(THR_LOCK_SUCCESS);
 
1029
  DBUG_RETURN(THR_LOCK_SUCCESS);
985
1030
}
986
1031
 
987
1032
  /* free all locks */
988
1033
 
989
 
void thr_multi_unlock(THR_LOCK_DATA **data,uint32_t count)
 
1034
void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
990
1035
{
991
1036
  THR_LOCK_DATA **pos,**end;
 
1037
  DBUG_ENTER("thr_multi_unlock");
 
1038
  DBUG_PRINT("lock",("data: 0x%lx  count: %d", (long) data, count));
992
1039
 
993
1040
  for (pos=data,end=data+count; pos < end ; pos++)
994
1041
  {
999
1046
#endif
1000
1047
    if ((*pos)->type != TL_UNLOCK)
1001
1048
      thr_unlock(*pos);
 
1049
    else
 
1050
    {
 
1051
      DBUG_PRINT("lock",("Free lock: data: 0x%lx  thread: 0x%lx  lock: 0x%lx",
 
1052
                         (long) *pos, (*pos)->owner->info->thread_id,
 
1053
                         (long) (*pos)->lock));
 
1054
    }
1002
1055
  }
1003
 
  return;
 
1056
  DBUG_VOID_RETURN;
1004
1057
}
1005
1058
 
1006
1059
/*
1008
1061
  TL_WRITE_ONLY to abort any new accesses to the lock
1009
1062
*/
1010
1063
 
1011
 
void thr_abort_locks(THR_LOCK *lock, bool upgrade_lock)
 
1064
void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock)
1012
1065
{
1013
1066
  THR_LOCK_DATA *data;
 
1067
  DBUG_ENTER("thr_abort_locks");
1014
1068
  pthread_mutex_lock(&lock->mutex);
1015
1069
 
1016
1070
  for (data=lock->read_wait.data; data ; data=data->next)
1032
1086
  if (upgrade_lock && lock->write.data)
1033
1087
    lock->write.data->type=TL_WRITE_ONLY;
1034
1088
  pthread_mutex_unlock(&lock->mutex);
1035
 
  return;
 
1089
  DBUG_VOID_RETURN;
1036
1090
}
1037
1091
 
1038
1092
 
1042
1096
  This is used to abort all locks for a specific thread
1043
1097
*/
1044
1098
 
1045
 
bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id)
 
1099
my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id)
1046
1100
{
1047
1101
  THR_LOCK_DATA *data;
1048
 
  bool found= false;
 
1102
  my_bool found= FALSE;
 
1103
  DBUG_ENTER("thr_abort_locks_for_thread");
1049
1104
 
1050
1105
  pthread_mutex_lock(&lock->mutex);
1051
1106
  for (data= lock->read_wait.data; data ; data= data->next)
1052
1107
  {
1053
1108
    if (data->owner->info->thread_id == thread_id)    /* purecov: tested */
1054
1109
    {
 
1110
      DBUG_PRINT("info",("Aborting read-wait lock"));
1055
1111
      data->type= TL_UNLOCK;                    /* Mark killed */
1056
1112
      /* It's safe to signal the cond first: we're still holding the mutex. */
1057
 
      found= true;
 
1113
      found= TRUE;
1058
1114
      pthread_cond_signal(data->cond);
1059
1115
      data->cond= 0;                            /* Removed from list */
1060
1116
 
1068
1124
  {
1069
1125
    if (data->owner->info->thread_id == thread_id) /* purecov: tested */
1070
1126
    {
 
1127
      DBUG_PRINT("info",("Aborting write-wait lock"));
1071
1128
      data->type= TL_UNLOCK;
1072
 
      found= true;
 
1129
      found= TRUE;
1073
1130
      pthread_cond_signal(data->cond);
1074
1131
      data->cond= 0;
1075
1132
 
1081
1138
  }
1082
1139
  wake_up_waiters(lock);
1083
1140
  pthread_mutex_unlock(&lock->mutex);
1084
 
  return(found);
 
1141
  DBUG_RETURN(found);
1085
1142
}
1086
1143
 
1087
1144
 
1119
1176
                              enum thr_lock_type new_lock_type)
1120
1177
{
1121
1178
  THR_LOCK *lock=in_data->lock;
 
1179
#ifndef DBUG_OFF
 
1180
  enum thr_lock_type old_lock_type= in_data->type;
 
1181
#endif
 
1182
  DBUG_ENTER("thr_downgrade_write_only_lock");
1122
1183
 
1123
1184
  pthread_mutex_lock(&lock->mutex);
 
1185
  DBUG_ASSERT(old_lock_type == TL_WRITE_ONLY);
 
1186
  DBUG_ASSERT(old_lock_type > new_lock_type);
1124
1187
  in_data->type= new_lock_type;
1125
1188
  check_locks(lock,"after downgrading lock",0);
1126
1189
 
1127
1190
  pthread_mutex_unlock(&lock->mutex);
1128
 
  return;
 
1191
  DBUG_VOID_RETURN;
1129
1192
}
1130
1193
 
1131
1194
/* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */
1132
1195
 
1133
 
bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
 
1196
my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
1134
1197
{
1135
1198
  THR_LOCK *lock=data->lock;
 
1199
  DBUG_ENTER("thr_upgrade_write_delay_lock");
1136
1200
 
1137
1201
  pthread_mutex_lock(&lock->mutex);
1138
1202
  if (data->type == TL_UNLOCK || data->type >= TL_WRITE_LOW_PRIORITY)
1139
1203
  {
1140
1204
    pthread_mutex_unlock(&lock->mutex);
1141
 
    return(data->type == TL_UNLOCK);    /* Test if Aborted */
 
1205
    DBUG_RETURN(data->type == TL_UNLOCK);       /* Test if Aborted */
1142
1206
  }
1143
1207
  check_locks(lock,"before upgrading lock",0);
1144
1208
  /* TODO:  Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */
1152
1216
      if (data->lock->get_status)
1153
1217
        (*data->lock->get_status)(data->status_param, 0);
1154
1218
      pthread_mutex_unlock(&lock->mutex);
1155
 
      return(0);
 
1219
      DBUG_RETURN(0);
1156
1220
    }
1157
1221
 
1158
1222
    if (((*data->prev)=data->next))             /* remove from lock-list */
1172
1236
  {
1173
1237
    check_locks(lock,"waiting for lock",0);
1174
1238
  }
1175
 
  return(wait_for_lock(&lock->write_wait,data,1));
 
1239
  DBUG_RETURN(wait_for_lock(&lock->write_wait,data,1));
1176
1240
}
1177
1241
 
1178
1242
 
1179
1243
/* downgrade a WRITE lock to a WRITE_DELAY lock if there is pending locks */
1180
1244
 
1181
 
bool thr_reschedule_write_lock(THR_LOCK_DATA *data)
 
1245
my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data)
1182
1246
{
1183
1247
  THR_LOCK *lock=data->lock;
 
1248
  DBUG_ENTER("thr_reschedule_write_lock");
1184
1249
 
1185
1250
  pthread_mutex_lock(&lock->mutex);
1186
1251
  if (!lock->read_wait.data)                    /* No waiting read locks */
1187
1252
  {
1188
1253
    pthread_mutex_unlock(&lock->mutex);
1189
 
    return(0);
 
1254
    DBUG_RETURN(0);
1190
1255
  }
1191
1256
 
1192
1257
  data->type=TL_WRITE_DELAYED;
1207
1272
  free_all_read_locks(lock,0);
1208
1273
 
1209
1274
  pthread_mutex_unlock(&lock->mutex);
1210
 
  return(thr_upgrade_write_delay_lock(data));
 
1275
  DBUG_RETURN(thr_upgrade_write_delay_lock(data));
1211
1276
}
1212
1277
 
1213
1278
 
1214
1279
#include <my_sys.h>
1215
1280
 
 
1281
static void thr_print_lock(const char* name,struct st_lock_list *list)
 
1282
{
 
1283
  THR_LOCK_DATA *data,**prev;
 
1284
  uint count=0;
 
1285
 
 
1286
  if (list->data)
 
1287
  {
 
1288
    printf("%-10s: ",name);
 
1289
    prev= &list->data;
 
1290
    for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
 
1291
    {
 
1292
      printf("0x%lx (%lu:%d); ", (ulong) data, data->owner->info->thread_id,
 
1293
             (int) data->type);
 
1294
      if (data->prev != prev)
 
1295
        printf("\nWarning: prev didn't point at previous lock\n");
 
1296
      prev= &data->next;
 
1297
    }
 
1298
    puts("");
 
1299
    if (prev != list->last)
 
1300
      printf("Warning: last didn't point at last lock\n");
 
1301
  }
 
1302
}
 
1303
 
 
1304
void thr_print_locks(void)
 
1305
{
 
1306
  LIST *list;
 
1307
  uint count=0;
 
1308
 
 
1309
  pthread_mutex_lock(&THR_LOCK_lock);
 
1310
  puts("Current locks:");
 
1311
  for (list= thr_lock_thread_list; list && count++ < MAX_THREADS;
 
1312
       list= list_rest(list))
 
1313
  {
 
1314
    THR_LOCK *lock=(THR_LOCK*) list->data;
 
1315
    VOID(pthread_mutex_lock(&lock->mutex));
 
1316
    printf("lock: 0x%lx:",(ulong) lock);
 
1317
    if ((lock->write_wait.data || lock->read_wait.data) &&
 
1318
        (! lock->read.data && ! lock->write.data))
 
1319
      printf(" WARNING: ");
 
1320
    if (lock->write.data)
 
1321
      printf(" write");
 
1322
    if (lock->write_wait.data)
 
1323
      printf(" write_wait");
 
1324
    if (lock->read.data)
 
1325
      printf(" read");
 
1326
    if (lock->read_wait.data)
 
1327
      printf(" read_wait");
 
1328
    puts("");
 
1329
    thr_print_lock("write",&lock->write);
 
1330
    thr_print_lock("write_wait",&lock->write_wait);
 
1331
    thr_print_lock("read",&lock->read);
 
1332
    thr_print_lock("read_wait",&lock->read_wait);
 
1333
    VOID(pthread_mutex_unlock(&lock->mutex));
 
1334
    puts("");
 
1335
  }
 
1336
  fflush(stdout);
 
1337
  pthread_mutex_unlock(&THR_LOCK_lock);
 
1338
}
 
1339
 
1216
1340
/*****************************************************************************
1217
1341
** Test of thread locks
1218
1342
****************************************************************************/
1220
1344
#ifdef MAIN
1221
1345
 
1222
1346
struct st_test {
1223
 
  uint32_t lock_nr;
 
1347
  uint lock_nr;
1224
1348
  enum thr_lock_type lock_type;
1225
1349
};
1226
1350
 
1269
1393
 
1270
1394
static pthread_cond_t COND_thread_count;
1271
1395
static pthread_mutex_t LOCK_thread_count;
1272
 
static uint32_t thread_count;
1273
 
static uint32_t sum=0;
 
1396
static uint thread_count;
 
1397
static ulong sum=0;
1274
1398
 
1275
1399
#define MAX_LOCK_COUNT 8
1276
1400
 
1290
1414
{
1291
1415
}
1292
1416
 
1293
 
static bool test_check_status(void* param __attribute__((unused)))
 
1417
static my_bool test_check_status(void* param __attribute__((unused)))
1294
1418
{
1295
1419
  return 0;
1296
1420
}
1329
1453
        sleep(2);
1330
1454
      else
1331
1455
      {
1332
 
        uint32_t k;
1333
 
        for (k=0 ; k < (uint32_t) (tmp-2)*100000L ; k++)
 
1456
        ulong k;
 
1457
        for (k=0 ; k < (ulong) (tmp-2)*100000L ; k++)
1334
1458
          sum+=k;
1335
1459
      }
1336
1460
    }
1342
1466
  thr_print_locks();
1343
1467
  pthread_mutex_lock(&LOCK_thread_count);
1344
1468
  thread_count--;
1345
 
  pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */
 
1469
  VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
1346
1470
  pthread_mutex_unlock(&LOCK_thread_count);
1347
 
  free((unsigned char*) arg);
 
1471
  free((uchar*) arg);
1348
1472
  return 0;
1349
1473
}
1350
1474
 
1355
1479
  pthread_attr_t thr_attr;
1356
1480
  int i,*param,error;
1357
1481
  MY_INIT(argv[0]);
 
1482
  if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#')
 
1483
    DBUG_PUSH(argv[1]+2);
1358
1484
 
1359
1485
  printf("Main thread: %s\n",my_thread_name());
1360
1486
 
1401
1527
  }
1402
1528
#endif
1403
1529
#ifdef HAVE_THR_SETCONCURRENCY
1404
 
  thr_setconcurrency(2);
 
1530
  VOID(thr_setconcurrency(2));
1405
1531
#endif
1406
1532
  for (i=0 ; i < (int) array_elements(lock_counts) ; i++)
1407
1533
  {