~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-06-02 22:35:45 UTC
  • mto: This revision was merged to the branch mainline in revision 1586.
  • Revision ID: mordred@inaugust.com-20100602223545-q8ekf9b40a85nwuf
Rearragned unittests into a single exe because of how we need to link it
(thanks lifeless)
Link with server symbols without needing to build a library.
Added an additional atomics test which tests whatever version of the atomics
lib the running platform would actually use.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
4
4
Copyright (c) 2008, Google Inc.
5
5
 
6
6
Portions of this file contain modifications contributed and copyrighted by
18
18
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19
19
 
20
20
You should have received a copy of the GNU General Public License along with
21
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22
 
St, Fifth Floor, Boston, MA 02110-1301 USA
 
21
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
22
Place, Suite 330, Boston, MA 02111-1307 USA
23
23
 
24
24
*****************************************************************************/
25
25
 
39
39
#include "buf0buf.h"
40
40
#include "srv0srv.h"
41
41
#include "buf0types.h"
42
 
#include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
43
 
#ifdef UNIV_SYNC_DEBUG
44
 
# include "srv0start.h" /* srv_is_being_started */
45
 
#endif /* UNIV_SYNC_DEBUG */
46
42
 
47
43
/*
48
44
        REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX
201
197
 
202
198
/** Mutex protecting sync_thread_level_arrays */
203
199
UNIV_INTERN mutex_t             sync_thread_mutex;
204
 
 
205
 
# ifdef UNIV_PFS_MUTEX
206
 
UNIV_INTERN mysql_pfs_key_t     sync_thread_mutex_key;
207
 
# endif /* UNIV_PFS_MUTEX */
208
200
#endif /* UNIV_SYNC_DEBUG */
209
201
 
210
202
/** Global list of database mutexes (not OS mutexes) created. */
213
205
/** Mutex protecting the mutex_list variable */
214
206
UNIV_INTERN mutex_t mutex_list_mutex;
215
207
 
216
 
#ifdef UNIV_PFS_MUTEX
217
 
UNIV_INTERN mysql_pfs_key_t     mutex_list_mutex_key;
218
 
#endif /* UNIV_PFS_MUTEX */
219
 
 
220
208
#ifdef UNIV_SYNC_DEBUG
221
209
/** Latching order checks start when this is set TRUE */
222
210
UNIV_INTERN ibool       sync_order_checks_on    = FALSE;
313
301
}
314
302
 
315
303
/******************************************************************//**
316
 
NOTE! Use the corresponding macro mutex_free(), not directly this function!
317
304
Calling this function is obligatory only if the memory buffer containing
318
305
the mutex is freed. Removes a mutex object from the mutex list. The mutex
319
306
is checked to be in the reset state. */
320
307
UNIV_INTERN
321
308
void
322
 
mutex_free_func(
323
 
/*============*/
 
309
mutex_free(
 
310
/*=======*/
324
311
        mutex_t*        mutex)  /*!< in: mutex */
325
312
{
326
313
        ut_ad(mutex_validate(mutex));
327
314
        ut_a(mutex_get_lock_word(mutex) == 0);
328
315
        ut_a(mutex_get_waiters(mutex) == 0);
329
316
 
330
 
#ifdef UNIV_MEM_DEBUG
331
 
        if (mutex == &mem_hash_mutex) {
332
 
                ut_ad(UT_LIST_GET_LEN(mutex_list) == 1);
333
 
                ut_ad(UT_LIST_GET_FIRST(mutex_list) == &mem_hash_mutex);
334
 
                UT_LIST_REMOVE(list, mutex_list, mutex);
335
 
                goto func_exit;
336
 
        }
337
 
#endif /* UNIV_MEM_DEBUG */
338
 
 
339
317
        if (mutex != &mutex_list_mutex
340
318
#ifdef UNIV_SYNC_DEBUG
341
319
            && mutex != &sync_thread_mutex
357
335
        }
358
336
 
359
337
        os_event_free(mutex->event);
360
 
#ifdef UNIV_MEM_DEBUG
361
 
func_exit:
362
 
#endif /* UNIV_MEM_DEBUG */
 
338
 
363
339
#if !defined(HAVE_ATOMIC_BUILTINS)
364
340
        os_fast_mutex_free(&(mutex->os_fast_mutex));
365
341
#endif
873
849
/*=================*/
874
850
        sync_level_t*   arr,    /*!< in: pointer to level array for an OS
875
851
                                thread */
876
 
        ulint           limit,  /*!< in: level limit */
877
 
        ulint           warn)   /*!< in: TRUE=display a diagnostic message */
 
852
        ulint           limit)  /*!< in: level limit */
878
853
{
879
854
        sync_level_t*   slot;
880
855
        rw_lock_t*      lock;
888
863
                if (slot->latch != NULL) {
889
864
                        if (slot->level <= limit) {
890
865
 
891
 
                                if (!warn) {
892
 
 
893
 
                                        return(FALSE);
894
 
                                }
895
 
 
896
866
                                lock = slot->latch;
897
867
                                mutex = slot->latch;
898
868
 
970
940
}
971
941
 
972
942
/******************************************************************//**
973
 
Checks if the level array for the current thread contains a
974
 
mutex or rw-latch at the specified level.
975
 
@return a matching latch, or NULL if not found */
976
 
UNIV_INTERN
977
 
void*
978
 
sync_thread_levels_contains(
979
 
/*========================*/
980
 
        ulint   level)                  /*!< in: latching order level
981
 
                                        (SYNC_DICT, ...)*/
982
 
{
983
 
        sync_level_t*   arr;
984
 
        sync_thread_t*  thread_slot;
985
 
        sync_level_t*   slot;
986
 
        ulint           i;
987
 
 
988
 
        if (!sync_order_checks_on) {
989
 
 
990
 
                return(NULL);
991
 
        }
992
 
 
993
 
        mutex_enter(&sync_thread_mutex);
994
 
 
995
 
        thread_slot = sync_thread_level_arrays_find_slot();
996
 
 
997
 
        if (thread_slot == NULL) {
998
 
 
999
 
                mutex_exit(&sync_thread_mutex);
1000
 
 
1001
 
                return(NULL);
1002
 
        }
1003
 
 
1004
 
        arr = thread_slot->levels;
1005
 
 
1006
 
        for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
1007
 
 
1008
 
                slot = sync_thread_levels_get_nth(arr, i);
1009
 
 
1010
 
                if (slot->latch != NULL && slot->level == level) {
1011
 
 
1012
 
                        mutex_exit(&sync_thread_mutex);
1013
 
                        return(slot->latch);
1014
 
                }
1015
 
        }
1016
 
 
1017
 
        mutex_exit(&sync_thread_mutex);
1018
 
 
1019
 
        return(NULL);
1020
 
}
1021
 
 
1022
 
/******************************************************************//**
1023
943
Checks that the level array for the current thread is empty.
1024
 
@return a latch, or NULL if empty except the exceptions specified below */
 
944
@return TRUE if empty except the exceptions specified below */
1025
945
UNIV_INTERN
1026
 
void*
1027
 
sync_thread_levels_nonempty_gen(
1028
 
/*============================*/
 
946
ibool
 
947
sync_thread_levels_empty_gen(
 
948
/*=========================*/
1029
949
        ibool   dict_mutex_allowed)     /*!< in: TRUE if dictionary mutex is
1030
950
                                        allowed to be owned by the thread,
1031
951
                                        also purge_is_running mutex is
1038
958
 
1039
959
        if (!sync_order_checks_on) {
1040
960
 
1041
 
                return(NULL);
 
961
                return(TRUE);
1042
962
        }
1043
963
 
1044
964
        mutex_enter(&sync_thread_mutex);
1049
969
 
1050
970
                mutex_exit(&sync_thread_mutex);
1051
971
 
1052
 
                return(NULL);
 
972
                return(TRUE);
1053
973
        }
1054
974
 
1055
975
        arr = thread_slot->levels;
1066
986
                        mutex_exit(&sync_thread_mutex);
1067
987
                        ut_error;
1068
988
 
1069
 
                        return(slot->latch);
 
989
                        return(FALSE);
1070
990
                }
1071
991
        }
1072
992
 
1073
993
        mutex_exit(&sync_thread_mutex);
1074
994
 
1075
 
        return(NULL);
 
995
        return(TRUE);
1076
996
}
1077
997
 
1078
998
/******************************************************************//**
1155
1075
        case SYNC_TREE_NODE_FROM_HASH:
1156
1076
                /* Do no order checking */
1157
1077
                break;
1158
 
        case SYNC_TRX_SYS_HEADER:
1159
 
                if (srv_is_being_started) {
1160
 
                        /* This is violated during trx_sys_create_rsegs()
1161
 
                        when creating additional rollback segments when
1162
 
                        upgrading in innobase_start_or_create_for_mysql(). */
1163
 
                        break;
1164
 
                }
1165
1078
        case SYNC_MEM_POOL:
1166
1079
        case SYNC_MEM_HASH:
1167
1080
        case SYNC_RECV:
1168
1081
        case SYNC_WORK_QUEUE:
1169
1082
        case SYNC_LOG:
1170
 
        case SYNC_LOG_FLUSH_ORDER:
1171
1083
        case SYNC_THR_LOCAL:
1172
1084
        case SYNC_ANY_LATCH:
 
1085
        case SYNC_TRX_SYS_HEADER:
1173
1086
        case SYNC_FILE_FORMAT_TAG:
1174
1087
        case SYNC_DOUBLEWRITE:
 
1088
        case SYNC_BUF_POOL:
1175
1089
        case SYNC_SEARCH_SYS:
1176
1090
        case SYNC_SEARCH_SYS_CONF:
1177
1091
        case SYNC_TRX_LOCK_HEAP:
1186
1100
        case SYNC_DICT_HEADER:
1187
1101
        case SYNC_TRX_I_S_RWLOCK:
1188
1102
        case SYNC_TRX_I_S_LAST_READ:
1189
 
                if (!sync_thread_levels_g(array, level, TRUE)) {
 
1103
                if (!sync_thread_levels_g(array, level)) {
1190
1104
                        fprintf(stderr,
1191
1105
                                "InnoDB: sync_thread_levels_g(array, %lu)"
1192
1106
                                " does not hold!\n", level);
1193
1107
                        ut_error;
1194
1108
                }
1195
1109
                break;
1196
 
        case SYNC_BUF_FLUSH_LIST:
1197
 
        case SYNC_BUF_POOL:
1198
 
                /* We can have multiple mutexes of this type therefore we
1199
 
                can only check whether the greater than condition holds. */
1200
 
                if (!sync_thread_levels_g(array, level-1, TRUE)) {
1201
 
                        fprintf(stderr,
1202
 
                                "InnoDB: sync_thread_levels_g(array, %lu)"
1203
 
                                " does not hold!\n", level-1);
1204
 
                        ut_error;
1205
 
                }
1206
 
                break;
1207
 
 
1208
1110
        case SYNC_BUF_BLOCK:
1209
1111
                /* Either the thread must own the buffer pool mutex
1210
1112
                (buf_pool_mutex), or it is allowed to latch only ONE
1211
1113
                buffer block (block->mutex or buf_pool_zip_mutex). */
1212
 
                if (!sync_thread_levels_g(array, level, FALSE)) {
1213
 
                        ut_a(sync_thread_levels_g(array, level - 1, TRUE));
 
1114
                if (!sync_thread_levels_g(array, level)) {
 
1115
                        ut_a(sync_thread_levels_g(array, level - 1));
1214
1116
                        ut_a(sync_thread_levels_contain(array, SYNC_BUF_POOL));
1215
1117
                }
1216
1118
                break;
1217
1119
        case SYNC_REC_LOCK:
1218
 
                if (sync_thread_levels_contain(array, SYNC_KERNEL)) {
1219
 
                        ut_a(sync_thread_levels_g(array, SYNC_REC_LOCK - 1,
1220
 
                                                  TRUE));
1221
 
                } else {
1222
 
                        ut_a(sync_thread_levels_g(array, SYNC_REC_LOCK, TRUE));
1223
 
                }
 
1120
                ut_a((sync_thread_levels_contain(array, SYNC_KERNEL)
 
1121
                      && sync_thread_levels_g(array, SYNC_REC_LOCK - 1))
 
1122
                     || sync_thread_levels_g(array, SYNC_REC_LOCK));
1224
1123
                break;
1225
1124
        case SYNC_IBUF_BITMAP:
1226
1125
                /* Either the thread must own the master mutex to all
1227
1126
                the bitmap pages, or it is allowed to latch only ONE
1228
1127
                bitmap page. */
1229
 
                if (sync_thread_levels_contain(array,
1230
 
                                               SYNC_IBUF_BITMAP_MUTEX)) {
1231
 
                        ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1,
1232
 
                                                  TRUE));
1233
 
                } else {
1234
 
                        /* This is violated during trx_sys_create_rsegs()
1235
 
                        when creating additional rollback segments when
1236
 
                        upgrading in innobase_start_or_create_for_mysql(). */
1237
 
                        ut_a(srv_is_being_started
1238
 
                             || sync_thread_levels_g(array, SYNC_IBUF_BITMAP,
1239
 
                                                     TRUE));
1240
 
                }
 
1128
                ut_a((sync_thread_levels_contain(array, SYNC_IBUF_BITMAP_MUTEX)
 
1129
                      && sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1))
 
1130
                     || sync_thread_levels_g(array, SYNC_IBUF_BITMAP));
1241
1131
                break;
1242
1132
        case SYNC_FSP_PAGE:
1243
1133
                ut_a(sync_thread_levels_contain(array, SYNC_FSP));
1244
1134
                break;
1245
1135
        case SYNC_FSP:
1246
1136
                ut_a(sync_thread_levels_contain(array, SYNC_FSP)
1247
 
                     || sync_thread_levels_g(array, SYNC_FSP, TRUE));
 
1137
                     || sync_thread_levels_g(array, SYNC_FSP));
1248
1138
                break;
1249
1139
        case SYNC_TRX_UNDO_PAGE:
1250
1140
                ut_a(sync_thread_levels_contain(array, SYNC_TRX_UNDO)
1251
1141
                     || sync_thread_levels_contain(array, SYNC_RSEG)
1252
1142
                     || sync_thread_levels_contain(array, SYNC_PURGE_SYS)
1253
 
                     || sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE, TRUE));
 
1143
                     || sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE));
1254
1144
                break;
1255
1145
        case SYNC_RSEG_HEADER:
1256
1146
                ut_a(sync_thread_levels_contain(array, SYNC_RSEG));
1262
1152
        case SYNC_TREE_NODE:
1263
1153
                ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE)
1264
1154
                     || sync_thread_levels_contain(array, SYNC_DICT_OPERATION)
1265
 
                     || sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
 
1155
                     || sync_thread_levels_g(array, SYNC_TREE_NODE - 1));
1266
1156
                break;
1267
1157
        case SYNC_TREE_NODE_NEW:
1268
1158
                ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE)
1269
1159
                     || sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
1270
1160
                break;
1271
1161
        case SYNC_INDEX_TREE:
1272
 
                if (sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
1273
 
                    && sync_thread_levels_contain(array, SYNC_FSP)) {
1274
 
                        ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1,
1275
 
                                                  TRUE));
1276
 
                } else {
1277
 
                        ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1,
1278
 
                                                  TRUE));
1279
 
                }
 
1162
                ut_a((sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
 
1163
                      && sync_thread_levels_contain(array, SYNC_FSP)
 
1164
                      && sync_thread_levels_g(array, SYNC_FSP_PAGE - 1))
 
1165
                     || sync_thread_levels_g(array, SYNC_TREE_NODE - 1));
1280
1166
                break;
1281
1167
        case SYNC_IBUF_MUTEX:
1282
 
                ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1, TRUE));
 
1168
                ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1));
1283
1169
                break;
1284
1170
        case SYNC_IBUF_PESS_INSERT_MUTEX:
1285
 
                ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE));
1286
 
                ut_a(!sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
 
1171
                ut_a(sync_thread_levels_g(array, SYNC_FSP - 1)
 
1172
                     && !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
1287
1173
                break;
1288
1174
        case SYNC_IBUF_HEADER:
1289
 
                ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE));
1290
 
                ut_a(!sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
1291
 
                ut_a(!sync_thread_levels_contain(array,
1292
 
                                                 SYNC_IBUF_PESS_INSERT_MUTEX));
 
1175
                ut_a(sync_thread_levels_g(array, SYNC_FSP - 1)
 
1176
                     && !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
 
1177
                     && !sync_thread_levels_contain(
 
1178
                             array, SYNC_IBUF_PESS_INSERT_MUTEX));
1293
1179
                break;
1294
1180
        case SYNC_DICT:
1295
1181
#ifdef UNIV_DEBUG
1296
1182
                ut_a(buf_debug_prints
1297
 
                     || sync_thread_levels_g(array, SYNC_DICT, TRUE));
 
1183
                     || sync_thread_levels_g(array, SYNC_DICT));
1298
1184
#else /* UNIV_DEBUG */
1299
 
                ut_a(sync_thread_levels_g(array, SYNC_DICT, TRUE));
 
1185
                ut_a(sync_thread_levels_g(array, SYNC_DICT));
1300
1186
#endif /* UNIV_DEBUG */
1301
1187
                break;
1302
1188
        default:
1432
1318
        /* Init the mutex list and create the mutex to protect it. */
1433
1319
 
1434
1320
        UT_LIST_INIT(mutex_list);
1435
 
        mutex_create(mutex_list_mutex_key, &mutex_list_mutex,
1436
 
                     SYNC_NO_ORDER_CHECK);
 
1321
        mutex_create(&mutex_list_mutex, SYNC_NO_ORDER_CHECK);
1437
1322
#ifdef UNIV_SYNC_DEBUG
1438
 
        mutex_create(sync_thread_mutex_key, &sync_thread_mutex,
1439
 
                     SYNC_NO_ORDER_CHECK);
 
1323
        mutex_create(&sync_thread_mutex, SYNC_NO_ORDER_CHECK);
1440
1324
#endif /* UNIV_SYNC_DEBUG */
1441
1325
 
1442
1326
        /* Init the rw-lock list and create the mutex to protect it. */
1443
1327
 
1444
1328
        UT_LIST_INIT(rw_lock_list);
1445
 
        mutex_create(rw_lock_list_mutex_key, &rw_lock_list_mutex,
1446
 
                     SYNC_NO_ORDER_CHECK);
 
1329
        mutex_create(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK);
1447
1330
 
1448
1331
#ifdef UNIV_SYNC_DEBUG
1449
 
        mutex_create(rw_lock_debug_mutex_key, &rw_lock_debug_mutex,
1450
 
                     SYNC_NO_ORDER_CHECK);
 
1332
        mutex_create(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK);
1451
1333
 
1452
1334
        rw_lock_debug_event = os_event_create(NULL);
1453
1335
        rw_lock_debug_waiters = FALSE;
1469
1351
        mutex = UT_LIST_GET_FIRST(mutex_list);
1470
1352
 
1471
1353
        while (mutex) {
1472
 
#ifdef UNIV_MEM_DEBUG
1473
 
                if (mutex == &mem_hash_mutex) {
1474
 
                        mutex = UT_LIST_GET_NEXT(list, mutex);
1475
 
                        continue;
1476
 
                }
1477
 
#endif /* UNIV_MEM_DEBUG */
1478
1354
                mutex_free(mutex);
1479
1355
                mutex = UT_LIST_GET_FIRST(mutex_list);
1480
1356
        }
1482
1358
        mutex_free(&mutex_list_mutex);
1483
1359
#ifdef UNIV_SYNC_DEBUG
1484
1360
        mutex_free(&sync_thread_mutex);
1485
 
 
1486
 
        /* Switch latching order checks on in sync0sync.c */
1487
 
        sync_order_checks_on = FALSE;
1488
1361
#endif /* UNIV_SYNC_DEBUG */
1489
 
 
1490
 
        sync_initialized = FALSE;       
1491
1362
}
1492
1363
 
1493
1364
/*******************************************************************//**
1506
1377
        fprintf(file,
1507
1378
                "Mutex spin waits %"PRId64", rounds %"PRId64", "
1508
1379
                "OS waits %"PRId64"\n"
1509
 
                "RW-shared spins %"PRId64", rounds %"PRId64", OS waits %"PRId64";"
1510
 
                " RW-excl spins %"PRId64", rounds %"PRId64", OS waits %"PRId64"\n",
 
1380
                "RW-shared spins %"PRId64", OS waits %"PRId64";"
 
1381
                " RW-excl spins %"PRId64", OS waits %"PRId64"\n",
1511
1382
                mutex_spin_wait_count,
1512
1383
                mutex_spin_round_count,
1513
1384
                mutex_os_wait_count,
1514
1385
                rw_s_spin_wait_count,
1515
 
                rw_s_spin_round_count,
1516
1386
                rw_s_os_wait_count,
1517
1387
                rw_x_spin_wait_count,
1518
 
                rw_x_spin_round_count,
1519
1388
                rw_x_os_wait_count);
1520
1389
 
1521
1390
        fprintf(file,