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