1 // Copyright (c) 2007-2008 Anshul Tandon 2 // Copyright (c) 2007-2017 Hartmut Kaiser 3 // Copyright (c) 2011 Bryce Lelbach 4 // 5 // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 8 #include <hpx/config.hpp> 9 #include <hpx/exception.hpp> 10 #include <hpx/runtime/actions/continuation.hpp> 11 #include <hpx/runtime/agas/interface.hpp> 12 #include <hpx/runtime/applier/applier.hpp> 13 #include <hpx/runtime/components/pinned_ptr.hpp> 14 #include <hpx/runtime/naming/resolver_client.hpp> 15 #include <hpx/runtime/parcelset/parcelhandler.hpp> 16 #include <hpx/runtime/parcelset/parcel.hpp> 17 #include <hpx/runtime/threads/threadmanager.hpp> 18 #include <hpx/runtime/threads/thread_helpers.hpp> 19 #include <hpx/util/assert.hpp> 20 #include <hpx/util/register_locks.hpp> 21 #include <hpx/util/thread_description.hpp> 22 23 #include <cstddef> 24 #include <cstdint> 25 #include <functional> 26 #include <memory> 27 #include <sstream> 28 #include <utility> 29 #include <vector> 30 31 namespace hpx { namespace applier 32 { 33 /////////////////////////////////////////////////////////////////////////// register_thread_plain(threads::thread_function_type && func,util::thread_description const & desc,threads::thread_state_enum state,bool run_now,threads::thread_priority priority,threads::thread_schedule_hint schedulehint,threads::thread_stacksize stacksize,error_code & ec)34 threads::thread_id_type register_thread_plain( 35 threads::thread_function_type && func, 36 util::thread_description const& desc, threads::thread_state_enum state, 37 bool run_now, threads::thread_priority priority, 38 threads::thread_schedule_hint schedulehint, 39 threads::thread_stacksize stacksize, error_code& ec) 40 { 41 hpx::applier::applier* app = hpx::applier::get_applier_ptr(); 42 if (nullptr == app) 43 { 44 HPX_THROWS_IF(ec, invalid_status, 45 "hpx::applier::register_thread_plain", 46 "global applier object is not accessible"); 47 return threads::invalid_thread_id; 48 } 49 50 util::thread_description d = 51 desc ? desc : util::thread_description(func, "register_thread_plain"); 52 53 threads::thread_init_data data(std::move(func), 54 d, 0, priority, schedulehint, threads::get_stack_size(stacksize)); 55 56 threads::thread_id_type id = threads::invalid_thread_id; 57 app->get_thread_manager().register_thread(data, id, state, run_now, ec); 58 return id; 59 } 60 register_thread_plain(threads::thread_init_data & data,threads::thread_state_enum state,bool run_now,error_code & ec)61 threads::thread_id_type register_thread_plain( 62 threads::thread_init_data& data, threads::thread_state_enum state, 63 bool run_now, error_code& ec) 64 { 65 hpx::applier::applier* app = hpx::applier::get_applier_ptr(); 66 if (nullptr == app) 67 { 68 HPX_THROWS_IF(ec, invalid_status, 69 "hpx::applier::register_thread_plain", 70 "global applier object is not accessible"); 71 return threads::invalid_thread_id; 72 } 73 74 threads::thread_id_type id = threads::invalid_thread_id; 75 app->get_thread_manager().register_thread(data, id, state, run_now, ec); 76 return id; 77 } 78 79 /////////////////////////////////////////////////////////////////////////// register_work_plain(threads::thread_function_type && func,util::thread_description const & desc,naming::address::address_type lva,threads::thread_state_enum state,threads::thread_priority priority,threads::thread_schedule_hint schedulehint,threads::thread_stacksize stacksize,error_code & ec)80 void register_work_plain( 81 threads::thread_function_type && func, 82 util::thread_description const& desc, naming::address::address_type lva, 83 threads::thread_state_enum state, threads::thread_priority priority, 84 threads::thread_schedule_hint schedulehint, 85 threads::thread_stacksize stacksize, 86 error_code& ec) 87 { 88 hpx::applier::applier* app = hpx::applier::get_applier_ptr(); 89 if (nullptr == app) 90 { 91 HPX_THROWS_IF(ec, invalid_status, 92 "hpx::applier::register_work_plain", 93 "global applier object is not accessible"); 94 return; 95 } 96 97 util::thread_description d = 98 desc ? desc : util::thread_description(func, "register_work_plain"); 99 100 threads::thread_init_data data(std::move(func), 101 d, lva, priority, schedulehint, threads::get_stack_size(stacksize)); 102 103 app->get_thread_manager().register_work(data, state, ec); 104 } 105 register_work_plain(threads::thread_init_data & data,threads::thread_state_enum state,error_code & ec)106 void register_work_plain( 107 threads::thread_init_data& data, threads::thread_state_enum state, 108 error_code& ec) 109 { 110 hpx::applier::applier* app = hpx::applier::get_applier_ptr(); 111 if (nullptr == app) 112 { 113 HPX_THROWS_IF(ec, invalid_status, 114 "hpx::applier::register_work_plain", 115 "global applier object is not accessible"); 116 return; 117 } 118 119 app->get_thread_manager().register_work(data, state, ec); 120 } 121 122 /////////////////////////////////////////////////////////////////////////// 123 hpx::util::thread_specific_ptr<applier*, applier::tls_tag> applier::applier_; 124 applier(parcelset::parcelhandler & ph,threads::threadmanager & tm)125 applier::applier(parcelset::parcelhandler &ph, threads::threadmanager& tm) 126 : parcel_handler_(ph), thread_manager_(tm) 127 {} 128 initialize(std::uint64_t rts,std::uint64_t mem)129 void applier::initialize(std::uint64_t rts, std::uint64_t mem) 130 { 131 naming::resolver_client & agas_client = get_agas_client(); 132 runtime_support_id_ = naming::id_type( 133 agas_client.get_local_locality().get_msb(), 134 rts, naming::id_type::unmanaged); 135 memory_id_ = naming::id_type( 136 agas_client.get_local_locality().get_msb(), 137 mem, naming::id_type::unmanaged); 138 } 139 get_agas_client()140 naming::resolver_client& applier::get_agas_client() 141 { 142 return hpx::naming::get_agas_client(); 143 } 144 get_parcel_handler()145 parcelset::parcelhandler& applier::get_parcel_handler() 146 { 147 return parcel_handler_; 148 } 149 get_thread_manager()150 threads::threadmanager& applier::get_thread_manager() 151 { 152 return thread_manager_; 153 } 154 get_raw_locality(error_code & ec) const155 naming::gid_type const& applier::get_raw_locality(error_code& ec) const 156 { 157 return hpx::naming::get_agas_client().get_local_locality(ec); 158 } 159 get_locality_id(error_code & ec) const160 std::uint32_t applier::get_locality_id(error_code& ec) const 161 { 162 return naming::get_locality_id_from_gid(get_raw_locality(ec)); 163 } 164 get_raw_remote_localities(std::vector<naming::gid_type> & prefixes,components::component_type type,error_code & ec) const165 bool applier::get_raw_remote_localities( 166 std::vector<naming::gid_type>& prefixes, 167 components::component_type type, error_code& ec) const 168 { 169 return parcel_handler_.get_raw_remote_localities(prefixes, type, ec); 170 } 171 get_remote_localities(std::vector<naming::id_type> & prefixes,components::component_type type,error_code & ec) const172 bool applier::get_remote_localities(std::vector<naming::id_type>& prefixes, 173 components::component_type type, error_code& ec) const 174 { 175 std::vector<naming::gid_type> raw_prefixes; 176 if (!parcel_handler_.get_raw_remote_localities(raw_prefixes, type, ec)) 177 return false; 178 179 for (naming::gid_type& gid : raw_prefixes) 180 prefixes.push_back(naming::id_type(gid, naming::id_type::unmanaged)); 181 182 return true; 183 } 184 get_raw_localities(std::vector<naming::gid_type> & prefixes,components::component_type type) const185 bool applier::get_raw_localities(std::vector<naming::gid_type>& prefixes, 186 components::component_type type) const 187 { 188 return parcel_handler_.get_raw_localities(prefixes, type); 189 } 190 get_localities(std::vector<naming::id_type> & prefixes,error_code & ec) const191 bool applier::get_localities(std::vector<naming::id_type>& prefixes, 192 error_code& ec) const 193 { 194 std::vector<naming::gid_type> raw_prefixes; 195 if (!parcel_handler_.get_raw_localities(raw_prefixes, 196 components::component_invalid, ec)) 197 return false; 198 199 for (naming::gid_type& gid : raw_prefixes) 200 prefixes.push_back(naming::id_type(gid, naming::id_type::unmanaged)); 201 202 return true; 203 } 204 get_localities(std::vector<naming::id_type> & prefixes,components::component_type type,error_code & ec) const205 bool applier::get_localities(std::vector<naming::id_type>& prefixes, 206 components::component_type type, error_code& ec) const 207 { 208 std::vector<naming::gid_type> raw_prefixes; 209 if (!parcel_handler_.get_raw_localities(raw_prefixes, type, ec)) 210 return false; 211 212 for (naming::gid_type& gid : raw_prefixes) 213 prefixes.push_back(naming::id_type(gid, naming::id_type::unmanaged)); 214 215 return true; 216 } 217 init_tss()218 void applier::init_tss() 219 { 220 if (nullptr == applier::applier_.get()) 221 applier::applier_.reset(new applier* (this)); 222 } 223 deinit_tss()224 void applier::deinit_tss() 225 { 226 applier::applier_.reset(); 227 } 228 get_applier()229 applier& get_applier() 230 { 231 // should have been initialized 232 HPX_ASSERT(nullptr != applier::applier_.get()); 233 return **applier::applier_; 234 } 235 get_applier_ptr()236 applier* get_applier_ptr() 237 { 238 applier** appl = applier::applier_.get(); 239 return appl ? *appl : nullptr; 240 } 241 242 // The function \a get_locality_id returns the id of this locality get_locality_id(error_code & ec)243 std::uint32_t get_locality_id(error_code& ec) //-V659 244 { 245 applier** appl = applier::applier_.get(); 246 return appl ? (*appl)->get_locality_id(ec) : naming::invalid_locality_id; 247 } 248 }} 249 250