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>
79
#if TIME_WITH_SYS_TIME
80
# include <sys/time.h>
84
# include <sys/time.h>
90
#include <drizzled/util/test.h>
83
92
bool thr_lock_inited=0;
84
ulong locks_immediate = 0L, locks_waited = 0L;
93
uint32_t locks_immediate = 0L, locks_waited = 0L;
85
94
ulong table_lock_wait_timeout;
86
95
enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE;
114
123
return rhs == lhs;
118
126
#ifdef EXTRA_DEBUG
119
127
#define MAX_FOUND_ERRORS 10 /* Report 10 first errors */
120
static uint found_errors=0;
128
static uint32_t found_errors=0;
122
130
static int check_lock(struct st_lock_list *list, const char* lock_type,
123
131
const char *where, bool same_owner, bool no_cond)
125
133
THR_LOCK_DATA *data,**prev;
127
135
THR_LOCK_OWNER *first_owner;
129
137
prev= &list->data;
182
190
static void check_locks(THR_LOCK *lock, const char *where,
183
191
bool allow_no_locks)
185
uint old_found_errors=found_errors;
186
DBUG_ENTER("check_locks");
193
uint32_t old_found_errors=found_errors;
188
195
if (found_errors < MAX_FOUND_ERRORS)
196
203
if (found_errors < MAX_FOUND_ERRORS)
199
206
THR_LOCK_DATA *data;
200
207
for (data=lock->read.data ; data ; data=data->next)
202
209
if ((int) data->type == (int) TL_READ_NO_INSERT)
204
211
/* Protect against infinite loop. */
205
DBUG_ASSERT(count <= lock->read_no_write_count);
212
assert(count <= lock->read_no_write_count);
207
214
if (count != lock->read_no_write_count)
276
283
"Warning at '%s': Found lock of type %d that is write and read locked\n",
277
284
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
287
if (lock->read_wait.data)
313
313
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));
315
memset(lock, 0, sizeof(*lock));
316
pthread_mutex_init(&lock->mutex,MY_MUTEX_INIT_FAST);
318
317
lock->read.last= &lock->read.data;
319
318
lock->read_wait.last= &lock->read_wait.data;
320
319
lock->write_wait.last= &lock->write_wait.data;
324
323
lock->list.data=(void*) lock;
325
324
thr_lock_thread_list=list_add(thr_lock_thread_list,&lock->list);
326
325
pthread_mutex_unlock(&THR_LOCK_lock);
331
330
void thr_lock_delete(THR_LOCK *lock)
333
DBUG_ENTER("thr_lock_delete");
334
VOID(pthread_mutex_destroy(&lock->mutex));
332
pthread_mutex_destroy(&lock->mutex);
335
333
pthread_mutex_lock(&THR_LOCK_lock);
336
334
thr_lock_thread_list=list_delete(thr_lock_thread_list,&lock->list);
337
335
pthread_mutex_unlock(&THR_LOCK_lock);
434
431
if (data->cond == 0)
436
DBUG_PRINT("thr_lock", ("lock granted/aborted"));
439
435
if (rc == ETIMEDOUT || rc == ETIME)
441
437
/* purecov: begin inspected */
442
DBUG_PRINT("thr_lock", ("lock timed out"));
443
438
result= THR_LOCK_WAIT_TIMEOUT;
445
440
/* purecov: end */
448
DBUG_PRINT("thr_lock", ("aborted: %d in_wait_list: %d",
449
thread_var->abort, in_wait_list));
451
443
if (data->cond || data->type == TL_UNLOCK)
453
445
if (data->cond) /* aborted or timed out */
492
483
enum enum_thr_lock_result result= THR_LOCK_SUCCESS;
493
484
struct st_lock_list *wait_queue;
494
485
THR_LOCK_DATA *lock_owner;
495
DBUG_ENTER("thr_lock");
498
488
data->cond=0; /* safety */
499
489
data->type=lock_type;
500
490
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));
491
pthread_mutex_lock(&lock->mutex);
505
492
check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ?
506
493
"enter read_lock" : "enter write_lock",0);
507
494
if ((int) lock_type <= (int) TL_READ_NO_INSERT)
518
505
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
508
if (thr_lock_owner_equal(data->owner, lock->write.data->owner) ||
524
509
(lock->write.data->type <= TL_WRITE_DELAYED &&
525
510
(((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) ||
631
616
We have already got a write lock or all locks are
632
617
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
620
(*lock->write.last)=data; /* Add to running fifo */
639
621
data->prev=lock->write.last;
644
626
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
632
if (!lock->write_wait.data)
655
633
{ /* no scheduled write locks */
656
634
bool concurrent_insert= 0;
683
DBUG_PRINT("lock",("write locked 3 by thread: 0x%lx type: %d",
684
lock->read.data->owner->info->thread_id, data->type));
686
662
wait_queue= &lock->write_wait;
694
670
lock_owner= lock->read.data ? lock->read.data : lock->write.data;
695
671
if (lock_owner && lock_owner->owner->info == owner->info)
697
DBUG_PRINT("lock",("deadlock"));
698
673
result= THR_LOCK_DEADLOCK;
701
676
/* Can't get lock yet; Wait for it */
702
DBUG_RETURN(wait_for_lock(wait_queue, data, 0));
677
return(wait_for_lock(wait_queue, data, 0));
704
679
pthread_mutex_unlock(&lock->mutex);
744
719
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
721
data->cond=0; /* Mark thread free */
751
VOID(pthread_cond_signal(cond));
722
pthread_cond_signal(cond);
752
723
} while ((data=data->next));
753
724
*lock->read_wait.last=0;
754
725
if (!lock->read_wait.data)
763
734
THR_LOCK *lock=data->lock;
764
735
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
736
pthread_mutex_lock(&lock->mutex);
769
737
check_locks(lock,"start of release lock",0);
833
799
lock->write_lock_count=0;
834
800
if (lock->read_wait.data)
836
DBUG_PRINT("info",("Freeing all read_locks because of max_write_lock_count"));
837
802
free_all_read_locks(lock,0);
851
816
if (data->type == TL_WRITE_CONCURRENT_INSERT &&
852
817
(*lock->check_status)(data->status_param))
853
818
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
820
pthread_cond_t *cond=data->cond;
860
821
data->cond=0; /* Mark thread free */
861
VOID(pthread_cond_signal(cond)); /* Start waiting thread */
822
pthread_cond_signal(cond); /* Start waiting thread */
863
824
if (data->type != TL_WRITE_ALLOW_WRITE ||
864
825
!lock->write_wait.data ||
876
837
(data->type == TL_WRITE_CONCURRENT_INSERT ||
877
838
data->type == TL_WRITE_ALLOW_WRITE));
880
DBUG_PRINT("lock",("No waiting read locks to free"));
884
841
(lock_type=data->type) <= TL_WRITE_DELAYED &&
909
866
lock->write.last= &data->next;
910
867
data->next=0; /* Only one write lock */
911
868
data->cond=0; /* Mark thread free */
912
VOID(pthread_cond_signal(cond)); /* Start waiting thread */
869
pthread_cond_signal(cond); /* Start waiting thread */
913
870
} while (lock_type == TL_WRITE_ALLOW_WRITE &&
914
871
(data=lock->write_wait.data) &&
915
872
data->type == TL_WRITE_ALLOW_WRITE);
937
#define LOCK_CMP(A,B) ((uchar*) (A->lock) - (uint) ((A)->type) < (uchar*) (B->lock)- (uint) ((B)->type))
894
#define LOCK_CMP(A,B) ((unsigned char*) (A->lock) - (uint) ((A)->type) < (unsigned char*) (B->lock)- (uint) ((B)->type))
939
static void sort_locks(THR_LOCK_DATA **data,uint count)
896
static void sort_locks(THR_LOCK_DATA **data,uint32_t count)
941
898
THR_LOCK_DATA **pos,**end,**prev,*tmp;
960
917
enum enum_thr_lock_result
961
thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner)
918
thr_multi_lock(THR_LOCK_DATA **data, uint32_t count, THR_LOCK_OWNER *owner)
963
920
THR_LOCK_DATA **pos,**end;
964
DBUG_ENTER("thr_multi_lock");
965
DBUG_PRINT("lock",("data: 0x%lx count: %d", (long) data, count));
967
922
sort_locks(data,count);
968
923
/* lock everything */
972
927
if (result != THR_LOCK_SUCCESS)
974
929
thr_multi_unlock(data,(uint) (pos-data));
978
933
printf("Thread: %s Got lock: 0x%lx type: %d\n",my_thread_name(),
1026
981
} while (pos != data);
1029
DBUG_RETURN(THR_LOCK_SUCCESS);
984
return(THR_LOCK_SUCCESS);
1032
987
/* free all locks */
1034
void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
989
void thr_multi_unlock(THR_LOCK_DATA **data,uint32_t count)
1036
991
THR_LOCK_DATA **pos,**end;
1037
DBUG_ENTER("thr_multi_unlock");
1038
DBUG_PRINT("lock",("data: 0x%lx count: %d", (long) data, count));
1040
993
for (pos=data,end=data+count; pos < end ; pos++)
1047
1000
if ((*pos)->type != TL_UNLOCK)
1048
1001
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));
1064
1011
void thr_abort_locks(THR_LOCK *lock, bool upgrade_lock)
1066
1013
THR_LOCK_DATA *data;
1067
DBUG_ENTER("thr_abort_locks");
1068
1014
pthread_mutex_lock(&lock->mutex);
1070
1016
for (data=lock->read_wait.data; data ; data=data->next)
1101
1047
THR_LOCK_DATA *data;
1102
1048
bool found= false;
1103
DBUG_ENTER("thr_abort_locks_for_thread");
1105
1050
pthread_mutex_lock(&lock->mutex);
1106
1051
for (data= lock->read_wait.data; data ; data= data->next)
1108
1053
if (data->owner->info->thread_id == thread_id) /* purecov: tested */
1110
DBUG_PRINT("info",("Aborting read-wait lock"));
1111
1055
data->type= TL_UNLOCK; /* Mark killed */
1112
1056
/* It's safe to signal the cond first: we're still holding the mutex. */
1176
1119
enum thr_lock_type new_lock_type)
1178
1121
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
1123
pthread_mutex_lock(&lock->mutex);
1185
DBUG_ASSERT(old_lock_type == TL_WRITE_ONLY);
1186
DBUG_ASSERT(old_lock_type > new_lock_type);
1187
1124
in_data->type= new_lock_type;
1188
1125
check_locks(lock,"after downgrading lock",0);
1190
1127
pthread_mutex_unlock(&lock->mutex);
1194
1131
/* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */
1196
1133
bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
1198
1135
THR_LOCK *lock=data->lock;
1199
DBUG_ENTER("thr_upgrade_write_delay_lock");
1201
1137
pthread_mutex_lock(&lock->mutex);
1202
1138
if (data->type == TL_UNLOCK || data->type >= TL_WRITE_LOW_PRIORITY)
1204
1140
pthread_mutex_unlock(&lock->mutex);
1205
DBUG_RETURN(data->type == TL_UNLOCK); /* Test if Aborted */
1141
return(data->type == TL_UNLOCK); /* Test if Aborted */
1207
1143
check_locks(lock,"before upgrading lock",0);
1208
1144
/* TODO: Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */
1216
1152
if (data->lock->get_status)
1217
1153
(*data->lock->get_status)(data->status_param, 0);
1218
1154
pthread_mutex_unlock(&lock->mutex);
1222
1158
if (((*data->prev)=data->next)) /* remove from lock-list */
1237
1173
check_locks(lock,"waiting for lock",0);
1239
DBUG_RETURN(wait_for_lock(&lock->write_wait,data,1));
1175
return(wait_for_lock(&lock->write_wait,data,1));
1245
1181
bool thr_reschedule_write_lock(THR_LOCK_DATA *data)
1247
1183
THR_LOCK *lock=data->lock;
1248
DBUG_ENTER("thr_reschedule_write_lock");
1250
1185
pthread_mutex_lock(&lock->mutex);
1251
1186
if (!lock->read_wait.data) /* No waiting read locks */
1253
1188
pthread_mutex_unlock(&lock->mutex);
1257
1192
data->type=TL_WRITE_DELAYED;
1272
1207
free_all_read_locks(lock,0);
1274
1209
pthread_mutex_unlock(&lock->mutex);
1275
DBUG_RETURN(thr_upgrade_write_delay_lock(data));
1210
return(thr_upgrade_write_delay_lock(data));
1279
1214
#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
1216
/*****************************************************************************
1341
1217
** Test of thread locks
1342
1218
****************************************************************************/
1466
1342
thr_print_locks();
1467
1343
pthread_mutex_lock(&LOCK_thread_count);
1468
1344
thread_count--;
1469
VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
1345
pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */
1470
1346
pthread_mutex_unlock(&LOCK_thread_count);
1347
free((unsigned char*) arg);