~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/sync/sync0sync.c

  • Committer: Brian Aker
  • Date: 2008-11-04 15:39:09 UTC
  • mfrom: (575.1.2 devel)
  • Revision ID: brian@tangent.org-20081104153909-c72hn65udxs1ccal
Merge of Monty's work

Show diffs side-by-side

added added

removed removed

Lines of Context:
95
95
it and did not see the waiters byte set to 1, a case which would lead the
96
96
other thread to an infinite wait.
97
97
 
98
 
LEMMA 1: After a thread resets the event of the cell it reserves for waiting
99
 
========
100
 
for a mutex, some thread will eventually call sync_array_signal_object with
101
 
the mutex as an argument. Thus no infinite wait is possible.
 
98
LEMMA 1: After a thread resets the event of a mutex (or rw_lock), some
 
99
=======
 
100
thread will eventually call os_event_set() on that particular event.
 
101
Thus no infinite wait is possible in this case.
102
102
 
103
103
Proof:  After making the reservation the thread sets the waiters field in the
104
104
mutex to 1. Then it checks that the mutex is still reserved by some thread,
105
105
or it reserves the mutex for itself. In any case, some thread (which may be
106
106
also some earlier thread, not necessarily the one currently holding the mutex)
107
107
will set the waiters field to 0 in mutex_exit, and then call
108
 
sync_array_signal_object with the mutex as an argument.
 
108
os_event_set() with the mutex as an argument.
 
109
Q.E.D.
 
110
 
 
111
LEMMA 2: If an os_event_set() call is made after some thread has called
 
112
=======
 
113
the os_event_reset() and before it starts wait on that event, the call
 
114
will not be lost to the second thread. This is true even if there is an
 
115
intervening call to os_event_reset() by another thread.
 
116
Thus no infinite wait is possible in this case.
 
117
 
 
118
Proof (non-windows platforms): os_event_reset() returns a monotonically
 
119
increasing value of signal_count. This value is increased at every
 
120
call of os_event_set() If thread A has called os_event_reset() followed
 
121
by thread B calling os_event_set() and then some other thread C calling
 
122
os_event_reset(), the is_set flag of the event will be set to FALSE;
 
123
but now if thread A calls os_event_wait_low() with the signal_count
 
124
value returned from the earlier call of os_event_reset(), it will
 
125
return immediately without waiting.
 
126
Q.E.D.
 
127
 
 
128
Proof (windows): If there is a writer thread which is forced to wait for
 
129
the lock, it may be able to set the state of rw_lock to RW_LOCK_WAIT_EX
 
130
The design of rw_lock ensures that there is one and only one thread
 
131
that is able to change the state to RW_LOCK_WAIT_EX and this thread is
 
132
guaranteed to acquire the lock after it is released by the current
 
133
holders and before any other waiter gets the lock.
 
134
On windows this thread waits on a separate event i.e.: wait_ex_event.
 
135
Since only one thread can wait on this event there is no chance
 
136
of this event getting reset before the writer starts wait on it.
 
137
Therefore, this thread is guaranteed to catch the os_set_event()
 
138
signalled unconditionally at the release of the lock.
109
139
Q.E.D. */
110
140
 
111
141
/* The number of system calls made in this module. Intended for performance
112
142
monitoring. */
113
143
 
114
 
ulint   mutex_system_call_count         = 0;
 
144
UNIV_INTERN ulint       mutex_system_call_count         = 0;
115
145
 
116
146
/* Number of spin waits on mutexes: for performance monitoring */
117
147
 
118
148
/* round=one iteration of a spin loop */
119
 
ulint   mutex_spin_round_count          = 0;
120
 
ulint   mutex_spin_wait_count           = 0;
121
 
ulint   mutex_os_wait_count             = 0;
122
 
ulint   mutex_exit_count                = 0;
 
149
UNIV_INTERN ulint       mutex_spin_round_count          = 0;
 
150
UNIV_INTERN ulint       mutex_spin_wait_count           = 0;
 
151
UNIV_INTERN ulint       mutex_os_wait_count             = 0;
 
152
UNIV_INTERN ulint       mutex_exit_count                = 0;
123
153
 
124
154
/* The global array of wait cells for implementation of the database's own
125
155
mutexes and read-write locks */
126
 
sync_array_t*   sync_primary_wait_array;
 
156
UNIV_INTERN sync_array_t*       sync_primary_wait_array;
127
157
 
128
158
/* This variable is set to TRUE when sync_init is called */
129
 
ibool   sync_initialized        = FALSE;
 
159
UNIV_INTERN ibool       sync_initialized        = FALSE;
130
160
 
131
161
 
132
162
typedef struct sync_level_struct        sync_level_t;
136
166
/* The latch levels currently owned by threads are stored in this data
137
167
structure; the size of this array is OS_THREAD_MAX_N */
138
168
 
139
 
sync_thread_t*  sync_thread_level_arrays;
 
169
UNIV_INTERN sync_thread_t*      sync_thread_level_arrays;
140
170
 
141
171
/* Mutex protecting sync_thread_level_arrays */
142
 
mutex_t sync_thread_mutex;
 
172
UNIV_INTERN mutex_t             sync_thread_mutex;
143
173
#endif /* UNIV_SYNC_DEBUG */
144
174
 
145
175
/* Global list of database mutexes (not OS mutexes) created. */
146
 
ut_list_base_node_t  mutex_list;
 
176
UNIV_INTERN ut_list_base_node_t  mutex_list;
147
177
 
148
178
/* Mutex protecting the mutex_list variable */
149
 
mutex_t mutex_list_mutex;
 
179
UNIV_INTERN mutex_t mutex_list_mutex;
150
180
 
151
181
#ifdef UNIV_SYNC_DEBUG
152
182
/* Latching order checks start when this is set TRUE */
153
 
ibool   sync_order_checks_on    = FALSE;
 
183
UNIV_INTERN ibool       sync_order_checks_on    = FALSE;
154
184
#endif /* UNIV_SYNC_DEBUG */
155
185
 
156
186
struct sync_thread_struct{
169
199
};
170
200
 
171
201
/**********************************************************************
172
 
A noninlined function that reserves a mutex. In ha_innodb.cc we have disabled
173
 
inlining of InnoDB functions, and no inlined functions should be called from
174
 
there. That is why we need to duplicate the inlined function here. */
175
 
 
176
 
void
177
 
mutex_enter_noninline(
178
 
/*==================*/
179
 
        mutex_t*        mutex)  /* in: mutex */
180
 
{
181
 
        mutex_enter(mutex);
182
 
}
183
 
 
184
 
/**********************************************************************
185
 
Releases a mutex. */
186
 
 
187
 
void
188
 
mutex_exit_noninline(
189
 
/*=================*/
190
 
        mutex_t*        mutex)  /* in: mutex */
191
 
{
192
 
        mutex_exit(mutex);
193
 
}
194
 
 
195
 
/**********************************************************************
196
202
Creates, or rather, initializes a mutex object in a specified memory
197
203
location (which must be appropriately aligned). The mutex is initialized
198
204
in the reset state. Explicit freeing of the mutex with mutex_free is
199
205
necessary only if the memory block containing it is freed. */
200
 
 
 
206
UNIV_INTERN
201
207
void
202
208
mutex_create_func(
203
209
/*==============*/
217
223
        os_fast_mutex_init(&(mutex->os_fast_mutex));
218
224
        mutex->lock_word = 0;
219
225
#endif
 
226
        mutex->event = os_event_create(NULL);
220
227
        mutex_set_waiters(mutex, 0);
221
228
#ifdef UNIV_DEBUG
222
229
        mutex->magic_n = MUTEX_MAGIC_N;
270
277
Calling this function is obligatory only if the memory buffer containing
271
278
the mutex is freed. Removes a mutex object from the mutex list. The mutex
272
279
is checked to be in the reset state. */
273
 
 
 
280
UNIV_INTERN
274
281
void
275
282
mutex_free(
276
283
/*=======*/
300
307
                mutex_exit(&mutex_list_mutex);
301
308
        }
302
309
 
 
310
        os_event_free(mutex->event);
 
311
 
303
312
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
304
313
        os_fast_mutex_free(&(mutex->os_fast_mutex));
305
314
#endif
315
324
NOTE! Use the corresponding macro in the header file, not this function
316
325
directly. Tries to lock the mutex for the current thread. If the lock is not
317
326
acquired immediately, returns with return value 1. */
318
 
 
 
327
UNIV_INTERN
319
328
ulint
320
329
mutex_enter_nowait_func(
321
330
/*====================*/
345
354
#ifdef UNIV_DEBUG
346
355
/**********************************************************************
347
356
Checks that the mutex has been initialized. */
348
 
 
 
357
UNIV_INTERN
349
358
ibool
350
359
mutex_validate(
351
360
/*===========*/
360
369
/**********************************************************************
361
370
Checks that the current thread owns the mutex. Works only in the debug
362
371
version. */
363
 
 
 
372
UNIV_INTERN
364
373
ibool
365
374
mutex_own(
366
375
/*======*/
376
385
 
377
386
/**********************************************************************
378
387
Sets the waiters field in a mutex. */
379
 
 
 
388
UNIV_INTERN
380
389
void
381
390
mutex_set_waiters(
382
391
/*==============*/
397
406
Reserves a mutex for the current thread. If the mutex is reserved, the
398
407
function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
399
408
for the mutex before suspending the thread. */
400
 
 
 
409
UNIV_INTERN
401
410
void
402
411
mutex_spin_wait(
403
412
/*============*/
409
418
        ulint      index; /* index of the reserved wait cell */
410
419
        ulint      i;     /* spin round count */
411
420
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
412
 
        ib_longlong lstart_time = 0, lfinish_time; /* for timing os_wait */
 
421
        ib_int64_t lstart_time = 0, lfinish_time; /* for timing os_wait */
413
422
        ulint ltime_diff;
414
423
        ulint sec;
415
424
        ulint ms;
446
455
                mutex->count_os_yield++;
447
456
                if (timed_mutexes == 1 && timer_started==0) {
448
457
                        ut_usectime(&sec, &ms);
449
 
                        lstart_time= (ib_longlong)sec * 1000000 + ms;
 
458
                        lstart_time= (ib_int64_t)sec * 1000000 + ms;
450
459
                        timer_started = 1;
451
460
                }
452
461
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
509
518
                if (mutex_test_and_set(mutex) == 0) {
510
519
                        /* Succeeded! Free the reserved wait cell */
511
520
 
512
 
                        sync_array_free_cell_protected(sync_primary_wait_array,
513
 
                                                       index);
 
521
                        sync_array_free_cell(sync_primary_wait_array, index);
514
522
 
515
523
                        ut_d(mutex->thread_id = os_thread_get_curr_id());
516
524
#ifdef UNIV_SYNC_DEBUG
553
561
 
554
562
        if (timed_mutexes == 1 && timer_started==0) {
555
563
                ut_usectime(&sec, &ms);
556
 
                lstart_time= (ib_longlong)sec * 1000000 + ms;
 
564
                lstart_time= (ib_int64_t)sec * 1000000 + ms;
557
565
                timer_started = 1;
558
566
        }
559
567
# endif /* UNIV_DEBUG */
566
574
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
567
575
        if (timed_mutexes == 1 && timer_started==1) {
568
576
                ut_usectime(&sec, &ms);
569
 
                lfinish_time= (ib_longlong)sec * 1000000 + ms;
 
577
                lfinish_time= (ib_int64_t)sec * 1000000 + ms;
570
578
 
571
579
                ltime_diff= (ulint) (lfinish_time - lstart_time);
572
580
                mutex->lspent_time += ltime_diff;
581
589
 
582
590
/**********************************************************************
583
591
Releases the threads waiting in the primary wait array for this mutex. */
584
 
 
 
592
UNIV_INTERN
585
593
void
586
594
mutex_signal_object(
587
595
/*================*/
591
599
 
592
600
        /* The memory order of resetting the waiters field and
593
601
        signaling the object is important. See LEMMA 1 above. */
594
 
 
595
 
        sync_array_signal_object(sync_primary_wait_array, mutex);
 
602
        os_event_set(mutex->event);
 
603
        sync_array_object_signalled(sync_primary_wait_array);
596
604
}
597
605
 
598
606
#ifdef UNIV_SYNC_DEBUG
599
607
/**********************************************************************
600
608
Sets the debug information for a reserved mutex. */
601
 
 
 
609
UNIV_INTERN
602
610
void
603
611
mutex_set_debug_info(
604
612
/*=================*/
617
625
 
618
626
/**********************************************************************
619
627
Gets the debug information for a reserved mutex. */
620
 
 
 
628
UNIV_INTERN
621
629
void
622
630
mutex_get_debug_info(
623
631
/*=================*/
679
687
 
680
688
/**********************************************************************
681
689
Counts currently reserved mutexes. Works only in the debug version. */
682
 
 
 
690
UNIV_INTERN
683
691
ulint
684
692
mutex_n_reserved(void)
685
693
/*==================*/
711
719
/**********************************************************************
712
720
Returns TRUE if no mutex or rw-lock is currently locked. Works only in
713
721
the debug version. */
714
 
 
 
722
UNIV_INTERN
715
723
ibool
716
724
sync_all_freed(void)
717
725
/*================*/
904
912
 
905
913
/**********************************************************************
906
914
Checks that the level array for the current thread is empty. */
907
 
 
 
915
UNIV_INTERN
908
916
ibool
909
917
sync_thread_levels_empty_gen(
910
918
/*=========================*/
961
969
 
962
970
/**********************************************************************
963
971
Checks that the level array for the current thread is empty. */
964
 
 
 
972
UNIV_INTERN
965
973
ibool
966
974
sync_thread_levels_empty(void)
967
975
/*==========================*/
974
982
Adds a latch and its level in the thread level array. Allocates the memory
975
983
for the array if called first time for this OS thread. Makes the checks
976
984
against other latch levels stored in the array for this thread. */
977
 
 
 
985
UNIV_INTERN
978
986
void
979
987
sync_thread_add_level(
980
988
/*==================*/
1040
1048
                /* Do no order checking */
1041
1049
                break;
1042
1050
        case SYNC_MEM_POOL:
1043
 
                ut_a(sync_thread_levels_g(array, SYNC_MEM_POOL));
1044
 
                break;
1045
1051
        case SYNC_MEM_HASH:
1046
 
                ut_a(sync_thread_levels_g(array, SYNC_MEM_HASH));
1047
 
                break;
1048
1052
        case SYNC_RECV:
1049
 
                ut_a(sync_thread_levels_g(array, SYNC_RECV));
1050
 
                break;
1051
1053
        case SYNC_WORK_QUEUE:
1052
 
                ut_a(sync_thread_levels_g(array, SYNC_WORK_QUEUE));
1053
 
                break;
1054
1054
        case SYNC_LOG:
1055
 
                ut_a(sync_thread_levels_g(array, SYNC_LOG));
1056
 
                break;
1057
1055
        case SYNC_THR_LOCAL:
1058
 
                ut_a(sync_thread_levels_g(array, SYNC_THR_LOCAL));
1059
 
                break;
1060
1056
        case SYNC_ANY_LATCH:
1061
 
                ut_a(sync_thread_levels_g(array, SYNC_ANY_LATCH));
1062
 
                break;
1063
1057
        case SYNC_TRX_SYS_HEADER:
1064
 
                ut_a(sync_thread_levels_g(array, SYNC_TRX_SYS_HEADER));
1065
 
                break;
 
1058
        case SYNC_FILE_FORMAT_TAG:
1066
1059
        case SYNC_DOUBLEWRITE:
1067
 
                ut_a(sync_thread_levels_g(array, SYNC_DOUBLEWRITE));
 
1060
        case SYNC_BUF_POOL:
 
1061
        case SYNC_SEARCH_SYS:
 
1062
        case SYNC_TRX_LOCK_HEAP:
 
1063
        case SYNC_KERNEL:
 
1064
        case SYNC_IBUF_BITMAP_MUTEX:
 
1065
        case SYNC_RSEG:
 
1066
        case SYNC_TRX_UNDO:
 
1067
        case SYNC_PURGE_LATCH:
 
1068
        case SYNC_PURGE_SYS:
 
1069
        case SYNC_DICT_AUTOINC_MUTEX:
 
1070
        case SYNC_DICT_OPERATION:
 
1071
        case SYNC_DICT_HEADER:
 
1072
        case SYNC_TRX_I_S_RWLOCK:
 
1073
        case SYNC_TRX_I_S_LAST_READ:
 
1074
                if (!sync_thread_levels_g(array, level)) {
 
1075
                        fprintf(stderr,
 
1076
                                "InnoDB: sync_thread_levels_g(array, %lu)"
 
1077
                                " does not hold!\n", level);
 
1078
                        ut_error;
 
1079
                }
1068
1080
                break;
1069
1081
        case SYNC_BUF_BLOCK:
1070
1082
                ut_a((sync_thread_levels_contain(array, SYNC_BUF_POOL)
1071
1083
                      && sync_thread_levels_g(array, SYNC_BUF_BLOCK - 1))
1072
1084
                     || sync_thread_levels_g(array, SYNC_BUF_BLOCK));
1073
1085
                break;
1074
 
        case SYNC_BUF_POOL:
1075
 
                ut_a(sync_thread_levels_g(array, SYNC_BUF_POOL));
1076
 
                break;
1077
 
        case SYNC_SEARCH_SYS:
1078
 
                ut_a(sync_thread_levels_g(array, SYNC_SEARCH_SYS));
1079
 
                break;
1080
 
        case SYNC_TRX_LOCK_HEAP:
1081
 
                ut_a(sync_thread_levels_g(array, SYNC_TRX_LOCK_HEAP));
1082
 
                break;
1083
1086
        case SYNC_REC_LOCK:
1084
1087
                ut_a((sync_thread_levels_contain(array, SYNC_KERNEL)
1085
1088
                      && sync_thread_levels_g(array, SYNC_REC_LOCK - 1))
1086
1089
                     || sync_thread_levels_g(array, SYNC_REC_LOCK));
1087
1090
                break;
1088
 
        case SYNC_KERNEL:
1089
 
                ut_a(sync_thread_levels_g(array, SYNC_KERNEL));
1090
 
                break;
1091
1091
        case SYNC_IBUF_BITMAP:
1092
1092
                ut_a((sync_thread_levels_contain(array, SYNC_IBUF_BITMAP_MUTEX)
1093
1093
                      && sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1))
1094
1094
                     || sync_thread_levels_g(array, SYNC_IBUF_BITMAP));
1095
1095
                break;
1096
 
        case SYNC_IBUF_BITMAP_MUTEX:
1097
 
                ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP_MUTEX));
1098
 
                break;
1099
1096
        case SYNC_FSP_PAGE:
1100
1097
                ut_a(sync_thread_levels_contain(array, SYNC_FSP));
1101
1098
                break;
1116
1113
                ut_a(sync_thread_levels_contain(array, SYNC_KERNEL)
1117
1114
                     && sync_thread_levels_contain(array, SYNC_FSP_PAGE));
1118
1115
                break;
1119
 
        case SYNC_RSEG:
1120
 
                ut_a(sync_thread_levels_g(array, SYNC_RSEG));
1121
 
                break;
1122
 
        case SYNC_TRX_UNDO:
1123
 
                ut_a(sync_thread_levels_g(array, SYNC_TRX_UNDO));
1124
 
                break;
1125
 
        case SYNC_PURGE_LATCH:
1126
 
                ut_a(sync_thread_levels_g(array, SYNC_PURGE_LATCH));
1127
 
                break;
1128
 
        case SYNC_PURGE_SYS:
1129
 
                ut_a(sync_thread_levels_g(array, SYNC_PURGE_SYS));
1130
 
                break;
1131
1116
        case SYNC_TREE_NODE:
1132
1117
                ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE)
 
1118
                     || sync_thread_levels_contain(array, SYNC_DICT_OPERATION)
1133
1119
                     || sync_thread_levels_g(array, SYNC_TREE_NODE - 1));
1134
1120
                break;
1135
1121
        case SYNC_TREE_NODE_NEW:
1155
1141
                     && !sync_thread_levels_contain(
1156
1142
                             array, SYNC_IBUF_PESS_INSERT_MUTEX));
1157
1143
                break;
1158
 
        case SYNC_DICT_AUTOINC_MUTEX:
1159
 
                ut_a(sync_thread_levels_g(array, SYNC_DICT_AUTOINC_MUTEX));
1160
 
                break;
1161
 
        case SYNC_DICT_OPERATION:
1162
 
                ut_a(sync_thread_levels_g(array, SYNC_DICT_OPERATION));
1163
 
                break;
1164
 
        case SYNC_DICT_HEADER:
1165
 
                ut_a(sync_thread_levels_g(array, SYNC_DICT_HEADER));
1166
 
                break;
1167
1144
        case SYNC_DICT:
1168
1145
#ifdef UNIV_DEBUG
1169
1146
                ut_a(buf_debug_prints
1195
1172
 
1196
1173
/**********************************************************************
1197
1174
Removes a latch from the thread level array if it is found there. */
1198
 
 
 
1175
UNIV_INTERN
1199
1176
ibool
1200
1177
sync_thread_reset_level(
1201
1178
/*====================*/
1248
1225
                }
1249
1226
        }
1250
1227
 
 
1228
        if (((mutex_t*) latch)->magic_n != MUTEX_MAGIC_N) {
 
1229
                rw_lock_t*      rw_lock;
 
1230
 
 
1231
                rw_lock = (rw_lock_t*) latch;
 
1232
 
 
1233
                if (rw_lock->level == SYNC_LEVEL_VARYING) {
 
1234
                        mutex_exit(&sync_thread_mutex);
 
1235
 
 
1236
                        return(TRUE);
 
1237
                }
 
1238
        }
 
1239
 
1251
1240
        ut_error;
1252
1241
 
1253
1242
        mutex_exit(&sync_thread_mutex);
1258
1247
 
1259
1248
/**********************************************************************
1260
1249
Initializes the synchronization data structures. */
1261
 
 
 
1250
UNIV_INTERN
1262
1251
void
1263
1252
sync_init(void)
1264
1253
/*===========*/
1313
1302
/**********************************************************************
1314
1303
Frees the resources in InnoDB's own synchronization data structures. Use
1315
1304
os_sync_free() after calling this. */
1316
 
 
 
1305
UNIV_INTERN
1317
1306
void
1318
1307
sync_close(void)
1319
1308
/*===========*/
1337
1326
 
1338
1327
/***********************************************************************
1339
1328
Prints wait info of the sync system. */
1340
 
 
 
1329
UNIV_INTERN
1341
1330
void
1342
1331
sync_print_wait_info(
1343
1332
/*=================*/
1363
1352
 
1364
1353
/***********************************************************************
1365
1354
Prints info of the sync system. */
1366
 
 
 
1355
UNIV_INTERN
1367
1356
void
1368
1357
sync_print(
1369
1358
/*=======*/