~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Jay Pipes
  • Date: 2008-09-09 20:10:57 UTC
  • mto: (383.2.4 fix-failing-tests)
  • mto: This revision was merged to the branch mainline in revision 386.
  • Revision ID: jay@mysql.com-20080909201057-3qkgcxqaps2s58y9
Re-enabled a number of passing tests from trunk

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 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.
 
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.
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
 
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.
 
108
sync_array_signal_object with the mutex as an argument.
139
109
Q.E.D. */
140
110
 
141
111
/* The number of system calls made in this module. Intended for performance
142
112
monitoring. */
143
113
 
144
 
UNIV_INTERN ulint       mutex_system_call_count         = 0;
 
114
ulint   mutex_system_call_count         = 0;
145
115
 
146
116
/* Number of spin waits on mutexes: for performance monitoring */
147
117
 
148
118
/* round=one iteration of a spin loop */
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;
 
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;
153
123
 
154
124
/* The global array of wait cells for implementation of the database's own
155
125
mutexes and read-write locks */
156
 
UNIV_INTERN sync_array_t*       sync_primary_wait_array;
 
126
sync_array_t*   sync_primary_wait_array;
157
127
 
158
128
/* This variable is set to TRUE when sync_init is called */
159
 
UNIV_INTERN ibool       sync_initialized        = FALSE;
 
129
ibool   sync_initialized        = FALSE;
160
130
 
161
131
 
162
132
typedef struct sync_level_struct        sync_level_t;
166
136
/* The latch levels currently owned by threads are stored in this data
167
137
structure; the size of this array is OS_THREAD_MAX_N */
168
138
 
169
 
UNIV_INTERN sync_thread_t*      sync_thread_level_arrays;
 
139
sync_thread_t*  sync_thread_level_arrays;
170
140
 
171
141
/* Mutex protecting sync_thread_level_arrays */
172
 
UNIV_INTERN mutex_t             sync_thread_mutex;
 
142
mutex_t sync_thread_mutex;
173
143
#endif /* UNIV_SYNC_DEBUG */
174
144
 
175
145
/* Global list of database mutexes (not OS mutexes) created. */
176
 
UNIV_INTERN ut_list_base_node_t  mutex_list;
 
146
ut_list_base_node_t  mutex_list;
177
147
 
178
148
/* Mutex protecting the mutex_list variable */
179
 
UNIV_INTERN mutex_t mutex_list_mutex;
 
149
mutex_t mutex_list_mutex;
180
150
 
181
151
#ifdef UNIV_SYNC_DEBUG
182
152
/* Latching order checks start when this is set TRUE */
183
 
UNIV_INTERN ibool       sync_order_checks_on    = FALSE;
 
153
ibool   sync_order_checks_on    = FALSE;
184
154
#endif /* UNIV_SYNC_DEBUG */
185
155
 
186
156
struct sync_thread_struct{
199
169
};
200
170
 
201
171
/**********************************************************************
 
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
/**********************************************************************
202
196
Creates, or rather, initializes a mutex object in a specified memory
203
197
location (which must be appropriately aligned). The mutex is initialized
204
198
in the reset state. Explicit freeing of the mutex with mutex_free is
205
199
necessary only if the memory block containing it is freed. */
206
 
UNIV_INTERN
 
200
 
207
201
void
208
202
mutex_create_func(
209
203
/*==============*/
223
217
        os_fast_mutex_init(&(mutex->os_fast_mutex));
224
218
        mutex->lock_word = 0;
225
219
#endif
226
 
        mutex->event = os_event_create(NULL);
227
220
        mutex_set_waiters(mutex, 0);
228
221
#ifdef UNIV_DEBUG
229
222
        mutex->magic_n = MUTEX_MAGIC_N;
277
270
Calling this function is obligatory only if the memory buffer containing
278
271
the mutex is freed. Removes a mutex object from the mutex list. The mutex
279
272
is checked to be in the reset state. */
280
 
UNIV_INTERN
 
273
 
281
274
void
282
275
mutex_free(
283
276
/*=======*/
307
300
                mutex_exit(&mutex_list_mutex);
308
301
        }
309
302
 
310
 
        os_event_free(mutex->event);
311
 
 
312
303
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
313
304
        os_fast_mutex_free(&(mutex->os_fast_mutex));
314
305
#endif
324
315
NOTE! Use the corresponding macro in the header file, not this function
325
316
directly. Tries to lock the mutex for the current thread. If the lock is not
326
317
acquired immediately, returns with return value 1. */
327
 
UNIV_INTERN
 
318
 
328
319
ulint
329
320
mutex_enter_nowait_func(
330
321
/*====================*/
354
345
#ifdef UNIV_DEBUG
355
346
/**********************************************************************
356
347
Checks that the mutex has been initialized. */
357
 
UNIV_INTERN
 
348
 
358
349
ibool
359
350
mutex_validate(
360
351
/*===========*/
369
360
/**********************************************************************
370
361
Checks that the current thread owns the mutex. Works only in the debug
371
362
version. */
372
 
UNIV_INTERN
 
363
 
373
364
ibool
374
365
mutex_own(
375
366
/*======*/
385
376
 
386
377
/**********************************************************************
387
378
Sets the waiters field in a mutex. */
388
 
UNIV_INTERN
 
379
 
389
380
void
390
381
mutex_set_waiters(
391
382
/*==============*/
406
397
Reserves a mutex for the current thread. If the mutex is reserved, the
407
398
function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
408
399
for the mutex before suspending the thread. */
409
 
UNIV_INTERN
 
400
 
410
401
void
411
402
mutex_spin_wait(
412
403
/*============*/
418
409
        ulint      index; /* index of the reserved wait cell */
419
410
        ulint      i;     /* spin round count */
420
411
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
421
 
        ib_int64_t lstart_time = 0, lfinish_time; /* for timing os_wait */
 
412
        ib_longlong lstart_time = 0, lfinish_time; /* for timing os_wait */
422
413
        ulint ltime_diff;
423
414
        ulint sec;
424
415
        ulint ms;
455
446
                mutex->count_os_yield++;
456
447
                if (timed_mutexes == 1 && timer_started==0) {
457
448
                        ut_usectime(&sec, &ms);
458
 
                        lstart_time= (ib_int64_t)sec * 1000000 + ms;
 
449
                        lstart_time= (ib_longlong)sec * 1000000 + ms;
459
450
                        timer_started = 1;
460
451
                }
461
452
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
518
509
                if (mutex_test_and_set(mutex) == 0) {
519
510
                        /* Succeeded! Free the reserved wait cell */
520
511
 
521
 
                        sync_array_free_cell(sync_primary_wait_array, index);
 
512
                        sync_array_free_cell_protected(sync_primary_wait_array,
 
513
                                                       index);
522
514
 
523
515
                        ut_d(mutex->thread_id = os_thread_get_curr_id());
524
516
#ifdef UNIV_SYNC_DEBUG
561
553
 
562
554
        if (timed_mutexes == 1 && timer_started==0) {
563
555
                ut_usectime(&sec, &ms);
564
 
                lstart_time= (ib_int64_t)sec * 1000000 + ms;
 
556
                lstart_time= (ib_longlong)sec * 1000000 + ms;
565
557
                timer_started = 1;
566
558
        }
567
559
# endif /* UNIV_DEBUG */
574
566
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
575
567
        if (timed_mutexes == 1 && timer_started==1) {
576
568
                ut_usectime(&sec, &ms);
577
 
                lfinish_time= (ib_int64_t)sec * 1000000 + ms;
 
569
                lfinish_time= (ib_longlong)sec * 1000000 + ms;
578
570
 
579
571
                ltime_diff= (ulint) (lfinish_time - lstart_time);
580
572
                mutex->lspent_time += ltime_diff;
589
581
 
590
582
/**********************************************************************
591
583
Releases the threads waiting in the primary wait array for this mutex. */
592
 
UNIV_INTERN
 
584
 
593
585
void
594
586
mutex_signal_object(
595
587
/*================*/
599
591
 
600
592
        /* The memory order of resetting the waiters field and
601
593
        signaling the object is important. See LEMMA 1 above. */
602
 
        os_event_set(mutex->event);
603
 
        sync_array_object_signalled(sync_primary_wait_array);
 
594
 
 
595
        sync_array_signal_object(sync_primary_wait_array, mutex);
604
596
}
605
597
 
606
598
#ifdef UNIV_SYNC_DEBUG
607
599
/**********************************************************************
608
600
Sets the debug information for a reserved mutex. */
609
 
UNIV_INTERN
 
601
 
610
602
void
611
603
mutex_set_debug_info(
612
604
/*=================*/
625
617
 
626
618
/**********************************************************************
627
619
Gets the debug information for a reserved mutex. */
628
 
UNIV_INTERN
 
620
 
629
621
void
630
622
mutex_get_debug_info(
631
623
/*=================*/
687
679
 
688
680
/**********************************************************************
689
681
Counts currently reserved mutexes. Works only in the debug version. */
690
 
UNIV_INTERN
 
682
 
691
683
ulint
692
684
mutex_n_reserved(void)
693
685
/*==================*/
719
711
/**********************************************************************
720
712
Returns TRUE if no mutex or rw-lock is currently locked. Works only in
721
713
the debug version. */
722
 
UNIV_INTERN
 
714
 
723
715
ibool
724
716
sync_all_freed(void)
725
717
/*================*/
912
904
 
913
905
/**********************************************************************
914
906
Checks that the level array for the current thread is empty. */
915
 
UNIV_INTERN
 
907
 
916
908
ibool
917
909
sync_thread_levels_empty_gen(
918
910
/*=========================*/
969
961
 
970
962
/**********************************************************************
971
963
Checks that the level array for the current thread is empty. */
972
 
UNIV_INTERN
 
964
 
973
965
ibool
974
966
sync_thread_levels_empty(void)
975
967
/*==========================*/
982
974
Adds a latch and its level in the thread level array. Allocates the memory
983
975
for the array if called first time for this OS thread. Makes the checks
984
976
against other latch levels stored in the array for this thread. */
985
 
UNIV_INTERN
 
977
 
986
978
void
987
979
sync_thread_add_level(
988
980
/*==================*/
1048
1040
                /* Do no order checking */
1049
1041
                break;
1050
1042
        case SYNC_MEM_POOL:
 
1043
                ut_a(sync_thread_levels_g(array, SYNC_MEM_POOL));
 
1044
                break;
1051
1045
        case SYNC_MEM_HASH:
 
1046
                ut_a(sync_thread_levels_g(array, SYNC_MEM_HASH));
 
1047
                break;
1052
1048
        case SYNC_RECV:
 
1049
                ut_a(sync_thread_levels_g(array, SYNC_RECV));
 
1050
                break;
1053
1051
        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;
1055
1057
        case SYNC_THR_LOCAL:
 
1058
                ut_a(sync_thread_levels_g(array, SYNC_THR_LOCAL));
 
1059
                break;
1056
1060
        case SYNC_ANY_LATCH:
 
1061
                ut_a(sync_thread_levels_g(array, SYNC_ANY_LATCH));
 
1062
                break;
1057
1063
        case SYNC_TRX_SYS_HEADER:
1058
 
        case SYNC_FILE_FORMAT_TAG:
 
1064
                ut_a(sync_thread_levels_g(array, SYNC_TRX_SYS_HEADER));
 
1065
                break;
1059
1066
        case 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
 
                }
 
1067
                ut_a(sync_thread_levels_g(array, SYNC_DOUBLEWRITE));
1080
1068
                break;
1081
1069
        case SYNC_BUF_BLOCK:
1082
1070
                ut_a((sync_thread_levels_contain(array, SYNC_BUF_POOL)
1083
1071
                      && sync_thread_levels_g(array, SYNC_BUF_BLOCK - 1))
1084
1072
                     || sync_thread_levels_g(array, SYNC_BUF_BLOCK));
1085
1073
                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;
1086
1083
        case SYNC_REC_LOCK:
1087
1084
                ut_a((sync_thread_levels_contain(array, SYNC_KERNEL)
1088
1085
                      && sync_thread_levels_g(array, SYNC_REC_LOCK - 1))
1089
1086
                     || sync_thread_levels_g(array, SYNC_REC_LOCK));
1090
1087
                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;
1096
1099
        case SYNC_FSP_PAGE:
1097
1100
                ut_a(sync_thread_levels_contain(array, SYNC_FSP));
1098
1101
                break;
1113
1116
                ut_a(sync_thread_levels_contain(array, SYNC_KERNEL)
1114
1117
                     && sync_thread_levels_contain(array, SYNC_FSP_PAGE));
1115
1118
                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;
1116
1131
        case SYNC_TREE_NODE:
1117
1132
                ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE)
1118
 
                     || sync_thread_levels_contain(array, SYNC_DICT_OPERATION)
1119
1133
                     || sync_thread_levels_g(array, SYNC_TREE_NODE - 1));
1120
1134
                break;
1121
1135
        case SYNC_TREE_NODE_NEW:
1141
1155
                     && !sync_thread_levels_contain(
1142
1156
                             array, SYNC_IBUF_PESS_INSERT_MUTEX));
1143
1157
                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;
1144
1167
        case SYNC_DICT:
1145
1168
#ifdef UNIV_DEBUG
1146
1169
                ut_a(buf_debug_prints
1172
1195
 
1173
1196
/**********************************************************************
1174
1197
Removes a latch from the thread level array if it is found there. */
1175
 
UNIV_INTERN
 
1198
 
1176
1199
ibool
1177
1200
sync_thread_reset_level(
1178
1201
/*====================*/
1225
1248
                }
1226
1249
        }
1227
1250
 
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
 
 
1240
1251
        ut_error;
1241
1252
 
1242
1253
        mutex_exit(&sync_thread_mutex);
1247
1258
 
1248
1259
/**********************************************************************
1249
1260
Initializes the synchronization data structures. */
1250
 
UNIV_INTERN
 
1261
 
1251
1262
void
1252
1263
sync_init(void)
1253
1264
/*===========*/
1302
1313
/**********************************************************************
1303
1314
Frees the resources in InnoDB's own synchronization data structures. Use
1304
1315
os_sync_free() after calling this. */
1305
 
UNIV_INTERN
 
1316
 
1306
1317
void
1307
1318
sync_close(void)
1308
1319
/*===========*/
1326
1337
 
1327
1338
/***********************************************************************
1328
1339
Prints wait info of the sync system. */
1329
 
UNIV_INTERN
 
1340
 
1330
1341
void
1331
1342
sync_print_wait_info(
1332
1343
/*=================*/
1352
1363
 
1353
1364
/***********************************************************************
1354
1365
Prints info of the sync system. */
1355
 
UNIV_INTERN
 
1366
 
1356
1367
void
1357
1368
sync_print(
1358
1369
/*=======*/