From 45959f9d1c5cecacfd2c673623b00cdc989df9d8 Mon Sep 17 00:00:00 2001 From: Hayodea Hekol Date: Fri, 26 Dec 2025 01:18:39 -0400 Subject: [PATCH] Libspinscale: begin splitting it off --- CMakeLists.txt | 2 + .../attachmentSupport/stimulusProducer.cpp | 2 +- commonLibs/livoxProto1/broadcastListener.h | 2 +- commonLibs/livoxProto1/core.cpp | 4 +- commonLibs/livoxProto1/core.h | 2 +- commonLibs/livoxProto1/device.cpp | 4 +- commonLibs/livoxProto1/device.h | 4 +- commonLibs/livoxProto1/livoxProto1.cpp | 2 +- commonLibs/livoxProto1/livoxProto1.h | 2 +- commonLibs/livoxProto1/udpCommandDemuxer.h | 2 +- include/user/senseApiDesc.h | 2 +- include/user/stimulusProducer.h | 2 +- libspinscale/CMakeLists.txt | 45 +++ .../include/spinscale}/asynchronousBridge.h | 0 .../spinscale}/asynchronousContinuation.h | 6 +- .../asynchronousContinuationChainLink.h | 0 .../include/spinscale}/asynchronousLoop.h | 0 .../include/spinscale}/callableTracer.h | 19 +- .../include/spinscale}/callback.h | 6 +- .../include/spinscale}/component.h | 2 +- .../include/spinscale/componentThread.h | 170 +++++++++ .../include/spinscale}/dependencyGraph.h | 0 .../include/spinscale}/lockSet.h | 4 +- .../include/spinscale}/lockerAndInvokerBase.h | 0 .../include/spinscale}/qutex.h | 4 +- .../qutexAcquisitionHistoryTracker.h | 0 .../serializedAsynchronousContinuation.h | 10 +- .../include/spinscale}/spinLock.h | 0 {smocore => libspinscale/src}/component.cpp | 2 +- libspinscale/src/componentThread.cpp | 318 +++++++++++++++++ libspinscale/src/lockerAndInvokerBase.cpp | 5 + {smocore => libspinscale/src}/qutex.cpp | 4 +- .../src}/qutexAcquisitionHistoryTracker.cpp | 8 +- main.cpp | 4 +- smocore/CMakeLists.txt | 16 +- smocore/body/body.cpp | 16 +- smocore/componentThread.cpp | 322 ++---------------- smocore/deviceManager/deviceManager.cpp | 12 +- smocore/deviceManager/deviceReattacher.cpp | 2 +- smocore/include/body/body.h | 4 +- smocore/include/componentThread.h | 185 +--------- smocore/include/deviceManager/device.h | 2 +- smocore/include/deviceManager/deviceManager.h | 6 +- .../include/deviceManager/deviceReattacher.h | 2 +- smocore/include/director/director.h | 2 +- smocore/include/marionette/marionette.h | 2 +- smocore/include/mind.h | 8 +- smocore/include/mindThread.h | 32 ++ smocore/include/simulator/simulator.h | 2 +- smocore/include/stimBuffApis/stimBuffApiLib.h | 2 +- .../include/stimBuffApis/stimBuffApiManager.h | 6 +- smocore/lockerAndInvokerBase.cpp | 5 - smocore/marionette/lifetime.cpp | 20 +- smocore/marionette/main.cpp | 2 +- smocore/marionette/negtrinEvent.cpp | 2 +- smocore/mind.cpp | 30 +- smocore/mindThread.cpp | 12 + smocore/stimBuffApis/stimBuffApiManager.cpp | 8 +- .../livoxGen1/ioUringAssemblyEngine.cpp | 12 +- .../livoxGen1/ioUringAssemblyEngine.h | 8 +- stimBuffApis/livoxGen1/livoxGen1.cpp | 4 +- .../openClCollatingAndMeshingEngine.cpp | 8 +- .../openClCollatingAndMeshingEngine.h | 6 +- .../livoxGen1/pcloudStimulusProducer.cpp | 6 +- .../livoxGen1/pcloudStimulusProducer.h | 4 +- stimBuffApis/xcbWindow/xcbWindow.cpp | 2 +- tests/smocore/qutex_tests.cpp | 4 +- 67 files changed, 776 insertions(+), 615 deletions(-) create mode 100644 libspinscale/CMakeLists.txt rename {include => libspinscale/include/spinscale}/asynchronousBridge.h (100%) rename {include => libspinscale/include/spinscale}/asynchronousContinuation.h (97%) rename {include => libspinscale/include/spinscale}/asynchronousContinuationChainLink.h (100%) rename {include => libspinscale/include/spinscale}/asynchronousLoop.h (100%) rename {include => libspinscale/include/spinscale}/callableTracer.h (87%) rename {include => libspinscale/include/spinscale}/callback.h (88%) rename {smocore/include => libspinscale/include/spinscale}/component.h (94%) create mode 100644 libspinscale/include/spinscale/componentThread.h rename {include => libspinscale/include/spinscale}/dependencyGraph.h (100%) rename {include => libspinscale/include/spinscale}/lockSet.h (98%) rename {include => libspinscale/include/spinscale}/lockerAndInvokerBase.h (100%) rename {include => libspinscale/include/spinscale}/qutex.h (97%) rename {include => libspinscale/include/spinscale}/qutexAcquisitionHistoryTracker.h (100%) rename {include => libspinscale/include/spinscale}/serializedAsynchronousContinuation.h (98%) rename {include => libspinscale/include/spinscale}/spinLock.h (100%) rename {smocore => libspinscale/src}/component.cpp (93%) create mode 100644 libspinscale/src/componentThread.cpp create mode 100644 libspinscale/src/lockerAndInvokerBase.cpp rename {smocore => libspinscale/src}/qutex.cpp (99%) rename {smocore => libspinscale/src}/qutexAcquisitionHistoryTracker.cpp (98%) create mode 100644 smocore/include/mindThread.h delete mode 100644 smocore/lockerAndInvokerBase.cpp create mode 100644 smocore/mindThread.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8904980..d79d6b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,7 @@ configure_file( # Include directories include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/libspinscale/include ${CMAKE_CURRENT_SOURCE_DIR}/smocore/include ${CMAKE_CURRENT_BINARY_DIR}/include ) @@ -177,6 +178,7 @@ if(ENABLE_TESTS) add_subdirectory(third_party) endif() add_subdirectory(compile) +add_subdirectory(libspinscale) # Add core components add_subdirectory(smocore) add_subdirectory(commonLibs) diff --git a/commonLibs/attachmentSupport/stimulusProducer.cpp b/commonLibs/attachmentSupport/stimulusProducer.cpp index 95b2a11..3dda6cf 100644 --- a/commonLibs/attachmentSupport/stimulusProducer.cpp +++ b/commonLibs/attachmentSupport/stimulusProducer.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include diff --git a/commonLibs/livoxProto1/broadcastListener.h b/commonLibs/livoxProto1/broadcastListener.h index 7f0ed83..4963a77 100644 --- a/commonLibs/livoxProto1/broadcastListener.h +++ b/commonLibs/livoxProto1/broadcastListener.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include "device.h" namespace livoxProto1 { diff --git a/commonLibs/livoxProto1/core.cpp b/commonLibs/livoxProto1/core.cpp index 6359f92..f096974 100644 --- a/commonLibs/livoxProto1/core.cpp +++ b/commonLibs/livoxProto1/core.cpp @@ -3,8 +3,8 @@ #include #include #include -#include -#include +#include +#include #include #include "protocol.h" #include "core.h" diff --git a/commonLibs/livoxProto1/core.h b/commonLibs/livoxProto1/core.h index 4ddddde..9cb6a9d 100644 --- a/commonLibs/livoxProto1/core.h +++ b/commonLibs/livoxProto1/core.h @@ -11,7 +11,7 @@ #include "broadcastListener.h" #include "udpCommandDemuxer.h" #include "livoxProto1.h" -#include +#include namespace livoxProto1 { diff --git a/commonLibs/livoxProto1/device.cpp b/commonLibs/livoxProto1/device.cpp index 377c13f..5d5ec39 100644 --- a/commonLibs/livoxProto1/device.cpp +++ b/commonLibs/livoxProto1/device.cpp @@ -17,8 +17,8 @@ #include #include #include -#include -#include +#include +#include #include "device.h" #include "protocol.h" #include "core.h" diff --git a/commonLibs/livoxProto1/device.h b/commonLibs/livoxProto1/device.h index 04c7acd..bdbc7ad 100644 --- a/commonLibs/livoxProto1/device.h +++ b/commonLibs/livoxProto1/device.h @@ -18,8 +18,8 @@ #include #include #include "protocol.h" -#include -#include +#include +#include // Custom hash function for std::pair namespace std { diff --git a/commonLibs/livoxProto1/livoxProto1.cpp b/commonLibs/livoxProto1/livoxProto1.cpp index cfd3718..b683e55 100644 --- a/commonLibs/livoxProto1/livoxProto1.cpp +++ b/commonLibs/livoxProto1/livoxProto1.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include "livoxProto1.h" #include "device.h" diff --git a/commonLibs/livoxProto1/livoxProto1.h b/commonLibs/livoxProto1/livoxProto1.h index 51d68ae..9891fd2 100644 --- a/commonLibs/livoxProto1/livoxProto1.h +++ b/commonLibs/livoxProto1/livoxProto1.h @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include // Forward declarations diff --git a/commonLibs/livoxProto1/udpCommandDemuxer.h b/commonLibs/livoxProto1/udpCommandDemuxer.h index d67fe03..9748036 100644 --- a/commonLibs/livoxProto1/udpCommandDemuxer.h +++ b/commonLibs/livoxProto1/udpCommandDemuxer.h @@ -6,7 +6,7 @@ #include #include #include -#include +#include namespace livoxProto1 { diff --git a/include/user/senseApiDesc.h b/include/user/senseApiDesc.h index 93d73c5..195523b 100644 --- a/include/user/senseApiDesc.h +++ b/include/user/senseApiDesc.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include #define CL_TARGET_OPENCL_VERSION 120 #include diff --git a/include/user/stimulusProducer.h b/include/user/stimulusProducer.h index 2513182..f8d0116 100644 --- a/include/user/stimulusProducer.h +++ b/include/user/stimulusProducer.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include "deviceAttachmentSpec.h" namespace smo { diff --git a/libspinscale/CMakeLists.txt b/libspinscale/CMakeLists.txt new file mode 100644 index 0000000..bfe00d6 --- /dev/null +++ b/libspinscale/CMakeLists.txt @@ -0,0 +1,45 @@ +add_library(spinscale SHARED + src/qutex.cpp + src/lockerAndInvokerBase.cpp + src/componentThread.cpp + src/component.cpp +) + +# Conditionally add qutexAcquisitionHistoryTracker.cpp only when debug locks +# are enabled, since the tracker is only referenced under CONFIG_ENABLE_DEBUG_LOCKS. +if(ENABLE_DEBUG_LOCKS) + target_sources(spinscale PRIVATE src/qutexAcquisitionHistoryTracker.cpp) +endif() + +# Ensure Boost uses dynamic linking (project-wide setting should handle this, +# but being explicit here for clarity) +target_compile_definitions(spinscale PRIVATE BOOST_ALL_DYN_LINK) +target_compile_features(spinscale PUBLIC cxx_std_20) + +target_include_directories(spinscale PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}/smocore/include + ${PROJECT_BINARY_DIR}/include + ${Boost_INCLUDE_DIRS} +) + +# Link against required dependencies for shared library +# Boost::system is PUBLIC because componentThread.h exposes Boost.Asio types +find_package(Threads REQUIRED) +target_link_libraries(spinscale PUBLIC + Threads::Threads + Boost::system + Boost::log +) + +# Verify Boost dynamic dependencies after build (only if script exists) +if(EXISTS ${CMAKE_SOURCE_DIR}/cmake/VerifyBoostDynamic.cmake) + add_custom_command(TARGET spinscale POST_BUILD + COMMAND ${CMAKE_COMMAND} -DVERIFY_FILE="$" + -P ${CMAKE_SOURCE_DIR}/cmake/VerifyBoostDynamic.cmake + COMMENT "Verifying Boost dynamic dependencies for spinscale" + ) +else() + message(WARNING "VerifyBoostDynamic.cmake not found - cannot verify Boost dependencies for spinscale") +endif() diff --git a/include/asynchronousBridge.h b/libspinscale/include/spinscale/asynchronousBridge.h similarity index 100% rename from include/asynchronousBridge.h rename to libspinscale/include/spinscale/asynchronousBridge.h diff --git a/include/asynchronousContinuation.h b/libspinscale/include/spinscale/asynchronousContinuation.h similarity index 97% rename from include/asynchronousContinuation.h rename to libspinscale/include/spinscale/asynchronousContinuation.h index a01a39b..a1e138e 100644 --- a/include/asynchronousContinuation.h +++ b/libspinscale/include/spinscale/asynchronousContinuation.h @@ -5,9 +5,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include namespace smo { diff --git a/include/asynchronousContinuationChainLink.h b/libspinscale/include/spinscale/asynchronousContinuationChainLink.h similarity index 100% rename from include/asynchronousContinuationChainLink.h rename to libspinscale/include/spinscale/asynchronousContinuationChainLink.h diff --git a/include/asynchronousLoop.h b/libspinscale/include/spinscale/asynchronousLoop.h similarity index 100% rename from include/asynchronousLoop.h rename to libspinscale/include/spinscale/asynchronousLoop.h diff --git a/include/callableTracer.h b/libspinscale/include/spinscale/callableTracer.h similarity index 87% rename from include/callableTracer.h rename to libspinscale/include/spinscale/callableTracer.h index 1b6ea70..4f707a9 100644 --- a/include/callableTracer.h +++ b/libspinscale/include/spinscale/callableTracer.h @@ -1,12 +1,17 @@ -#ifndef CALLABLE_TRACER_H -#define CALLABLE_TRACER_H +#ifndef SPINSCALE_CALLABLE_TRACER_H +#define SPINSCALE_CALLABLE_TRACER_H #include #include #include #include #include -#include +#include + +// Forward declaration - OptionParser is defined in smocore/include/opts.h +// If you need tracing, include opts.h before including this header +// The code will check for OPTS_H define to see if opts.h has been included +class OptionParser; namespace smo { @@ -45,6 +50,10 @@ public: void operator()() { + // OptionParser::getOptions() requires opts.h to be included + // Only check traceCallables if opts.h has been included (OPTS_H is defined) + #ifdef CONFIG_DEBUG_TRACE_CALLABLES + #ifdef OPTS_H if (OptionParser::getOptions().traceCallables) { std::cout << "" << __func__ << ": On thread " @@ -56,6 +65,8 @@ public: << ", return addr 1: " << returnAddr1 << std::endl; } + #endif + #endif callable(); } @@ -135,4 +146,4 @@ private: #define STC(arg) arg #endif -#endif // CALLABLE_TRACER_H +#endif // SPINSCALE_CALLABLE_TRACER_H diff --git a/include/callback.h b/libspinscale/include/spinscale/callback.h similarity index 88% rename from include/callback.h rename to libspinscale/include/spinscale/callback.h index 60640c4..baaf293 100644 --- a/include/callback.h +++ b/libspinscale/include/spinscale/callback.h @@ -1,5 +1,5 @@ -#ifndef CALLBACK_H -#define CALLBACK_H +#ifndef SPINSCALE_CALLBACK_H +#define SPINSCALE_CALLBACK_H #include @@ -28,4 +28,4 @@ public: } // namespace smo -#endif // CALLBACK_H +#endif // SPINSCALE_CALLBACK_H diff --git a/smocore/include/component.h b/libspinscale/include/spinscale/component.h similarity index 94% rename from smocore/include/component.h rename to libspinscale/include/spinscale/component.h index dac1094..91ecd77 100644 --- a/smocore/include/component.h +++ b/libspinscale/include/spinscale/component.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace smo { diff --git a/libspinscale/include/spinscale/componentThread.h b/libspinscale/include/spinscale/componentThread.h new file mode 100644 index 0000000..494c28e --- /dev/null +++ b/libspinscale/include/spinscale/componentThread.h @@ -0,0 +1,170 @@ +#ifndef COMPONENT_THREAD_H +#define COMPONENT_THREAD_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace smo { + +class MarionetteThread; +class PuppetThread; + +// ThreadId is a generic type - application-specific enums should be defined elsewhere +typedef uint8_t ThreadId; + +class ComponentThread +{ +protected: + ComponentThread(ThreadId _id) + : id(_id), name(getThreadName(_id)), + work(io_service) + {} + +public: + virtual ~ComponentThread() = default; + + // getThreadName implementation is provided by application code + static std::string getThreadName(ThreadId id); + + void cleanup(void); + + boost::asio::io_service& getIoService(void) { return io_service; } + + static const std::shared_ptr getSelf(void); + static bool tlsInitialized(void); + static std::shared_ptr getMrntt(); + + typedef void (mainFn)(ComponentThread &self); + + // CPU management methods + static int getAvailableCpuCount(); + + typedef std::function mindShutdownIndOpCbFn; + // Intentionally doesn't take a callback. + void exceptionInd(const std::shared_ptr &faultyThread); + // Intentionally doesn't take a callback. + void userShutdownInd(); + +public: + ThreadId id; + std::string name; + boost::asio::io_service io_service; + boost::asio::io_service::work work; + std::atomic keepLooping; +}; + +class MarionetteThread +: public std::enable_shared_from_this, + public ComponentThread +{ +public: + MarionetteThread(ThreadId id = 0) + : ComponentThread(id), + thread(main, std::ref(*this)) + { + } + + static void main(MarionetteThread& self); + void initializeTls(void); + +public: + std::thread thread; +}; + +class PuppetThread +: public std::enable_shared_from_this, + public ComponentThread +{ +public: + enum class ThreadOp + { + START, + PAUSE, + RESUME, + EXIT, + JOLT, + N_ITEMS + }; + + PuppetThread(ThreadId _id) + : ComponentThread(_id), + pinnedCpuId(-1), + pause_work(pause_io_service), + thread(main, std::ref(*this)) + { + } + + virtual ~PuppetThread() = default; + + static void main(PuppetThread& self); + void initializeTls(void); + + // Thread management methods + typedef std::function threadLifetimeMgmtOpCbFn; + void startThreadReq(Callback callback); + void exitThreadReq(Callback callback); + void pauseThreadReq(Callback callback); + void resumeThreadReq(Callback callback); + + /** + * JOLTs this thread to begin processing after global initialization. + * + * JOLTing is the mechanism that allows threads to enter their main + * event loops and set up TLS vars after all global constructors have + * completed. This prevents race conditions during system startup. + * + * @param selfPtr Shared pointer to this thread (required because TLS + * isn't set up yet, so shared_from_this() can't be used) + * @param callback Callback to invoke when JOLT completes + */ + void joltThreadReq( + const std::shared_ptr& selfPtr, + Callback callback); + + // CPU management methods + void pinToCpu(int cpuId); + +protected: + /** + * Handle exception - called from main() when an exception occurs. + * Derived classes can override to provide application-specific handling. + */ + virtual void handleException() {} + +public: + int pinnedCpuId; + boost::asio::io_service pause_io_service; + boost::asio::io_service::work pause_work; + std::thread thread; + +public: + class ThreadLifetimeMgmtOp; +}; + +namespace mrntt { +extern std::shared_ptr thread; +} // namespace mrntt + +} // namespace smo + +// Forward declaration for spinscale namespace functions and variables +// Must be after smo namespace so ThreadId is defined +namespace spinscale { + extern smo::ThreadId marionetteThreadId; + void setMarionetteThreadId(smo::ThreadId id); +} + +#endif // COMPONENT_THREAD_H diff --git a/include/dependencyGraph.h b/libspinscale/include/spinscale/dependencyGraph.h similarity index 100% rename from include/dependencyGraph.h rename to libspinscale/include/spinscale/dependencyGraph.h diff --git a/include/lockSet.h b/libspinscale/include/spinscale/lockSet.h similarity index 98% rename from include/lockSet.h rename to libspinscale/include/spinscale/lockSet.h index 05ec03e..e87c382 100644 --- a/include/lockSet.h +++ b/libspinscale/include/spinscale/lockSet.h @@ -6,8 +6,8 @@ #include #include #include -#include -#include +#include +#include namespace smo { diff --git a/include/lockerAndInvokerBase.h b/libspinscale/include/spinscale/lockerAndInvokerBase.h similarity index 100% rename from include/lockerAndInvokerBase.h rename to libspinscale/include/spinscale/lockerAndInvokerBase.h diff --git a/include/qutex.h b/libspinscale/include/spinscale/qutex.h similarity index 97% rename from include/qutex.h rename to libspinscale/include/spinscale/qutex.h index af5ae70..6686e42 100644 --- a/include/qutex.h +++ b/libspinscale/include/spinscale/qutex.h @@ -5,8 +5,8 @@ #include #include #include -#include -#include +#include +#include namespace smo { diff --git a/include/qutexAcquisitionHistoryTracker.h b/libspinscale/include/spinscale/qutexAcquisitionHistoryTracker.h similarity index 100% rename from include/qutexAcquisitionHistoryTracker.h rename to libspinscale/include/spinscale/qutexAcquisitionHistoryTracker.h diff --git a/include/serializedAsynchronousContinuation.h b/libspinscale/include/spinscale/serializedAsynchronousContinuation.h similarity index 98% rename from include/serializedAsynchronousContinuation.h rename to libspinscale/include/spinscale/serializedAsynchronousContinuation.h index 2fd2279..6fda6d9 100644 --- a/include/serializedAsynchronousContinuation.h +++ b/libspinscale/include/spinscale/serializedAsynchronousContinuation.h @@ -8,11 +8,11 @@ #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include namespace smo { diff --git a/include/spinLock.h b/libspinscale/include/spinscale/spinLock.h similarity index 100% rename from include/spinLock.h rename to libspinscale/include/spinscale/spinLock.h diff --git a/smocore/component.cpp b/libspinscale/src/component.cpp similarity index 93% rename from smocore/component.cpp rename to libspinscale/src/component.cpp index cbe9315..f476012 100644 --- a/smocore/component.cpp +++ b/libspinscale/src/component.cpp @@ -1,4 +1,4 @@ -#include +#include #include namespace smo { diff --git a/libspinscale/src/componentThread.cpp b/libspinscale/src/componentThread.cpp new file mode 100644 index 0000000..8625b38 --- /dev/null +++ b/libspinscale/src/componentThread.cpp @@ -0,0 +1,318 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spinscale { + +// Global variable to store the marionette thread ID +// Default value is 0, but should be set by application code via setMarionetteThreadId() +smo::ThreadId marionetteThreadId = 0; + +void setMarionetteThreadId(smo::ThreadId id) +{ + marionetteThreadId = id; +} + +} // namespace spinscale + +namespace smo { + +thread_local std::shared_ptr thisComponentThread; + +// Implementation of static method +std::shared_ptr ComponentThread::getMrntt() +{ + return mrntt::thread; +} + +void MarionetteThread::initializeTls(void) +{ + thisComponentThread = shared_from_this(); +} + +void PuppetThread::initializeTls(void) +{ + thisComponentThread = shared_from_this(); +} + +bool ComponentThread::tlsInitialized(void) +{ + return thisComponentThread != nullptr; +} + +const std::shared_ptr ComponentThread::getSelf(void) +{ + if (!thisComponentThread) + { + throw std::runtime_error(std::string(__func__) + + ": TLS not initialized"); + } + + return thisComponentThread; +} + +class PuppetThread::ThreadLifetimeMgmtOp +: public PostedAsynchronousContinuation +{ +public: + ThreadLifetimeMgmtOp( + const std::shared_ptr &caller, + const std::shared_ptr &target, + Callback callback) + : PostedAsynchronousContinuation( + caller, callback), + target(target) + {} + +public: + const std::shared_ptr target; + +public: + void joltThreadReq1_posted( + [[maybe_unused]] std::shared_ptr context + ) + { + std::cout << __func__ << ": Thread '" << target->name << "': handling " + "JOLT request." + << "\n"; + + target->io_service.stop(); + callOriginalCb(); + } + + void startThreadReq1_posted( + [[maybe_unused]] std::shared_ptr context + ) + { + std::cout << __func__ << ": Thread '" << target->name << "': handling " + "startThread." + << "\n"; + + // Execute private setup sequence here + // This is where each thread would implement its specific initialization + + callOriginalCb(); + } + + void exitThreadReq1_mainQueue_posted( + [[maybe_unused]] std::shared_ptr context + ) + { + std::cout << __func__ << ": Thread '" << target->name << "': handling " + "exitThread (main queue)." << "\n"; + + target->cleanup(); + target->io_service.stop(); + callOriginalCb(); + } + + void exitThreadReq1_pauseQueue_posted( + [[maybe_unused]] std::shared_ptr context + ) + { + std::cout << __func__ << ": Thread '" << target->name << "': handling " + "exitThread (pause queue)."<< "\n"; + + target->cleanup(); + target->pause_io_service.stop(); + target->io_service.stop(); + callOriginalCb(); + } + + void pauseThreadReq1_posted( + [[maybe_unused]] std::shared_ptr context + ) + { + std::cout << __func__ << ": Thread '" << target->name << "': handling " + "pauseThread." << "\n"; + + /* We have to invoke the callback here before moving on because + * our next operation is going to block the thread, so it won't + * have a chance to invoke the callback until it's unblocked. + */ + callOriginalCb(); + target->pause_io_service.reset(); + target->pause_io_service.run(); + } + + void resumeThreadReq1_posted( + [[maybe_unused]] std::shared_ptr context + ) + { + std::cout << __func__ << ": Thread '" << target->name << "': handling " + "resumeThread." << "\n"; + + target->pause_io_service.stop(); + callOriginalCb(); + } +}; + +void ComponentThread::cleanup(void) +{ + this->keepLooping = false; +} + +void PuppetThread::joltThreadReq( + const std::shared_ptr& selfPtr, + Callback callback) +{ + /** EXPLANATION: + * We can't use shared_from_this() here because JOLTing occurs prior to + * TLS being set up. + * + * We also can't use getSelf() as yet for the same reason: getSelf() + * requires TLS to be set up. + * + * To obtain a sh_ptr to the caller, we just supply the mrntt thread since + * JOLT is always invoked by the mrntt thread. The JOLT sequence that the + * CRT main() function invokes on the mrntt thread is special since it + * supplies cmdline args and envp. + * + * To obtain a sh_ptr to the target thread, we use the selfPtr parameter + * passed in by the caller. + */ + if (id == spinscale::marionetteThreadId) + { + throw std::runtime_error(std::string(__func__) + + ": invoked on mrntt thread"); + } + + std::shared_ptr mrntt = mrntt::thread; + + auto request = std::make_shared( + mrntt, selfPtr, callback); + + this->getIoService().post( + STC(std::bind( + &ThreadLifetimeMgmtOp::joltThreadReq1_posted, + request.get(), request))); +} + +// Thread management method implementations +void PuppetThread::startThreadReq(Callback callback) +{ + std::shared_ptr caller = getSelf(); + auto request = std::make_shared( + caller, std::static_pointer_cast(shared_from_this()), + callback); + + this->getIoService().post( + STC(std::bind( + &ThreadLifetimeMgmtOp::startThreadReq1_posted, + request.get(), request))); +} + +void PuppetThread::exitThreadReq(Callback callback) +{ + std::shared_ptr caller = getSelf(); + auto request = std::make_shared( + caller, std::static_pointer_cast(shared_from_this()), + callback); + + this->getIoService().post( + STC(std::bind( + &ThreadLifetimeMgmtOp::exitThreadReq1_mainQueue_posted, + request.get(), request))); + + pause_io_service.post( + STC(std::bind( + &ThreadLifetimeMgmtOp::exitThreadReq1_pauseQueue_posted, + request.get(), request))); +} + +void PuppetThread::pauseThreadReq(Callback callback) +{ + if (id == spinscale::marionetteThreadId) + { + throw std::runtime_error(std::string(__func__) + + ": invoked on mrntt thread"); + } + + std::shared_ptr caller = getSelf(); + auto request = std::make_shared( + caller, std::static_pointer_cast(shared_from_this()), + callback); + + this->getIoService().post( + STC(std::bind( + &ThreadLifetimeMgmtOp::pauseThreadReq1_posted, + request.get(), request))); +} + +void PuppetThread::resumeThreadReq(Callback callback) +{ + if (id == spinscale::marionetteThreadId) + { + throw std::runtime_error(std::string(__func__) + + ": invoked on mrntt thread"); + } + + // Post to the pause_io_service to unblock the paused thread + std::shared_ptr caller = getSelf(); + auto request = std::make_shared( + caller, std::static_pointer_cast(shared_from_this()), + callback); + + pause_io_service.post( + STC(std::bind( + &ThreadLifetimeMgmtOp::resumeThreadReq1_posted, + request.get(), request))); +} + +// CPU management method implementations +int ComponentThread::getAvailableCpuCount() +{ + int cpuCount = sysconf(_SC_NPROCESSORS_ONLN); + if (cpuCount <= 0) + { + throw std::runtime_error(std::string(__func__) + + ": Failed to determine CPU count"); + } + + // Check if std::thread::hardware_concurrency() matches sysconf result + unsigned int hwConcurrency = std::thread::hardware_concurrency(); + if (hwConcurrency != static_cast(cpuCount)) + { + std::cerr << "Warning: CPU count mismatch - " + "std::thread::hardware_concurrency() = " + << hwConcurrency << ", sysconf(_SC_NPROCESSORS_ONLN) = " + << cpuCount << "\n"; + } + + return cpuCount; +} + +void PuppetThread::pinToCpu(int cpuId) +{ + if (cpuId < 0) + { + throw std::runtime_error(std::string(__func__) + + ": Invalid CPU ID: " + std::to_string(cpuId)); + } + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(cpuId, &cpuset); + + int result = pthread_setaffinity_np( + thread.native_handle(), sizeof(cpu_set_t), &cpuset); + if (result != 0) + { + throw std::runtime_error(std::string(__func__) + + ": Failed to pin thread to CPU " + std::to_string(cpuId) + + ": " + std::strerror(result)); + } + + pinnedCpuId = cpuId; +} + +} // namespace smo diff --git a/libspinscale/src/lockerAndInvokerBase.cpp b/libspinscale/src/lockerAndInvokerBase.cpp new file mode 100644 index 0000000..0f0c22f --- /dev/null +++ b/libspinscale/src/lockerAndInvokerBase.cpp @@ -0,0 +1,5 @@ +#include + +namespace smo { + +} // namespace smo diff --git a/smocore/qutex.cpp b/libspinscale/src/qutex.cpp similarity index 99% rename from smocore/qutex.cpp rename to libspinscale/src/qutex.cpp index 967fe73..672bc2c 100644 --- a/smocore/qutex.cpp +++ b/libspinscale/src/qutex.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include namespace smo { diff --git a/smocore/qutexAcquisitionHistoryTracker.cpp b/libspinscale/src/qutexAcquisitionHistoryTracker.cpp similarity index 98% rename from smocore/qutexAcquisitionHistoryTracker.cpp rename to libspinscale/src/qutexAcquisitionHistoryTracker.cpp index 26e835a..1964c47 100644 --- a/smocore/qutexAcquisitionHistoryTracker.cpp +++ b/libspinscale/src/qutexAcquisitionHistoryTracker.cpp @@ -1,7 +1,7 @@ -#include "qutexAcquisitionHistoryTracker.h" -#include "serializedAsynchronousContinuation.h" -#include "qutex.h" -#include "dependencyGraph.h" +#include +#include +#include +#include #include #include #include diff --git a/main.cpp b/main.cpp index e88ded9..ef0684c 100644 --- a/main.cpp +++ b/main.cpp @@ -2,10 +2,12 @@ #include #include #include - +#include int main(int argc, char *argv[], char *envp[]) { + // Set the marionette thread ID before using any ComponentThread functionality + spinscale::setMarionetteThreadId(smo::SmoThreadId::MRNTT); pthread_setname_np(pthread_self(), "smo:CRT:main"); /* We don't do anything inside of main() * Main merely waits for the marionette thread to exit. diff --git a/smocore/CMakeLists.txt b/smocore/CMakeLists.txt index c077039..3344450 100644 --- a/smocore/CMakeLists.txt +++ b/smocore/CMakeLists.txt @@ -5,11 +5,9 @@ include(${CMAKE_SOURCE_DIR}/cmake/flexYacc.cmake) add_library(smocore STATIC # Core files mind.cpp - opts.cpp + mindThread.cpp componentThread.cpp - component.cpp - qutex.cpp - lockerAndInvokerBase.cpp + opts.cpp # Body body/body.cpp @@ -41,11 +39,6 @@ add_library(smocore STATIC mindManager/mindManager.cpp ) -# Conditionally add qutexAcquisitionHistoryTracker.cpp only when debug locks are enabled -if(ENABLE_DEBUG_LOCKS) - target_sources(smocore PRIVATE qutexAcquisitionHistoryTracker.cpp) -endif() - target_include_directories(smocore PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR} @@ -53,6 +46,11 @@ target_include_directories(smocore PUBLIC ${OPENCL_INCLUDE_DIRS} ) +# smocore public headers expose Qutex and friends +target_link_libraries(smocore PUBLIC + spinscale +) + # Link against pthread for CPU affinity functions find_package(Threads REQUIRED) target_link_libraries(smocore PRIVATE diff --git a/smocore/body/body.cpp b/smocore/body/body.cpp index 45d2add..cb74df0 100644 --- a/smocore/body/body.cpp +++ b/smocore/body/body.cpp @@ -1,9 +1,9 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -38,7 +38,7 @@ public: ) { auto self = ComponentThread::getSelf(); - if (self->id != ComponentThread::BODY) + if (self->id != SmoThreadId::BODY) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Body thread"); @@ -113,7 +113,7 @@ public: ) { auto self = ComponentThread::getSelf(); - if (self->id != ComponentThread::BODY) + if (self->id != SmoThreadId::BODY) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Body thread"); @@ -149,7 +149,7 @@ void Body::initializeReq(Callback callback) { auto mrntt = ComponentThread::getSelf(); - if (mrntt->id != ComponentThread::MRNTT) + if (mrntt->id != SmoThreadId::MRNTT) { throw std::runtime_error(std::string(__func__) + ": Must be invoked by Mrntt thread"); @@ -168,7 +168,7 @@ void Body::finalizeReq(Callback callback) { auto mrntt = ComponentThread::getSelf(); - if (mrntt->id != ComponentThread::MRNTT) + if (mrntt->id != SmoThreadId::MRNTT) { std::cerr << __func__ << ": Must be invoked by Mrntt thread" << std::endl; diff --git a/smocore/componentThread.cpp b/smocore/componentThread.cpp index d8763b8..3197161 100644 --- a/smocore/componentThread.cpp +++ b/smocore/componentThread.cpp @@ -1,66 +1,40 @@ -#include -#include -#include +#include #include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include namespace smo { -thread_local std::shared_ptr thisComponentThread; - -// Implementation of static method -std::shared_ptr ComponentThread::getMrntt() +std::string ComponentThread::getThreadName(ThreadId id) { - return mrntt::thread; -} - -void MarionetteThread::initializeTls(void) -{ - thisComponentThread = shared_from_this(); -} - -void MindThread::initializeTls(void) -{ - thisComponentThread = shared_from_this(); -} - -bool ComponentThread::tlsInitialized(void) -{ - return thisComponentThread != nullptr; -} - -const std::shared_ptr ComponentThread::getSelf(void) -{ - if (!thisComponentThread) + // Cast ThreadId to SmoThreadId for validation and lookup + SmoThreadId smoId = static_cast(id); + if (static_cast(smoId) >= static_cast(SmoThreadId::N_ITEMS)) { throw std::runtime_error(std::string(__func__) - + ": TLS not initialized"); + + ": Invalid thread ID"); } - return thisComponentThread; + // Use function-local static to ensure proper initialization order + static const std::string threadNames[static_cast(SmoThreadId::N_ITEMS)] + = { + "mrntt", + "director", + "simulator", + "subconscious", + "body", + "world" + }; + + return threadNames[static_cast(smoId)]; } -void MindThread::main(MindThread& self) +void PuppetThread::main(PuppetThread& self) { std::string threadName = "smo:" + self.name; pthread_setname_np(pthread_self(), threadName.c_str()); - if (OptionParser::getOptions().verbose) - { - std::cout << self.name << ":" << __func__ << ": Waiting for JOLT" - <<"\n"; - } - self.getIoService().run(); self.initializeTls(); @@ -106,265 +80,11 @@ void MindThread::main(MindThread& self) if (sendExceptionInd) { - mrntt::mrntt.exceptionInd(); + self.handleException(); } } std::cout << self.name << ":" << __func__ << ": Exited event loop" << "\n"; } -class MindThread::ThreadLifetimeMgmtOp -: public PostedAsynchronousContinuation -{ -public: - ThreadLifetimeMgmtOp( - const std::shared_ptr &caller, - const std::shared_ptr &target, - Callback callback) - : PostedAsynchronousContinuation( - caller, callback), - target(target) - {} - -public: - const std::shared_ptr target; - -public: - void joltThreadReq1_posted( - [[maybe_unused]] std::shared_ptr context - ) - { - std::cout << __func__ << ": Thread '" << target->name << "': handling " - "JOLT request." - << "\n"; - - target->io_service.stop(); - callOriginalCb(); - } - - void startThreadReq1_posted( - [[maybe_unused]] std::shared_ptr context - ) - { - std::cout << __func__ << ": Thread '" << target->name << "': handling " - "startThread." - << "\n"; - - // Execute private setup sequence here - // This is where each thread would implement its specific initialization - - callOriginalCb(); - } - - void exitThreadReq1_mainQueue_posted( - [[maybe_unused]] std::shared_ptr context - ) - { - std::cout << __func__ << ": Thread '" << target->name << "': handling " - "exitThread (main queue)." << "\n"; - - target->cleanup(); - target->io_service.stop(); - callOriginalCb(); - } - - void exitThreadReq1_pauseQueue_posted( - [[maybe_unused]] std::shared_ptr context - ) - { - std::cout << __func__ << ": Thread '" << target->name << "': handling " - "exitThread (pause queue)."<< "\n"; - - target->cleanup(); - target->pause_io_service.stop(); - target->io_service.stop(); - callOriginalCb(); - } - - void pauseThreadReq1_posted( - [[maybe_unused]] std::shared_ptr context - ) - { - std::cout << __func__ << ": Thread '" << target->name << "': handling " - "pauseThread." << "\n"; - - /* We have to invoke the callback here before moving on because - * our next operation is going to block the thread, so it won't - * have a chance to invoke the callback until it's unblocked. - */ - callOriginalCb(); - target->pause_io_service.reset(); - target->pause_io_service.run(); - } - - void resumeThreadReq1_posted( - [[maybe_unused]] std::shared_ptr context - ) - { - std::cout << __func__ << ": Thread '" << target->name << "': handling " - "resumeThread." << "\n"; - - target->pause_io_service.stop(); - callOriginalCb(); - } -}; - -void ComponentThread::cleanup(void) -{ - this->keepLooping = false; -} - -void MindThread::joltThreadReq(Callback callback) -{ - /** EXPLANATION: - * We can't use shared_from_this() here because JOLTing occurs prior to - * TLS being set up. - * - * We also can't use getSelf() as yet for the same reason: getSelf() - * requires TLS to be set up. - * - * To obtain a sh_ptr to the caller, we just supply the mrntt thread since - * JOLT is always invoked by the mrntt thread. The JOLT sequence that the - * CRT main() function invokes on the mrntt thread is special since it - * supplies cmdline args and envp. - * - * To obtain a sh_ptr to the target thread, we explicitly look it up in the - * Mind object's collection of component threads. - */ - if (id == ComponentThread::MRNTT) - { - throw std::runtime_error(std::string(__func__) - + ": invoked on mrntt thread"); - } - - std::shared_ptr mrntt = mrntt::thread; - std::shared_ptr target = getParent().getComponentThread(id); - - auto request = std::make_shared( - mrntt, target, callback); - - this->getIoService().post( - STC(std::bind( - &ThreadLifetimeMgmtOp::joltThreadReq1_posted, - request.get(), request))); -} - -// Thread management method implementations -void MindThread::startThreadReq(Callback callback) -{ - std::shared_ptr caller = getSelf(); - auto request = std::make_shared( - caller, shared_from_this(), callback); - - this->getIoService().post( - STC(std::bind( - &ThreadLifetimeMgmtOp::startThreadReq1_posted, - request.get(), request))); -} - -void MindThread::exitThreadReq(Callback callback) -{ - std::shared_ptr caller = getSelf(); - auto request = std::make_shared( - caller, shared_from_this(), callback); - - this->getIoService().post( - STC(std::bind( - &ThreadLifetimeMgmtOp::exitThreadReq1_mainQueue_posted, - request.get(), request))); - - pause_io_service.post( - STC(std::bind( - &ThreadLifetimeMgmtOp::exitThreadReq1_pauseQueue_posted, - request.get(), request))); -} - -void MindThread::pauseThreadReq(Callback callback) -{ - if (id == ComponentThread::MRNTT) - { - throw std::runtime_error(std::string(__func__) - + ": invoked on mrntt thread"); - } - - std::shared_ptr caller = getSelf(); - auto request = std::make_shared( - caller, shared_from_this(), callback); - - this->getIoService().post( - STC(std::bind( - &ThreadLifetimeMgmtOp::pauseThreadReq1_posted, - request.get(), request))); -} - -void MindThread::resumeThreadReq(Callback callback) -{ - if (id == ComponentThread::MRNTT) - { - throw std::runtime_error(std::string(__func__) - + ": invoked on mrntt thread"); - } - - // Post to the pause_io_service to unblock the paused thread - std::shared_ptr caller = getSelf(); - auto request = std::make_shared( - caller, shared_from_this(), callback); - - pause_io_service.post( - STC(std::bind( - &ThreadLifetimeMgmtOp::resumeThreadReq1_posted, - request.get(), request))); -} - -// CPU management method implementations -int ComponentThread::getAvailableCpuCount() -{ - int cpuCount = sysconf(_SC_NPROCESSORS_ONLN); - if (cpuCount <= 0) - { - throw std::runtime_error(std::string(__func__) - + ": Failed to determine CPU count"); - } - - // Check if std::thread::hardware_concurrency() matches sysconf result - unsigned int hwConcurrency = std::thread::hardware_concurrency(); - if (hwConcurrency != static_cast(cpuCount)) - { - std::cerr << "Warning: CPU count mismatch - " - "std::thread::hardware_concurrency() = " - << hwConcurrency << ", sysconf(_SC_NPROCESSORS_ONLN) = " - << cpuCount << "\n"; - } - - return cpuCount; -} - -void MindThread::pinToCpu(int cpuId) -{ - if (cpuId < 0) - { - throw std::runtime_error(std::string(__func__) - + ": Invalid CPU ID: " + std::to_string(cpuId)); - } - - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(cpuId, &cpuset); - - int result = pthread_setaffinity_np( - thread.native_handle(), sizeof(cpu_set_t), &cpuset); - if (result != 0) - { - throw std::runtime_error(std::string(__func__) - + ": Failed to pin thread to CPU " + std::to_string(cpuId) - + ": " + std::strerror(result)); - } - - pinnedCpuId = cpuId; - if (OptionParser::getOptions().verbose) - { - std::cout << name << ": Pinned to CPU " << cpuId << "\n"; - } -} - } // namespace smo diff --git a/smocore/deviceManager/deviceManager.cpp b/smocore/deviceManager/deviceManager.cpp index c15d293..94f58f1 100644 --- a/smocore/deviceManager/deviceManager.cpp +++ b/smocore/deviceManager/deviceManager.cpp @@ -6,10 +6,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -351,7 +351,7 @@ public: [[maybe_unused]] std::shared_ptr context ) { - if (caller->id != ComponentThread::MRNTT) + if (caller->id != SmoThreadId::MRNTT) { std::cerr << std::string(__func__) << ": executed on non-mrntt thread: " @@ -421,7 +421,7 @@ public: [[maybe_unused]] std::shared_ptr context ) { - if (caller->id != ComponentThread::MRNTT) + if (caller->id != SmoThreadId::MRNTT) { std::cerr << std::string(__func__) << ": executed on non-mrntt thread: " diff --git a/smocore/deviceManager/deviceReattacher.cpp b/smocore/deviceManager/deviceReattacher.cpp index dc2bd72..bdee16d 100644 --- a/smocore/deviceManager/deviceReattacher.cpp +++ b/smocore/deviceManager/deviceReattacher.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include diff --git a/smocore/include/body/body.h b/smocore/include/body/body.h index 15ef3ce..e8d4f61 100644 --- a/smocore/include/body/body.h +++ b/smocore/include/body/body.h @@ -1,9 +1,9 @@ #ifndef _BODY_COMPONENT_H #define _BODY_COMPONENT_H -#include +#include #include -#include +#include namespace smo { diff --git a/smocore/include/componentThread.h b/smocore/include/componentThread.h index 584839d..b7f793f 100644 --- a/smocore/include/componentThread.h +++ b/smocore/include/componentThread.h @@ -1,178 +1,25 @@ -#ifndef COMPONENT_THREAD_H -#define COMPONENT_THREAD_H +#ifndef SMO_COMPONENT_THREAD_H +#define SMO_COMPONENT_THREAD_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +// Include the spinscale componentThread.h which provides ComponentThread, PuppetThread, etc. +#include namespace smo { -class Mind; // Forward declaration -class MarionetteThread; -class MindThread; - -class ComponentThread +// Application-specific thread ID enum +// Using regular enum (not enum class) to allow implicit conversion to ThreadId +enum SmoThreadId : ThreadId { -public: - enum ThreadId - { - MRNTT = 0, - DIRECTOR, - SIMULATOR, - SUBCONSCIOUS, - BODY, - WORLD, - N_ITEMS - }; - -protected: - ComponentThread(ThreadId _id) - : id(_id), name(getThreadName(_id)), - work(io_service) - {} - -public: - virtual ~ComponentThread() = default; - - void cleanup(void); - - boost::asio::io_service& getIoService(void) { return io_service; } - - static const std::shared_ptr getSelf(void); - static bool tlsInitialized(void); - static std::shared_ptr getMrntt(); - - typedef void (mainFn)(ComponentThread &self); - - // CPU management methods - static int getAvailableCpuCount(); - - typedef std::function mindShutdownIndOpCbFn; - // Intentionally doesn't take a callback. - void exceptionInd(const std::shared_ptr &faultyThread); - // Intentionally doesn't take a callback. - void userShutdownInd(); - -public: - ThreadId id; - std::string name; - boost::asio::io_service io_service; - boost::asio::io_service::work work; - std::atomic keepLooping; - - static const std::string getThreadName(ThreadId id) - { - if (id < 0 || id >= ComponentThread::N_ITEMS) - { - throw std::runtime_error(std::string(__func__) - + ": Invalid thread ID"); - } - - // Use function-local static to ensure proper initialization order - static const std::string threadNames[N_ITEMS] = { - "mrntt", - "director", - "simulator", - "subconscious", - "body", - "world" - }; - - return threadNames[id]; - } + MRNTT = 0, + DIRECTOR, + SIMULATOR, + SUBCONSCIOUS, + BODY, + WORLD, + N_ITEMS }; -class MarionetteThread -: public std::enable_shared_from_this, - public ComponentThread -{ -public: - MarionetteThread() - : ComponentThread(MRNTT), - thread(main, std::ref(*this)) - { - } - - static void main(MarionetteThread& self); - void initializeTls(void); - -public: - std::thread thread; -}; - -class MindThread -: public std::enable_shared_from_this, public ComponentThread -{ -public: - enum class ThreadOp - { - START, - PAUSE, - RESUME, - EXIT, - JOLT, - N_ITEMS - }; - - MindThread(ThreadId _id, Mind& parent) - : ComponentThread(_id), - pinnedCpuId(-1), - pause_work(pause_io_service), - parent(parent), - thread(main, std::ref(*this)) - { - } - - static void main(MindThread& self); - void initializeTls(void); - - Mind& getParent() const { return parent; } - - // Thread management methods - typedef std::function threadLifetimeMgmtOpCbFn; - void startThreadReq(Callback callback); - void exitThreadReq(Callback callback); - void pauseThreadReq(Callback callback); - void resumeThreadReq(Callback callback); - - /** - * JOLTs this thread to begin processing after global initialization. - * - * JOLTing is the mechanism that allows threads to enter their main - * event loops and set up TLS vars after all global constructors have - * completed. This prevents race conditions during system startup. - */ - void joltThreadReq(Callback callback); - - // CPU management methods - void pinToCpu(int cpuId); - -public: - int pinnedCpuId; - boost::asio::io_service pause_io_service; - boost::asio::io_service::work pause_work; - Mind& parent; - std::thread thread; - -public: - class ThreadLifetimeMgmtOp; - class MindShutdownIndOp; -}; - -namespace mrntt { -extern std::shared_ptr thread; -} // namespace mrntt - } // namespace smo -#endif // COMPONENT_THREAD_H +#endif // SMO_COMPONENT_THREAD_H diff --git a/smocore/include/deviceManager/device.h b/smocore/include/deviceManager/device.h index b9b9456..5caba7f 100644 --- a/smocore/include/deviceManager/device.h +++ b/smocore/include/deviceManager/device.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include namespace smo { namespace device { diff --git a/smocore/include/deviceManager/deviceManager.h b/smocore/include/deviceManager/deviceManager.h index ada17eb..c0c38a8 100644 --- a/smocore/include/deviceManager/deviceManager.h +++ b/smocore/include/deviceManager/deviceManager.h @@ -10,12 +10,12 @@ #include #include #include -#include +#include #include #include #include -#include -#include +#include +#include namespace smo { namespace device { diff --git a/smocore/include/deviceManager/deviceReattacher.h b/smocore/include/deviceManager/deviceReattacher.h index 0ae487f..85af6f3 100644 --- a/smocore/include/deviceManager/deviceReattacher.h +++ b/smocore/include/deviceManager/deviceReattacher.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include namespace smo { diff --git a/smocore/include/director/director.h b/smocore/include/director/director.h index d5a79a3..24f618c 100644 --- a/smocore/include/director/director.h +++ b/smocore/include/director/director.h @@ -2,7 +2,7 @@ #define DIRECTOR_H #include -#include +#include #include #include diff --git a/smocore/include/marionette/marionette.h b/smocore/include/marionette/marionette.h index 5610ccc..d3413b0 100644 --- a/smocore/include/marionette/marionette.h +++ b/smocore/include/marionette/marionette.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace smo { diff --git a/smocore/include/mind.h b/smocore/include/mind.h index 84cb2a7..e362248 100644 --- a/smocore/include/mind.h +++ b/smocore/include/mind.h @@ -7,10 +7,11 @@ #include #include #include -#include +#include -#include +#include #include +#include #include #include #include @@ -28,8 +29,7 @@ public: void finalizeReq(Callback callback); // ComponentThread access methods - std::shared_ptr getComponentThread( - ComponentThread::ThreadId id) const; + std::shared_ptr getComponentThread(ThreadId id) const; std::shared_ptr getComponentThread( const std::string& name) const; // Get all this Mind's component threads. diff --git a/smocore/include/mindThread.h b/smocore/include/mindThread.h new file mode 100644 index 0000000..2b89f66 --- /dev/null +++ b/smocore/include/mindThread.h @@ -0,0 +1,32 @@ +#ifndef MIND_THREAD_H +#define MIND_THREAD_H + +#include +#include + +namespace smo { + +class Mind; // Forward declaration + +class MindThread +: public PuppetThread +{ +public: + MindThread(ThreadId _id, Mind& parent) + : PuppetThread(_id), + parent(parent) + { + } + + Mind& getParent() const { return parent; } + +protected: + void handleException() override; + +public: + Mind& parent; +}; + +} // namespace smo + +#endif // MIND_THREAD_H diff --git a/smocore/include/simulator/simulator.h b/smocore/include/simulator/simulator.h index 8015bc6..b2b5b35 100644 --- a/smocore/include/simulator/simulator.h +++ b/smocore/include/simulator/simulator.h @@ -2,7 +2,7 @@ #define SIMULATOR_H #include -#include +#include #include namespace smo { diff --git a/smocore/include/stimBuffApis/stimBuffApiLib.h b/smocore/include/stimBuffApis/stimBuffApiLib.h index eb1f784..5e1b2f9 100644 --- a/smocore/include/stimBuffApis/stimBuffApiLib.h +++ b/smocore/include/stimBuffApis/stimBuffApiLib.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include namespace smo { namespace stim_buff { diff --git a/smocore/include/stimBuffApis/stimBuffApiManager.h b/smocore/include/stimBuffApis/stimBuffApiManager.h index 5491a6a..81dede0 100644 --- a/smocore/include/stimBuffApis/stimBuffApiManager.h +++ b/smocore/include/stimBuffApis/stimBuffApiManager.h @@ -7,11 +7,11 @@ #include #include #include -#include +#include #include #include -#include -#include +#include +#include namespace smo { namespace stim_buff { diff --git a/smocore/lockerAndInvokerBase.cpp b/smocore/lockerAndInvokerBase.cpp deleted file mode 100644 index f375ccc..0000000 --- a/smocore/lockerAndInvokerBase.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include - -namespace smo { - -} // namespace smo diff --git a/smocore/marionette/lifetime.cpp b/smocore/marionette/lifetime.cpp index 4f544c2..3897ca0 100644 --- a/smocore/marionette/lifetime.cpp +++ b/smocore/marionette/lifetime.cpp @@ -1,9 +1,9 @@ #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include @@ -33,7 +33,7 @@ public: ) { auto self = ComponentThread::getSelf(); - if (self->id != ComponentThread::MRNTT) + if (self->id != SmoThreadId::MRNTT) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Marionette thread"); @@ -71,7 +71,7 @@ public: ) { auto self = ComponentThread::getSelf(); - if (self->id != ComponentThread::MRNTT) + if (self->id != SmoThreadId::MRNTT) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Marionette thread"); @@ -133,7 +133,7 @@ public: ) { auto self = ComponentThread::getSelf(); - if (self->id != ComponentThread::MRNTT) + if (self->id != SmoThreadId::MRNTT) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Marionette thread"); @@ -150,7 +150,7 @@ void MarionetteComponent::initializeReq( { auto mrntt = ComponentThread::getSelf(); - if (mrntt->id != ComponentThread::MRNTT) + if (mrntt->id != SmoThreadId::MRNTT) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Marionette thread"); @@ -170,7 +170,7 @@ void MarionetteComponent::finalizeReq( { auto mrntt = ComponentThread::getSelf(); - if (mrntt->id != ComponentThread::MRNTT) + if (mrntt->id != SmoThreadId::MRNTT) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Marionette thread"); diff --git a/smocore/marionette/main.cpp b/smocore/marionette/main.cpp index 0aba7fa..2a2450d 100644 --- a/smocore/marionette/main.cpp +++ b/smocore/marionette/main.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/smocore/marionette/negtrinEvent.cpp b/smocore/marionette/negtrinEvent.cpp index eba0a6b..8466edf 100644 --- a/smocore/marionette/negtrinEvent.cpp +++ b/smocore/marionette/negtrinEvent.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/smocore/mind.cpp b/smocore/mind.cpp index 7b4ea31..151e4d3 100644 --- a/smocore/mind.cpp +++ b/smocore/mind.cpp @@ -1,11 +1,11 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include -#include +#include #include #include #include @@ -15,12 +15,12 @@ namespace smo { Mind::Mind(void) : componentThreads{ - std::make_shared(ComponentThread::DIRECTOR, *this), - std::make_shared(ComponentThread::SIMULATOR, *this), - std::make_shared(ComponentThread::SUBCONSCIOUS, *this), - std::make_shared(ComponentThread::BODY, *this) + std::make_shared(SmoThreadId::DIRECTOR, *this), + std::make_shared(SmoThreadId::SIMULATOR, *this), + std::make_shared(SmoThreadId::SUBCONSCIOUS, *this), + std::make_shared(SmoThreadId::BODY, *this) #ifndef CONFIG_WORLD_USE_BODY_THREAD - , std::make_shared(ComponentThread::WORLD, *this) + , std::make_shared(SmoThreadId::WORLD, *this) #endif }, director(*this, componentThreads[0]), @@ -38,9 +38,9 @@ Mind::Mind(void) } std::shared_ptr -Mind::getComponentThread(ComponentThread::ThreadId id) const +Mind::getComponentThread(ThreadId id) const { - if (id == ComponentThread::MRNTT) + if (id == SmoThreadId::MRNTT) { throw std::runtime_error( std::string(__func__) + @@ -339,7 +339,11 @@ void Mind::joltAllMindThreadsReq( for (auto& thread : componentThreads) { - thread->joltThreadReq( + std::shared_ptr puppetThread = + std::static_pointer_cast(thread); + + thread->joltThreadReq( + puppetThread, {request, std::bind( &MindThreadLifetimeMgmtOp::joltAllMindThreadsReq1, request.get(), request)}); diff --git a/smocore/mindThread.cpp b/smocore/mindThread.cpp new file mode 100644 index 0000000..5487a53 --- /dev/null +++ b/smocore/mindThread.cpp @@ -0,0 +1,12 @@ +#include +#include +#include + +namespace smo { + +void MindThread::handleException() +{ + mrntt::mrntt.exceptionInd(); +} + +} // namespace smo diff --git a/smocore/stimBuffApis/stimBuffApiManager.cpp b/smocore/stimBuffApis/stimBuffApiManager.cpp index 1b319b5..67f62ad 100644 --- a/smocore/stimBuffApis/stimBuffApiManager.cpp +++ b/smocore/stimBuffApis/stimBuffApiManager.cpp @@ -5,10 +5,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/stimBuffApis/livoxGen1/ioUringAssemblyEngine.cpp b/stimBuffApis/livoxGen1/ioUringAssemblyEngine.cpp index 33a65bc..b807fd0 100644 --- a/stimBuffApis/livoxGen1/ioUringAssemblyEngine.cpp +++ b/stimBuffApis/livoxGen1/ioUringAssemblyEngine.cpp @@ -17,12 +17,12 @@ #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include "ioUringAssemblyEngine.h" #include "pcloudStimulusProducer.h" #include "livoxGen1.h" diff --git a/stimBuffApis/livoxGen1/ioUringAssemblyEngine.h b/stimBuffApis/livoxGen1/ioUringAssemblyEngine.h index ae4fc4d..21a5b86 100644 --- a/stimBuffApis/livoxGen1/ioUringAssemblyEngine.h +++ b/stimBuffApis/livoxGen1/ioUringAssemblyEngine.h @@ -16,10 +16,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #define IOURINGASSM_ENGN_FRAME_ASSEM_TIMEOUT_MS \ diff --git a/stimBuffApis/livoxGen1/livoxGen1.cpp b/stimBuffApis/livoxGen1/livoxGen1.cpp index e7b9062..7355f09 100644 --- a/stimBuffApis/livoxGen1/livoxGen1.cpp +++ b/stimBuffApis/livoxGen1/livoxGen1.cpp @@ -10,11 +10,11 @@ #include #include #include -#include +#include #include #include #include -#include +#include #include #include "pcloudStimulusProducer.h" #include "livoxGen1.h" diff --git a/stimBuffApis/livoxGen1/openClCollatingAndMeshingEngine.cpp b/stimBuffApis/livoxGen1/openClCollatingAndMeshingEngine.cpp index 340df90..936b17f 100644 --- a/stimBuffApis/livoxGen1/openClCollatingAndMeshingEngine.cpp +++ b/stimBuffApis/livoxGen1/openClCollatingAndMeshingEngine.cpp @@ -9,10 +9,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/stimBuffApis/livoxGen1/openClCollatingAndMeshingEngine.h b/stimBuffApis/livoxGen1/openClCollatingAndMeshingEngine.h index 8b933d7..718e2ef 100644 --- a/stimBuffApis/livoxGen1/openClCollatingAndMeshingEngine.h +++ b/stimBuffApis/livoxGen1/openClCollatingAndMeshingEngine.h @@ -13,9 +13,9 @@ #include #define CL_TARGET_OPENCL_VERSION 120 #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/stimBuffApis/livoxGen1/pcloudStimulusProducer.cpp b/stimBuffApis/livoxGen1/pcloudStimulusProducer.cpp index c69eeeb..17a86e1 100644 --- a/stimBuffApis/livoxGen1/pcloudStimulusProducer.cpp +++ b/stimBuffApis/livoxGen1/pcloudStimulusProducer.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -119,9 +119,9 @@ tempStimulusFrame( << device->componentThread->name << std::endl; #ifndef CONFIG_WORLD_USE_BODY_THREAD - if (smoHooksPtr->ComponentThread_getSelf()->id != ComponentThread::WORLD) + if (smoHooksPtr->ComponentThread_getSelf()->id != SmoThreadId::WORLD) #else - if (smoHooksPtr->ComponentThread_getSelf()->id != ComponentThread::BODY) + if (smoHooksPtr->ComponentThread_getSelf()->id != SmoThreadId::BODY) #endif { std::string errMsg = std::string(__func__) + diff --git a/stimBuffApis/livoxGen1/pcloudStimulusProducer.h b/stimBuffApis/livoxGen1/pcloudStimulusProducer.h index 7581fee..dfabc60 100644 --- a/stimBuffApis/livoxGen1/pcloudStimulusProducer.h +++ b/stimBuffApis/livoxGen1/pcloudStimulusProducer.h @@ -6,8 +6,8 @@ #include #include #include -#include -#include +#include +#include #include #include "ioUringAssemblyEngine.h" #include "openClCollatingAndMeshingEngine.h" diff --git a/stimBuffApis/xcbWindow/xcbWindow.cpp b/stimBuffApis/xcbWindow/xcbWindow.cpp index ff20bc7..7d8dae9 100644 --- a/stimBuffApis/xcbWindow/xcbWindow.cpp +++ b/stimBuffApis/xcbWindow/xcbWindow.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include "xcbWindow.h" diff --git a/tests/smocore/qutex_tests.cpp b/tests/smocore/qutex_tests.cpp index d45d1b1..8504d02 100644 --- a/tests/smocore/qutex_tests.cpp +++ b/tests/smocore/qutex_tests.cpp @@ -1,6 +1,6 @@ #include -#include -#include +#include +#include #include #include #include