2015-05-12 Pierre-Marie de Rodat <derodat@adacore.com>
[official-gcc.git] / liboffloadmic / runtime / compiler_if_host.cpp
blobc4e2a15633f7182037d7852fbc190a56f11c7283
1 /*
2 Copyright (c) 2014 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
6 are met:
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"
33 #include <malloc.h>
34 #ifndef TARGET_WINNT
35 #include <alloca.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,
47 int target_number,
48 int is_optional,
49 _Offload_status* status,
50 const char* file,
51 uint64_t line
54 bool retval;
55 OFFLOAD ofld;
57 // initialize status
58 if (status != 0) {
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 // initalize 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
87 retval = true;
89 else if (target_type == TARGET_MIC) {
90 if (target_number >= -1) {
91 if (retval) {
92 if (target_number >= 0) {
93 // User provided the device number
94 target_number = target_number % mic_engines_total;
96 else {
97 // use device 0
98 target_number = 0;
101 // reserve device in ORSL
102 if (is_optional) {
103 if (!ORSL::try_reserve(target_number)) {
104 target_number = -1;
107 else {
108 if (!ORSL::reserve(target_number)) {
109 target_number = -1;
113 // initialize device
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);
121 else {
122 // fallback to CPU
123 target_number = -1;
126 if (target_number < 0 || !retval) {
127 if (!is_optional && status == 0) {
128 LIBOFFLOAD_ERROR(c_device_is_not_available);
129 exit(1);
132 retval = false;
135 else {
136 LIBOFFLOAD_ERROR(c_invalid_device_number);
137 exit(1);
141 if (retval) {
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);
153 else {
154 ofld = NULL;
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);
161 return ofld;
164 extern "C" OFFLOAD OFFLOAD_TARGET_ACQUIRE1(
165 const int* device_num,
166 const char* file,
167 uint64_t line
170 int target_number;
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);
175 exit(1);
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;
200 else {
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);
207 exit(1);
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);
216 exit(1);
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);
228 OFFLOAD ofld =
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",
237 target_number);
239 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_target_acquire);
241 return ofld;
244 int offload_offload_wrap(
245 OFFLOAD ofld,
246 const char *name,
247 int is_empty,
248 int num_vars,
249 VarDesc *vars,
250 VarDesc2 *vars2,
251 int num_waits,
252 const void **waits,
253 const void **signal,
254 int entry_id,
255 const void *stack_addr
258 bool ret = ofld->offload(name, is_empty, vars, vars2, num_vars,
259 waits, num_waits, signal, entry_id, stack_addr);
260 if (!ret || signal == 0) {
261 delete ofld;
263 return ret;
266 extern "C" int OFFLOAD_OFFLOAD1(
267 OFFLOAD ofld,
268 const char *name,
269 int is_empty,
270 int num_vars,
271 VarDesc *vars,
272 VarDesc2 *vars2,
273 int num_waits,
274 const void **waits,
275 const void **signal
278 return offload_offload_wrap(ofld, name, is_empty,
279 num_vars, vars, vars2,
280 num_waits, waits,
281 signal, NULL, NULL);
284 extern "C" int OFFLOAD_OFFLOAD2(
285 OFFLOAD ofld,
286 const char *name,
287 int is_empty,
288 int num_vars,
289 VarDesc *vars,
290 VarDesc2 *vars2,
291 int num_waits,
292 const void** waits,
293 const void** signal,
294 int entry_id,
295 const void *stack_addr
298 return offload_offload_wrap(ofld, name, is_empty,
299 num_vars, vars, vars2,
300 num_waits, waits,
301 signal, entry_id, stack_addr);
304 extern "C" int OFFLOAD_OFFLOAD(
305 OFFLOAD ofld,
306 const char *name,
307 int is_empty,
308 int num_vars,
309 VarDesc *vars,
310 VarDesc2 *vars2,
311 int num_waits,
312 const void **waits,
313 const void *signal,
314 int entry_id,
315 const void *stack_addr
318 // signal is passed by reference now
319 const void **signal_new = (signal != 0) ? &signal : 0;
320 const void **waits_new = 0;
321 int num_waits_new = 0;
323 // remove NULL values from the list of signals to wait for
324 if (num_waits > 0) {
325 waits_new = (const void**) alloca(sizeof(void*) * num_waits);
326 for (int i = 0; i < num_waits; i++) {
327 if (waits[i] != 0) {
328 waits_new[num_waits_new++] = waits[i];
333 return OFFLOAD_OFFLOAD1(ofld, name, is_empty,
334 num_vars, vars, vars2,
335 num_waits_new, waits_new,
336 signal_new);
339 extern "C" int OFFLOAD_CALL_COUNT()
341 offload_call_count++;
342 return offload_call_count;