73
#if !defined(MAIN) && !defined(DBUG_OFF) && !defined(EXTRA_DEBUG)
74
#define FORCE_DBUG_OFF
77
73
#include "mysys_priv.h"
79
75
#include "thr_lock.h"
76
#include <mystrings/m_string.h>
83
my_bool thr_lock_inited=0;
84
ulong locks_immediate = 0L, locks_waited = 0L;
79
bool thr_lock_inited=0;
80
uint32_t locks_immediate = 0L, locks_waited = 0L;
85
81
ulong table_lock_wait_timeout;
86
82
enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE;
102
98
** For the future (now the thread specific cond is alloced by my_pthread.c)
105
my_bool init_thr_lock()
107
103
thr_lock_inited=1;
111
static inline my_bool
112
108
thr_lock_owner_equal(THR_LOCK_OWNER *rhs, THR_LOCK_OWNER *lhs)
114
110
return rhs == lhs;
118
113
#ifdef EXTRA_DEBUG
119
114
#define MAX_FOUND_ERRORS 10 /* Report 10 first errors */
120
115
static uint found_errors=0;
122
117
static int check_lock(struct st_lock_list *list, const char* lock_type,
123
const char *where, my_bool same_owner, my_bool no_cond)
118
const char *where, bool same_owner, bool no_cond)
125
120
THR_LOCK_DATA *data,**prev;
182
177
static void check_locks(THR_LOCK *lock, const char *where,
183
my_bool allow_no_locks)
185
180
uint old_found_errors=found_errors;
186
DBUG_ENTER("check_locks");
188
182
if (found_errors < MAX_FOUND_ERRORS)
202
196
if ((int) data->type == (int) TL_READ_NO_INSERT)
204
198
/* Protect against infinite loop. */
205
DBUG_ASSERT(count <= lock->read_no_write_count);
199
assert(count <= lock->read_no_write_count);
207
201
if (count != lock->read_no_write_count)
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));
283
274
if (lock->read_wait.data)
313
300
void thr_lock_init(THR_LOCK *lock)
315
DBUG_ENTER("thr_lock_init");
316
bzero((char*) lock,sizeof(*lock));
317
VOID(pthread_mutex_init(&lock->mutex,MY_MUTEX_INIT_FAST));
302
memset(lock, 0, sizeof(*lock));
303
pthread_mutex_init(&lock->mutex,MY_MUTEX_INIT_FAST);
318
304
lock->read.last= &lock->read.data;
319
305
lock->read_wait.last= &lock->read_wait.data;
320
306
lock->write_wait.last= &lock->write_wait.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);
331
317
void thr_lock_delete(THR_LOCK *lock)
333
DBUG_ENTER("thr_lock_delete");
334
VOID(pthread_mutex_destroy(&lock->mutex));
319
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);
388
373
static enum enum_thr_lock_result
389
374
wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
390
my_bool in_wait_list)
392
377
struct st_my_thread_var *thread_var= my_thread_var;
393
378
pthread_cond_t *cond= &thread_var->suspend;
394
379
struct timespec wait_timeout;
395
380
enum enum_thr_lock_result result= THR_LOCK_ABORTED;
396
my_bool can_deadlock= test(data->owner->info->n_cursors);
397
DBUG_ENTER("wait_for_lock");
381
bool can_deadlock= test(data->owner->info->n_cursors);
399
383
if (!in_wait_list)
434
418
if (data->cond == 0)
436
DBUG_PRINT("thr_lock", ("lock granted/aborted"));
439
422
if (rc == ETIMEDOUT || rc == ETIME)
441
424
/* purecov: begin inspected */
442
DBUG_PRINT("thr_lock", ("lock timed out"));
443
425
result= THR_LOCK_WAIT_TIMEOUT;
445
427
/* purecov: end */
448
DBUG_PRINT("thr_lock", ("aborted: %d in_wait_list: %d",
449
thread_var->abort, in_wait_list));
451
430
if (data->cond || data->type == TL_UNLOCK)
453
432
if (data->cond) /* aborted or timed out */
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");
498
475
data->cond=0; /* safety */
499
476
data->type=lock_type;
500
477
data->owner= owner; /* Must be reset ! */
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));
478
pthread_mutex_lock(&lock->mutex);
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
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
634
DBUG_PRINT("info", ("write_wait.data: 0x%lx old_type: %d",
635
(ulong) lock->write_wait.data,
636
lock->write.data->type));
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);
647
DBUG_PRINT("lock",("write locked 2 by thread: 0x%lx",
648
lock->write.data->owner->info->thread_id));
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
my_bool concurrent_insert= 0;
621
bool concurrent_insert= 0;
657
622
if (lock_type == TL_WRITE_CONCURRENT_INSERT)
659
624
concurrent_insert= 1;
683
DBUG_PRINT("lock",("write locked 3 by thread: 0x%lx type: %d",
684
lock->read.data->owner->info->thread_id, data->type));
686
649
wait_queue= &lock->write_wait;
694
657
lock_owner= lock->read.data ? lock->read.data : lock->write.data;
695
658
if (lock_owner && lock_owner->owner->info == owner->info)
697
DBUG_PRINT("lock",("deadlock"));
698
660
result= THR_LOCK_DEADLOCK;
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));
704
666
pthread_mutex_unlock(&lock->mutex);
709
671
static inline void free_all_read_locks(THR_LOCK *lock,
710
my_bool using_concurrent_insert)
672
bool using_concurrent_insert)
712
674
THR_LOCK_DATA *data=lock->read_wait.data;
744
706
lock->read_no_write_count++;
746
/* purecov: begin inspected */
747
DBUG_PRINT("lock",("giving read lock to thread: 0x%lx",
748
data->owner->info->thread_id));
750
708
data->cond=0; /* Mark thread free */
751
VOID(pthread_cond_signal(cond));
709
pthread_cond_signal(cond);
752
710
} while ((data=data->next));
753
711
*lock->read_wait.last=0;
754
712
if (!lock->read_wait.data)
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);
833
786
lock->write_lock_count=0;
834
787
if (lock->read_wait.data)
836
DBUG_PRINT("info",("Freeing all read_locks because of max_write_lock_count"));
837
789
free_all_read_locks(lock,0);
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));
859
807
pthread_cond_t *cond=data->cond;
860
808
data->cond=0; /* Mark thread free */
861
VOID(pthread_cond_signal(cond)); /* Start waiting thread */
809
pthread_cond_signal(cond); /* Start waiting thread */
863
811
if (data->type != TL_WRITE_ALLOW_WRITE ||
864
812
!lock->write_wait.data ||
876
824
(data->type == TL_WRITE_CONCURRENT_INSERT ||
877
825
data->type == TL_WRITE_ALLOW_WRITE));
880
DBUG_PRINT("lock",("No waiting read locks to free"));
884
828
(lock_type=data->type) <= TL_WRITE_DELAYED &&
909
853
lock->write.last= &data->next;
910
854
data->next=0; /* Only one write lock */
911
855
data->cond=0; /* Mark thread free */
912
VOID(pthread_cond_signal(cond)); /* Start waiting thread */
856
pthread_cond_signal(cond); /* Start waiting thread */
913
857
} while (lock_type == TL_WRITE_ALLOW_WRITE &&
914
858
(data=lock->write_wait.data) &&
915
859
data->type == TL_WRITE_ALLOW_WRITE);
961
905
thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner)
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));
967
909
sort_locks(data,count);
968
910
/* lock everything */
972
914
if (result != THR_LOCK_SUCCESS)
974
916
thr_multi_unlock(data,(uint) (pos-data));
978
920
printf("Thread: %s Got lock: 0x%lx type: %d\n",my_thread_name(),
1034
976
void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
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));
1040
980
for (pos=data,end=data+count; pos < end ; pos++)
1047
987
if ((*pos)->type != TL_UNLOCK)
1048
988
thr_unlock(*pos);
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));
1061
995
TL_WRITE_ONLY to abort any new accesses to the lock
1064
void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock)
998
void thr_abort_locks(THR_LOCK *lock, bool upgrade_lock)
1066
1000
THR_LOCK_DATA *data;
1067
DBUG_ENTER("thr_abort_locks");
1068
1001
pthread_mutex_lock(&lock->mutex);
1070
1003
for (data=lock->read_wait.data; data ; data=data->next)
1096
1029
This is used to abort all locks for a specific thread
1099
my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id)
1032
bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id)
1101
1034
THR_LOCK_DATA *data;
1102
my_bool found= FALSE;
1103
DBUG_ENTER("thr_abort_locks_for_thread");
1105
1037
pthread_mutex_lock(&lock->mutex);
1106
1038
for (data= lock->read_wait.data; data ; data= data->next)
1108
1040
if (data->owner->info->thread_id == thread_id) /* purecov: tested */
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. */
1114
1045
pthread_cond_signal(data->cond);
1115
1046
data->cond= 0; /* Removed from list */
1176
1106
enum thr_lock_type new_lock_type)
1178
1108
THR_LOCK *lock=in_data->lock;
1180
enum thr_lock_type old_lock_type= in_data->type;
1182
DBUG_ENTER("thr_downgrade_write_only_lock");
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);
1190
1114
pthread_mutex_unlock(&lock->mutex);
1194
1118
/* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */
1196
my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
1120
bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
1198
1122
THR_LOCK *lock=data->lock;
1199
DBUG_ENTER("thr_upgrade_write_delay_lock");
1201
1124
pthread_mutex_lock(&lock->mutex);
1202
1125
if (data->type == TL_UNLOCK || data->type >= TL_WRITE_LOW_PRIORITY)
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 */
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);
1222
1145
if (((*data->prev)=data->next)) /* remove from lock-list */
1237
1160
check_locks(lock,"waiting for lock",0);
1239
DBUG_RETURN(wait_for_lock(&lock->write_wait,data,1));
1162
return(wait_for_lock(&lock->write_wait,data,1));
1243
1166
/* downgrade a WRITE lock to a WRITE_DELAY lock if there is pending locks */
1245
my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data)
1168
bool thr_reschedule_write_lock(THR_LOCK_DATA *data)
1247
1170
THR_LOCK *lock=data->lock;
1248
DBUG_ENTER("thr_reschedule_write_lock");
1250
1172
pthread_mutex_lock(&lock->mutex);
1251
1173
if (!lock->read_wait.data) /* No waiting read locks */
1253
1175
pthread_mutex_unlock(&lock->mutex);
1257
1179
data->type=TL_WRITE_DELAYED;
1272
1194
free_all_read_locks(lock,0);
1274
1196
pthread_mutex_unlock(&lock->mutex);
1275
DBUG_RETURN(thr_upgrade_write_delay_lock(data));
1197
return(thr_upgrade_write_delay_lock(data));
1279
1201
#include <my_sys.h>
1281
static void thr_print_lock(const char* name,struct st_lock_list *list)
1283
THR_LOCK_DATA *data,**prev;
1288
printf("%-10s: ",name);
1290
for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
1292
printf("0x%lx (%lu:%d); ", (ulong) data, data->owner->info->thread_id,
1294
if (data->prev != prev)
1295
printf("\nWarning: prev didn't point at previous lock\n");
1299
if (prev != list->last)
1300
printf("Warning: last didn't point at last lock\n");
1304
void thr_print_locks(void)
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))
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)
1322
if (lock->write_wait.data)
1323
printf(" write_wait");
1324
if (lock->read.data)
1326
if (lock->read_wait.data)
1327
printf(" read_wait");
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));
1337
pthread_mutex_unlock(&THR_LOCK_lock);
1340
1203
/*****************************************************************************
1341
1204
** Test of thread locks
1342
1205
****************************************************************************/
1466
1329
thr_print_locks();
1467
1330
pthread_mutex_lock(&LOCK_thread_count);
1468
1331
thread_count--;
1469
VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
1332
pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */
1470
1333
pthread_mutex_unlock(&LOCK_thread_count);
1471
1334
free((uchar*) arg);