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