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_target.h"
34
35// OpenMP API
36
37void omp_set_default_device(int num) __GOMP_NOTHROW
38{
39}
40
41int omp_get_default_device(void) __GOMP_NOTHROW
42{
43    return mic_index;
44}
45
46int omp_get_num_devices() __GOMP_NOTHROW
47{
48    return mic_engines_total;
49}
50
51// OpenMP API wrappers
52
53static void omp_send_int_to_host(
54    void *ofld_,
55    int setting
56)
57{
58    OFFLOAD ofld = (OFFLOAD) ofld_;
59    VarDesc vars[1] = {0};
60
61    vars[0].type.src = c_data;
62    vars[0].type.dst = c_data;
63    vars[0].direction.bits = c_parameter_out;
64    vars[0].ptr = &setting;
65
66    OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
67    OFFLOAD_TARGET_LEAVE(ofld);
68}
69
70static int omp_get_int_from_host(
71    void *ofld_
72)
73{
74    OFFLOAD ofld = (OFFLOAD) ofld_;
75    VarDesc vars[1] = {0};
76    int setting;
77
78    vars[0].type.src = c_data;
79    vars[0].type.dst = c_data;
80    vars[0].direction.bits = c_parameter_in;
81    vars[0].ptr = &setting;
82
83    OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
84    OFFLOAD_TARGET_LEAVE(ofld);
85
86    return setting;
87}
88
89void omp_set_num_threads_lrb(
90    void *ofld
91)
92{
93    int num_threads;
94
95    num_threads = omp_get_int_from_host(ofld);
96    omp_set_num_threads(num_threads);
97}
98
99void omp_get_max_threads_lrb(
100    void *ofld
101)
102{
103    int num_threads;
104
105    num_threads = omp_get_max_threads();
106    omp_send_int_to_host(ofld, num_threads);
107}
108
109void omp_get_num_procs_lrb(
110    void *ofld
111)
112{
113    int num_procs;
114
115    num_procs = omp_get_num_procs();
116    omp_send_int_to_host(ofld, num_procs);
117}
118
119void omp_set_dynamic_lrb(
120    void *ofld
121)
122{
123    int dynamic;
124
125    dynamic = omp_get_int_from_host(ofld);
126    omp_set_dynamic(dynamic);
127}
128
129void omp_get_dynamic_lrb(
130    void *ofld
131)
132{
133    int dynamic;
134
135    dynamic = omp_get_dynamic();
136    omp_send_int_to_host(ofld, dynamic);
137}
138
139void omp_set_nested_lrb(
140    void *ofld
141)
142{
143    int nested;
144
145    nested = omp_get_int_from_host(ofld);
146    omp_set_nested(nested);
147}
148
149void omp_get_nested_lrb(
150    void *ofld
151)
152{
153    int nested;
154
155    nested = omp_get_nested();
156    omp_send_int_to_host(ofld, nested);
157}
158
159void omp_set_schedule_lrb(
160    void *ofld_
161)
162{
163    OFFLOAD ofld = (OFFLOAD) ofld_;
164    VarDesc vars[2] = {0};
165    omp_sched_t kind;
166    int modifier;
167
168    vars[0].type.src = c_data;
169    vars[0].type.dst = c_data;
170    vars[0].direction.bits = c_parameter_in;
171    vars[0].ptr = &kind;
172
173    vars[1].type.src = c_data;
174    vars[1].type.dst = c_data;
175    vars[1].direction.bits = c_parameter_in;
176    vars[1].ptr = &modifier;
177
178    OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
179    omp_set_schedule(kind, modifier);
180    OFFLOAD_TARGET_LEAVE(ofld);
181}
182
183void omp_get_schedule_lrb(
184    void *ofld_
185)
186{
187    OFFLOAD ofld = (OFFLOAD) ofld_;
188    VarDesc vars[2] = {0};
189    omp_sched_t kind;
190    int modifier;
191
192    vars[0].type.src = c_data;
193    vars[0].type.dst = c_data;
194    vars[0].direction.bits = c_parameter_out;
195    vars[0].ptr = &kind;
196
197    vars[1].type.src = c_data;
198    vars[1].type.dst = c_data;
199    vars[1].direction.bits = c_parameter_out;
200    vars[1].ptr = &modifier;
201
202    OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
203    omp_get_schedule(&kind, &modifier);
204    OFFLOAD_TARGET_LEAVE(ofld);
205}
206
207// lock API functions
208
209void omp_init_lock_lrb(
210    void *ofld_
211)
212{
213    OFFLOAD ofld = (OFFLOAD) ofld_;
214    VarDesc vars[1] = {0};
215    omp_lock_target_t lock;
216
217    vars[0].type.src = c_data;
218    vars[0].type.dst = c_data;
219    vars[0].direction.bits = c_parameter_out;
220    vars[0].ptr = &lock;
221
222    OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
223    omp_init_lock(&lock.lock);
224    OFFLOAD_TARGET_LEAVE(ofld);
225}
226
227void omp_destroy_lock_lrb(
228    void *ofld_
229)
230{
231    OFFLOAD ofld = (OFFLOAD) ofld_;
232    VarDesc vars[1] = {0};
233    omp_lock_target_t lock;
234
235    vars[0].type.src = c_data;
236    vars[0].type.dst = c_data;
237    vars[0].direction.bits = c_parameter_in;
238    vars[0].ptr = &lock;
239
240    OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
241    omp_destroy_lock(&lock.lock);
242    OFFLOAD_TARGET_LEAVE(ofld);
243}
244
245void omp_set_lock_lrb(
246    void *ofld_
247)
248{
249    OFFLOAD ofld = (OFFLOAD) ofld_;
250    VarDesc vars[1] = {0};
251    omp_lock_target_t lock;
252
253    vars[0].type.src = c_data;
254    vars[0].type.dst = c_data;
255    vars[0].direction.bits = c_parameter_inout;
256    vars[0].ptr = &lock;
257
258    OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
259    omp_set_lock(&lock.lock);
260    OFFLOAD_TARGET_LEAVE(ofld);
261}
262
263void omp_unset_lock_lrb(
264    void *ofld_
265)
266{
267    OFFLOAD ofld = (OFFLOAD) ofld_;
268    VarDesc vars[1] = {0};
269    omp_lock_target_t lock;
270
271    vars[0].type.src = c_data;
272    vars[0].type.dst = c_data;
273    vars[0].direction.bits = c_parameter_inout;
274    vars[0].ptr = &lock;
275
276    OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
277    omp_unset_lock(&lock.lock);
278    OFFLOAD_TARGET_LEAVE(ofld);
279}
280
281void omp_test_lock_lrb(
282    void *ofld_
283)
284{
285    OFFLOAD ofld = (OFFLOAD) ofld_;
286    VarDesc vars[2] = {0};
287    omp_lock_target_t lock;
288    int result;
289
290    vars[0].type.src = c_data;
291    vars[0].type.dst = c_data;
292    vars[0].direction.bits = c_parameter_inout;
293    vars[0].ptr = &lock;
294
295    vars[1].type.src = c_data;
296    vars[1].type.dst = c_data;
297    vars[1].direction.bits = c_parameter_out;
298    vars[1].ptr = &result;
299
300    OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
301    result = omp_test_lock(&lock.lock);
302    OFFLOAD_TARGET_LEAVE(ofld);
303}
304
305// nested lock API functions
306
307void omp_init_nest_lock_lrb(
308    void *ofld_
309)
310{
311    OFFLOAD ofld = (OFFLOAD) ofld_;
312    VarDesc vars[1] = {0};
313    omp_nest_lock_target_t lock;
314
315    vars[0].type.src = c_data;
316    vars[0].type.dst = c_data;
317    vars[0].direction.bits = c_parameter_out;
318    vars[0].ptr = &lock;
319
320    OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
321    omp_init_nest_lock(&lock.lock);
322    OFFLOAD_TARGET_LEAVE(ofld);
323}
324
325void omp_destroy_nest_lock_lrb(
326    void *ofld_
327)
328{
329    OFFLOAD ofld = (OFFLOAD) ofld_;
330    VarDesc vars[1] = {0};
331    omp_nest_lock_target_t lock;
332
333    vars[0].type.src = c_data;
334    vars[0].type.dst = c_data;
335    vars[0].direction.bits = c_parameter_in;
336    vars[0].ptr = &lock;
337
338    OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
339    omp_destroy_nest_lock(&lock.lock);
340    OFFLOAD_TARGET_LEAVE(ofld);
341}
342
343void omp_set_nest_lock_lrb(
344    void *ofld_
345)
346{
347    OFFLOAD ofld = (OFFLOAD) ofld_;
348    VarDesc vars[1] = {0};
349    omp_nest_lock_target_t lock;
350
351    vars[0].type.src = c_data;
352    vars[0].type.dst = c_data;
353    vars[0].direction.bits = c_parameter_inout;
354    vars[0].ptr = &lock;
355
356    OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
357    omp_set_nest_lock(&lock.lock);
358    OFFLOAD_TARGET_LEAVE(ofld);
359}
360
361void omp_unset_nest_lock_lrb(
362    void *ofld_
363)
364{
365    OFFLOAD ofld = (OFFLOAD) ofld_;
366    VarDesc vars[1] = {0};
367    omp_nest_lock_target_t lock;
368
369    vars[0].type.src = c_data;
370    vars[0].type.dst = c_data;
371    vars[0].direction.bits = c_parameter_inout;
372    vars[0].ptr = &lock;
373
374    OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
375    omp_unset_nest_lock(&lock.lock);
376    OFFLOAD_TARGET_LEAVE(ofld);
377}
378
379void omp_test_nest_lock_lrb(
380    void *ofld_
381)
382{
383    OFFLOAD ofld = (OFFLOAD) ofld_;
384    VarDesc vars[2] = {0};
385    omp_nest_lock_target_t lock;
386    int result;
387
388    vars[0].type.src = c_data;
389    vars[0].type.dst = c_data;
390    vars[0].direction.bits = c_parameter_inout;
391    vars[0].ptr = &lock;
392
393    vars[1].type.src = c_data;
394    vars[1].type.dst = c_data;
395    vars[1].direction.bits = c_parameter_out;
396    vars[1].ptr = &result;
397
398    OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
399    result = omp_test_nest_lock(&lock.lock);
400    OFFLOAD_TARGET_LEAVE(ofld);
401}
402
403// Target-side stubs for the host functions (to avoid unresolveds)
404// These are needed for the offloadm table
405
406void omp_set_num_threads_target(
407    TARGET_TYPE target_type,
408    int target_number,
409    int num_threads
410)
411{
412}
413
414int omp_get_max_threads_target(
415    TARGET_TYPE target_type,
416    int target_number
417)
418{
419    return 0;
420}
421
422int omp_get_num_procs_target(
423    TARGET_TYPE target_type,
424    int target_number
425)
426{
427    return 0;
428}
429
430void omp_set_dynamic_target(
431    TARGET_TYPE target_type,
432    int target_number,
433    int num_threads
434)
435{
436}
437
438int omp_get_dynamic_target(
439    TARGET_TYPE target_type,
440    int target_number
441)
442{
443    return 0;
444}
445
446void omp_set_nested_target(
447    TARGET_TYPE target_type,
448    int target_number,
449    int num_threads
450)
451{
452}
453
454int omp_get_nested_target(
455    TARGET_TYPE target_type,
456    int target_number
457)
458{
459    return 0;
460}
461
462void omp_set_schedule_target(
463    TARGET_TYPE target_type,
464    int target_number,
465    omp_sched_t kind,
466    int modifier
467)
468{
469}
470
471void omp_get_schedule_target(
472    TARGET_TYPE target_type,
473    int target_number,
474    omp_sched_t *kind,
475    int *modifier
476)
477{
478}
479
480void omp_init_lock_target(
481    TARGET_TYPE target_type,
482    int target_number,
483    omp_lock_target_t *lock
484)
485{
486}
487
488void omp_destroy_lock_target(
489    TARGET_TYPE target_type,
490    int target_number,
491    omp_lock_target_t *lock
492)
493{
494}
495
496void omp_set_lock_target(
497    TARGET_TYPE target_type,
498    int target_number,
499    omp_lock_target_t *lock
500)
501{
502}
503
504void omp_unset_lock_target(
505    TARGET_TYPE target_type,
506    int target_number,
507    omp_lock_target_t *lock
508)
509{
510}
511
512int omp_test_lock_target(
513    TARGET_TYPE target_type,
514    int target_number,
515    omp_lock_target_t *lock
516)
517{
518    return 0;
519}
520
521void omp_init_nest_lock_target(
522    TARGET_TYPE target_type,
523    int target_number,
524    omp_nest_lock_target_t *lock
525)
526{
527}
528
529void omp_destroy_nest_lock_target(
530    TARGET_TYPE target_type,
531    int target_number,
532    omp_nest_lock_target_t *lock
533)
534{
535}
536
537void omp_set_nest_lock_target(
538    TARGET_TYPE target_type,
539    int target_number,
540    omp_nest_lock_target_t *lock
541)
542{
543}
544
545void omp_unset_nest_lock_target(
546    TARGET_TYPE target_type,
547    int target_number,
548    omp_nest_lock_target_t *lock
549)
550{
551}
552
553int omp_test_nest_lock_target(
554    TARGET_TYPE target_type,
555    int target_number,
556    omp_nest_lock_target_t *lock
557)
558{
559    return 0;
560}
561