1 /* Plugin for offload execution on Intel MIC devices.
3 Copyright (C) 2014-2016 Free Software Foundation, Inc.
5 Contributed by Ilya Verbin <ilya.verbin@intel.com>.
7 This file is part of the GNU Offloading and Multi Processing Library
10 Libgomp is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
15 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
20 Under Section 7 of GPL version 3, you are granted additional
21 permissions described in the GCC Runtime Library Exception, version
22 3.1, as published by the Free Software Foundation.
24 You should have received a copy of the GNU General Public License and
25 a copy of the GCC Runtime Library Exception along with this program;
26 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
27 <http://www.gnu.org/licenses/>. */
29 /* Target side part of a libgomp plugin. */
34 #include "compiler_if_target.h"
40 fprintf (stderr, "TARGET:\t%s:%s ", __FILE__, __FUNCTION__); \
41 fprintf (stderr, __VA_ARGS__); \
42 fprintf (stderr, "\n"); \
49 static VarDesc vd_host2tgt
= {
50 { 1, 1 }, /* dst, src */
51 { 1, 0 }, /* in, out */
56 { 0, 0, 0, 0, 0, 0, 0, 0 }, /* is_static, is_static_dstn, has_length,
57 is_stack_buf, sink_addr, alloc_disp,
58 is_noncont_src, is_noncont_dst */
67 static VarDesc vd_tgt2host
= {
68 { 1, 1 }, /* dst, src */
69 { 0, 1 }, /* in, out */
74 { 0, 0, 0, 0, 0, 0, 0, 0 }, /* is_static, is_static_dstn, has_length,
75 is_stack_buf, sink_addr, alloc_disp,
76 is_noncont_src, is_noncont_dst */
85 /* Pointer to the descriptor of the last loaded shared library. */
86 static void *last_loaded_library
= NULL
;
88 /* Pointer and size of the variable, used in __offload_target_host2tgt_p[12]
89 and __offload_target_tgt2host_p[12]. */
90 static void *last_var_ptr
= NULL
;
91 static int last_var_size
= 0;
94 /* Override the corresponding functions from libgomp. */
96 omp_is_initial_device (void) __GOMP_NOTHROW
102 omp_is_initial_device_ (void)
104 return omp_is_initial_device ();
108 /* Dummy function needed for the initialization of target process during the
109 first call to __offload_offload1. */
111 __offload_target_init_proc (OFFLOAD ofldt
)
116 /* Collect addresses of the offload functions and of the global variables from
117 the library descriptor and send them to host.
118 Part 1: Send num_funcs and num_vars to host. */
120 __offload_target_table_p1 (OFFLOAD ofldt
)
122 void ***lib_descr
= (void ***) last_loaded_library
;
124 if (lib_descr
== NULL
)
127 fprintf (stderr
, "Error! No shared libraries loaded on target.\n");
131 void **func_table_begin
= lib_descr
[0];
132 void **func_table_end
= lib_descr
[1];
133 void **var_table_begin
= lib_descr
[2];
134 void **var_table_end
= lib_descr
[3];
136 /* The func table contains only addresses, the var table contains addresses
137 and corresponding sizes. */
138 int num_funcs
= func_table_end
- func_table_begin
;
139 int num_vars
= (var_table_end
- var_table_begin
) / 2;
140 TRACE ("(num_funcs = %d, num_vars = %d)", num_funcs
, num_vars
);
142 VarDesc vd
[2] = { vd_tgt2host
, vd_tgt2host
};
143 vd
[0].ptr
= &num_funcs
;
144 vd
[0].size
= sizeof (num_funcs
);
145 vd
[1].ptr
= &num_vars
;
146 vd
[1].size
= sizeof (num_vars
);
148 __offload_target_enter (ofldt
, 2, vd
, NULL
);
149 __offload_target_leave (ofldt
);
152 /* Part 2: Send the table with addresses to host. */
154 __offload_target_table_p2 (OFFLOAD ofldt
)
156 void ***lib_descr
= (void ***) last_loaded_library
;
157 void **func_table_begin
= lib_descr
[0];
158 void **func_table_end
= lib_descr
[1];
159 void **var_table_begin
= lib_descr
[2];
160 void **var_table_end
= lib_descr
[3];
162 int num_funcs
= func_table_end
- func_table_begin
;
163 int num_vars
= (var_table_end
- var_table_begin
) / 2;
164 int table_size
= (num_funcs
+ 2 * num_vars
) * sizeof (void *);
165 void **table
= (void **) malloc (table_size
);
166 TRACE ("(table_size = %d)", table_size
);
168 VarDesc vd
= vd_tgt2host
;
170 vd
.size
= table_size
;
172 __offload_target_enter (ofldt
, 1, &vd
, NULL
);
176 for (p
= func_table_begin
; p
< func_table_end
; p
++, i
++)
179 for (p
= var_table_begin
; p
< var_table_end
; p
++, i
++)
182 __offload_target_leave (ofldt
);
186 /* Allocate size bytes and send a pointer to the allocated memory to host. */
188 __offload_target_alloc (OFFLOAD ofldt
)
193 VarDesc vd
[2] = { vd_host2tgt
, vd_tgt2host
};
195 vd
[0].size
= sizeof (size
);
197 vd
[1].size
= sizeof (void *);
199 __offload_target_enter (ofldt
, 2, vd
, NULL
);
201 TRACE ("(size = %d): ptr = %p", size
, ptr
);
202 __offload_target_leave (ofldt
);
205 /* Free the memory space pointed to by ptr. */
207 __offload_target_free (OFFLOAD ofldt
)
211 VarDesc vd
= vd_host2tgt
;
213 vd
.size
= sizeof (void *);
215 __offload_target_enter (ofldt
, 1, &vd
, NULL
);
216 TRACE ("(ptr = %p)", ptr
);
218 __offload_target_leave (ofldt
);
221 /* Receive var_size bytes from host and store to var_ptr.
222 Part 1: Receive var_ptr and var_size from host. */
224 __offload_target_host2tgt_p1 (OFFLOAD ofldt
)
226 void *var_ptr
= NULL
;
229 VarDesc vd
[2] = { vd_host2tgt
, vd_host2tgt
};
230 vd
[0].ptr
= &var_ptr
;
231 vd
[0].size
= sizeof (void *);
232 vd
[1].ptr
= &var_size
;
233 vd
[1].size
= sizeof (var_size
);
235 __offload_target_enter (ofldt
, 2, vd
, NULL
);
236 TRACE ("(var_ptr = %p, var_size = %d)", var_ptr
, var_size
);
237 last_var_ptr
= var_ptr
;
238 last_var_size
= var_size
;
239 __offload_target_leave (ofldt
);
242 /* Part 2: Receive the data from host. */
244 __offload_target_host2tgt_p2 (OFFLOAD ofldt
)
246 TRACE ("(last_var_ptr = %p, last_var_size = %d)",
247 last_var_ptr
, last_var_size
);
249 VarDesc vd
= vd_host2tgt
;
250 vd
.ptr
= last_var_ptr
;
251 vd
.size
= last_var_size
;
253 __offload_target_enter (ofldt
, 1, &vd
, NULL
);
254 __offload_target_leave (ofldt
);
257 /* Send var_size bytes from var_ptr to host.
258 Part 1: Receive var_ptr and var_size from host. */
260 __offload_target_tgt2host_p1 (OFFLOAD ofldt
)
262 void *var_ptr
= NULL
;
265 VarDesc vd
[2] = { vd_host2tgt
, vd_host2tgt
};
266 vd
[0].ptr
= &var_ptr
;
267 vd
[0].size
= sizeof (void *);
268 vd
[1].ptr
= &var_size
;
269 vd
[1].size
= sizeof (var_size
);
271 __offload_target_enter (ofldt
, 2, vd
, NULL
);
272 TRACE ("(var_ptr = %p, var_size = %d)", var_ptr
, var_size
);
273 last_var_ptr
= var_ptr
;
274 last_var_size
= var_size
;
275 __offload_target_leave (ofldt
);
278 /* Part 2: Send the data to host. */
280 __offload_target_tgt2host_p2 (OFFLOAD ofldt
)
282 TRACE ("(last_var_ptr = %p, last_var_size = %d)",
283 last_var_ptr
, last_var_size
);
285 VarDesc vd
= vd_tgt2host
;
286 vd
.ptr
= last_var_ptr
;
287 vd
.size
= last_var_size
;
289 __offload_target_enter (ofldt
, 1, &vd
, NULL
);
290 __offload_target_leave (ofldt
);
293 /* Copy SIZE bytes from SRC_PTR to DST_PTR. */
295 __offload_target_tgt2tgt (OFFLOAD ofldt
)
297 void *src_ptr
= NULL
;
298 void *dst_ptr
= NULL
;
301 VarDesc vd
[3] = { vd_host2tgt
, vd_host2tgt
, vd_host2tgt
};
302 vd
[0].ptr
= &dst_ptr
;
303 vd
[0].size
= sizeof (void *);
304 vd
[1].ptr
= &src_ptr
;
305 vd
[1].size
= sizeof (void *);
307 vd
[2].size
= sizeof (size
);
309 __offload_target_enter (ofldt
, 3, vd
, NULL
);
310 TRACE ("(dst_ptr = %p, src_ptr = %p, size = %d)", dst_ptr
, src_ptr
, size
);
311 memcpy (dst_ptr
, src_ptr
, size
);
312 __offload_target_leave (ofldt
);
315 /* Call offload function by the address fn_ptr and pass vars_ptr to it. */
317 __offload_target_run (OFFLOAD ofldt
)
322 VarDesc vd
[2] = { vd_host2tgt
, vd_host2tgt
};
324 vd
[0].size
= sizeof (void *);
325 vd
[1].ptr
= &vars_ptr
;
326 vd
[1].size
= sizeof (void *);
328 __offload_target_enter (ofldt
, 2, vd
, NULL
);
329 TRACE ("(fn_ptr = %p, vars_ptr = %p)", fn_ptr
, vars_ptr
);
330 void (*fn
)(void *) = (void (*)(void *)) fn_ptr
;
332 __offload_target_leave (ofldt
);
336 /* This should be called from every library with offloading. */
338 target_register_lib (const void *target_table
)
340 TRACE ("(target_table = %p { %p, %p, %p, %p })", target_table
,
341 ((void **) target_table
)[0], ((void **) target_table
)[1],
342 ((void **) target_table
)[2], ((void **) target_table
)[3]);
344 last_loaded_library
= (void *) target_table
;
347 /* Use __offload_target_main from liboffload. */
349 main (int argc
, char **argv
)
351 __offload_target_main ();
356 /* Register offload_target_main's functions in the liboffload. */
363 #define REGISTER(f) \
364 extern "C" const Entry __offload_target_##f##_$entry \
365 __attribute__ ((section(".OffloadEntryTable."))) = { \
366 "__offload_target_"#f, \
367 (void *) __offload_target_##f \
369 REGISTER (init_proc
);
374 REGISTER (host2tgt_p1
);
375 REGISTER (host2tgt_p2
);
376 REGISTER (tgt2host_p1
);
377 REGISTER (tgt2host_p2
);