2 Copyright (c) 2014-2015 Intel Corporation. All Rights Reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "compiler_if_host.h"
36 #endif // TARGET_WINNT
38 // Global counter on host.
39 // This variable is used if P2OPT_offload_do_data_persistence == 2.
40 // The variable used to identify offload constructs contained in one procedure.
41 // Increment of OFFLOAD_CALL_COUNT is inserted at entries of HOST routines with
42 // offload constructs.
43 static int offload_call_count
= 0;
45 extern "C" OFFLOAD
OFFLOAD_TARGET_ACQUIRE(
46 TARGET_TYPE target_type
,
49 _Offload_status
* status
,
59 status
->result
= OFFLOAD_UNAVAILABLE
;
60 status
->device_number
= -1;
61 status
->data_sent
= 0;
62 status
->data_received
= 0;
65 // make sure libray is initialized
66 retval
= __offload_init_library();
68 // OFFLOAD_TIMER_INIT must follow call to __offload_init_library
69 OffloadHostTimerData
* timer_data
= OFFLOAD_TIMER_INIT(file
, line
);
71 OFFLOAD_TIMER_START(timer_data
, c_offload_host_total_offload
);
73 OFFLOAD_TIMER_START(timer_data
, c_offload_host_initialize
);
75 // initialize all devices is init_type is on_offload_all
76 if (retval
&& __offload_init_type
== c_init_on_offload_all
) {
77 for (int i
= 0; i
< mic_engines_total
; i
++) {
78 mic_engines
[i
].init();
81 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_initialize
);
83 OFFLOAD_TIMER_START(timer_data
, c_offload_host_target_acquire
);
85 if (target_type
== TARGET_HOST
) {
86 // Host always available
89 else if (target_type
== TARGET_MIC
) {
90 if (target_number
>= -1) {
92 if (target_number
>= 0) {
93 // User provided the device number
94 target_number
= target_number
% mic_engines_total
;
101 // reserve device in ORSL
103 if (!ORSL::try_reserve(target_number
)) {
108 if (!ORSL::reserve(target_number
)) {
114 if (target_number
>= 0 &&
115 __offload_init_type
== c_init_on_offload
) {
116 OFFLOAD_TIMER_START(timer_data
, c_offload_host_initialize
);
117 mic_engines
[target_number
].init();
118 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_initialize
);
126 if (target_number
< 0 || !retval
) {
127 if (!is_optional
&& status
== 0) {
128 LIBOFFLOAD_ERROR(c_device_is_not_available
);
136 LIBOFFLOAD_ERROR(c_invalid_device_number
);
142 ofld
= new OffloadDescriptor(target_number
, status
,
143 !is_optional
, false, timer_data
);
144 OFFLOAD_TIMER_HOST_MIC_NUM(timer_data
, target_number
);
145 Offload_Report_Prolog(timer_data
);
146 OFFLOAD_DEBUG_TRACE_1(2, timer_data
->offload_number
, c_offload_start
,
147 "Starting offload: target_type = %d, "
148 "number = %d, is_optional = %d\n",
149 target_type
, target_number
, is_optional
);
151 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_target_acquire
);
156 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_target_acquire
);
157 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_total_offload
);
158 offload_report_free_data(timer_data
);
164 extern "C" OFFLOAD
OFFLOAD_TARGET_ACQUIRE1(
165 const int* device_num
,
172 // make sure libray is initialized and at least one device is available
173 if (!__offload_init_library()) {
174 LIBOFFLOAD_ERROR(c_device_is_not_available
);
178 // OFFLOAD_TIMER_INIT must follow call to __offload_init_library
180 OffloadHostTimerData
* timer_data
= OFFLOAD_TIMER_INIT(file
, line
);
182 OFFLOAD_TIMER_START(timer_data
, c_offload_host_total_offload
);
184 OFFLOAD_TIMER_START(timer_data
, c_offload_host_initialize
);
186 if (__offload_init_type
== c_init_on_offload_all
) {
187 for (int i
= 0; i
< mic_engines_total
; i
++) {
188 mic_engines
[i
].init();
192 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_initialize
);
194 OFFLOAD_TIMER_START(timer_data
, c_offload_host_target_acquire
);
196 // use default device number if it is not provided
197 if (device_num
!= 0) {
198 target_number
= *device_num
;
201 target_number
= __omp_device_num
;
204 // device number should be a non-negative integer value
205 if (target_number
< 0) {
206 LIBOFFLOAD_ERROR(c_omp_invalid_device_num
);
210 // should we do this for OpenMP?
211 target_number
%= mic_engines_total
;
213 // reserve device in ORSL
214 if (!ORSL::reserve(target_number
)) {
215 LIBOFFLOAD_ERROR(c_device_is_not_available
);
219 // initialize device(s)
220 OFFLOAD_TIMER_START(timer_data
, c_offload_host_initialize
);
222 if (__offload_init_type
== c_init_on_offload
) {
223 mic_engines
[target_number
].init();
226 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_initialize
);
229 new OffloadDescriptor(target_number
, 0, true, true, timer_data
);
231 OFFLOAD_TIMER_HOST_MIC_NUM(timer_data
, target_number
);
233 Offload_Report_Prolog(timer_data
);
235 OFFLOAD_DEBUG_TRACE_1(2, timer_data
->offload_number
, c_offload_start
,
236 "Starting OpenMP offload, device = %d\n",
239 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_target_acquire
);
244 extern "C" OFFLOAD
OFFLOAD_TARGET_ACQUIRE2(
245 TARGET_TYPE target_type
,
248 _Offload_status
* status
,
259 status
->result
= OFFLOAD_UNAVAILABLE
;
260 status
->device_number
= -1;
261 status
->data_sent
= 0;
262 status
->data_received
= 0;
265 // make sure libray is initialized
266 retval
= __offload_init_library();
267 // OFFLOAD_TIMER_INIT must follow call to __offload_init_library
268 OffloadHostTimerData
* timer_data
= OFFLOAD_TIMER_INIT(file
, line
);
270 OFFLOAD_TIMER_START(timer_data
, c_offload_host_total_offload
);
272 OFFLOAD_TIMER_START(timer_data
, c_offload_host_initialize
);
274 // initalize all devices if init_type is on_offload_all
275 if (retval
&& __offload_init_type
== c_init_on_offload_all
) {
276 for (int i
= 0; i
< mic_engines_total
; i
++) {
277 mic_engines
[i
].init();
280 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_initialize
);
282 OFFLOAD_TIMER_START(timer_data
, c_offload_host_target_acquire
);
284 if (target_type
== TARGET_HOST
) {
285 // Host always available
288 else if (target_type
== TARGET_MIC
) {
289 _Offload_stream handle
= *(reinterpret_cast<_Offload_stream
*>(stream
));
290 Stream
* stream
= handle
? Stream::find_stream(handle
, false) : NULL
;
291 if (target_number
>= -1) {
293 // device number is defined by stream
295 target_number
= stream
->get_device();
296 target_number
= target_number
% mic_engines_total
;
299 // reserve device in ORSL
300 if (target_number
!= -1) {
302 if (!ORSL::try_reserve(target_number
)) {
307 if (!ORSL::reserve(target_number
)) {
314 if (target_number
>= 0 &&
315 __offload_init_type
== c_init_on_offload
) {
316 OFFLOAD_TIMER_START(timer_data
, c_offload_host_initialize
);
317 mic_engines
[target_number
].init();
318 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_initialize
);
325 if (!(target_number
== -1 && handle
== 0)) {
326 if (target_number
< 0 || !retval
) {
327 if (!is_optional
&& status
== 0) {
328 LIBOFFLOAD_ERROR(c_device_is_not_available
);
337 LIBOFFLOAD_ERROR(c_invalid_device_number
);
343 ofld
= new OffloadDescriptor(target_number
, status
,
344 !is_optional
, false, timer_data
);
345 OFFLOAD_TIMER_HOST_MIC_NUM(timer_data
, target_number
);
346 Offload_Report_Prolog(timer_data
);
347 OFFLOAD_DEBUG_TRACE_1(2, timer_data
->offload_number
, c_offload_start
,
348 "Starting offload: target_type = %d, "
349 "number = %d, is_optional = %d\n",
350 target_type
, target_number
, is_optional
);
352 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_target_acquire
);
357 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_target_acquire
);
358 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_total_offload
);
359 offload_report_free_data(timer_data
);
365 static int offload_offload_wrap(
376 const void *stack_addr
,
377 OffloadFlags offload_flags
380 bool ret
= ofld
->offload(name
, is_empty
, vars
, vars2
, num_vars
,
381 waits
, num_waits
, signal
, entry_id
,
382 stack_addr
, offload_flags
);
383 if (!ret
|| (signal
== 0 && ofld
->get_stream() == 0 &&
384 !offload_flags
.bits
.omp_async
)) {
390 extern "C" int OFFLOAD_OFFLOAD1(
402 return offload_offload_wrap(ofld
, name
, is_empty
,
403 num_vars
, vars
, vars2
,
405 signal
, 0, NULL
, {0});
408 extern "C" int OFFLOAD_OFFLOAD2(
419 const void *stack_addr
422 return offload_offload_wrap(ofld
, name
, is_empty
,
423 num_vars
, vars
, vars2
,
425 signal
, entry_id
, stack_addr
, {0});
428 extern "C" int OFFLOAD_OFFLOAD3(
439 const void *stack_addr
,
440 OffloadFlags offload_flags
,
444 // 1. if the source is compiled with -traceback then stream is 0
445 // 2. if offload has a stream clause then stream is address of stream value
447 ofld
->set_stream(*(reinterpret_cast<_Offload_stream
*>(stream
)));
450 return offload_offload_wrap(ofld
, name
, is_empty
,
451 num_vars
, vars
, vars2
,
453 signal
, entry_id
, stack_addr
, offload_flags
);
456 extern "C" int OFFLOAD_OFFLOAD(
467 const void *stack_addr
470 // signal is passed by reference now
471 const void **signal_new
= (signal
!= 0) ? &signal
: 0;
472 const void **waits_new
= 0;
473 int num_waits_new
= 0;
475 // remove NULL values from the list of signals to wait for
477 waits_new
= (const void**) alloca(sizeof(void*) * num_waits
);
478 for (int i
= 0; i
< num_waits
; i
++) {
480 waits_new
[num_waits_new
++] = waits
[i
];
485 return OFFLOAD_OFFLOAD1(ofld
, name
, is_empty
,
486 num_vars
, vars
, vars2
,
487 num_waits_new
, waits_new
,
491 extern "C" int OFFLOAD_CALL_COUNT()
493 offload_call_count
++;
494 return offload_call_count
;