WL#14235: InnoDB: Converting old atomic code to C++11
Affects: Server-8.0 — Status: Complete
There is an old InnoDB code for atomics, but we started using C++11 atomics. To be more consistent and get rid of unnecessary code we want to remove InnoDB atomic code and use atomics from C++11 standards. We leave old behavior when it comes to memory barriers for now.
NFR1: No behavior should change. NFR2: There shouldn't be any difference in performance.
Variables, which uses os_atomic_inc_* or os_atomic_dec_*, os_compare_and_swap, test_and_swap are now changed to std::atomic<> and uses .fetch_add() and .fetch_sub() .compare_exchange_strong() .store() instead. As atomic operations are now implemented the same way on all platforms the startup diagnostic message IB_ATOMICS_STARTUP_MSG with multiple variants: • "Mutexes and rw_locks use Windows interlocked functions", • "Mutexes and rw_locks use GCC atomic builtins", and • "Mutexes use GCC atomic builtins, rw_locks do not" is now removed.
Fields that are changed to std::atomic<>: - in innorwlocktest.cc: os_n_pending_reads and os_n_pending_writes, n_s_locks, n_x_locks, n_sx_locks and test_status. (In this file removed test_mutex since it wasn't used even before my changes), - in dict0mem.cc: dict_temp_file_num, - in buf0buf.h inside buf_block_t: n_pointers, - in buf0buf.h inside buf_pool_stat_t: n_pages_read, n_pages_written, n_pages_created, n_ra_pages_read_rnd, n_ra_pages_read, - in buf0buf.h inside buf_buddy_stat_t: used, - in buf0buf.h inside buf_buddy_pool_t: n_pend_reads, n_pend_unzip, - in buf0buf.h inside buf_page_t: buf_fix_count, - in buf0flu.h inside FlushObserver: *m_flushed, and *m_removed (to be exact there is a vector of atomics, we couldn't use a vector normally since std::atomic doesn't have copy constructor, and there would be a problem when resizing vector, but there is no resizing in this case), - in dict0mem.h inside zip_pad_info_t: pad and mutex_created, - in dict0mem.h inside dict_table_t: n_foreign_key_checks_running, stats_latch_created, - in dict0mem.h inside dict_table_t mutex_created, n_foreign_checks_running, state_latch_created, autoinc_mutex_created, - in ibuf0ibuf.ic inside ibuf_t: n_merges, n_merged_ops and n_discarded_ops - in os0file.h inside struct Block: m_in_use, - in os0proc.h: os_total_large_mem_allocated, - in srv0mon.h inside monitor_value_t: mon_value, - in sync0rw.h inside rw_lock_t: lock_word_t, waiters, - in trx0purge.h inside trx_purge_t: n_completed, - in trx0sys.h inside trx_sys_t: rseg_history_len, - in trx0trx.h inside trx_t: killed_by, - in os0file.cc: os_n_pending_writes, os_n_pending_reads, - in os0proc.cc: os_total_large_mem_allocated, - in row0ins.cc inside ib_dec_in_dtor: counter, - in trx0trx.cc rseg_counter, temp_rseg_counter, - Removed os0atomic.ic - Removed most of os0atomic.h code leaving only memory barriers. - Removed struct TTASMutex since it's no longer used. - Removed definition of IB_GCC_ATOMIC_COMPARE_EXCHANGE, IB_GCC_ATOMIC_BUILTINS and IB_ATOMIC_PTHREAD_T_GCC since there are no longer used, also from cmake files. - srv_fatal_semaphore_wait_treshold is a MYSQL_SYSVAR, which used some atomic operations. Couldn't change it to std::atomic, so now we have an atomic addition - srv_fatal_semaphore_wait_extend. Also, improved code around this. - In monitor counters (srv0mon.h) in monitor_value_t there is a field mon_type_t mov_value, which sometimes was used in atomic way (in MONITOR_ATOMIC_INC and MONITOR_ATOMIC_DEC) and sometimes in "normal" way (MONITOR_INC_*, MONITOR_DEC_*). Made this std::atomic
, and in places, where we wanted it to be non-atomic, we used std::memory_order_relaxed, to leave old behavior. Also did some refactoring there, introducing inline functions, to make it easier to read the code and debug. - Added structure buf_buddy_stat_t::snapshot_t and method buf_buddy_stat_t::snapshot_t buf_buddy_stat_t.take_snapshot(), which gives a non-atomic snapshot of buf_buddy_stat_t. - In Block (os0file.h) removed byte pad, instead used alignas(ut::INNODB_CACHE_LINE_SIZE) for fields inside. - In rw_lock_t changed lock_word from lint to int32_t and waiters from ulint to bool - it used only 0 and 1, but used atomic operations, which weren't defined for bool, so couldn't be bool before.
Copyright (c) 2000, 2021, Oracle Corporation and/or its affiliates. All rights reserved.