1 /* 2 Copyright (c) 2014-2015 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 /*! \file 32 \brief The parts of the runtime library common to host and target 33 */ 34 35 #ifndef OFFLOAD_COMMON_H_INCLUDED 36 #define OFFLOAD_COMMON_H_INCLUDED 37 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <memory.h> 42 43 #include "offload.h" 44 #include "offload_table.h" 45 #include "offload_trace.h" 46 #include "offload_timer.h" 47 #include "offload_util.h" 48 #include "cean_util.h" 49 #include "dv_util.h" 50 #include "liboffload_error_codes.h" 51 52 #include <stdarg.h> 53 54 // Use secure getenv if it's supported 55 #ifdef HAVE_SECURE_GETENV 56 #define getenv(x) secure_getenv(x) 57 #elif HAVE___SECURE_GETENV 58 #define getenv(x) __secure_getenv(x) 59 #endif 60 61 // The debug routines 62 63 // Host console and file logging 64 DLL_LOCAL extern int console_enabled; 65 DLL_LOCAL extern int offload_report_level; 66 67 68 DLL_LOCAL extern const char *prefix; 69 DLL_LOCAL extern int offload_number; 70 #if !HOST_LIBRARY 71 DLL_LOCAL extern int mic_index; 72 #define OFFLOAD_DO_TRACE (offload_report_level == 3) 73 #else 74 #define OFFLOAD_DO_TRACE (offload_report_enabled && (offload_report_level == 3)) 75 #endif 76 77 #if HOST_LIBRARY 78 DLL_LOCAL void Offload_Report_Prolog(OffloadHostTimerData* timer_data); 79 DLL_LOCAL void Offload_Report_Epilog(OffloadHostTimerData* timer_data); 80 DLL_LOCAL void offload_report_free_data(OffloadHostTimerData * timer_data); 81 DLL_LOCAL void Offload_Timer_Print(void); 82 83 #ifndef TARGET_WINNT 84 #define OFFLOAD_DEBUG_INCR_OFLD_NUM() \ 85 __sync_add_and_fetch(&offload_number, 1) 86 #else 87 #define OFFLOAD_DEBUG_INCR_OFLD_NUM() \ 88 _InterlockedIncrement(reinterpret_cast<long*>(&offload_number)) 89 #endif 90 91 #define OFFLOAD_DEBUG_PRINT_TAG_PREFIX() \ 92 printf("%s: ", prefix); 93 94 #define OFFLOAD_DEBUG_PRINT_PREFIX() \ 95 printf("%s: ", prefix); 96 #else 97 #define OFFLOAD_DEBUG_PRINT_PREFIX() \ 98 printf("%s%d: ", prefix, mic_index); 99 #endif // HOST_LIBRARY 100 101 #define OFFLOAD_TRACE(trace_level, ...) \ 102 if (console_enabled >= trace_level) { \ 103 OFFLOAD_DEBUG_PRINT_PREFIX(); \ 104 printf(__VA_ARGS__); \ 105 fflush(NULL); \ 106 } 107 108 #if OFFLOAD_DEBUG > 0 109 110 #define OFFLOAD_DEBUG_TRACE(level, ...) \ 111 OFFLOAD_TRACE(level, __VA_ARGS__) 112 113 #define OFFLOAD_REPORT(level, offload_number, stage, ...) \ 114 if (OFFLOAD_DO_TRACE) { \ 115 offload_stage_print(stage, offload_number, __VA_ARGS__); \ 116 fflush(NULL); \ 117 } 118 119 #define OFFLOAD_DEBUG_TRACE_1(level, offload_number, stage, ...) \ 120 if (OFFLOAD_DO_TRACE) { \ 121 offload_stage_print(stage, offload_number, __VA_ARGS__); \ 122 fflush(NULL); \ 123 } \ 124 if (!OFFLOAD_DO_TRACE) { \ 125 OFFLOAD_TRACE(level, __VA_ARGS__) \ 126 } 127 128 #define OFFLOAD_DEBUG_DUMP_BYTES(level, a, b) \ 129 __dump_bytes(level, a, b) 130 131 DLL_LOCAL extern void __dump_bytes( 132 int level, 133 const void *data, 134 int len 135 ); 136 137 #else 138 139 #define OFFLOAD_DEBUG_LOG(level, ...) 140 #define OFFLOAD_DEBUG_DUMP_BYTES(level, a, b) 141 142 #endif 143 144 // Runtime interface 145 146 #define OFFLOAD_PREFIX(a) __offload_##a 147 148 #define OFFLOAD_MALLOC OFFLOAD_PREFIX(malloc) 149 #define OFFLOAD_FREE(a) _mm_free(a) 150 151 // Forward functions 152 153 extern void *OFFLOAD_MALLOC(size_t size, size_t align); 154 155 // The Marshaller 156 157 // Flags describing an offload 158 159 //! Flags describing an offload 160 union OffloadFlags{ 161 uint32_t flags; 162 struct { 163 uint32_t fortran_traceback : 1; //!< Fortran traceback requested 164 uint32_t omp_async : 1; //!< OpenMP asynchronous offload 165 } bits; 166 }; 167 168 //! \enum Indicator for the type of entry on an offload item list. 169 enum OffloadItemType { 170 c_data = 1, //!< Plain data 171 c_data_ptr, //!< Pointer data 172 c_func_ptr, //!< Function pointer 173 c_void_ptr, //!< void* 174 c_string_ptr, //!< C string 175 c_dv, //!< Dope vector variable 176 c_dv_data, //!< Dope-vector data 177 c_dv_data_slice, //!< Dope-vector data's slice 178 c_dv_ptr, //!< Dope-vector variable pointer 179 c_dv_ptr_data, //!< Dope-vector pointer data 180 c_dv_ptr_data_slice,//!< Dope-vector pointer data's slice 181 c_cean_var, //!< CEAN variable 182 c_cean_var_ptr, //!< Pointer to CEAN variable 183 c_data_ptr_array, //!< Pointer to data pointer array 184 c_func_ptr_array, //!< Pointer to function pointer array 185 c_void_ptr_array, //!< Pointer to void* pointer array 186 c_string_ptr_array //!< Pointer to char* pointer array 187 }; 188 189 #define VAR_TYPE_IS_PTR(t) ((t) == c_string_ptr || \ 190 (t) == c_data_ptr || \ 191 (t) == c_cean_var_ptr || \ 192 (t) == c_dv_ptr) 193 194 #define VAR_TYPE_IS_SCALAR(t) ((t) == c_data || \ 195 (t) == c_void_ptr || \ 196 (t) == c_cean_var || \ 197 (t) == c_dv) 198 199 #define VAR_TYPE_IS_DV_DATA(t) ((t) == c_dv_data || \ 200 (t) == c_dv_ptr_data) 201 202 #define VAR_TYPE_IS_DV_DATA_SLICE(t) ((t) == c_dv_data_slice || \ 203 (t) == c_dv_ptr_data_slice) 204 205 206 //! \enum Specify direction to copy offloaded variable. 207 enum OffloadParameterType { 208 c_parameter_unknown = -1, //!< Unknown clause 209 c_parameter_nocopy, //!< Variable listed in "nocopy" clause 210 c_parameter_in, //!< Variable listed in "in" clause 211 c_parameter_out, //!< Variable listed in "out" clause 212 c_parameter_inout //!< Variable listed in "inout" clause 213 }; 214 215 216 //! Flags describing an offloaded variable 217 union varDescFlags { 218 struct { 219 //! source variable has persistent storage 220 uint32_t is_static : 1; 221 //! destination variable has persistent storage 222 uint32_t is_static_dstn : 1; 223 //! has length for c_dv && c_dv_ptr 224 uint32_t has_length : 1; 225 //! persisted local scalar is in stack buffer 226 uint32_t is_stack_buf : 1; 227 //! "targetptr" modifier used 228 uint32_t targetptr : 1; 229 //! "preallocated" modifier used 230 uint32_t preallocated : 1; 231 //! Needs documentation 232 uint32_t is_pointer : 1; 233 234 //! buffer address is sent in data 235 uint32_t sink_addr : 1; 236 //! alloc displacement is sent in data 237 uint32_t alloc_disp : 1; 238 //! source data is noncontiguous 239 uint32_t is_noncont_src : 1; 240 //! destination data is noncontiguous 241 uint32_t is_noncont_dst : 1; 242 243 //! "OpenMP always" modifier used 244 uint32_t always_copy : 1; 245 //! "OpenMP delete" modifier used 246 uint32_t always_delete : 1; 247 //! CPU memory pinning/unpinning operation 248 uint32_t pin : 1; 249 }; 250 uint32_t bits; 251 }; 252 253 //! An Offload Variable descriptor 254 struct VarDesc { 255 //! OffloadItemTypes of source and destination 256 union { 257 struct { 258 uint8_t dst : 4; //!< OffloadItemType of destination 259 uint8_t src : 4; //!< OffloadItemType of source 260 }; 261 uint8_t bits; 262 } type; 263 264 //! OffloadParameterType that describes direction of data transfer 265 union { 266 struct { 267 uint8_t in : 1; //!< Set if IN or INOUT 268 uint8_t out : 1; //!< Set if OUT or INOUT 269 }; 270 uint8_t bits; 271 } direction; 272 273 uint8_t alloc_if; //!< alloc_if modifier value 274 uint8_t free_if; //!< free_if modifier value 275 uint32_t align; //!< MIC alignment requested for pointer data 276 //! Not used by compiler; set to 0 277 /*! Used by runtime as offset to data from start of MIC buffer */ 278 uint32_t mic_offset; 279 //! Flags describing this variable 280 varDescFlags flags; 281 //! Not used by compiler; set to 0 282 /*! Used by runtime as offset to base from data stored in a buffer */ 283 int64_t offset; 284 //! Element byte-size of data to be transferred 285 /*! For dope-vector, the size of the dope-vector */ 286 int64_t size; 287 union { 288 //! Set to 0 for array expressions and dope-vectors 289 /*! Set to 1 for scalars */ 290 /*! Set to value of length modifier for pointers */ 291 int64_t count; 292 //! Displacement not used by compiler 293 int64_t disp; 294 }; 295 296 //! This field not used by OpenMP 4.0 297 /*! The alloc section expression in #pragma offload */ 298 union { 299 void *alloc; 300 int64_t ptr_arr_offset; 301 }; 302 303 //! This field not used by OpenMP 4.0 304 /*! The into section expression in #pragma offload */ 305 /*! For c_data_ptr_array this is the into ptr array */ 306 void *into; 307 308 //! For an ordinary variable, address of the variable 309 /*! For c_cean_var (C/C++ array expression), 310 pointer to arr_desc, which is an array descriptor. */ 311 /*! For c_data_ptr_array (array of data pointers), 312 pointer to ptr_array_descriptor, 313 which is a descriptor for pointer array transfers. */ 314 void *ptr; 315 }; 316 317 //! Auxiliary struct used when -g is enabled that holds variable names 318 struct VarDesc2 { 319 const char *sname; //!< Source name 320 const char *dname; //!< Destination name (when "into" is used) 321 }; 322 323 /*! When the OffloadItemType is c_data_ptr_array 324 the ptr field of the main descriptor points to this struct. */ 325 /*! The type in VarDesc1 merely says c_cean_data_ptr, but the pointer 326 type can be c_data_ptr, c_func_ptr, c_void_ptr, or c_string_ptr. 327 Therefore the actual pointer type is in the flags field of VarDesc3. */ 328 /*! If flag_align_is_array/flag_alloc_if_is_array/flag_free_if_is_array 329 is 0 then alignment/alloc_if/free_if are specified in VarDesc1. */ 330 /*! If flag_align_is_array/flag_alloc_if_is_array/flag_free_if_is_array 331 is 1 then align_array/alloc_if_array/free_if_array specify 332 the set of alignment/alloc_if/free_if values. */ 333 /*! For the other fields, if neither the scalar nor the array flag 334 is set, then that modifier was not specified. If the bits are set 335 they specify which modifier was set and whether it was a 336 scalar or an array expression. */ 337 struct VarDesc3 338 { 339 void *ptr_array; //!< Pointer to arr_desc of array of pointers 340 void *align_array; //!< Scalar value or pointer to arr_desc 341 void *alloc_if_array; //!< Scalar value or pointer to arr_desc 342 void *free_if_array; //!< Scalar value or pointer to arr_desc 343 void *extent_start; //!< Scalar value or pointer to arr_desc 344 void *extent_elements; //!< Scalar value or pointer to arr_desc 345 void *into_start; //!< Scalar value or pointer to arr_desc 346 void *into_elements; //!< Scalar value or pointer to arr_desc 347 void *alloc_start; //!< Scalar value or pointer to arr_desc 348 void *alloc_elements; //!< Scalar value or pointer to arr_desc 349 /*! Flags that describe the pointer type and whether each field 350 is a scalar value or an array expression. */ 351 /*! First 6 bits are pointer array element type: 352 c_data_ptr, c_func_ptr, c_void_ptr, c_string_ptr */ 353 /*! Then single bits specify: */ 354 /*! align_array is an array */ 355 /*! alloc_if_array is an array */ 356 /*! free_if_array is an array */ 357 /*! extent_start is a scalar expression */ 358 /*! extent_start is an array expression */ 359 /*! extent_elements is a scalar expression */ 360 /*! extent_elements is an array expression */ 361 /*! into_start is a scalar expression */ 362 /*! into_start is an array expression */ 363 /*! into_elements is a scalar expression */ 364 /*! into_elements is an array expression */ 365 /*! alloc_start is a scalar expression */ 366 /*! alloc_start is an array expression */ 367 /*! alloc_elements is a scalar expression */ 368 /*! alloc_elements is an array expression */ 369 uint32_t array_fields; 370 }; 371 const int flag_align_is_array = 6; 372 const int flag_alloc_if_is_array = 7; 373 const int flag_free_if_is_array = 8; 374 const int flag_extent_start_is_scalar = 9; 375 const int flag_extent_start_is_array = 10; 376 const int flag_extent_elements_is_scalar = 11; 377 const int flag_extent_elements_is_array = 12; 378 const int flag_into_start_is_scalar = 13; 379 const int flag_into_start_is_array = 14; 380 const int flag_into_elements_is_scalar = 15; 381 const int flag_into_elements_is_array = 16; 382 const int flag_alloc_start_is_scalar = 17; 383 const int flag_alloc_start_is_array = 18; 384 const int flag_alloc_elements_is_scalar = 19; 385 const int flag_alloc_elements_is_array = 20; 386 387 // The Marshaller 388 class Marshaller 389 { 390 private: 391 // Start address of buffer 392 char *buffer_start; 393 394 // Current pointer within buffer 395 char *buffer_ptr; 396 397 // Physical size of data sent (including flags) 398 long long buffer_size; 399 400 // User data sent/received 401 long long tfr_size; 402 403 public: 404 // Constructor Marshaller()405 Marshaller() : 406 buffer_start(0), buffer_ptr(0), 407 buffer_size(0), tfr_size(0) 408 { 409 } 410 411 // Return count of user data sent/received get_tfr_size()412 long long get_tfr_size() const 413 { 414 return tfr_size; 415 } 416 417 // Return pointer to buffer get_buffer_start()418 char *get_buffer_start() const 419 { 420 return buffer_start; 421 } 422 423 // Return current size of data in buffer get_buffer_size()424 long long get_buffer_size() const 425 { 426 return buffer_size; 427 } 428 429 // Set buffer pointer init_buffer(char * d,long long s)430 void init_buffer( 431 char *d, 432 long long s 433 ) 434 { 435 buffer_start = buffer_ptr = d; 436 buffer_size = s; 437 } 438 439 // Send data 440 void send_data( 441 const void *data, 442 int64_t length 443 ); 444 445 // Receive data 446 void receive_data( 447 void *data, 448 int64_t length 449 ); 450 451 // Send function pointer 452 void send_func_ptr( 453 const void* data 454 ); 455 456 // Receive function pointer 457 void receive_func_ptr( 458 const void** data 459 ); 460 }; 461 462 // End of the Marshaller 463 464 // The offloaded function descriptor. 465 // Sent from host to target to specify which function to run. 466 // Also, sets console and file tracing levels. 467 struct FunctionDescriptor 468 { 469 // Input data size. 470 long long in_datalen; 471 472 // Output data size. 473 long long out_datalen; 474 475 // Whether trace is requested on console. 476 // A value of 1 produces only function name and data sent/received. 477 // Values > 1 produce copious trace information. 478 uint8_t console_enabled; 479 480 // Flag controlling timing on the target side. 481 // Values > 0 enable timing on sink. 482 uint8_t timer_enabled; 483 484 int offload_report_level; 485 int offload_number; 486 487 // number of variable descriptors 488 int vars_num; 489 490 // inout data offset if data is passed as misc/return data 491 // otherwise it should be zero. 492 int data_offset; 493 494 // The name of the offloaded function 495 char data[]; 496 }; 497 498 // typedef OFFLOAD. 499 // Pointer to OffloadDescriptor. 500 typedef struct OffloadDescriptor *OFFLOAD; 501 502 // Use for setting affinity of a stream 503 enum affinity_type { 504 affinity_compact, 505 affinity_scatter 506 }; 507 struct affinity_spec { 508 uint64_t sink_mask[16]; 509 int affinity_type; 510 int num_cores; 511 int num_threads; 512 }; 513 514 #endif // OFFLOAD_COMMON_H_INCLUDED 515