@@ -619,7 +619,8 @@ struct srv_sys_t{
619619ulint n_sys_threads;/* !< size of the sys_threads
620620array */
621621
622- srv_slot_t sys_threads[32 + 1 ];/* !< server thread table;
622+ srv_slot_t
623+ sys_threads[srv_max_purge_threads + 1 ];/* !< server thread table;
623624os_event_set() and
624625os_event_reset() on
625626sys_threads[]->event are
@@ -661,11 +662,15 @@ and/or load it during startup. */
661662char srv_buffer_pool_dump_at_shutdown = TRUE ;
662663char srv_buffer_pool_load_at_startup = TRUE ;
663664
665+ /* * Slot index in the srv_sys.sys_threads array for the master thread. */
666+ constexpr ulint SRV_MASTER_SLOT = 0 ;
667+
664668/* * Slot index in the srv_sys.sys_threads array for the purge thread. */
665- static const ulint SRV_PURGE_SLOT = 1 ;
669+ constexpr ulint SRV_PURGE_SLOT = 1 ;
666670
667- /* * Slot index in the srv_sys.sys_threads array for the master thread. */
668- static const ulint SRV_MASTER_SLOT = 0 ;
671+ /* * Slot index in the srv_sys.sys_threads array from which purge workers start.
672+ */
673+ constexpr ulint SRV_WORKER_SLOTS_START = 2 ;
669674
670675#ifdef HAVE_PSI_STAGE_INTERFACE
671676/* * Performance schema stage event for monitoring ALTER TABLE progress
@@ -813,7 +818,7 @@ srv_reserve_slot(
813818
814819case SRV_WORKER:
815820/* Find an empty slot, skip the master and purge slots. */
816- for (slot = &srv_sys.sys_threads [2 ];
821+ for (slot = &srv_sys.sys_threads [SRV_WORKER_SLOTS_START ];
817822 slot->in_use ;
818823 ++slot) {
819824
@@ -2530,10 +2535,11 @@ srv_purge_should_exit(ulint n_purged)
25302535
25312536/* ********************************************************************/ /* *
25322537Fetch and execute a task from the work queue.
2538+ @param [in,out] slot purge worker thread slot
25332539@return true if a task was executed */
25342540static
25352541bool
2536- srv_task_execute (void )
2542+ srv_task_execute (ut_d ( srv_slot_t *slot) )
25372543/* ==================*/
25382544{
25392545que_thr_t * thr = NULL ;
@@ -2555,6 +2561,7 @@ srv_task_execute(void)
25552561mutex_exit (&srv_sys.tasks_mutex );
25562562
25572563if (thr != NULL ) {
2564+ ut_d (thr->thread_slot = slot);
25582565
25592566que_run_threads (thr);
25602567
@@ -2591,6 +2598,13 @@ DECLARE_THREAD(srv_worker_thread)(
25912598
25922599slot = srv_reserve_slot (SRV_WORKER);
25932600
2601+ #ifdef UNIV_DEBUG
2602+ UT_LIST_INIT (slot->debug_sync ,
2603+ &srv_slot_t ::debug_sync_t ::debug_sync_list);
2604+ rw_lock_create (PFS_NOT_INSTRUMENTED, &slot->debug_sync_lock ,
2605+ SYNC_NO_ORDER_CHECK);
2606+ #endif
2607+
25942608ut_a (srv_n_purge_threads > 1 );
25952609ut_a (ulong (my_atomic_loadlint (&srv_sys.n_threads_active [SRV_WORKER]))
25962610 < srv_n_purge_threads);
@@ -2603,7 +2617,7 @@ DECLARE_THREAD(srv_worker_thread)(
26032617srv_suspend_thread (slot);
26042618srv_resume_thread (slot);
26052619
2606- if (srv_task_execute ()) {
2620+ if (srv_task_execute (ut_d (slot) )) {
26072621
26082622/* If there are tasks in the queue, wakeup
26092623the purge coordinator thread. */
@@ -2640,10 +2654,15 @@ DECLARE_THREAD(srv_worker_thread)(
26402654
26412655/* * Do the actual purge operation.
26422656@param[in,out] n_total_purged total number of purged pages
2657+ @param[in,out] slot purge coordinator thread slot
26432658@return length of history list before the last purge batch. */
26442659static
26452660ulint
2646- srv_do_purge (ulint* n_total_purged)
2661+ srv_do_purge (ulint* n_total_purged
2662+ #ifdef UNIV_DEBUG
2663+ , srv_slot_t *slot
2664+ #endif
2665+ )
26472666{
26482667ulint n_pages_purged;
26492668
@@ -2709,7 +2728,11 @@ srv_do_purge(ulint* n_total_purged)
27092728
27102729n_pages_purged = trx_purge (
27112730n_use_threads, srv_purge_batch_size,
2712- (++count % rseg_truncate_frequency) == 0 );
2731+ (++count % rseg_truncate_frequency) == 0
2732+ #ifdef UNIV_DEBUG
2733+ , slot
2734+ #endif
2735+ );
27132736
27142737*n_total_purged += n_pages_purged;
27152738} while (!srv_purge_should_exit (n_pages_purged)
@@ -2829,6 +2852,12 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
28292852
28302853slot = srv_reserve_slot (SRV_PURGE);
28312854
2855+ #ifdef UNIV_DEBUG
2856+ UT_LIST_INIT (slot->debug_sync ,
2857+ &srv_slot_t ::debug_sync_t ::debug_sync_list);
2858+ rw_lock_create (PFS_NOT_INSTRUMENTED, &slot->debug_sync_lock ,
2859+ SYNC_NO_ORDER_CHECK);
2860+ #endif
28322861ulint rseg_history_len = trx_sys->rseg_history_len ;
28332862
28342863do {
@@ -2851,7 +2880,11 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
28512880
28522881n_total_purged = 0 ;
28532882
2854- rseg_history_len = srv_do_purge (&n_total_purged);
2883+ rseg_history_len = srv_do_purge (&n_total_purged
2884+ #ifdef UNIV_DEBUG
2885+ , slot
2886+ #endif
2887+ );
28552888} while (!srv_purge_should_exit (n_total_purged));
28562889
28572890/* The task queue should always be empty, independent of fast
@@ -3012,3 +3045,35 @@ srv_was_tablespace_truncated(const fil_space_t* space)
30123045return (!is_system_tablespace (space->id )
30133046&& truncate_t::was_tablespace_truncated (space->id ));
30143047}
3048+
3049+ #ifdef UNIV_DEBUG
3050+ static uint get_first_slot (srv_thread_type type)
3051+ {
3052+ switch (type) {
3053+ case SRV_MASTER:
3054+ return SRV_MASTER_SLOT;
3055+ case SRV_PURGE:
3056+ return SRV_PURGE_SLOT;
3057+ case SRV_WORKER:
3058+ /* Find an empty slot, skip the master and purge slots. */
3059+ return SRV_WORKER_SLOTS_START;
3060+ default :
3061+ ut_error;
3062+ }
3063+ }
3064+
3065+ void srv_for_each_thread (srv_thread_type type,
3066+ srv_slot_callback_t callback,
3067+ const void *arg)
3068+ {
3069+ int slot_idx= get_first_slot (type);
3070+ while (slot_idx < srv_sys.n_sys_threads
3071+ && srv_sys.sys_threads [slot_idx].in_use
3072+ && srv_sys.sys_threads [slot_idx].type == type)
3073+ {
3074+ srv_slot_t *slot= &srv_sys.sys_threads [slot_idx];
3075+ callback (slot, arg);
3076+ slot_idx++;
3077+ }
3078+ }
3079+ #endif
0 commit comments