~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/thr_lock.c

  • Committer: Brian Aker
  • Date: 2008-07-18 20:10:26 UTC
  • mfrom: (51.3.29 remove-dbug)
  • Revision ID: brian@tangent.org-20080718201026-tto5golt0xhwqe4a
Merging in Jay's final patch on dbug.

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
 
 
77
73
#include "mysys_priv.h"
78
74
 
79
75
#include "thr_lock.h"
114
110
  return rhs == lhs;
115
111
}
116
112
 
117
 
 
118
113
#ifdef EXTRA_DEBUG
119
114
#define MAX_FOUND_ERRORS        10              /* Report 10 first errors */
120
115
static uint found_errors=0;
183
178
                        bool allow_no_locks)
184
179
{
185
180
  uint old_found_errors=found_errors;
186
 
  DBUG_ENTER("check_locks");
187
181
 
188
182
  if (found_errors < MAX_FOUND_ERRORS)
189
183
  {
202
196
        if ((int) data->type == (int) TL_READ_NO_INSERT)
203
197
          count++;
204
198
        /* Protect against infinite loop. */
205
 
        DBUG_ASSERT(count <= lock->read_no_write_count);
 
199
        assert(count <= lock->read_no_write_count);
206
200
      }
207
201
      if (count != lock->read_no_write_count)
208
202
      {
275
269
            fprintf(stderr,
276
270
                    "Warning at '%s': Found lock of type %d that is write and read locked\n",
277
271
                    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
 
 
281
272
          }
282
273
        }
283
274
        if (lock->read_wait.data)
295
286
        }
296
287
      }
297
288
    }
298
 
    if (found_errors != old_found_errors)
299
 
    {
300
 
      DBUG_PRINT("error",("Found wrong lock"));
301
 
    }
302
289
  }
303
 
  DBUG_VOID_RETURN;
 
290
  return;
304
291
}
305
292
 
306
293
#else /* EXTRA_DEBUG */
312
299
 
313
300
void thr_lock_init(THR_LOCK *lock)
314
301
{
315
 
  DBUG_ENTER("thr_lock_init");
316
302
  bzero((char*) lock,sizeof(*lock));
317
303
  VOID(pthread_mutex_init(&lock->mutex,MY_MUTEX_INIT_FAST));
318
304
  lock->read.last= &lock->read.data;
324
310
  lock->list.data=(void*) lock;
325
311
  thr_lock_thread_list=list_add(thr_lock_thread_list,&lock->list);
326
312
  pthread_mutex_unlock(&THR_LOCK_lock);
327
 
  DBUG_VOID_RETURN;
 
313
  return;
328
314
}
329
315
 
330
316
 
331
317
void thr_lock_delete(THR_LOCK *lock)
332
318
{
333
 
  DBUG_ENTER("thr_lock_delete");
334
319
  VOID(pthread_mutex_destroy(&lock->mutex));
335
320
  pthread_mutex_lock(&THR_LOCK_lock);
336
321
  thr_lock_thread_list=list_delete(thr_lock_thread_list,&lock->list);
337
322
  pthread_mutex_unlock(&THR_LOCK_lock);
338
 
  DBUG_VOID_RETURN;
 
323
  return;
339
324
}
340
325
 
341
326
 
394
379
  struct timespec wait_timeout;
395
380
  enum enum_thr_lock_result result= THR_LOCK_ABORTED;
396
381
  bool can_deadlock= test(data->owner->info->n_cursors);
397
 
  DBUG_ENTER("wait_for_lock");
398
382
 
399
383
  if (!in_wait_list)
400
384
  {
433
417
    */
434
418
    if (data->cond == 0)
435
419
    {
436
 
      DBUG_PRINT("thr_lock", ("lock granted/aborted"));
437
420
      break;
438
421
    }
439
422
    if (rc == ETIMEDOUT || rc == ETIME)
440
423
    {
441
424
      /* purecov: begin inspected */
442
 
      DBUG_PRINT("thr_lock", ("lock timed out"));
443
425
      result= THR_LOCK_WAIT_TIMEOUT;
444
426
      break;
445
427
      /* purecov: end */
446
428
    }
447
429
  }
448
 
  DBUG_PRINT("thr_lock", ("aborted: %d  in_wait_list: %d",
449
 
                          thread_var->abort, in_wait_list));
450
 
 
451
430
  if (data->cond || data->type == TL_UNLOCK)
452
431
  {
453
432
    if (data->cond)                             /* aborted or timed out */
462
441
    }
463
442
    else
464
443
    {
465
 
      DBUG_PRINT("thr_lock", ("lock aborted"));
466
444
      check_locks(data->lock, "aborted wait_for_lock", 0);
467
445
    }
468
446
  }
480
458
  thread_var->current_mutex= 0;
481
459
  thread_var->current_cond=  0;
482
460
  pthread_mutex_unlock(&thread_var->mutex);
483
 
  DBUG_RETURN(result);
 
461
  return(result);
484
462
}
485
463
 
486
464
 
492
470
  enum enum_thr_lock_result result= THR_LOCK_SUCCESS;
493
471
  struct st_lock_list *wait_queue;
494
472
  THR_LOCK_DATA *lock_owner;
495
 
  DBUG_ENTER("thr_lock");
496
473
 
497
474
  data->next=0;
498
475
  data->cond=0;                                 /* safety */
499
476
  data->type=lock_type;
500
477
  data->owner= owner;                           /* Must be reset ! */
501
478
  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));
505
479
  check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ?
506
480
              "enter read_lock" : "enter write_lock",0);
507
481
  if ((int) lock_type <= (int) TL_READ_NO_INSERT)
518
492
           and the read lock is not TL_READ_NO_INSERT
519
493
      */
520
494
 
521
 
      DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx",
522
 
                         lock->write.data->owner->info->thread_id));
523
495
      if (thr_lock_owner_equal(data->owner, lock->write.data->owner) ||
524
496
          (lock->write.data->type <= TL_WRITE_DELAYED &&
525
497
           (((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) ||
631
603
          We have already got a write lock or all locks are
632
604
          TL_WRITE_ALLOW_WRITE
633
605
        */
634
 
        DBUG_PRINT("info", ("write_wait.data: 0x%lx  old_type: %d",
635
 
                            (ulong) lock->write_wait.data,
636
 
                            lock->write.data->type));
637
606
 
638
607
        (*lock->write.last)=data;       /* Add to running fifo */
639
608
        data->prev=lock->write.last;
644
613
        statistic_increment(locks_immediate,&THR_LOCK_lock);
645
614
        goto end;
646
615
      }
647
 
      DBUG_PRINT("lock",("write locked 2 by thread: 0x%lx",
648
 
                         lock->write.data->owner->info->thread_id));
649
616
    }
650
617
    else
651
618
    {
652
 
      DBUG_PRINT("info", ("write_wait.data: 0x%lx",
653
 
                          (ulong) lock->write_wait.data));
654
619
      if (!lock->write_wait.data)
655
620
      {                                         /* no scheduled write locks */
656
621
        bool concurrent_insert= 0;
680
645
          goto end;
681
646
        }
682
647
      }
683
 
      DBUG_PRINT("lock",("write locked 3 by thread: 0x%lx  type: %d",
684
 
                         lock->read.data->owner->info->thread_id, data->type));
685
648
    }
686
649
    wait_queue= &lock->write_wait;
687
650
  }
694
657
  lock_owner= lock->read.data ? lock->read.data : lock->write.data;
695
658
  if (lock_owner && lock_owner->owner->info == owner->info)
696
659
  {
697
 
    DBUG_PRINT("lock",("deadlock"));
698
660
    result= THR_LOCK_DEADLOCK;
699
661
    goto end;
700
662
  }
701
663
  /* Can't get lock yet;  Wait for it */
702
 
  DBUG_RETURN(wait_for_lock(wait_queue, data, 0));
 
664
  return(wait_for_lock(wait_queue, data, 0));
703
665
end:
704
666
  pthread_mutex_unlock(&lock->mutex);
705
 
  DBUG_RETURN(result);
 
667
  return(result);
706
668
}
707
669
 
708
670
 
743
705
      }
744
706
      lock->read_no_write_count++;
745
707
    }      
746
 
    /* purecov: begin inspected */
747
 
    DBUG_PRINT("lock",("giving read lock to thread: 0x%lx",
748
 
                       data->owner->info->thread_id));
749
 
    /* purecov: end */
750
708
    data->cond=0;                               /* Mark thread free */
751
709
    VOID(pthread_cond_signal(cond));
752
710
  } while ((data=data->next));
762
720
{
763
721
  THR_LOCK *lock=data->lock;
764
722
  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));
768
723
  pthread_mutex_lock(&lock->mutex);
769
724
  check_locks(lock,"start of release lock",0);
770
725
 
798
753
  check_locks(lock,"after releasing lock",1);
799
754
  wake_up_waiters(lock);
800
755
  pthread_mutex_unlock(&lock->mutex);
801
 
  DBUG_VOID_RETURN;
 
756
  return;
802
757
}
803
758
 
804
759
 
815
770
  THR_LOCK_DATA *data;
816
771
  enum thr_lock_type lock_type;
817
772
 
818
 
  DBUG_ENTER("wake_up_waiters");
819
 
 
820
773
  if (!lock->write.data)                        /* If no active write locks */
821
774
  {
822
775
    data=lock->write_wait.data;
833
786
          lock->write_lock_count=0;
834
787
          if (lock->read_wait.data)
835
788
          {
836
 
            DBUG_PRINT("info",("Freeing all read_locks because of max_write_lock_count"));
837
789
            free_all_read_locks(lock,0);
838
790
            goto end;
839
791
          }
851
803
          if (data->type == TL_WRITE_CONCURRENT_INSERT &&
852
804
              (*lock->check_status)(data->status_param))
853
805
            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 */
858
806
          {
859
807
            pthread_cond_t *cond=data->cond;
860
808
            data->cond=0;                               /* Mark thread free */
875
823
                            data &&
876
824
                            (data->type == TL_WRITE_CONCURRENT_INSERT ||
877
825
                             data->type == TL_WRITE_ALLOW_WRITE));
878
 
      else
879
 
      {
880
 
        DBUG_PRINT("lock",("No waiting read locks to free"));
881
 
      }
882
826
    }
883
827
    else if (data &&
884
828
             (lock_type=data->type) <= TL_WRITE_DELAYED &&
923
867
  }
924
868
end:
925
869
  check_locks(lock, "after waking up waiters", 0);
926
 
  DBUG_VOID_RETURN;
 
870
  return;
927
871
}
928
872
 
929
873
 
961
905
thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner)
962
906
{
963
907
  THR_LOCK_DATA **pos,**end;
964
 
  DBUG_ENTER("thr_multi_lock");
965
 
  DBUG_PRINT("lock",("data: 0x%lx  count: %d", (long) data, count));
966
908
  if (count > 1)
967
909
    sort_locks(data,count);
968
910
  /* lock everything */
972
914
    if (result != THR_LOCK_SUCCESS)
973
915
    {                                           /* Aborted */
974
916
      thr_multi_unlock(data,(uint) (pos-data));
975
 
      DBUG_RETURN(result);
 
917
      return(result);
976
918
    }
977
919
#ifdef MAIN
978
920
    printf("Thread: %s  Got lock: 0x%lx  type: %d\n",my_thread_name(),
1026
968
    } while (pos != data);
1027
969
  }
1028
970
#endif
1029
 
  DBUG_RETURN(THR_LOCK_SUCCESS);
 
971
  return(THR_LOCK_SUCCESS);
1030
972
}
1031
973
 
1032
974
  /* free all locks */
1034
976
void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
1035
977
{
1036
978
  THR_LOCK_DATA **pos,**end;
1037
 
  DBUG_ENTER("thr_multi_unlock");
1038
 
  DBUG_PRINT("lock",("data: 0x%lx  count: %d", (long) data, count));
1039
979
 
1040
980
  for (pos=data,end=data+count; pos < end ; pos++)
1041
981
  {
1046
986
#endif
1047
987
    if ((*pos)->type != TL_UNLOCK)
1048
988
      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
 
    }
1055
989
  }
1056
 
  DBUG_VOID_RETURN;
 
990
  return;
1057
991
}
1058
992
 
1059
993
/*
1064
998
void thr_abort_locks(THR_LOCK *lock, bool upgrade_lock)
1065
999
{
1066
1000
  THR_LOCK_DATA *data;
1067
 
  DBUG_ENTER("thr_abort_locks");
1068
1001
  pthread_mutex_lock(&lock->mutex);
1069
1002
 
1070
1003
  for (data=lock->read_wait.data; data ; data=data->next)
1086
1019
  if (upgrade_lock && lock->write.data)
1087
1020
    lock->write.data->type=TL_WRITE_ONLY;
1088
1021
  pthread_mutex_unlock(&lock->mutex);
1089
 
  DBUG_VOID_RETURN;
 
1022
  return;
1090
1023
}
1091
1024
 
1092
1025
 
1100
1033
{
1101
1034
  THR_LOCK_DATA *data;
1102
1035
  bool found= false;
1103
 
  DBUG_ENTER("thr_abort_locks_for_thread");
1104
1036
 
1105
1037
  pthread_mutex_lock(&lock->mutex);
1106
1038
  for (data= lock->read_wait.data; data ; data= data->next)
1107
1039
  {
1108
1040
    if (data->owner->info->thread_id == thread_id)    /* purecov: tested */
1109
1041
    {
1110
 
      DBUG_PRINT("info",("Aborting read-wait lock"));
1111
1042
      data->type= TL_UNLOCK;                    /* Mark killed */
1112
1043
      /* It's safe to signal the cond first: we're still holding the mutex. */
1113
1044
      found= true;
1124
1055
  {
1125
1056
    if (data->owner->info->thread_id == thread_id) /* purecov: tested */
1126
1057
    {
1127
 
      DBUG_PRINT("info",("Aborting write-wait lock"));
1128
1058
      data->type= TL_UNLOCK;
1129
1059
      found= true;
1130
1060
      pthread_cond_signal(data->cond);
1138
1068
  }
1139
1069
  wake_up_waiters(lock);
1140
1070
  pthread_mutex_unlock(&lock->mutex);
1141
 
  DBUG_RETURN(found);
 
1071
  return(found);
1142
1072
}
1143
1073
 
1144
1074
 
1176
1106
                              enum thr_lock_type new_lock_type)
1177
1107
{
1178
1108
  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");
1183
1109
 
1184
1110
  pthread_mutex_lock(&lock->mutex);
1185
 
  DBUG_ASSERT(old_lock_type == TL_WRITE_ONLY);
1186
 
  DBUG_ASSERT(old_lock_type > new_lock_type);
1187
1111
  in_data->type= new_lock_type;
1188
1112
  check_locks(lock,"after downgrading lock",0);
1189
1113
 
1190
1114
  pthread_mutex_unlock(&lock->mutex);
1191
 
  DBUG_VOID_RETURN;
 
1115
  return;
1192
1116
}
1193
1117
 
1194
1118
/* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */
1196
1120
bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
1197
1121
{
1198
1122
  THR_LOCK *lock=data->lock;
1199
 
  DBUG_ENTER("thr_upgrade_write_delay_lock");
1200
1123
 
1201
1124
  pthread_mutex_lock(&lock->mutex);
1202
1125
  if (data->type == TL_UNLOCK || data->type >= TL_WRITE_LOW_PRIORITY)
1203
1126
  {
1204
1127
    pthread_mutex_unlock(&lock->mutex);
1205
 
    DBUG_RETURN(data->type == TL_UNLOCK);       /* Test if Aborted */
 
1128
    return(data->type == TL_UNLOCK);    /* Test if Aborted */
1206
1129
  }
1207
1130
  check_locks(lock,"before upgrading lock",0);
1208
1131
  /* TODO:  Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */
1216
1139
      if (data->lock->get_status)
1217
1140
        (*data->lock->get_status)(data->status_param, 0);
1218
1141
      pthread_mutex_unlock(&lock->mutex);
1219
 
      DBUG_RETURN(0);
 
1142
      return(0);
1220
1143
    }
1221
1144
 
1222
1145
    if (((*data->prev)=data->next))             /* remove from lock-list */
1236
1159
  {
1237
1160
    check_locks(lock,"waiting for lock",0);
1238
1161
  }
1239
 
  DBUG_RETURN(wait_for_lock(&lock->write_wait,data,1));
 
1162
  return(wait_for_lock(&lock->write_wait,data,1));
1240
1163
}
1241
1164
 
1242
1165
 
1245
1168
bool thr_reschedule_write_lock(THR_LOCK_DATA *data)
1246
1169
{
1247
1170
  THR_LOCK *lock=data->lock;
1248
 
  DBUG_ENTER("thr_reschedule_write_lock");
1249
1171
 
1250
1172
  pthread_mutex_lock(&lock->mutex);
1251
1173
  if (!lock->read_wait.data)                    /* No waiting read locks */
1252
1174
  {
1253
1175
    pthread_mutex_unlock(&lock->mutex);
1254
 
    DBUG_RETURN(0);
 
1176
    return(0);
1255
1177
  }
1256
1178
 
1257
1179
  data->type=TL_WRITE_DELAYED;
1272
1194
  free_all_read_locks(lock,0);
1273
1195
 
1274
1196
  pthread_mutex_unlock(&lock->mutex);
1275
 
  DBUG_RETURN(thr_upgrade_write_delay_lock(data));
 
1197
  return(thr_upgrade_write_delay_lock(data));
1276
1198
}
1277
1199
 
1278
1200
 
1479
1401
  pthread_attr_t thr_attr;
1480
1402
  int i,*param,error;
1481
1403
  MY_INIT(argv[0]);
1482
 
  if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#')
1483
 
    DBUG_PUSH(argv[1]+2);
1484
1404
 
1485
1405
  printf("Main thread: %s\n",my_thread_name());
1486
1406