1/*
2    Copyright (c) 2014 Intel Corporation.  All Rights Reserved.
3
4    Redistribution and use in source and binary forms, with or without
5    modification, are permitted provided that the following conditions
6    are met:
7
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.
16
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.
28*/
29
30
31#include <omp.h>
32#include "offload.h"
33#include "compiler_if_host.h"
34
35// OpenMP API
36
37void omp_set_default_device(int num) __GOMP_NOTHROW
38{
39    if (num >= 0) {
40        __omp_device_num = num;
41    }
42}
43
44int omp_get_default_device(void) __GOMP_NOTHROW
45{
46    return __omp_device_num;
47}
48
49int omp_get_num_devices() __GOMP_NOTHROW
50{
51    __offload_init_library();
52    return mic_engines_total;
53}
54
55// OpenMP API wrappers
56
57static void omp_set_int_target(
58    TARGET_TYPE target_type,
59    int target_number,
60    int setting,
61    const char* f_name
62)
63{
64    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
65                                          f_name, 0);
66    if (ofld) {
67        VarDesc vars[1] = {0};
68
69        vars[0].type.src = c_data;
70        vars[0].type.dst = c_data;
71        vars[0].direction.bits = c_parameter_in;
72        vars[0].size = sizeof(int);
73        vars[0].count = 1;
74        vars[0].ptr = &setting;
75
76        OFFLOAD_OFFLOAD(ofld, f_name, 0, 1, vars, NULL, 0, 0, 0);
77    }
78}
79
80static int omp_get_int_target(
81    TARGET_TYPE target_type,
82    int target_number,
83    const char * f_name
84)
85{
86    int setting = 0;
87
88    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
89                                          f_name, 0);
90    if (ofld) {
91        VarDesc vars[1] = {0};
92
93        vars[0].type.src = c_data;
94        vars[0].type.dst = c_data;
95        vars[0].direction.bits = c_parameter_out;
96        vars[0].size = sizeof(int);
97        vars[0].count = 1;
98        vars[0].ptr = &setting;
99
100        OFFLOAD_OFFLOAD(ofld, f_name, 0, 1, vars, NULL, 0, 0, 0);
101    }
102    return setting;
103}
104
105void omp_set_num_threads_target(
106    TARGET_TYPE target_type,
107    int target_number,
108    int num_threads
109)
110{
111    omp_set_int_target(target_type, target_number, num_threads,
112                       "omp_set_num_threads_target");
113}
114
115int omp_get_max_threads_target(
116    TARGET_TYPE target_type,
117    int target_number
118)
119{
120    return omp_get_int_target(target_type, target_number,
121                              "omp_get_max_threads_target");
122}
123
124int omp_get_num_procs_target(
125    TARGET_TYPE target_type,
126    int target_number
127)
128{
129    return omp_get_int_target(target_type, target_number,
130                              "omp_get_num_procs_target");
131}
132
133void omp_set_dynamic_target(
134    TARGET_TYPE target_type,
135    int target_number,
136    int num_threads
137)
138{
139    omp_set_int_target(target_type, target_number, num_threads,
140                       "omp_set_dynamic_target");
141}
142
143int omp_get_dynamic_target(
144    TARGET_TYPE target_type,
145    int target_number
146)
147{
148    return omp_get_int_target(target_type, target_number,
149                              "omp_get_dynamic_target");
150}
151
152void omp_set_nested_target(
153    TARGET_TYPE target_type,
154    int target_number,
155    int nested
156)
157{
158    omp_set_int_target(target_type, target_number, nested,
159                       "omp_set_nested_target");
160}
161
162int omp_get_nested_target(
163    TARGET_TYPE target_type,
164    int target_number
165)
166{
167    return omp_get_int_target(target_type, target_number,
168                              "omp_get_nested_target");
169}
170
171void omp_set_schedule_target(
172    TARGET_TYPE target_type,
173    int target_number,
174    omp_sched_t kind,
175    int modifier
176)
177{
178    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
179                                          __func__, 0);
180    if (ofld != 0) {
181        VarDesc vars[2] = {0};
182
183        vars[0].type.src = c_data;
184        vars[0].type.dst = c_data;
185        vars[0].direction.bits = c_parameter_in;
186        vars[0].size = sizeof(omp_sched_t);
187        vars[0].count = 1;
188        vars[0].ptr = &kind;
189
190        vars[1].type.src = c_data;
191        vars[1].type.dst = c_data;
192        vars[1].direction.bits = c_parameter_in;
193        vars[1].size = sizeof(int);
194        vars[1].count = 1;
195        vars[1].ptr = &modifier;
196
197        OFFLOAD_OFFLOAD(ofld, "omp_set_schedule_target",
198                        0, 2, vars, NULL, 0, 0, 0);
199    }
200}
201
202void omp_get_schedule_target(
203    TARGET_TYPE target_type,
204    int target_number,
205    omp_sched_t *kind,
206    int *modifier
207)
208{
209    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
210                                          __func__, 0);
211    if (ofld != 0) {
212        VarDesc vars[2] = {0};
213
214        vars[0].type.src = c_data;
215        vars[0].type.dst = c_data;
216        vars[0].direction.bits = c_parameter_out;
217        vars[0].size = sizeof(omp_sched_t);
218        vars[0].count = 1;
219        vars[0].ptr = kind;
220
221        vars[1].type.src = c_data;
222        vars[1].type.dst = c_data;
223        vars[1].direction.bits = c_parameter_out;
224        vars[1].size = sizeof(int);
225        vars[1].count = 1;
226        vars[1].ptr = modifier;
227
228        OFFLOAD_OFFLOAD(ofld, "omp_get_schedule_target",
229                        0, 2, vars, NULL, 0, 0, 0);
230    }
231}
232
233// lock API functions
234
235void omp_init_lock_target(
236    TARGET_TYPE target_type,
237    int target_number,
238    omp_lock_target_t *lock
239)
240{
241    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
242                                          __func__, 0);
243    if (ofld != 0) {
244        VarDesc vars[1] = {0};
245
246        vars[0].type.src = c_data;
247        vars[0].type.dst = c_data;
248        vars[0].direction.bits = c_parameter_out;
249        vars[0].size = sizeof(omp_lock_target_t);
250        vars[0].count = 1;
251        vars[0].ptr = lock;
252
253        OFFLOAD_OFFLOAD(ofld, "omp_init_lock_target",
254                        0, 1, vars, NULL, 0, 0, 0);
255    }
256}
257
258void omp_destroy_lock_target(
259    TARGET_TYPE target_type,
260    int target_number,
261    omp_lock_target_t *lock
262)
263{
264    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
265                                          __func__, 0);
266    if (ofld != 0) {
267        VarDesc vars[1] = {0};
268
269        vars[0].type.src = c_data;
270        vars[0].type.dst = c_data;
271        vars[0].direction.bits = c_parameter_in;
272        vars[0].size = sizeof(omp_lock_target_t);
273        vars[0].count = 1;
274        vars[0].ptr = lock;
275
276        OFFLOAD_OFFLOAD(ofld, "omp_destroy_lock_target",
277                        0, 1, vars, NULL, 0, 0, 0);
278    }
279}
280
281void omp_set_lock_target(
282    TARGET_TYPE target_type,
283    int target_number,
284    omp_lock_target_t *lock
285)
286{
287    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
288                                          __func__, 0);
289    if (ofld != 0) {
290        VarDesc vars[1] = {0};
291
292        vars[0].type.src = c_data;
293        vars[0].type.dst = c_data;
294        vars[0].direction.bits = c_parameter_inout;
295        vars[0].size = sizeof(omp_lock_target_t);
296        vars[0].count = 1;
297        vars[0].ptr = lock;
298
299        OFFLOAD_OFFLOAD(ofld, "omp_set_lock_target",
300                        0, 1, vars, NULL, 0, 0, 0);
301    }
302}
303
304void omp_unset_lock_target(
305    TARGET_TYPE target_type,
306    int target_number,
307    omp_lock_target_t *lock
308)
309{
310    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
311                                          __func__, 0);
312    if (ofld != 0) {
313        VarDesc vars[1] = {0};
314
315        vars[0].type.src = c_data;
316        vars[0].type.dst = c_data;
317        vars[0].direction.bits = c_parameter_inout;
318        vars[0].size = sizeof(omp_lock_target_t);
319        vars[0].count = 1;
320        vars[0].ptr = lock;
321
322        OFFLOAD_OFFLOAD(ofld, "omp_unset_lock_target",
323                        0, 1, vars, NULL, 0, 0, 0);
324    }
325}
326
327int omp_test_lock_target(
328    TARGET_TYPE target_type,
329    int target_number,
330    omp_lock_target_t *lock
331)
332{
333    int result = 0;
334
335    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
336                                          __func__, 0);
337    if (ofld != 0) {
338        VarDesc vars[2] = {0};
339
340        vars[0].type.src = c_data;
341        vars[0].type.dst = c_data;
342        vars[0].direction.bits = c_parameter_inout;
343        vars[0].size = sizeof(omp_lock_target_t);
344        vars[0].count = 1;
345        vars[0].ptr = lock;
346
347        vars[1].type.src = c_data;
348        vars[1].type.dst = c_data;
349        vars[1].direction.bits = c_parameter_out;
350        vars[1].size = sizeof(int);
351        vars[1].count = 1;
352        vars[1].ptr = &result;
353
354        OFFLOAD_OFFLOAD(ofld, "omp_test_lock_target",
355                        0, 2, vars, NULL, 0, 0, 0);
356    }
357    return result;
358}
359
360// nested lock API functions
361
362void omp_init_nest_lock_target(
363    TARGET_TYPE target_type,
364    int target_number,
365    omp_nest_lock_target_t *lock
366)
367{
368    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
369                                          __func__, 0);
370    if (ofld != 0) {
371        VarDesc vars[1] = {0};
372
373        vars[0].type.src = c_data;
374        vars[0].type.dst = c_data;
375        vars[0].direction.bits = c_parameter_out;
376        vars[0].size = sizeof(omp_nest_lock_target_t);
377        vars[0].count = 1;
378        vars[0].ptr = lock;
379
380        OFFLOAD_OFFLOAD(ofld, "omp_init_nest_lock_target",
381                        0, 1, vars, NULL, 0, 0, 0);
382    }
383}
384
385void omp_destroy_nest_lock_target(
386    TARGET_TYPE target_type,
387    int target_number,
388    omp_nest_lock_target_t *lock
389)
390{
391    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
392                                          __func__, 0);
393    if (ofld != 0) {
394        VarDesc vars[1] = {0};
395
396        vars[0].type.src = c_data;
397        vars[0].type.dst = c_data;
398        vars[0].direction.bits = c_parameter_in;
399        vars[0].size = sizeof(omp_nest_lock_target_t);
400        vars[0].count = 1;
401        vars[0].ptr = lock;
402
403        OFFLOAD_OFFLOAD(ofld, "omp_destroy_nest_lock_target",
404                        0, 1, vars, NULL, 0, 0, 0);
405    }
406}
407
408void omp_set_nest_lock_target(
409    TARGET_TYPE target_type,
410    int target_number,
411    omp_nest_lock_target_t *lock
412)
413{
414    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
415                                          __func__, 0);
416    if (ofld != 0) {
417        VarDesc vars[1] = {0};
418
419        vars[0].type.src = c_data;
420        vars[0].type.dst = c_data;
421        vars[0].direction.bits = c_parameter_inout;
422        vars[0].size = sizeof(omp_nest_lock_target_t);
423        vars[0].count = 1;
424        vars[0].ptr = lock;
425
426        OFFLOAD_OFFLOAD(ofld, "omp_set_nest_lock_target",
427                        0, 1, vars, NULL, 0, 0, 0);
428    }
429}
430
431void omp_unset_nest_lock_target(
432    TARGET_TYPE target_type,
433    int target_number,
434    omp_nest_lock_target_t *lock
435)
436{
437    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
438                                          __func__, 0);
439    if (ofld != 0) {
440        VarDesc vars[1] = {0};
441
442        vars[0].type.src = c_data;
443        vars[0].type.dst = c_data;
444        vars[0].direction.bits = c_parameter_inout;
445        vars[0].size = sizeof(omp_nest_lock_target_t);
446        vars[0].count = 1;
447        vars[0].ptr = lock;
448
449        OFFLOAD_OFFLOAD(ofld, "omp_unset_nest_lock_target",
450                        0, 1, vars, NULL, 0, 0, 0);
451    }
452}
453
454int omp_test_nest_lock_target(
455    TARGET_TYPE target_type,
456    int target_number,
457    omp_nest_lock_target_t *lock
458)
459{
460    int result = 0;
461
462    OFFLOAD ofld = OFFLOAD_TARGET_ACQUIRE(target_type, target_number, 0, NULL,
463                                          __func__, 0);
464    if (ofld != 0) {
465        VarDesc vars[2] = {0};
466
467        vars[0].type.src = c_data;
468        vars[0].type.dst = c_data;
469        vars[0].direction.bits = c_parameter_inout;
470        vars[0].size = sizeof(omp_nest_lock_target_t);
471        vars[0].count = 1;
472        vars[0].ptr = lock;
473
474        vars[1].type.src = c_data;
475        vars[1].type.dst = c_data;
476        vars[1].direction.bits = c_parameter_out;
477        vars[1].size = sizeof(int);
478        vars[1].count = 1;
479        vars[1].ptr = &result;
480
481        OFFLOAD_OFFLOAD(ofld, "omp_test_nest_lock_target",
482                        0, 2, vars, NULL, 0, 0, 0);
483    }
484    return result;
485}
486