aboutsummaryrefslogtreecommitdiff
path: root/liboffloadmic/runtime/offload_host.h
blob: 2a43fd6a68a2eb9b0b219eaf4ed97118bf3d032d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
/*
    Copyright (c) 2014-2015 Intel Corporation.  All Rights Reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

      * Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
      * Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
      * Neither the name of Intel Corporation nor the names of its
        contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


/*! \file
    \brief The parts of the runtime library used only on the host
*/

#ifndef OFFLOAD_HOST_H_INCLUDED
#define OFFLOAD_HOST_H_INCLUDED

#ifndef TARGET_WINNT
#include <unistd.h>
#endif // TARGET_WINNT
#include "offload_common.h"
#include "offload_util.h"
#include "offload_engine.h"
#include "offload_env.h"
#include "offload_orsl.h"
#include "coi/coi_client.h"

// MIC engines.
DLL_LOCAL extern Engine*  mic_engines;
DLL_LOCAL extern uint32_t mic_engines_total;

// DMA channel count used by COI and set via
// OFFLOAD_DMA_CHANNEL_COUNT environment variable
DLL_LOCAL extern uint32_t mic_dma_channel_count;

//! The target image is packed as follows.
/*!      1. 8 bytes containing the size of the target binary          */
/*!      2. a null-terminated string which is the binary name         */
/*!      3. <size> number of bytes that are the contents of the image */
/*!      The address of symbol __offload_target_image
             is the address of this structure.                        */
struct Image {
     int64_t size; //!< Size in bytes of the target binary name and contents
     char data[];  //!< The name and contents of the target image
};

// The offload descriptor.
class OffloadDescriptor
{
public:
    enum  OmpAsyncLastEventType {
        c_last_not,     // not last event
        c_last_write,   // the last event that is write
        c_last_read,    // the last event that is read
        c_last_runfunc  // the last event that is runfunction
    };
    
    OffloadDescriptor(
        int index,
        _Offload_status *status,
        bool is_mandatory,
        bool is_openmp,
        OffloadHostTimerData * timer_data
    ) :
        m_device(mic_engines[index == -1 ? 0 : index % mic_engines_total]),
        m_is_mandatory(is_mandatory),
        m_is_openmp(is_openmp),
        m_inout_buf(0),
        m_func_desc(0),
        m_func_desc_size(0),
        m_in_deps(0),
        m_in_deps_total(0),
        m_in_deps_allocated(0),        
        m_out_deps(0),
        m_out_deps_total(0),
        m_out_deps_allocated(0),
        m_vars(0),
        m_vars_extra(0),
        m_status(status),
        m_timer_data(timer_data),
        m_out_with_preallocated(false),
        m_preallocated_alloc(false),
        m_traceback_called(false),
        m_stream(-1),
        m_omp_async_last_event_type(c_last_not)
    {
        m_wait_all_devices = index == -1;
    }

    ~OffloadDescriptor()
    {
        if (m_in_deps != 0) {
            free(m_in_deps);
        }
        if (m_out_deps != 0) {
            free(m_out_deps);
        }
        if (m_func_desc != 0) {
            free(m_func_desc);
        }
        if (m_vars != 0) {
            free(m_vars);
            free(m_vars_extra);
        }
    }

    bool offload(const char *name, bool is_empty,
                 VarDesc *vars, VarDesc2 *vars2, int vars_total,
                 const void **waits, int num_waits, const void **signal,
                 int entry_id, const void *stack_addr,
                 OffloadFlags offload_flags);

    bool offload_finish(bool is_traceback);

    bool is_signaled();

    OffloadHostTimerData* get_timer_data() const {
        return m_timer_data;
    }

    void set_stream(_Offload_stream stream) {
        m_stream = stream;
    }

    _Offload_stream get_stream() {
        return(m_stream);
    }

private:
    bool offload_wrap(const char *name, bool is_empty,
                 VarDesc *vars, VarDesc2 *vars2, int vars_total,
                 const void **waits, int num_waits, const void **signal,
                 int entry_id, const void *stack_addr,
                 OffloadFlags offload_flags);
    bool wait_dependencies(const void **waits, int num_waits,
                           _Offload_stream stream);
    bool setup_descriptors(VarDesc *vars, VarDesc2 *vars2, int vars_total,
                           int entry_id, const void *stack_addr);
    bool setup_misc_data(const char *name);
    bool send_pointer_data(bool is_async, void* info);
    bool send_noncontiguous_pointer_data(
        int i,
        PtrData* src_buf,
        PtrData* dst_buf,
        COIEVENT *event,
        uint64_t  &sent_data,
        uint32_t in_deps_amount,
        COIEVENT *in_deps
        );
    bool receive_noncontiguous_pointer_data(
        int i,
        COIBUFFER dst_buf,
        COIEVENT *event,
        uint64_t  &received_data,
        uint32_t in_deps_amount,
        COIEVENT *in_deps
        );

    bool gather_copyin_data();

    bool compute(void *);

    bool receive_pointer_data(bool is_async, bool first_run, void * info);
    bool scatter_copyout_data();

    void cleanup();

    bool find_ptr_data(PtrData* &ptr_data, void *base, int64_t disp,
                       int64_t length, bool is_targptr,
                       bool error_does_not_exist = true);
    bool alloc_ptr_data(PtrData* &ptr_data, void *base, int64_t disp,
                        int64_t length, int64_t alloc_disp, int align,
                        bool is_targptr, bool is_prealloc, bool pin);
    bool create_preallocated_buffer(PtrData* ptr_data, void *base);
    bool init_static_ptr_data(PtrData *ptr_data);
    bool init_mic_address(PtrData *ptr_data);
    bool offload_stack_memory_manager(const void * stack_begin, int routine_id,
                                      int buf_size, int align, bool *is_new);
    bool nullify_target_stack(COIBUFFER targ_buf, uint64_t size);

    bool gen_var_descs_for_pointer_array(int i);

    void get_stream_in_dependencies(uint32_t &in_deps_amount,
                                    COIEVENT* &in_deps);

    void report_coi_error(error_types msg, COIRESULT res);
    _Offload_result translate_coi_error(COIRESULT res) const;
    
    void setup_omp_async_info();
    void register_omp_event_call_back(const COIEVENT *event, const void *info);
    
private:
    typedef std::list<COIBUFFER> BufferList;

    // extra data associated with each variable descriptor
    struct VarExtra {
        PtrData* src_data;
        PtrData* dst_data;
        AutoData* auto_data;
        int64_t cpu_disp;
        int64_t cpu_offset;
        void *alloc;
        CeanReadRanges *read_rng_src;
        CeanReadRanges *read_rng_dst;
        int64_t ptr_arr_offset;
        bool is_arr_ptr_el;
        OmpAsyncLastEventType omp_last_event_type;
    };

    template<typename T> class ReadArrElements {
    public:
        ReadArrElements():
            ranges(NULL),
            el_size(sizeof(T)),
            offset(0),
            count(0),
            is_empty(true),
            base(NULL)
        {}

        bool read_next(bool flag)
        {
            if (flag != 0) {
                if (is_empty) {
                    if (ranges) {
                        if (!get_next_range(ranges, &offset)) {
                            // ranges are over
                            return false;
                        }
                    }
                    // all contiguous elements are over
                    else if (count != 0) {
                        return false;
                    }

                    length_cur = size;
                }
                else {
                    offset += el_size;
                }
                val = (T)get_el_value(base, offset, el_size);
                length_cur -= el_size;
                count++;
                is_empty = length_cur == 0;
            }
            return true;
        }
    public:
        CeanReadRanges * ranges;
        T       val;
        int     el_size;
        int64_t size,
                offset,
                length_cur;
        bool    is_empty;
        int     count;
        char   *base;
    };

    // ptr_data for persistent auto objects
    PtrData*    m_stack_ptr_data;
    PtrDataList m_destroy_stack;

    // Engine
    Engine& m_device;

    // true for offload_wait target(mic) stream(0)
    bool m_wait_all_devices;

    // if true offload is mandatory
    bool m_is_mandatory;

    // if true offload has openmp origin
    const bool m_is_openmp;

    // The Marshaller for the inputs of the offloaded region.
    Marshaller m_in;

    // The Marshaller for the outputs of the offloaded region.
    Marshaller m_out;

    // List of buffers that are passed to dispatch call
    BufferList m_compute_buffers;

    // List of buffers that need to be destroyed at the end of offload
    BufferList m_destroy_buffers;

    // Variable descriptors
    VarDesc*  m_vars;
    VarExtra* m_vars_extra;
    int       m_vars_total;

    // Pointer to a user-specified status variable
    _Offload_status *m_status;

    // Function descriptor
    FunctionDescriptor* m_func_desc;
    uint32_t            m_func_desc_size;

    // Buffer for transferring copyin/copyout data
    COIBUFFER m_inout_buf;

    // Dependencies
    COIEVENT *m_in_deps;
    uint32_t  m_in_deps_total;
    uint32_t  m_in_deps_allocated;    
    COIEVENT *m_out_deps;
    uint32_t  m_out_deps_total;
    uint32_t  m_out_deps_allocated;     

    // Stream
    _Offload_stream m_stream;

    // Timer data
    OffloadHostTimerData *m_timer_data;

    // copyin/copyout data length
    uint64_t m_in_datalen;
    uint64_t m_out_datalen;

    // a boolean value calculated in setup_descriptors. If true we need to do
    // a run function on the target. Otherwise it may be optimized away.
    bool m_need_runfunction;

    // initialized value of m_need_runfunction;
    // is used to recognize offload_transfer
    bool m_initial_need_runfunction;

    // a Boolean value set to true when OUT clauses with preallocated targetptr
    // is encountered to indicate that call receive_pointer_data needs to be
    // invoked again after call to scatter_copyout_data.
    bool m_out_with_preallocated;

    // a Boolean value set to true if an alloc_if(1) is used with preallocated
    // targetptr to indicate the need to scatter_copyout_data even for
    // async offload
    bool m_preallocated_alloc;

    // a Boolean value set to true if traceback routine is called
    bool m_traceback_called;  

    OmpAsyncLastEventType m_omp_async_last_event_type;
};

// Initialization types for MIC
enum OffloadInitType {
    c_init_on_start,         // all devices before entering main
    c_init_on_offload,       // single device before starting the first offload
    c_init_on_offload_all    // all devices before starting the first offload
};

// Determines if MIC code is an executable or a shared library
extern "C" bool __offload_target_image_is_executable(const void *target_image);

// Initializes library and registers specified offload image.
extern "C" bool __offload_register_image(const void* image);
extern "C" void __offload_unregister_image(const void* image);

// Registers asynchronous task completion callback
extern "C" void __offload_register_task_callback(void (*cb)(void *));

// Initializes offload runtime library.
DLL_LOCAL extern int __offload_init_library(void);

// thread data for associating pipelines with threads
DLL_LOCAL extern pthread_key_t mic_thread_key;

// location of offload_main executable
// To be used if the main application has no offload and is not built
// with -offload but dynamic library linked in has offload pragma
DLL_LOCAL extern char* mic_device_main;

// Environment variables for devices
DLL_LOCAL extern MicEnvVar mic_env_vars;

// CPU frequency
DLL_LOCAL extern uint64_t cpu_frequency;

// LD_LIBRARY_PATH for MIC libraries
DLL_LOCAL extern char* mic_library_path;

// stack size for target
DLL_LOCAL extern uint32_t mic_stack_size;

// Preallocated memory size for buffers on MIC
DLL_LOCAL extern uint64_t mic_buffer_size;

// Preallocated 4K page memory size for buffers on MIC
DLL_LOCAL extern uint64_t mic_4k_buffer_size;

// Preallocated 2M page memory size for buffers on MIC
DLL_LOCAL extern uint64_t mic_2m_buffer_size;

// Setting controlling inout proxy
DLL_LOCAL extern bool  mic_proxy_io;
DLL_LOCAL extern char* mic_proxy_fs_root;

// Threshold for creating buffers with large pages
DLL_LOCAL extern uint64_t __offload_use_2mb_buffers;

// offload initialization type
DLL_LOCAL extern OffloadInitType __offload_init_type;

// Device number to offload to when device is not explicitly specified.
DLL_LOCAL extern int __omp_device_num;

// target executable
DLL_LOCAL extern TargetImage* __target_exe;

// IDB support

// Called by the offload runtime after initialization of offload infrastructure
// has been completed.
extern "C" void  __dbg_target_so_loaded();

// Called by the offload runtime when the offload infrastructure is about to be
// shut down, currently at application exit.
extern "C" void  __dbg_target_so_unloaded();

// Null-terminated string containing path to the process image of the hosting
// application (offload_main)
#define MAX_TARGET_NAME 512
extern "C" char  __dbg_target_exe_name[MAX_TARGET_NAME];

// Integer specifying the process id
extern "C" pid_t __dbg_target_so_pid;

// Integer specifying the 0-based device number
extern "C" int   __dbg_target_id;

// Set to non-zero by the host-side debugger to enable offload debugging
// support
extern "C" int   __dbg_is_attached;

// Major version of the debugger support API
extern "C" const int __dbg_api_major_version;

// Minor version of the debugger support API
extern "C" const int __dbg_api_minor_version;

#endif // OFFLOAD_HOST_H_INCLUDED