1 // Copyright (c) 2007-2018 Hartmut Kaiser 2 // Copyright (c) 2011 Bryce Lelbach 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 #if !defined(HPX_RUNTIME_RUNTIME_JUN_10_2008_1012AM) 8 #define HPX_RUNTIME_RUNTIME_JUN_10_2008_1012AM 9 10 #include <hpx/config.hpp> 11 #include <hpx/compat/mutex.hpp> 12 #include <hpx/lcos/local/spinlock.hpp> 13 #include <hpx/performance_counters/counters.hpp> 14 #include <hpx/runtime/applier_fwd.hpp> 15 #include <hpx/runtime/components/component_type.hpp> 16 #include <hpx/runtime/parcelset/locality.hpp> 17 #include <hpx/runtime/parcelset_fwd.hpp> 18 #include <hpx/runtime/runtime_mode.hpp> 19 #include <hpx/runtime/shutdown_function.hpp> 20 #include <hpx/runtime/startup_function.hpp> 21 #include <hpx/runtime/thread_hooks.hpp> 22 #include <hpx/runtime/threads/policies/callback_notifier.hpp> 23 #include <hpx/runtime/threads/topology.hpp> 24 #include <hpx/runtime_fwd.hpp> 25 #include <hpx/state.hpp> 26 #include <hpx/util/runtime_configuration.hpp> 27 #include <hpx/util/thread_specific_ptr.hpp> 28 29 #include <boost/smart_ptr/scoped_ptr.hpp> 30 31 #include <atomic> 32 #include <cstddef> 33 #include <cstdint> 34 #include <exception> 35 #include <map> 36 #include <memory> 37 #include <mutex> 38 #include <string> 39 #include <vector> 40 41 #include <hpx/config/warnings_prefix.hpp> 42 43 /////////////////////////////////////////////////////////////////////////////// 44 namespace hpx 45 { 46 // \brief Returns if HPX continues past connection signals 47 // caused by crashed nodes 48 HPX_EXPORT bool tolerate_node_faults(); 49 namespace util 50 { 51 class thread_mapper; 52 class query_counters; 53 class unique_id_ranges; 54 } 55 namespace components 56 { 57 struct static_factory_load_data_type; 58 59 namespace server 60 { 61 class runtime_support; 62 class HPX_EXPORT memory; 63 } 64 } 65 66 namespace performance_counters 67 { 68 class registry; 69 } 70 71 int pre_main(runtime_mode); 72 73 /////////////////////////////////////////////////////////////////////////// 74 class HPX_EXPORT runtime_impl; 75 76 class HPX_EXPORT runtime 77 { 78 public: 79 get_state() const80 state get_state() const { return state_.load(); } 81 82 /// The \a hpx_main_function_type is the default function type usable 83 /// as the main HPX thread function. 84 typedef int hpx_main_function_type(); 85 86 /// 87 typedef void hpx_errorsink_function_type( 88 std::uint32_t, std::string const&); 89 90 /// construct a new instance of a runtime 91 runtime(util::runtime_configuration & rtcfg); 92 93 virtual ~runtime(); 94 95 /// \brief Manage list of functions to call on exit on_exit(util::function_nonser<void ()> const & f)96 void on_exit(util::function_nonser<void()> const& f) 97 { 98 std::lock_guard<compat::mutex> l(mtx_); 99 on_exit_functions_.push_back(f); 100 } 101 102 /// \brief Manage runtime 'stopped' state starting()103 void starting() 104 { 105 state_.store(state_pre_main); 106 } 107 108 /// \brief Call all registered on_exit functions stopping()109 void stopping() 110 { 111 state_.store(state_stopped); 112 113 typedef util::function_nonser<void()> value_type; 114 115 std::lock_guard<compat::mutex> l(mtx_); 116 for (value_type const& f : on_exit_functions_) 117 f(); 118 } 119 120 /// This accessor returns whether the runtime instance has been stopped stopped() const121 bool stopped() const 122 { 123 return state_.load() == state_stopped; 124 } 125 126 // the TSS holds a pointer to the runtime associated with a given 127 // OS thread 128 struct tls_tag {}; 129 static util::thread_specific_ptr<runtime*, tls_tag> runtime_; 130 static util::thread_specific_ptr<std::string, tls_tag> thread_name_; 131 static util::thread_specific_ptr<std::uint64_t, tls_tag> uptime_; 132 133 /// \brief access configuration information get_config()134 util::runtime_configuration& get_config() 135 { 136 return ini_; 137 } get_config() const138 util::runtime_configuration const& get_config() const 139 { 140 return ini_; 141 } 142 get_instance_number() const143 std::size_t get_instance_number() const 144 { 145 return static_cast<std::size_t>(instance_number_); 146 } 147 148 /// \brief Return the name of the calling thread. 149 static std::string get_thread_name(); 150 151 /// \brief Return the system uptime measure on the thread executing this call 152 static std::uint64_t get_system_uptime(); 153 154 /// \brief Allow access to the registry counter registry instance used 155 /// by the HPX runtime. 156 performance_counters::registry& get_counter_registry(); 157 158 /// \brief Allow access to the registry counter registry instance used 159 /// by the HPX runtime. 160 performance_counters::registry const& get_counter_registry() const; 161 162 /// \brief Return a reference to the internal PAPI thread manager 163 util::thread_mapper& get_thread_mapper(); 164 get_topology() const165 threads::topology const& get_topology() const 166 { 167 return topology_; 168 } 169 170 std::uint32_t assign_cores(std::string const& locality_basename, 171 std::uint32_t num_threads); 172 173 std::uint32_t assign_cores(); 174 175 /// \brief Install all performance counters related to this runtime 176 /// instance 177 void register_counter_types(); 178 179 /////////////////////////////////////////////////////////////////////// 180 virtual int run(util::function_nonser<hpx_main_function_type> const& func) = 0; 181 182 virtual int run() = 0; 183 184 virtual void rethrow_exception() = 0; 185 186 virtual int start(util::function_nonser<hpx_main_function_type> const& func, 187 bool blocking = false) = 0; 188 189 virtual int start(bool blocking = false) = 0; 190 191 virtual int wait() = 0; 192 193 virtual void stop(bool blocking = true) = 0; 194 195 virtual int suspend() = 0; 196 virtual int resume() = 0; 197 198 virtual parcelset::parcelhandler& get_parcel_handler() = 0; 199 virtual parcelset::parcelhandler const& get_parcel_handler() const = 0; 200 201 virtual threads::threadmanager& get_thread_manager() = 0; 202 203 virtual naming::resolver_client& get_agas_client() = 0; 204 205 virtual parcelset::endpoints_type const& endpoints() const = 0; 206 virtual std::string here() const = 0; 207 208 virtual applier::applier& get_applier() = 0; 209 210 virtual std::uint64_t get_runtime_support_lva() const = 0; 211 212 virtual std::uint64_t get_memory_lva() const = 0; 213 214 virtual bool report_error(std::size_t num_thread, 215 std::exception_ptr const& e) = 0; 216 217 virtual bool report_error(std::exception_ptr const& e) = 0; 218 219 virtual naming::gid_type get_next_id(std::size_t count = 1) = 0; 220 221 virtual util::unique_id_ranges& get_id_pool() = 0; 222 223 virtual void add_pre_startup_function(startup_function_type f) = 0; 224 225 virtual void add_startup_function(startup_function_type f) = 0; 226 227 virtual void add_pre_shutdown_function(shutdown_function_type f) = 0; 228 229 virtual void add_shutdown_function(shutdown_function_type f) = 0; 230 231 /// Access one of the internal thread pools (io_service instances) 232 /// HPX is using to perform specific tasks. The three possible values 233 /// for the argument \p name are "main_pool", "io_pool", "parcel_pool", 234 /// and "timer_pool". For any other argument value the function will 235 /// return zero. 236 virtual hpx::util::io_service_pool* get_thread_pool(char const* name) = 0; 237 238 /// \brief Register an external OS-thread with HPX 239 /// 240 /// This function should be called from any OS-thread which is external to 241 /// HPX (not created by HPX), but which needs to access HPX functionality, 242 /// such as setting a value on a promise or similar. 243 /// 244 /// \param name [in] The name to use for thread registration. 245 /// \param num [in] The sequence number to use for thread 246 /// registration. The default for this parameter 247 /// is zero. 248 /// \param service_thread [in] The thread should be registered as a 249 /// service thread. The default for this parameter 250 /// is 'true'. Any service threads will be pinned 251 /// to cores not currently used by any of the HPX 252 /// worker threads. 253 /// 254 /// \note The function will compose a thread name of the form 255 /// '<name>-thread#<num>' which is used to register the thread. It 256 /// is the user's responsibility to ensure that each (composed) 257 /// thread name is unique. HPX internally uses the following names 258 /// for the threads it creates, do not reuse those: 259 /// 260 /// 'main', 'io', 'timer', 'parcel', 'worker' 261 /// 262 /// \note This function should be called for each thread exactly once. It 263 /// will fail if it is called more than once. 264 /// 265 /// \returns This function will return whether th erequested operation 266 /// succeeded or not. 267 /// 268 virtual bool register_thread(char const* name, std::size_t num = 0, 269 bool service_thread = true, error_code& ec = throws) = 0; 270 271 /// \brief Unregister an external OS-thread with HPX 272 /// 273 /// This function will unregister any external OS-thread from HPX. 274 /// 275 /// \note This function should be called for each thread exactly once. It 276 /// will fail if it is called more than once. It will fail as well 277 /// if the thread has not been registered before (see 278 /// \a register_thread). 279 /// 280 /// \returns This function will return whether th erequested operation 281 /// succeeded or not. 282 /// 283 virtual bool unregister_thread() = 0; 284 285 /// Generate a new notification policy instance for the given thread 286 /// name prefix 287 typedef threads::policies::callback_notifier notification_policy_type; 288 virtual notification_policy_type 289 get_notification_policy(char const* prefix) = 0; 290 291 /////////////////////////////////////////////////////////////////////// 292 // management API for active performance counters 293 void register_query_counters( 294 std::shared_ptr<util::query_counters> const& active_counters); 295 296 void start_active_counters(error_code& ec = throws); 297 void stop_active_counters(error_code& ec = throws); 298 void reset_active_counters(error_code& ec = throws); 299 void reinit_active_counters(bool reset = true, error_code& ec = throws); 300 void evaluate_active_counters(bool reset = false, 301 char const* description = nullptr, error_code& ec = throws); 302 303 // stop periodic evaluation of counters during shutdown 304 void stop_evaluating_counters(); 305 306 void register_message_handler(char const* message_handler_type, 307 char const* action, error_code& ec = throws); 308 parcelset::policies::message_handler* create_message_handler( 309 char const* message_handler_type, char const* action, 310 parcelset::parcelport* pp, std::size_t num_messages, 311 std::size_t interval, error_code& ec = throws); 312 serialization::binary_filter* create_binary_filter( 313 char const* binary_filter_type, bool compress, 314 serialization::binary_filter* next_filter, error_code& ec = throws); 315 316 notification_policy_type::on_startstop_type on_start_func() const; 317 notification_policy_type::on_startstop_type on_stop_func() const; 318 notification_policy_type::on_error_type on_error_func() const; 319 320 notification_policy_type::on_startstop_type on_start_func( 321 notification_policy_type::on_startstop_type&&); 322 notification_policy_type::on_startstop_type on_stop_func( 323 notification_policy_type::on_startstop_type&&); 324 notification_policy_type::on_error_type on_error_func( 325 notification_policy_type::on_error_type&&); 326 327 protected: 328 void init_tss(); 329 void deinit_tss(); 330 331 public: 332 void set_state(state s); 333 334 protected: 335 // list of functions to call on exit 336 typedef std::vector<util::function_nonser<void()> > on_exit_type; 337 on_exit_type on_exit_functions_; 338 mutable compat::mutex mtx_; 339 340 util::runtime_configuration ini_; 341 std::shared_ptr<performance_counters::registry> counters_; 342 std::shared_ptr<util::query_counters> active_counters_; 343 344 long instance_number_; 345 static std::atomic<int> instance_number_counter_; 346 347 // certain components (such as PAPI) require all threads to be 348 // registered with the library 349 boost::scoped_ptr<util::thread_mapper> thread_support_; 350 351 // topology and affinity data 352 threads::topology& topology_; 353 354 // locality basename -> used cores 355 typedef std::map<std::string, std::uint32_t> used_cores_map_type; 356 used_cores_map_type used_cores_map_; 357 358 std::atomic<state> state_; 359 360 boost::scoped_ptr<components::server::memory> memory_; 361 boost::scoped_ptr<components::server::runtime_support> runtime_support_; 362 363 // support tieing in external functions to be called for thread events 364 notification_policy_type::on_startstop_type on_start_func_; 365 notification_policy_type::on_startstop_type on_stop_func_; 366 notification_policy_type::on_error_type on_error_func_; 367 }; 368 } // namespace hpx 369 370 #include <hpx/config/warnings_suffix.hpp> 371 372 #endif 373