Line | % of fetches | Source |
---|---|---|
1 | // Copyright (c) 2007-2008 Anshul Tandon | |
2 | // Copyright (c) 2007-2016 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/components/server/runtime_support.hpp> | |
15 | #include <hpx/runtime/naming/resolver_client.hpp> | |
16 | #include <hpx/runtime/parcelset/parcelhandler.hpp> | |
17 | #include <hpx/runtime/parcelset/parcel.hpp> | |
18 | #include <hpx/runtime/threads/threadmanager.hpp> | |
19 | #include <hpx/runtime/threads/thread_helpers.hpp> | |
20 | #include <hpx/util/register_locks.hpp> | |
21 | #include <hpx/util/thread_description.hpp> | |
22 | #if defined(HPX_HAVE_SECURITY) | |
23 | #include <hpx/components/security/capability.hpp> | |
24 | #include <hpx/components/security/certificate.hpp> | |
25 | #include <hpx/components/security/signed_type.hpp> | |
26 | #endif | |
27 | ||
28 | #include <cstddef> | |
29 | #include <cstdint> | |
30 | #include <functional> | |
31 | #include <memory> | |
32 | #include <sstream> | |
33 | #include <utility> | |
34 | #include <vector> | |
35 | ||
36 | namespace hpx { namespace applier | |
37 | { | |
38 | /////////////////////////////////////////////////////////////////////////// | |
39 | static inline threads::thread_result_type thread_function( | |
40 | util::unique_function_nonser<void(threads::thread_state_ex_enum)> func) | |
41 | { | |
42 | // execute the actual thread function | |
43 | func(threads::wait_signaled); | |
44 | ||
45 | // Verify that there are no more registered locks for this | |
46 | // OS-thread. This will throw if there are still any locks | |
47 | // held. | |
48 | util::force_error_on_lock(); | |
49 | ||
50 | return threads::thread_result_type(threads::terminated, nullptr); | |
51 | } | |
52 | ||
53 | static inline threads::thread_result_type thread_function_nullary( | |
54 | util::unique_function_nonser<void()> func) | |
55 | { | |
56 | // execute the actual thread function | |
57 | func(); | |
58 | ||
59 | // Verify that there are no more registered locks for this | |
60 | // OS-thread. This will throw if there are still any locks | |
61 | // held. | |
62 | util::force_error_on_lock(); | |
63 | ||
64 | return threads::thread_result_type(threads::terminated, nullptr); | |
65 | } | |
66 | ||
67 | /////////////////////////////////////////////////////////////////////////// | |
68 | threads::thread_id_type register_thread_nullary( | |
69 | util::unique_function_nonser<void()> && func, | |
70 | util::thread_description const& desc, | |
71 | threads::thread_state_enum state, bool run_now, | |
72 | threads::thread_priority priority, std::size_t os_thread, | |
73 | threads::thread_stacksize stacksize, error_code& ec) | |
74 | { | |
75 | hpx::applier::applier* app = hpx::applier::get_applier_ptr(); | |
76 | if (nullptr == app) | |
77 | { | |
78 | HPX_THROWS_IF(ec, invalid_status, | |
79 | "hpx::applier::register_thread_nullary", | |
80 | "global applier object is not accessible"); | |
81 | return threads::invalid_thread_id; | |
82 | } | |
83 | ||
84 | util::thread_description d = | |
85 | desc ? desc : util::thread_description(func, "register_thread_nullary"); | |
86 | ||
87 | threads::thread_init_data data( | |
88 | util::bind(util::one_shot(&thread_function_nullary), std::move(func)), | |
89 | d, 0, priority, os_thread, threads::get_stack_size(stacksize)); | |
90 | ||
91 | threads::thread_id_type id = threads::invalid_thread_id; | |
92 | app->get_thread_manager().register_thread(data, id, state, run_now, ec); | |
93 | return id; | |
94 | } | |
95 | ||
96 | threads::thread_id_type register_thread( | |
97 | util::unique_function_nonser<void(threads::thread_state_ex_enum)> && func, | |
98 | util::thread_description const& desc, threads::thread_state_enum state, | |
99 | bool run_now, threads::thread_priority priority, std::size_t os_thread, | |
100 | threads::thread_stacksize stacksize, error_code& ec) | |
101 | { | |
102 | hpx::applier::applier* app = hpx::applier::get_applier_ptr(); | |
103 | if (nullptr == app) | |
104 | { | |
105 | HPX_THROWS_IF(ec, invalid_status, | |
106 | "hpx::applier::register_thread", | |
107 | "global applier object is not accessible"); | |
108 | return threads::invalid_thread_id; | |
109 | } | |
110 | ||
111 | util::thread_description d = | |
112 | desc ? desc : util::thread_description(func, "register_thread"); | |
113 | ||
114 | threads::thread_init_data data( | |
115 | util::bind(util::one_shot(&thread_function), std::move(func)), | |
116 | d, 0, priority, os_thread, threads::get_stack_size(stacksize)); | |
117 | ||
118 | threads::thread_id_type id = threads::invalid_thread_id; | |
119 | app->get_thread_manager().register_thread(data, id, state, run_now, ec); | |
120 | return id; | |
121 | } | |
122 | ||
123 | threads::thread_id_type register_thread_plain( | |
124 | threads::thread_function_type && func, | |
125 | util::thread_description const& desc, threads::thread_state_enum state, | |
126 | bool run_now, threads::thread_priority priority, std::size_t os_thread, | |
127 | threads::thread_stacksize stacksize, error_code& ec) | |
128 | { | |
129 | hpx::applier::applier* app = hpx::applier::get_applier_ptr(); | |
130 | if (nullptr == app) | |
131 | { | |
132 | HPX_THROWS_IF(ec, invalid_status, | |
133 | "hpx::applier::register_thread_plain", | |
134 | "global applier object is not accessible"); | |
135 | return threads::invalid_thread_id; | |
136 | } | |
137 | ||
138 | util::thread_description d = | |
139 | desc ? desc : util::thread_description(func, "register_thread_plain"); | |
140 | ||
141 | threads::thread_init_data data(std::move(func), | |
142 | d, 0, priority, os_thread, threads::get_stack_size(stacksize)); | |
143 | ||
144 | threads::thread_id_type id = threads::invalid_thread_id; | |
145 | app->get_thread_manager().register_thread(data, id, state, run_now, ec); | |
146 | return id; | |
147 | } | |
148 | ||
149 | threads::thread_id_type register_thread_plain( | |
150 | threads::thread_init_data& data, threads::thread_state_enum state, | |
151 | bool run_now, error_code& ec) | |
152 | { | |
153 | hpx::applier::applier* app = hpx::applier::get_applier_ptr(); | |
154 | if (nullptr == app) | |
155 | { | |
156 | HPX_THROWS_IF(ec, invalid_status, | |
157 | "hpx::applier::register_thread_plain", | |
158 | "global applier object is not accessible"); | |
159 | return threads::invalid_thread_id; | |
160 | } | |
161 | ||
162 | threads::thread_id_type id = threads::invalid_thread_id; | |
163 | app->get_thread_manager().register_thread(data, id, state, run_now, ec); | |
164 | return id; | |
165 | } | |
166 | ||
167 | /////////////////////////////////////////////////////////////////////////// | |
168 | void register_work_nullary( | |
169 | util::unique_function_nonser<void()> && func, | |
170 | util::thread_description const& desc, | |
171 | threads::thread_state_enum state, threads::thread_priority priority, | |
172 | std::size_t os_thread, threads::thread_stacksize stacksize, | |
173 | error_code& ec) | |
174 | { | |
175 | hpx::applier::applier* app = hpx::applier::get_applier_ptr(); | |
176 | if (nullptr == app) | |
177 | { | |
178 | HPX_THROWS_IF(ec, invalid_status, | |
179 | "hpx::applier::register_work_nullary", | |
180 | "global applier object is not accessible"); | |
181 | return; | |
182 | } | |
183 | ||
184 | util::thread_description d = | |
185 | desc ? desc : util::thread_description(func, "register_thread_nullary"); | |
186 | ||
187 | threads::thread_init_data data( | |
188 | util::bind(util::one_shot(&thread_function_nullary), std::move(func)), | |
189 | d, 0, priority, os_thread, threads::get_stack_size(stacksize)); | |
190 | ||
191 | app->get_thread_manager().register_work(data, state, ec); | |
192 | } | |
193 | ||
194 | void register_work( | |
195 | util::unique_function_nonser<void(threads::thread_state_ex_enum)> && func, | |
196 | util::thread_description const& desc, threads::thread_state_enum state, | |
197 | threads::thread_priority priority, std::size_t os_thread, | |
198 | threads::thread_stacksize stacksize, error_code& ec) | |
199 | { | |
200 | hpx::applier::applier* app = hpx::applier::get_applier_ptr(); | |
201 | if (nullptr == app) | |
202 | { | |
203 | HPX_THROWS_IF(ec, invalid_status, | |
204 | "hpx::applier::register_work", | |
205 | "global applier object is not accessible"); | |
206 | return; | |
207 | } | |
208 | ||
209 | util::thread_description d = | |
210 | desc ? desc : util::thread_description(func, "register_work"); | |
211 | ||
212 | threads::thread_init_data data( | |
213 | util::bind(util::one_shot(&thread_function), std::move(func)), | |
214 | d, 0, priority, os_thread, threads::get_stack_size(stacksize)); | |
215 | ||
216 | app->get_thread_manager().register_work(data, state, ec); | |
217 | } | |
218 | ||
219 | void register_work_plain( | |
220 | threads::thread_function_type && func, | |
221 | util::thread_description const& desc, naming::address::address_type lva, | |
222 | threads::thread_state_enum state, threads::thread_priority priority, | |
223 | std::size_t os_thread, threads::thread_stacksize stacksize, | |
224 | error_code& ec) | |
225 | { | |
226 | hpx::applier::applier* app = hpx::applier::get_applier_ptr(); | |
227 | if (nullptr == app) | |
228 | { | |
229 | HPX_THROWS_IF(ec, invalid_status, | |
230 | "hpx::applier::register_work_plain", | |
231 | "global applier object is not accessible"); | |
232 | return; | |
233 | } | |
234 | ||
235 | util::thread_description d = | |
236 | desc ? desc : util::thread_description(func, "register_work_plain"); | |
237 | ||
238 | threads::thread_init_data data(std::move(func), | |
239 | d, lva, priority, os_thread, threads::get_stack_size(stacksize)); | |
240 | ||
241 | app->get_thread_manager().register_work(data, state, ec); | |
242 | } | |
243 | ||
244 | void register_work_plain( | |
245 | threads::thread_init_data& data, threads::thread_state_enum state, | |
246 | error_code& ec) | |
247 | { | |
248 | hpx::applier::applier* app = hpx::applier::get_applier_ptr(); | |
249 | if (nullptr == app) | |
250 | { | |
251 | HPX_THROWS_IF(ec, invalid_status, | |
252 | "hpx::applier::register_work_plain", | |
253 | "global applier object is not accessible"); | |
254 | return; | |
255 | } | |
256 | ||
257 | app->get_thread_manager().register_work(data, state, ec); | |
258 | } | |
259 | ||
260 | /////////////////////////////////////////////////////////////////////////// | |
261 | hpx::util::thread_specific_ptr<applier*, applier::tls_tag> applier::applier_; | |
262 | ||
263 | applier::applier(parcelset::parcelhandler &ph, threads::threadmanager_base& tm) | |
264 | : parcel_handler_(ph), thread_manager_(tm) | |
265 | #if defined(HPX_HAVE_SECURITY) | |
266 | , verify_capabilities_(false) | |
267 | #endif | |
268 | {} | |
269 | ||
270 | void applier::initialize(std::uint64_t rts, std::uint64_t mem) | |
271 | { | |
272 | naming::resolver_client & agas_client = get_agas_client(); | |
273 | runtime_support_id_ = naming::id_type( | |
274 | agas_client.get_local_locality().get_msb(), | |
275 | rts, naming::id_type::unmanaged); | |
276 | memory_id_ = naming::id_type( | |
277 | agas_client.get_local_locality().get_msb(), | |
278 | mem, naming::id_type::unmanaged); | |
279 | } | |
280 | ||
281 | naming::resolver_client& applier::get_agas_client() | |
282 | { | |
283 | return hpx::naming::get_agas_client(); | |
284 | } | |
285 | ||
286 | parcelset::parcelhandler& applier::get_parcel_handler() | |
287 | { | |
288 | return parcel_handler_; | |
289 | } | |
290 | ||
291 | threads::threadmanager_base& applier::get_thread_manager() | |
292 | { | |
293 | return thread_manager_; | |
294 | } | |
295 | ||
296 | naming::gid_type const& applier::get_raw_locality(error_code& ec) const | |
297 | { | |
298 | return hpx::naming::get_agas_client().get_local_locality(ec); | |
299 | } | |
300 | ||
301 | std::uint32_t applier::get_locality_id(error_code& ec) const | |
302 | { | |
303 | return naming::get_locality_id_from_gid(get_raw_locality(ec)); | |
304 | } | |
305 | ||
306 | bool applier::get_raw_remote_localities( | |
307 | std::vector<naming::gid_type>& prefixes, | |
308 | components::component_type type, error_code& ec) const | |
309 | { | |
310 | return parcel_handler_.get_raw_remote_localities(prefixes, type, ec); | |
311 | } | |
312 | ||
313 | bool applier::get_remote_localities(std::vector<naming::id_type>& prefixes, | |
314 | components::component_type type, error_code& ec) const | |
315 | { | |
316 | std::vector<naming::gid_type> raw_prefixes; | |
317 | if (!parcel_handler_.get_raw_remote_localities(raw_prefixes, type, ec)) | |
318 | return false; | |
319 | ||
320 | for (naming::gid_type& gid : raw_prefixes) | |
321 | prefixes.push_back(naming::id_type(gid, naming::id_type::unmanaged)); | |
322 | ||
323 | return true; | |
324 | } | |
325 | ||
326 | bool applier::get_raw_localities(std::vector<naming::gid_type>& prefixes, | |
327 | components::component_type type) const | |
328 | { | |
329 | return parcel_handler_.get_raw_localities(prefixes, type); | |
330 | } | |
331 | ||
332 | bool applier::get_localities(std::vector<naming::id_type>& prefixes, | |
333 | error_code& ec) const | |
334 | { | |
335 | std::vector<naming::gid_type> raw_prefixes; | |
336 | if (!parcel_handler_.get_raw_localities(raw_prefixes, | |
337 | components::component_invalid, ec)) | |
338 | return false; | |
339 | ||
340 | for (naming::gid_type& gid : raw_prefixes) | |
341 | prefixes.push_back(naming::id_type(gid, naming::id_type::unmanaged)); | |
342 | ||
343 | return true; | |
344 | } | |
345 | ||
346 | bool applier::get_localities(std::vector<naming::id_type>& prefixes, | |
347 | components::component_type type, error_code& ec) const | |
348 | { | |
349 | std::vector<naming::gid_type> raw_prefixes; | |
350 | if (!parcel_handler_.get_raw_localities(raw_prefixes, type, ec)) | |
351 | return false; | |
352 | ||
353 | for (naming::gid_type& gid : raw_prefixes) | |
354 | prefixes.push_back(naming::id_type(gid, naming::id_type::unmanaged)); | |
355 | ||
356 | return true; | |
357 | } | |
358 | ||
359 | void applier::init_tss() | |
360 | { | |
361 | if (nullptr == applier::applier_.get()) | |
362 | applier::applier_.reset(new applier* (this)); | |
363 | } | |
364 | ||
365 | void applier::deinit_tss() | |
366 | { | |
367 | applier::applier_.reset(); | |
368 | } | |
369 | ||
370 | applier& get_applier() | |
371 | { | |
372 | // should have been initialized | |
373 | HPX_ASSERT(nullptr != applier::applier_.get()); | |
374 | return **applier::applier_; | |
375 | } | |
376 | ||
377 | applier* get_applier_ptr() | |
378 | { | |
379 | applier** appl = applier::applier_.get(); | |
380 | return appl ? *appl : nullptr; | |
381 | } | |
382 | ||
383 | // The function \a get_locality_id returns the id of this locality | |
384 | std::uint32_t get_locality_id(error_code& ec) //-V659 | |
385 | { | |
386 | applier** appl = applier::applier_.get(); | |
387 | return appl ? (*appl)->get_locality_id(ec) : naming::invalid_locality_id; | |
388 | } | |
389 | }} | |
390 | ||
391 |
Copyright (c) 2006-2012 Rogue Wave Software, Inc. All Rights Reserved.
Patents pending.