diff --git a/3d-viewer/3d_rendering/raytracing/render_3d_raytrace_base.cpp b/3d-viewer/3d_rendering/raytracing/render_3d_raytrace_base.cpp
index 81e37c389e..8d42b2ce97 100644
--- a/3d-viewer/3d_rendering/raytracing/render_3d_raytrace_base.cpp
+++ b/3d-viewer/3d_rendering/raytracing/render_3d_raytrace_base.cpp
@@ -32,7 +32,7 @@
 #include "../color_rgba.h"
 #include "3d_fastmath.h"
 #include "3d_math.h"
-#include <core/thread_pool.h>
+#include <pgm_base.h>
 #include <core/profile.h>        // To use GetRunningMicroSecs or another profiling utility
 #include <wx/log.h>
 
@@ -190,7 +190,7 @@ void RENDER_3D_RAYTRACE_BASE::renderTracing( uint8_t* ptrPBO, REPORTER* aStatusR
     std::atomic<size_t> numBlocksRendered( 0 );
     std::atomic<size_t> currentBlock( 0 );
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
     const int timeLimit = m_blockPositions.size() > 40000 ? 750 : 400;
 
     auto processBlocks = [&]()
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a2d6d41a42..fa3cb59b67 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -918,6 +918,7 @@ set( INC_BEFORE
 
 set( INC_AFTER
     ${CMAKE_BINARY_DIR}
+    $<TARGET_PROPERTY:thread-pool,INTERFACE_INCLUDE_DIRECTORIES>
     )
 
 #
diff --git a/common/design_block_info_impl.cpp b/common/design_block_info_impl.cpp
index a4783192a1..5d22d7dbf1 100644
--- a/common/design_block_info_impl.cpp
+++ b/common/design_block_info_impl.cpp
@@ -28,7 +28,7 @@
 #include <lib_id.h>
 #include <progress_reporter.h>
 #include <string_utils.h>
-#include <core/thread_pool.h>
+#include <pgm_base.h>
 #include <wildcards_and_files_ext.h>
 
 #include <kiplatform/io.h>
@@ -164,7 +164,7 @@ bool DESIGN_BLOCK_LIST_IMPL::ReadDesignBlockFiles( DESIGN_BLOCK_LIB_TABLE* aTabl
 
 void DESIGN_BLOCK_LIST_IMPL::loadLibs()
 {
-    thread_pool&                     tp = GetKiCadThreadPool();
+    BS::thread_pool&                 tp = Pgm().GetThreadPool();
     size_t                           num_returns = m_queue_in.size();
     std::vector<std::future<size_t>> returns( num_returns );
 
@@ -221,7 +221,7 @@ void DESIGN_BLOCK_LIST_IMPL::loadDesignBlocks()
     // TODO: blast LOCALE_IO into the sun
 
     SYNC_QUEUE<std::unique_ptr<DESIGN_BLOCK_INFO>> queue_parsed;
-    thread_pool&                                tp = GetKiCadThreadPool();
+    BS::thread_pool&                            tp = Pgm().GetThreadPool();
     size_t                                      num_elements = m_queue_out.size();
     std::vector<std::future<size_t>>            returns( num_elements );
 
diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp
index eb1c92401c..ab6bfbea03 100644
--- a/common/gal/opengl/opengl_gal.cpp
+++ b/common/gal/opengl/opengl_gal.cpp
@@ -49,7 +49,6 @@
 
 #include <macros.h>
 #include <geometry/geometry_utils.h>
-#include <core/thread_pool.h>
 
 #include <core/profile.h>
 #include <trace_helpers.h>
diff --git a/common/pgm_base.cpp b/common/pgm_base.cpp
index eccf0fb5f0..715657aab7 100644
--- a/common/pgm_base.cpp
+++ b/common/pgm_base.cpp
@@ -63,7 +63,6 @@
 #include <settings/settings_manager.h>
 #include <string_utils.h>
 #include <systemdirsappend.h>
-#include <core/thread_pool.h>
 #include <trace_helpers.h>
 
 #include <widgets/wx_splash.h>
@@ -472,6 +471,10 @@ bool PGM_BASE::InitPgm( bool aHeadless, bool aSkipPyInit, bool aIsUnitTest )
 #ifdef KICAD_USE_SENTRY
     sentryInit();
 #endif
+
+    // Initialize the singleton instance
+    m_singleton.Init();
+
     wxString pgm_name;
 
     /// Should never happen but boost unit_test isn't playing nicely in some cases
diff --git a/eeschema/connection_graph.cpp b/eeschema/connection_graph.cpp
index bd36fe16a3..20993151c8 100644
--- a/eeschema/connection_graph.cpp
+++ b/eeschema/connection_graph.cpp
@@ -30,6 +30,7 @@
 #include <core/kicad_algo.h>
 #include <erc/erc.h>
 #include <pin_type.h>
+#include <pgm_base.h>
 #include <sch_bus_entry.h>
 #include <sch_symbol.h>
 #include <sch_edit_frame.h>
@@ -47,7 +48,6 @@
 #include <project/net_settings.h>
 #include <widgets/ui_common.h>
 #include <string_utils.h>
-#include <core/thread_pool.h>
 #include <wx/log.h>
 
 #include <advanced_config.h> // for realtime connectivity switch in release builds
@@ -1344,7 +1344,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
             return 1;
         };
 
-        thread_pool& tp = GetKiCadThreadPool();
+        BS::thread_pool& tp = Pgm().GetThreadPool();
 
         tp.push_loop( connection_vec.size(),
                 [&]( const int a, const int b)
@@ -1500,7 +1500,7 @@ void CONNECTION_GRAPH::resolveAllDrivers()
         return 1;
     };
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
 
     tp.push_loop( dirty_graphs.size(),
             [&]( const int a, const int b)
@@ -2136,7 +2136,7 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
     for( CONNECTION_SUBGRAPH* subgraph : m_driver_subgraphs )
         m_sheet_to_subgraphs_map[ subgraph->m_sheet ].emplace_back( subgraph );
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
 
     tp.push_loop( m_driver_subgraphs.size(),
             [&]( const int a, const int b)
diff --git a/eeschema/sim/spice_library_parser.cpp b/eeschema/sim/spice_library_parser.cpp
index 64008e55c4..25cde4768d 100644
--- a/eeschema/sim/spice_library_parser.cpp
+++ b/eeschema/sim/spice_library_parser.cpp
@@ -26,7 +26,7 @@
 
 #include <utility>
 
-#include <core/thread_pool.h>
+#include <pgm_base.h>
 #include <ki_exception.h>
 #include <sim/sim_library_spice.h>
 #include <sim/spice_grammar.h>
@@ -138,7 +138,7 @@ void SPICE_LIBRARY_PARSER::ReadFile( const wxString& aFilePath, REPORTER& aRepor
             };
 
     // Read all self-contained models in parallel
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
 
     tp.push_loop( modelQueue.size(),
             [&]( const int a, const int b )
diff --git a/include/pgm_base.h b/include/pgm_base.h
index 3608101e16..e43906fca9 100644
--- a/include/pgm_base.h
+++ b/include/pgm_base.h
@@ -32,6 +32,7 @@
 #define  PGM_BASE_H_
 
 #include <kicommon.h>
+#include <singleton.h>
 #include <exception>
 #include <map>
 #include <vector>
@@ -104,33 +105,13 @@ public:
     PGM_BASE();
     virtual ~PGM_BASE();
 
-#if 0
-    /*
-
-    Derived classes must implement these two functions: OnPgmInit() and
-    OnPgmExit(), and since they are only called from same source file as their
-    implementation, these need not be virtual here. In fact, in the case of
-    python project manager's class PGM_PYTHON, these functions are actually
-    written in python. In total there are three implementations, corresponding
-    to the three defines given by kiface.h's KFCTL_* #defines.
-
-    */
-
-    /**
-     * This is the first executed function (like main() ).
-     *
-     * @return true if the application can be started.
-     */
-    virtual bool OnPgmInit() = 0;           // call this from wxApp::OnInit()
-
-    virtual void OnPgmExit() = 0;           // call this from wxApp::OnExit()
-#endif
-
     /**
      * Builds the UTF8 based argv variable
      */
     void BuildArgvUtf8();
 
+    BS::thread_pool& GetThreadPool() { return *m_singleton.m_ThreadPool; }
+
     /**
      * Specific to MacOSX (not used under Linux or Windows).
      *
@@ -429,6 +410,8 @@ protected:
 
     wxString        m_text_editor;
 
+    KICAD_SINGLETON m_singleton;
+
 #ifdef KICAD_USE_SENTRY
     wxFileName      m_sentry_optin_fn;
     wxFileName      m_sentry_uid_fn;
diff --git a/include/singleton.h b/include/singleton.h
new file mode 100644
index 0000000000..7a0f5f1a86
--- /dev/null
+++ b/include/singleton.h
@@ -0,0 +1,48 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KICAD_SINGLETON_H
+#define KICAD_SINGLETON_H
+
+#include <bs_thread_pool.hpp>
+
+class KICAD_SINGLETON
+{
+public:
+    KICAD_SINGLETON(){};
+
+    ~KICAD_SINGLETON()
+    {
+        // This will wait for all threads to finish and then join them to the main thread
+        delete m_ThreadPool;
+
+        m_ThreadPool = nullptr;
+    };
+
+
+    void Init()
+    {
+        m_ThreadPool = new BS::thread_pool();
+    }
+
+    BS::thread_pool* m_ThreadPool;
+};
+
+
+#endif // KICAD_SINGLETON_H
\ No newline at end of file
diff --git a/kicad/pcm/CMakeLists.txt b/kicad/pcm/CMakeLists.txt
index 4d56751046..fe1ac3ae59 100644
--- a/kicad/pcm/CMakeLists.txt
+++ b/kicad/pcm/CMakeLists.txt
@@ -5,6 +5,7 @@ if( COMPILER_SUPPORTS_WARNINGS )
 endif()
 
 include_directories( BEFORE ${INC_BEFORE} )
+include_directories( AFTER ${INC_AFTER} )
 
 add_compile_definitions( PCM )
 
diff --git a/kicad/update_manager.cpp b/kicad/update_manager.cpp
index 522685b1db..a622580693 100644
--- a/kicad/update_manager.cpp
+++ b/kicad/update_manager.cpp
@@ -48,10 +48,8 @@
 #include <wx/notifmsg.h>
 
 #include <background_jobs_monitor.h>
-
-#include <core/thread_pool.h>
-
 #include <build_version.h>
+#include <pgm_base.h>
 
 
 struct UPDATE_REQUEST
@@ -261,6 +259,6 @@ void UPDATE_MANAGER::CheckForUpdate( wxWindow* aNoticeParent )
         m_working = false;
     };
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
     tp.push_task( update_check );
 }
diff --git a/libs/core/CMakeLists.txt b/libs/core/CMakeLists.txt
index 6c351a3143..1e8bc33dfe 100644
--- a/libs/core/CMakeLists.txt
+++ b/libs/core/CMakeLists.txt
@@ -10,7 +10,6 @@ add_library( core STATIC
     observable.cpp
     profile.cpp
     utf8.cpp
-    thread_pool.cpp
     version_compare.cpp
     wx_stl_compat.cpp
 )
@@ -21,7 +20,6 @@ target_link_libraries( core PUBLIC
 
 target_include_directories( core PUBLIC
     ${CMAKE_CURRENT_SOURCE_DIR}/include
-    $<TARGET_PROPERTY:thread-pool,INTERFACE_INCLUDE_DIRECTORIES>
     PRIVATE
     ${CMAKE_BINARY_DIR} # to get config.h
 )
\ No newline at end of file
diff --git a/libs/core/include/core/thread_pool.h b/libs/core/include/core/thread_pool.h
deleted file mode 100644
index 90a0bd87ad..0000000000
--- a/libs/core/include/core/thread_pool.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright The KiCad Developers, see CHANGELOG.TXT for contributors.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, you may find one here:
- * http://www.gnu.org/licenses/gpl-3.0.html
- * or you may search the http://www.gnu.org website for the version 3 license,
- * or you may write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-#pragma once
-#ifndef INCLUDE_THREAD_POOL_H_
-#define INCLUDE_THREAD_POOL_H_
-
-#include <bs_thread_pool.hpp>
-
-using thread_pool = BS::thread_pool;
-
-/**
- * Get a reference to the current thread pool.  N.B., you cannot copy the thread pool
- * so if you accidentally write thread_pool tp = GetKiCadThreadPool(), you will break
- * your compilation
- *
- * @return Reference to the current (potentially newly constructed) thread pool
- */
-thread_pool& GetKiCadThreadPool();
-
-
-#endif /* INCLUDE_THREAD_POOL_H_ */
diff --git a/libs/core/thread_pool.cpp b/libs/core/thread_pool.cpp
deleted file mode 100644
index b03a07d74f..0000000000
--- a/libs/core/thread_pool.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright The KiCad Developers, see CHANGELOG.TXT for contributors.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, you may find one here:
- * http://www.gnu.org/licenses/gpl-3.0.html
- * or you may search the http://www.gnu.org website for the version 3 license,
- * or you may write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-
-#include <core/thread_pool.h>
-
-// Under mingw, there is a problem with the destructor when creating a static instance
-// of a thread_pool: probably the DTOR is called too late, and the application hangs.
-// so we create it on the heap.
-static thread_pool* tp = nullptr;
-
-thread_pool& GetKiCadThreadPool()
-{
-#if 0   // Turn this on to disable multi-threading for debugging
-    if( !tp ) tp = new thread_pool( 1 );
-#else
-    if( !tp ) tp = new thread_pool;
-#endif
-
-    return *tp;
-}
diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp
index 284530ee69..32fcfd5786 100644
--- a/pcbnew/board.cpp
+++ b/pcbnew/board.cpp
@@ -63,7 +63,6 @@
 #include <tool/tool_manager.h>
 #include <tool/selection_conditions.h>
 #include <string_utils.h>
-#include <core/thread_pool.h>
 #include <zone.h>
 #include <mutex>
 
@@ -982,7 +981,7 @@ void BOARD::CacheTriangulation( PROGRESS_REPORTER* aReporter, const std::vector<
     if( aReporter )
         aReporter->Report( _( "Tessellating copper zones..." ) );
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
     std::vector<std::future<size_t>> returns;
 
     returns.reserve( zones.size() );
diff --git a/pcbnew/connectivity/connectivity_algo.cpp b/pcbnew/connectivity/connectivity_algo.cpp
index 5bcb169bfe..dacc238de9 100644
--- a/pcbnew/connectivity/connectivity_algo.cpp
+++ b/pcbnew/connectivity/connectivity_algo.cpp
@@ -33,8 +33,8 @@
 #include <progress_reporter.h>
 #include <geometry/geometry_utils.h>
 #include <board_commit.h>
-#include <core/thread_pool.h>
 #include <pcb_shape.h>
+#include <pgm_base.h>
 
 #include <wx/log.h>
 
@@ -249,7 +249,7 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
     PROF_TIMER search_basic( "search-basic" );
 #endif
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
     std::vector<CN_ITEM*> dirtyItems;
     std::copy_if( m_itemList.begin(), m_itemList.end(), std::back_inserter( dirtyItems ),
                   [] ( CN_ITEM* aItem )
@@ -495,7 +495,7 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
 
     // Generate RTrees for CN_ZONE_LAYER items (in parallel)
     //
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
     std::vector<std::future<size_t>> returns( zitems.size() );
 
     auto cache_zones =
diff --git a/pcbnew/connectivity/connectivity_data.cpp b/pcbnew/connectivity/connectivity_data.cpp
index 43df014541..5954542a49 100644
--- a/pcbnew/connectivity/connectivity_data.cpp
+++ b/pcbnew/connectivity/connectivity_data.cpp
@@ -39,8 +39,8 @@
 #include <geometry/shape_segment.h>
 #include <geometry/shape_circle.h>
 #include <ratsnest/ratsnest_data.h>
+#include <pgm_base.h>
 #include <progress_reporter.h>
-#include <core/thread_pool.h>
 #include <trigo.h>
 #include <drc/drc_rtree.h>
 
@@ -190,7 +190,7 @@ void CONNECTIVITY_DATA::updateRatsnest()
                 return aNet->IsDirty() && aNet->GetNodeCount() > 0;
             } );
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
 
     tp.push_loop( dirty_nets.size(),
             [&]( const int a, const int b )
@@ -371,7 +371,7 @@ void CONNECTIVITY_DATA::ComputeLocalRatsnest( const std::vector<BOARD_ITEM*>& aI
         }
     };
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
     size_t num_nets = std::min( m_nets.size(), aDynamicData->m_nets.size() );
 
     tp.push_loop( 1, num_nets,
diff --git a/pcbnew/dialogs/dialog_export_odbpp.cpp b/pcbnew/dialogs/dialog_export_odbpp.cpp
index 62aa78dc0a..67bf8f28d2 100644
--- a/pcbnew/dialogs/dialog_export_odbpp.cpp
+++ b/pcbnew/dialogs/dialog_export_odbpp.cpp
@@ -37,7 +37,6 @@
 
 #include <set>
 #include <vector>
-#include <core/thread_pool.h>
 #include <io/io_mgr.h>
 #include <jobs/job_export_pcb_odb.h>
 #include <pcb_io/pcb_io_mgr.h>
@@ -467,7 +466,7 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
         }
     };
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
     auto         ret = tp.submit( saveFile );
 
     std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
diff --git a/pcbnew/drc/drc_cache_generator.cpp b/pcbnew/drc/drc_cache_generator.cpp
index 5a5b5441b4..a7aa7b2e76 100644
--- a/pcbnew/drc/drc_cache_generator.cpp
+++ b/pcbnew/drc/drc_cache_generator.cpp
@@ -24,7 +24,7 @@
 #include <common.h>
 #include <board_design_settings.h>
 #include <footprint.h>
-#include <core/thread_pool.h>
+#include <pgm_base.h>
 #include <zone.h>
 #include <connectivity/connectivity_data.h>
 #include <drc/drc_engine.h>
@@ -36,11 +36,11 @@ bool DRC_CACHE_GENERATOR::Run()
 {
     m_board = m_drcEngine->GetBoard();
 
-    int&           largestClearance = m_board->m_DRCMaxClearance;
-    int&           largestPhysicalClearance = m_board->m_DRCMaxPhysicalClearance;
-    DRC_CONSTRAINT worstConstraint;
-    LSET           boardCopperLayers = LSET::AllCuMask( m_board->GetCopperLayerCount() );
-    thread_pool&   tp = GetKiCadThreadPool();
+    int&             largestClearance = m_board->m_DRCMaxClearance;
+    int&             largestPhysicalClearance = m_board->m_DRCMaxPhysicalClearance;
+    DRC_CONSTRAINT   worstConstraint;
+    LSET             boardCopperLayers = LSET::AllCuMask( m_board->GetCopperLayerCount() );
+    BS::thread_pool& tp = Pgm().GetThreadPool();
 
 
     largestClearance = std::max( largestClearance, m_board->GetMaxClearanceValue() );
diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp
index e4ceab9bb7..b4792b56dc 100644
--- a/pcbnew/drc/drc_engine.cpp
+++ b/pcbnew/drc/drc_engine.cpp
@@ -41,7 +41,6 @@
 #include <pad.h>
 #include <pcb_track.h>
 #include <core/profile.h>
-#include <core/thread_pool.h>
 #include <zone.h>
 
 
diff --git a/pcbnew/drc/drc_test_provider_connection_width.cpp b/pcbnew/drc/drc_test_provider_connection_width.cpp
index c543a1da47..c602e6cf72 100644
--- a/pcbnew/drc/drc_test_provider_connection_width.cpp
+++ b/pcbnew/drc/drc_test_provider_connection_width.cpp
@@ -45,9 +45,9 @@
 #include <math/vector2d.h>
 #include <pcb_shape.h>
 #include <progress_reporter.h>
-#include <core/thread_pool.h>
 #include <pcb_track.h>
 #include <pad.h>
+#include <pgm_base.h>
 #include <zone.h>
 
 /*
@@ -520,7 +520,7 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
         }
     }
 
-    thread_pool&                     tp = GetKiCadThreadPool();
+    BS::thread_pool&                 tp = Pgm().GetThreadPool();
     std::vector<std::future<size_t>> returns;
     size_t                           total_effort = 0;
 
diff --git a/pcbnew/drc/drc_test_provider_copper_clearance.cpp b/pcbnew/drc/drc_test_provider_copper_clearance.cpp
index a5364e98d8..fcd8e52b06 100644
--- a/pcbnew/drc/drc_test_provider_copper_clearance.cpp
+++ b/pcbnew/drc/drc_test_provider_copper_clearance.cpp
@@ -29,7 +29,7 @@
 #include <pcb_shape.h>
 #include <pad.h>
 #include <pcb_track.h>
-#include <core/thread_pool.h>
+#include <pgm_base.h>
 #include <zone.h>
 
 #include <geometry/seg.h>
@@ -724,7 +724,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
         }
     };
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
 
     tp.push_loop( m_board->Tracks().size(), testTrack );
 
@@ -978,7 +978,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadAgainstItem( PAD* pad, SHAPE* pa
 
 void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadClearances( )
 {
-    thread_pool&        tp = GetKiCadThreadPool();
+    BS::thread_pool&    tp = Pgm().GetThreadPool();
     size_t              count = 0;
     std::atomic<size_t> done( 1 );
 
@@ -1062,7 +1062,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadClearances( )
 
 void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testGraphicClearances( )
 {
-    thread_pool&        tp = GetKiCadThreadPool();
+    BS::thread_pool&    tp = Pgm().GetThreadPool();
     size_t              count = m_board->Drawings().size();
     std::atomic<size_t> done( 1 );
 
@@ -1226,7 +1226,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
     using report_data = std::tuple<int, int, VECTOR2I, int, int, PCB_LAYER_ID>;
 
     std::vector<std::future<report_data>> futures;
-    thread_pool&                          tp = GetKiCadThreadPool();
+    BS::thread_pool&                      tp = Pgm().GetThreadPool();
     std::atomic<size_t>                   done( 1 );
 
     auto checkZones =
diff --git a/pcbnew/drc/drc_test_provider_disallow.cpp b/pcbnew/drc/drc_test_provider_disallow.cpp
index 3177125708..cf322f75c1 100644
--- a/pcbnew/drc/drc_test_provider_disallow.cpp
+++ b/pcbnew/drc/drc_test_provider_disallow.cpp
@@ -31,7 +31,7 @@
 #include <drc/drc_test_provider.h>
 #include <pad.h>
 #include <progress_reporter.h>
-#include <core/thread_pool.h>
+#include <pgm_base.h>
 #include <zone.h>
 #include <mutex>
 
@@ -173,7 +173,7 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
                 return 1;
             };
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool&                 tp = Pgm().GetThreadPool();
     std::vector<std::future<size_t>> returns;
 
     returns.reserve( toCache.size() );
diff --git a/pcbnew/drc/drc_test_provider_sliver_checker.cpp b/pcbnew/drc/drc_test_provider_sliver_checker.cpp
index ed61c01b19..d39b536126 100644
--- a/pcbnew/drc/drc_test_provider_sliver_checker.cpp
+++ b/pcbnew/drc/drc_test_provider_sliver_checker.cpp
@@ -22,18 +22,19 @@
  */
 
 #include <atomic>
+
+#include <advanced_config.h>
 #include <board.h>
 #include <board_design_settings.h>
-#include <zone.h>
-#include <footprint.h>
-#include <pcb_shape.h>
-#include <geometry/shape_poly_set.h>
-#include <drc/drc_rule.h>
 #include <drc/drc_item.h>
+#include <drc/drc_rule.h>
 #include <drc/drc_test_provider.h>
-#include <advanced_config.h>
+#include <footprint.h>
+#include <geometry/shape_poly_set.h>
+#include <pcb_shape.h>
+#include <pgm_base.h>
 #include <progress_reporter.h>
-#include <core/thread_pool.h>
+#include <zone.h>
 
 /*
     Checks for slivers in copper layers
@@ -160,7 +161,7 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
                 return 1;
             };
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool&                 tp = Pgm().GetThreadPool();
     std::vector<std::future<size_t>> returns;
 
     returns.reserve( copperLayers.size() );
diff --git a/pcbnew/drc/drc_test_provider_track_angle.cpp b/pcbnew/drc/drc_test_provider_track_angle.cpp
index 26ed943766..2f4a77a340 100644
--- a/pcbnew/drc/drc_test_provider_track_angle.cpp
+++ b/pcbnew/drc/drc_test_provider_track_angle.cpp
@@ -21,15 +21,16 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <core/thread_pool.h>
-#include "geometry/eda_angle.h"
 #include <numbers>
-#include <pcb_track.h>
+
+#include <connectivity/connectivity_data.h>
 #include <drc/drc_engine.h>
 #include <drc/drc_item.h>
 #include <drc/drc_rule.h>
 #include <drc/drc_test_provider.h>
-#include <connectivity/connectivity_data.h>
+#include <geometry/eda_angle.h>
+#include <pcb_track.h>
+#include <pgm_base.h>
 
 
 /*
@@ -204,7 +205,7 @@ bool DRC_TEST_PROVIDER_TRACK_ANGLE::Run()
     const int progressDelta = 250;
     int       ii = 0;
 
-    thread_pool&                   tp = GetKiCadThreadPool();
+    BS::thread_pool&               tp = Pgm().GetThreadPool();
     std::vector<std::future<bool>> returns;
 
     returns.reserve( m_drcEngine->GetBoard()->Tracks().size() );
diff --git a/pcbnew/drc/drc_test_provider_track_segment_length.cpp b/pcbnew/drc/drc_test_provider_track_segment_length.cpp
index 2147d9c5a0..da4838d2b7 100644
--- a/pcbnew/drc/drc_test_provider_track_segment_length.cpp
+++ b/pcbnew/drc/drc_test_provider_track_segment_length.cpp
@@ -21,12 +21,12 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <core/thread_pool.h>
-#include <pcb_track.h>
 #include <drc/drc_engine.h>
 #include <drc/drc_item.h>
 #include <drc/drc_rule.h>
 #include <drc/drc_test_provider.h>
+#include <pcb_track.h>
+#include <pgm_base.h>
 
 
 /*
@@ -161,7 +161,7 @@ bool DRC_TEST_PROVIDER_TRACK_SEGMENT_LENGTH::Run()
     const int progressDelta = 250;
     int       ii = 0;
 
-    thread_pool&                   tp = GetKiCadThreadPool();
+    BS::thread_pool&               tp = Pgm().GetThreadPool();
     std::vector<std::future<bool>> returns;
 
     returns.reserve( m_drcEngine->GetBoard()->Tracks().size() );
diff --git a/pcbnew/drc/drc_test_provider_zone_connections.cpp b/pcbnew/drc/drc_test_provider_zone_connections.cpp
index dd77db80da..26fb9f731f 100644
--- a/pcbnew/drc/drc_test_provider_zone_connections.cpp
+++ b/pcbnew/drc/drc_test_provider_zone_connections.cpp
@@ -23,13 +23,13 @@
 
 #include <board.h>
 #include <board_design_settings.h>
-#include <connectivity/connectivity_data.h>
-#include <zone.h>
 #include <footprint.h>
 #include <pad.h>
 #include <pcb_track.h>
-#include <core/thread_pool.h>
+#include <pgm_base.h>
+#include <zone.h>
 
+#include <connectivity/connectivity_data.h>
 #include <geometry/shape_line_chain.h>
 #include <geometry/shape_poly_set.h>
 #include <drc/drc_rule.h>
@@ -272,7 +272,7 @@ bool DRC_TEST_PROVIDER_ZONE_CONNECTIONS::Run()
 
     total_effort = std::max( (size_t) 1, total_effort );
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool&              tp = Pgm().GetThreadPool();
     std::vector<std::future<int>> returns;
 
     returns.reserve( zoneLayers.size() );
diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp
index b4849fbf4a..9613568c51 100644
--- a/pcbnew/files.cpp
+++ b/pcbnew/files.cpp
@@ -29,7 +29,6 @@
 #include <confirm.h>
 #include <kidialog.h>
 #include <core/arraydim.h>
-#include <core/thread_pool.h>
 #include <dialog_HTML_reporter_base.h>
 #include <gestfich.h>
 #include <pcb_edit_frame.h>
@@ -1344,7 +1343,7 @@ void PCB_EDIT_FRAME::GenIPC2581File( wxCommandEvent& event )
                 }
             };
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
     auto ret = tp.submit( saveFile );
 
 
diff --git a/pcbnew/footprint_info_impl.cpp b/pcbnew/footprint_info_impl.cpp
index f101b93dc6..e3f88a02f9 100644
--- a/pcbnew/footprint_info_impl.cpp
+++ b/pcbnew/footprint_info_impl.cpp
@@ -29,9 +29,9 @@
 #include <kiway.h>
 #include <locale_io.h>
 #include <lib_id.h>
+#include <pgm_base.h>
 #include <progress_reporter.h>
 #include <string_utils.h>
-#include <core/thread_pool.h>
 #include <wildcards_and_files_ext.h>
 
 #include <kiplatform/io.h>
@@ -178,7 +178,7 @@ bool FOOTPRINT_LIST_IMPL::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxStri
 
 void FOOTPRINT_LIST_IMPL::loadLibs()
 {
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
     size_t num_returns = m_queue_in.size();
     std::vector<std::future<size_t>> returns( num_returns );
 
@@ -235,7 +235,7 @@ void FOOTPRINT_LIST_IMPL::loadFootprints()
     // TODO: blast LOCALE_IO into the sun
 
     SYNC_QUEUE<std::unique_ptr<FOOTPRINT_INFO>> queue_parsed;
-    thread_pool&                                tp = GetKiCadThreadPool();
+    BS::thread_pool&                            tp = Pgm().GetThreadPool();
     size_t                                      num_elements = m_queue_out.size();
     std::vector<std::future<size_t>>            returns( num_elements );
 
diff --git a/pcbnew/tracks_cleaner.cpp b/pcbnew/tracks_cleaner.cpp
index bd72b79f74..50585ce727 100644
--- a/pcbnew/tracks_cleaner.cpp
+++ b/pcbnew/tracks_cleaner.cpp
@@ -31,8 +31,8 @@
 #include <cleanup_item.h>
 #include <connectivity/connectivity_algo.h>
 #include <connectivity/connectivity_data.h>
-#include <core/thread_pool.h>
 #include <lset.h>
+#include <pgm_base.h>
 #include <tool/tool_manager.h>
 #include <tools/pcb_actions.h>
 #include <tools/global_edit_tool.h>
@@ -572,7 +572,7 @@ void TRACKS_CLEANER::cleanup( bool aDeleteDuplicateVias, bool aDeleteNullSegment
         // The idea here is to parallelize the loop that does not modify the connectivity
         // and extract all of the pairs of segments that might be merged.  Then, perform
         // the actual merge in the main loop.
-        thread_pool& tp = GetKiCadThreadPool();
+        BS::thread_pool& tp = Pgm().GetThreadPool();
         auto merge_returns = tp.parallelize_loop( 0, m_brd->Tracks().size(), track_loop );
 
         for( size_t ii = 0; ii < merge_returns.size(); ++ii )
diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp
index 77805f8f95..5ba4b82a45 100644
--- a/pcbnew/zone_filler.cpp
+++ b/pcbnew/zone_filler.cpp
@@ -38,6 +38,7 @@
 #include <pcb_tablecell.h>
 #include <pcb_table.h>
 #include <pcb_dimension.h>
+#include <pgm_base.h>
 #include <connectivity/connectivity_data.h>
 #include <convert_basic_shapes_to_polygon.h>
 #include <board_commit.h>
@@ -47,7 +48,6 @@
 #include <geometry/geometry_utils.h>
 #include <geometry/vertex_set.h>
 #include <kidialog.h>
-#include <core/thread_pool.h>
 #include <math/util.h>      // for KiROUND
 #include "zone_filler.h"
 
@@ -592,7 +592,7 @@ bool ZONE_FILLER::Fill( const std::vector<ZONE*>& aZones, bool aCheck, wxWindow*
     size_t finished = 0;
     bool cancelled = false;
 
-    thread_pool& tp = GetKiCadThreadPool();
+    BS::thread_pool& tp = Pgm().GetThreadPool();
 
     for( const std::pair<ZONE*, PCB_LAYER_ID>& fillItem : toFill )
         returns.emplace_back( std::make_pair( tp.submit( fill_lambda, fillItem ), 0 ) );
diff --git a/qa/qa_utils/CMakeLists.txt b/qa/qa_utils/CMakeLists.txt
index 1ba96e8f8c..aadd363e62 100644
--- a/qa/qa_utils/CMakeLists.txt
+++ b/qa/qa_utils/CMakeLists.txt
@@ -39,6 +39,7 @@ add_library( qa_utils STATIC
 )
 
 include_directories( BEFORE ${INC_BEFORE} )
+include_directories( AFTER ${INC_AFTER} )
 
 # for some obscure reason, on mingw/msys2 Boost::unit_test_framework does not work
 # So use the actual lib filename:
diff --git a/qa/tests/CMakeLists.txt b/qa/tests/CMakeLists.txt
index 05424f1937..4467ea42a3 100644
--- a/qa/tests/CMakeLists.txt
+++ b/qa/tests/CMakeLists.txt
@@ -31,6 +31,8 @@ if( KICAD_SPICE_QA )
     add_subdirectory( spice )
 endif()
 
+include_directories( AFTER ${INC_AFTER} )
+
 if( KICAD_TEST_XML_OUTPUT )
     # To do this, you will need xmlrunner
     set( PYTEST_ARGS_QAPYTHON --junitxml=${CMAKE_CURRENT_BINARY_DIR}/qapython.junit-results.xml )
diff --git a/qa/tests/gerbview/CMakeLists.txt b/qa/tests/gerbview/CMakeLists.txt
index 8a1b0442c3..4056dd534c 100644
--- a/qa/tests/gerbview/CMakeLists.txt
+++ b/qa/tests/gerbview/CMakeLists.txt
@@ -20,6 +20,8 @@
 # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
 
+include_directories( AFTER ${INC_AFTER} )
+
 set( QA_GERBVIEW_SRCS
     # The main test entry points
     test_module.cpp
diff --git a/qa/tests/libs/kimath/CMakeLists.txt b/qa/tests/libs/kimath/CMakeLists.txt
index 4aa7cd2b27..64f71f0c12 100644
--- a/qa/tests/libs/kimath/CMakeLists.txt
+++ b/qa/tests/libs/kimath/CMakeLists.txt
@@ -22,6 +22,8 @@
 #
 # Unit tests for KiCad math routines.
 
+include_directories( AFTER ${INC_AFTER} )
+
 set( QA_KIMATH_SRCS
     kimath_test_module.cpp
 
diff --git a/scripting/CMakeLists.txt b/scripting/CMakeLists.txt
index 5ec2face6b..b8b91bc584 100644
--- a/scripting/CMakeLists.txt
+++ b/scripting/CMakeLists.txt
@@ -40,6 +40,7 @@ set_source_files_properties( kicad_scripting_main.cpp PROPERTIES
     )
 
 target_include_directories( scripting_kiface PRIVATE
+    $<TARGET_PROPERTY:thread-pool,INTERFACE_INCLUDE_DIRECTORIES>
     ${PROJECT_SOURCE_DIR}/resources/bitmaps_png/include
     ${PROJECT_SOURCE_DIR}/include
     ${wxWidgets_LIBRARIES}