threads::thread_priority get_thread_priority(thread_id_type id, error_code& ec) { hpx::applier::applier* app = hpx::applier::get_applier_ptr(); if (NULL == app) { HPX_THROWS_IF(ec, invalid_status, "hpx::threads::get_thread_priority", "global applier object is not accessible"); return threads::thread_priority_unknown; } if (&ec != &throws) ec = make_success_code(); return app->get_thread_manager().get_priority(id); }
std::size_t set_thread_data(thread_id_type id, std::size_t d, error_code& ec) { hpx::applier::applier* app = hpx::applier::get_applier_ptr(); if (NULL == app) { HPX_THROWS_IF(ec, invalid_status, "hpx::threads::set_thread_data", "global applier object is not accessible"); return 0; } if (&ec != &throws) ec = make_success_code(); return app->get_thread_manager().set_thread_data(id, d, ec); }
util::backtrace const* get_thread_backtrace(thread_id_type id, error_code& ec) { hpx::applier::applier* app = hpx::applier::get_applier_ptr(); if (NULL == app) { HPX_THROWS_IF(ec, invalid_status, "hpx::threads::get_thread_backtrace", "global applier object is not accessible"); return NULL; } if (&ec != &throws) ec = make_success_code(); return app->get_thread_manager().get_backtrace(id); }
counter_status install( HPX_STD_FUNCTION<create_counter_func> const& create_counter, HPX_STD_FUNCTION<discover_counters_func> const& discover_counters, error_code& ec = throws) { if (status_invalid_data != status_) { HPX_THROWS_IF(ec, hpx::invalid_status, "manage_counter_type::install", "generic counter type " + info_.fullname_ + " has been already installed."); return status_invalid_data; } return status_ = add_counter_type( info_, create_counter, discover_counters, ec); }
void decode_compact_distribution(hwloc_topology& t, std::vector<mask_type>& affinities, error_code& ec) { std::size_t num_threads = affinities.size(); for(std::size_t i = 0; i != num_threads; ++i) { if (any(affinities[i])) { HPX_THROWS_IF(ec, bad_parameter, "decode_compact_distribution", boost::str(boost::format("affinity mask for thread %1% has " "already been set") % i)); return; } affinities[i] = t.init_thread_affinity_mask(i); } }
threads::thread_state_ex_enum suspend( boost::posix_time::time_duration const& after_duration, char const* description, error_code& ec) { // handle interruption, if needed this_thread::interruption_point(); // schedule a thread waking us up after_duration threads::thread_self& self = threads::get_self(); threads::thread_id_type id = self.get_thread_id(); threads::set_thread_state(id, after_duration, threads::pending, threads::wait_signaled, threads::thread_priority_critical, ec); if (ec) return threads::wait_unknown; // let the thread manager do other things while waiting threads::thread_state_ex_enum statex = threads::wait_unknown; { // verify that there are no more registered locks for this OS-thread util::verify_no_locks(); // suspend the HPX-thread detail::reset_lco_description desc(id, description, ec); #if HPX_THREAD_MAINTAIN_BACKTRACE_ON_SUSPENSION detail::reset_backtrace bt(id, ec); #endif statex = self.yield(threads::suspended); } // handle interrupt and abort this_thread::interruption_point(); if (statex == threads::wait_abort) { hpx::util::osstream strm; strm << "thread(" << id << ", " << threads::get_thread_description(id) << ") aborted (yield returned wait_abort)"; HPX_THROWS_IF(ec, yield_aborted, description, hpx::util::osstream_get_string(strm)); } if (&ec != &throws) ec = make_success_code(); return statex; }
threads::thread_id_type register_thread_plain( threads::thread_init_data& data, threads::thread_state_enum state, bool run_now, error_code& ec) { hpx::applier::applier* app = hpx::applier::get_applier_ptr(); if (NULL == app) { HPX_THROWS_IF(ec, invalid_status, "hpx::applier::register_thread_plain", "global applier object is not accessible"); return threads::invalid_thread_id; } threads::thread_id_type id = threads::invalid_thread_id; app->get_thread_manager().register_thread(data, id, state, run_now, ec); return id; }
parcelset::endpoints_type request::get_endpoints( error_code& ec ) const { // {{{ switch (data->which()) { case request_data::subtype_locality_count: return data->get_data<request_data::subtype_locality_count, 0>(ec); default: { HPX_THROWS_IF(ec, bad_parameter, "request::get_endpoints", "invalid operation for request type"); return parcelset::endpoints_type(); } } } // }}}
char const* set_thread_lco_description(thread_id_type const& id, char const* desc, error_code& ec) { hpx::applier::applier* app = hpx::applier::get_applier_ptr(); if (NULL == app) { HPX_THROWS_IF(ec, invalid_status, "hpx::threads::set_thread_lco_description", "global applier object is not accessible"); return NULL; } if (&ec != &throws) ec = make_success_code(); return app->get_thread_manager().set_lco_description(id, desc); }
// Stop the executor identified with the given cookie void resource_manager::stop_executor(std::size_t cookie, error_code& ec) { std::lock_guard<mutex_type> l(mtx_); proxies_map_type::iterator it = proxies_.find(cookie); if (it == proxies_.end()) { HPX_THROWS_IF(ec, bad_parameter, "resource_manager::detach", "the given cookie is not known to the resource manager"); return; } // inform executor to give up virtual cores proxy_data& p = (*it).second; for (coreids_type coreids : p.core_ids_) { p.proxy_->remove_processing_unit(coreids.second, ec); } }
/// The function \a suspend will return control to the thread manager /// (suspends the current thread). It sets the new state of this thread /// to the thread state passed as the parameter. /// /// If the suspension was aborted, this function will throw a /// \a yield_aborted exception. threads::thread_state_ex_enum suspend(threads::thread_state_enum state, char const* description, error_code& ec) { // handle interruption, if needed this_thread::interruption_point(); // let the thread manager do other things while waiting threads::thread_self& self = threads::get_self(); threads::thread_state_ex_enum statex = threads::wait_unknown; { // verify that there are no more registered locks for this OS-thread #if HPX_HAVE_VERIFY_LOCKS util::verify_no_locks(); #endif #if HPX_THREAD_MAINTAIN_DESCRIPTION threads::thread_id_type id = self.get_thread_id(); detail::reset_lco_description desc(id, description, ec); #endif #if HPX_THREAD_MAINTAIN_BACKTRACE_ON_SUSPENSION detail::reset_backtrace bt(id, ec); #endif // suspend the HPX-thread statex = self.yield(state); } // handle interruption, if needed this_thread::interruption_point(); // handle interrupt and abort if (statex == threads::wait_abort) { threads::thread_id_type id = self.get_thread_id(); hpx::util::osstream strm; strm << "thread(" << id << ", " << threads::get_thread_description(id) << ") aborted (yield returned wait_abort)"; HPX_THROWS_IF(ec, yield_aborted, description, hpx::util::osstream_get_string(strm)); } if (&ec != &throws) ec = make_success_code(); return statex; }
void hwloc_topology::set_thread_affinity_mask( mask_type mask , error_code& ec ) const { // {{{ hwloc_cpuset_t cpuset = hwloc_bitmap_alloc(); for (std::size_t i = 0; i < sizeof(std::size_t) * CHAR_BIT; ++i) { if (mask & (static_cast<std::size_t>(1) << i)) { hwloc_bitmap_set(cpuset, static_cast<unsigned int>(i)); } } { scoped_lock lk(topo_mtx); if (hwloc_set_cpubind(topo, cpuset, HWLOC_CPUBIND_STRICT | HWLOC_CPUBIND_THREAD)) { // Strict binding not supported or failed, try weak binding. if (hwloc_set_cpubind(topo, cpuset, HWLOC_CPUBIND_THREAD)) { hwloc_bitmap_free(cpuset); HPX_THROWS_IF(ec, kernel_error , "hpx::threads::hwloc_topology::set_thread_affinity_mask" , boost::str(boost::format( "failed to set thread %x affinity mask") % mask)); if (ec) return; } } } #if defined(__linux) || defined(linux) || defined(__linux__) || defined(__FreeBSD__) sleep(0); // Allow the OS to pick up the change. #endif hwloc_bitmap_free(cpuset); if (&ec != &throws) ec = make_success_code(); } // }}}
void set_thread_affinity_mask( boost::thread& thrd , mask_type mask , error_code& ec = throws ) const { // {{{ if (!SetThreadAffinityMask(thrd.native_handle(), DWORD_PTR(mask))) { HPX_THROWS_IF(ec, kernel_error , "hpx::threads::windows_topology::set_thread_affinity_mask" , boost::str(boost::format( "failed to set thread %1% affinity mask") % mask)); } else if (&ec != &throws) ec = make_success_code(); } // }}}
thread_state set_thread_state(thread_id_type id, thread_state_enum state, thread_state_ex_enum stateex, thread_priority priority, error_code& ec) { hpx::applier::applier* app = hpx::applier::get_applier_ptr(); if (NULL == app) { HPX_THROWS_IF(ec, invalid_status, "hpx::threads::set_thread_state", "global applier object is not accessible"); return thread_state(unknown); } if (&ec != &throws) ec = make_success_code(); return app->get_thread_manager().set_state(id, state, stateex, priority, ec); }
// Return the requested policy element std::size_t generic_thread_pool_executor::get_policy_element( threads::detail::executor_parameter p, error_code& ec) const { switch(p) { case threads::detail::min_concurrency: case threads::detail::max_concurrency: case threads::detail::current_concurrency: return hpx::get_os_thread_count(); default: break; } HPX_THROWS_IF(ec, bad_parameter, "thread_pool_executor::get_policy_element", "requested value of invalid policy element"); return std::size_t(-1); }
naming::gid_type get_next_id( std::size_t count , error_code& ec ) { if (get_runtime_ptr() == 0) { HPX_THROWS_IF(ec, invalid_status, "get_next_id", "the runtime system has not been started yet."); return naming::invalid_gid; } naming::resolver_client& agas_ = naming::get_agas_client(); naming::gid_type lower_bound, upper_bound; agas_.get_id_range(count, lower_bound, upper_bound, ec); if (ec) return naming::invalid_gid; return lower_bound; }
thread_id_type set_thread_state(thread_id_type const& id, boost::posix_time::time_duration const& after, thread_state_enum state, thread_state_ex_enum stateex, thread_priority priority, error_code& ec) { hpx::applier::applier* app = hpx::applier::get_applier_ptr(); if (NULL == app) { HPX_THROWS_IF(ec, invalid_status, "hpx::threads::set_thread_state", "global applier object is not accessible"); return invalid_thread_id; } if (&ec != &throws) ec = make_success_code(); return app->get_thread_manager().set_state(after, id, state, stateex, priority, ec); }
response component_namespace::bind_name( request const& req , error_code& ec ) { // {{{ bind_name implementation // parameters std::string key = req.get_name(); std::unique_lock<mutex_type> l(mutex_); component_id_table_type::left_map::iterator it = component_ids_.left.find(key) , end = component_ids_.left.end(); // If the name is not in the table, register it (this is only done so // we can implement a backwards compatible get_component_id). if (it == end) { if (HPX_UNLIKELY(!util::insert_checked(component_ids_.left.insert( std::make_pair(key, type_counter)), it))) { l.unlock(); HPX_THROWS_IF(ec, lock_error , "component_namespace::bind_name" , "component id table insertion failed due to a locking " "error or memory corruption"); return response(); } // If the insertion succeeded, we need to increment the type // counter. ++type_counter; } LAGAS_(info) << (boost::format( "component_namespace::bind_name, key(%1%), ctype(%2%)") % key % it->second); if (&ec != &throws) ec = make_success_code(); return response(component_ns_bind_name, it->second); } // }}}
void decode_balanced_distribution(hwloc_topology& t, std::vector<mask_type>& affinities, std::size_t used_cores, std::size_t max_cores, std::vector<std::size_t>& num_pus, error_code& ec) { std::size_t num_threads = affinities.size(); std::size_t num_cores = (std::min)(max_cores, t.get_number_of_cores()); std::vector<std::size_t> num_pus_cores(num_cores, 0); num_pus.resize(num_threads); // At first, calculate the number of used pus per core. // This needs to be done to make sure that we occupy all the available cores for (std::size_t num_thread = 0; num_thread != num_threads; /**/) { for(std::size_t num_core = 0; num_core != num_cores; ++num_core) { num_pus_cores[num_core]++; if(++num_thread == num_threads) break; } } // Iterate over the cores and assigned pus per core. this additional loop // is needed so that we have consecutive worker thread numbers std::size_t num_thread = 0; for(std::size_t num_core = 0; num_core != num_cores; ++num_core) { for(std::size_t num_pu = 0; num_pu != num_pus_cores[num_core]; ++num_pu) { if (any(affinities[num_thread])) { HPX_THROWS_IF(ec, bad_parameter, "decode_balanced_distribution", boost::str(boost::format("affinity mask for thread %1% has " "already been set") % num_thread)); return; } num_pus[num_thread] = t.get_pu_number(num_core + used_cores, num_pu); affinities[num_thread] = t.init_thread_affinity_mask( num_core + used_cores, num_pu); ++num_thread; } } }
// Detach the executor identified with the given cookie void resource_manager::detach(std::size_t cookie, error_code& ec) { std::lock_guard<mutex_type> l(mtx_); proxies_map_type::iterator it = proxies_.find(cookie); if (it == proxies_.end()) { HPX_THROWS_IF(ec, bad_parameter, "resource_manager::detach", "the given cookie is not known to the resource manager"); return; } // adjust resource usage count proxy_data& p = (*it).second; for (coreids_type coreids : p.core_ids_) { HPX_ASSERT(punits_[coreids.first].use_count_ != 0); --punits_[coreids.first].use_count_; } proxies_.erase(cookie); }
boost::uint64_t request::get_count( error_code& ec ) const { // {{{ switch (data->which()) { case request_data::subtype_gid_count: return data->get_data<request_data::subtype_gid_count, 1>(ec); case request_data::subtype_locality_count: return data->get_data<request_data::subtype_locality_count, 1>(ec); default: { HPX_THROWS_IF(ec, bad_parameter, "request::get_count", "invalid operation for request type"); return 0; } } } // }}}
std::size_t get_numa_node_number( std::size_t num_thread , error_code& ec = throws ) const { // {{{ if (num_thread < numa_node_numbers_.size()) { if (&ec != &throws) ec = make_success_code(); return numa_node_numbers_[num_thread]; } HPX_THROWS_IF(ec, bad_parameter , "hpx::threads::windows_topology::get_numa_node_number" , boost::str(boost::format( "thread number %1% is out of range") % num_thread)); return std::size_t(-1); } // }}}
std::string regex_from_pattern(std::string const& pattern, error_code& ec) { std::string result; std::string::const_iterator end = pattern.end(); for (std::string::const_iterator it = pattern.begin(); it != end; ++it) { char c = *it; switch (c) { case '*': result.append(".*"); break; case '?': result.append(1, '.'); break; case '[': { std::string r = regex_from_character_set(it, end, ec); if (ec) return ""; result.append(r); } break; case '\\': if (++it == end) { HPX_THROWS_IF(ec, bad_parameter, "regex_from_pattern", "Invalid escape sequence at: " + pattern); return ""; } result.append(1, *it); break; default: result.append(1, c); break; } } return result; }
std::vector<mask_info> extract_socket_or_numanode_masks(hwloc_topology const& t, spec_type const& s, error_code& ec) { switch (s.type_) { case spec_type::socket: // requested top level is a socket { std::size_t num_sockets = t.get_number_of_sockets(); return extract_socket_masks( t, extract_bounds(s, num_sockets, ec)); } case spec_type::numanode: // requested top level is a NUMA node { std::size_t num_numanodes = t.get_number_of_numa_nodes(); return extract_numanode_masks( t, extract_bounds(s, num_numanodes, ec)); } case spec_type::unknown: { std::vector<mask_info> masks; masks.push_back(util::make_tuple( std::size_t(-1), extract_machine_mask(t, ec) )); return masks; } default: HPX_THROWS_IF(ec, bad_parameter, "extract_socket_or_numanode_mask", boost::str(boost::format( "unexpected specification type %s" ) % spec_type::type_name(s.type_))); break; } return std::vector<mask_info>(); }
void register_work_plain( threads::thread_function_type && func, char const* desc, naming::address::address_type lva, threads::thread_state_enum state, threads::thread_priority priority, std::size_t os_thread, threads::thread_stacksize stacksize, error_code& ec) { hpx::applier::applier* app = hpx::applier::get_applier_ptr(); if (NULL == app) { HPX_THROWS_IF(ec, invalid_status, "hpx::applier::register_work_plain", "global applier object is not accessible"); return; } threads::thread_init_data data(std::move(func), desc ? desc : "<unknown>", lva, priority, os_thread, threads::get_stack_size(stacksize)); app->get_thread_manager().register_work(data, state, ec); }
/// \brief Create a full name of a counter from the contents of the given /// \a counter_path_elements instance. counter_status get_counter_type_name(counter_type_path_elements const& path, std::string& result, error_code& ec) { if (path.objectname_.empty()) { HPX_THROWS_IF(ec, bad_parameter, "get_counter_type_name", "empty counter object name"); return status_invalid_data; } result = "/"; result += path.objectname_; if (!path.countername_.empty()) { result += "/"; result += path.countername_; } if (&ec != &throws) ec = make_success_code(); return status_valid_data; }
void register_non_suspendable_work( util::unique_function_nonser<void(threads::thread_state_ex_enum)> && func, char const* desc, threads::thread_state_enum state, threads::thread_priority priority, std::size_t os_thread, error_code& ec) { hpx::applier::applier* app = hpx::applier::get_applier_ptr(); if (NULL == app) { HPX_THROWS_IF(ec, invalid_status, "hpx::applier::register_work", "global applier object is not accessible"); return; } threads::thread_init_data data( util::bind(util::one_shot(&thread_function), std::move(func)), desc ? desc : "<unknown>", 0, priority, os_thread, threads::get_stack_size(threads::thread_stacksize_nostack)); app->get_thread_manager().register_work(data, state, ec); }
boost::uint32_t request::get_locality_id( error_code& ec ) const { switch (data->which()) { case request_data::subtype_gid_gva_prefix: return naming::get_locality_id_from_gid( data->get_data<request_data::subtype_gid_gva_prefix, 2>(ec)); case request_data::subtype_name_prefix: return data->get_data<request_data::subtype_name_prefix, 1>(ec); default: { HPX_THROWS_IF(ec, bad_parameter, "request::get_locality_id", "invalid operation for request type"); return naming::invalid_locality_id; } } }
boost::int64_t request::get_credit( error_code& ec ) const { switch (data->which()) { case request_data::subtype_gid_gid_credit: return data->get_data<request_data::subtype_gid_gid_credit, 2>(ec); case request_data::subtype_gid_count: return static_cast<boost::int64_t>( data->get_data<request_data::subtype_gid_count, 1>(ec)); default: { HPX_THROWS_IF(ec, bad_parameter, "request::get_credit", "invalid operation for request type"); return 0; } } }
naming::gid_type retrieve_agas_counter(std::string const& name, naming::id_type const& agas_id, error_code& ec) { naming::gid_type id; // get action code from counter type agas::namespace_action_code service_code = agas::detail::retrieve_action_service_code(name, ec); if (agas::invalid_request == service_code) return id; // compose request agas::request req(service_code, name); agas::response rep; switch (service_code) { case agas::component_ns_statistics_counter: rep = agas::stubs::component_namespace::service( agas_id, req, threads::thread_priority_default, ec); break; case agas::primary_ns_statistics_counter: rep = agas::stubs::primary_namespace::service( agas_id, req, threads::thread_priority_default, ec); break; case agas::symbol_ns_statistics_counter: rep = agas::stubs::symbol_namespace::service( agas_id, req, threads::thread_priority_default, ec); break; case agas::locality_ns_statistics_counter: rep = agas::stubs::locality_namespace::service( agas_id, req, threads::thread_priority_default, ec); break; default: HPX_THROWS_IF(ec, bad_parameter, "retrieve_statistics_counter", "unknown counter agas counter name: " + name); break; } if (!ec) id = rep.get_statistics_counter(); return id; }