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/*
32 * Include file for Offload API.
33 */
34
35#ifndef OFFLOAD_H_INCLUDED
36#define OFFLOAD_H_INCLUDED
37
38#if defined(LINUX) || defined(FREEBSD)
39#include <bits/functexcept.h>
40#endif
41
42#include <stddef.h>
43#include <omp.h>
44
45#ifdef __cplusplus
46extern "C" {
47#endif
48
49#define TARGET_ATTRIBUTE __declspec(target(mic))
50
51/*
52 *  The target architecture.
53 */
54typedef enum TARGET_TYPE {
55    TARGET_NONE,    /* Undefine target */
56    TARGET_HOST,    /* Host used as target */
57    TARGET_MIC      /* MIC target */
58} TARGET_TYPE;
59
60/*
61 *  The default target type.
62 */
63#define DEFAULT_TARGET_TYPE TARGET_MIC
64
65/*
66 *  The default target number.
67 */
68#define DEFAULT_TARGET_NUMBER 0
69
70/*
71 *  Offload status.
72 */
73typedef enum {
74    OFFLOAD_SUCCESS = 0,
75    OFFLOAD_DISABLED,               /* offload is disabled */
76    OFFLOAD_UNAVAILABLE,            /* card is not available */
77    OFFLOAD_OUT_OF_MEMORY,          /* not enough memory on device */
78    OFFLOAD_PROCESS_DIED,           /* target process has died */
79    OFFLOAD_ERROR                   /* unspecified error */
80} _Offload_result;
81
82typedef struct {
83    _Offload_result result;         /* result, see above */
84    int             device_number;  /* device number */
85    size_t          data_sent;      /* number of bytes sent to the target */
86    size_t          data_received;  /* number of bytes received by host */
87} _Offload_status;
88
89#define OFFLOAD_STATUS_INIT(x) \
90    ((x).result = OFFLOAD_DISABLED)
91
92#define OFFLOAD_STATUS_INITIALIZER \
93    { OFFLOAD_DISABLED, -1, 0, 0 }
94
95/* Offload runtime interfaces */
96
97extern int _Offload_number_of_devices(void);
98extern int _Offload_get_device_number(void);
99extern int _Offload_get_physical_device_number(void);
100
101extern void* _Offload_shared_malloc(size_t size);
102extern void  _Offload_shared_free(void *ptr);
103
104extern void* _Offload_shared_aligned_malloc(size_t size, size_t align);
105extern void  _Offload_shared_aligned_free(void *ptr);
106
107extern int _Offload_signaled(int index, void *signal);
108extern void _Offload_report(int val);
109
110/* OpenMP API */
111
112extern void omp_set_default_device(int num) __GOMP_NOTHROW;
113extern int  omp_get_default_device(void) __GOMP_NOTHROW;
114extern int  omp_get_num_devices(void) __GOMP_NOTHROW;
115
116/* OpenMP API wrappers */
117
118/* Set num_threads on target */
119extern void omp_set_num_threads_target(
120    TARGET_TYPE target_type,
121    int target_number,
122    int num_threads
123);
124
125/* Get max_threads from target */
126extern int omp_get_max_threads_target(
127    TARGET_TYPE target_type,
128    int target_number
129);
130
131/* Get num_procs from target */
132extern int omp_get_num_procs_target(
133    TARGET_TYPE target_type,
134    int target_number
135);
136
137/* Set dynamic on target */
138extern void omp_set_dynamic_target(
139    TARGET_TYPE target_type,
140    int target_number,
141    int num_threads
142);
143
144/* Get dynamic from target */
145extern int omp_get_dynamic_target(
146    TARGET_TYPE target_type,
147    int target_number
148);
149
150/* Set nested on target */
151extern void omp_set_nested_target(
152    TARGET_TYPE target_type,
153    int target_number,
154    int nested
155);
156
157/* Get nested from target */
158extern int omp_get_nested_target(
159    TARGET_TYPE target_type,
160    int target_number
161);
162
163extern void omp_set_num_threads_target(
164    TARGET_TYPE target_type,
165    int target_number,
166    int num_threads
167);
168
169extern int omp_get_max_threads_target(
170    TARGET_TYPE target_type,
171    int target_number
172);
173
174extern int omp_get_num_procs_target(
175    TARGET_TYPE target_type,
176    int target_number
177);
178
179extern void omp_set_dynamic_target(
180    TARGET_TYPE target_type,
181    int target_number,
182    int num_threads
183);
184
185extern int omp_get_dynamic_target(
186    TARGET_TYPE target_type,
187    int target_number
188);
189
190extern void omp_set_nested_target(
191    TARGET_TYPE target_type,
192    int target_number,
193    int num_threads
194);
195
196extern int omp_get_nested_target(
197    TARGET_TYPE target_type,
198    int target_number
199);
200
201extern void omp_set_schedule_target(
202    TARGET_TYPE target_type,
203    int target_number,
204    omp_sched_t kind,
205    int modifier
206);
207
208extern void omp_get_schedule_target(
209    TARGET_TYPE target_type,
210    int target_number,
211    omp_sched_t *kind,
212    int *modifier
213);
214
215/* lock API functions */
216
217typedef struct {
218    omp_lock_t lock;
219} omp_lock_target_t;
220
221extern void omp_init_lock_target(
222    TARGET_TYPE target_type,
223    int target_number,
224    omp_lock_target_t *lock
225);
226
227extern void omp_destroy_lock_target(
228    TARGET_TYPE target_type,
229    int target_number,
230    omp_lock_target_t *lock
231);
232
233extern void omp_set_lock_target(
234    TARGET_TYPE target_type,
235    int target_number,
236    omp_lock_target_t *lock
237);
238
239extern void omp_unset_lock_target(
240    TARGET_TYPE target_type,
241    int target_number,
242    omp_lock_target_t *lock
243);
244
245extern int omp_test_lock_target(
246    TARGET_TYPE target_type,
247    int target_number,
248    omp_lock_target_t *lock
249);
250
251/* nested lock API functions */
252
253typedef struct {
254    omp_nest_lock_t lock;
255} omp_nest_lock_target_t;
256
257extern void omp_init_nest_lock_target(
258    TARGET_TYPE target_type,
259    int target_number,
260    omp_nest_lock_target_t *lock
261);
262
263extern void omp_destroy_nest_lock_target(
264    TARGET_TYPE target_type,
265    int target_number,
266    omp_nest_lock_target_t *lock
267);
268
269extern void omp_set_nest_lock_target(
270    TARGET_TYPE target_type,
271    int target_number,
272    omp_nest_lock_target_t *lock
273);
274
275extern void omp_unset_nest_lock_target(
276    TARGET_TYPE target_type,
277    int target_number,
278    omp_nest_lock_target_t *lock
279);
280
281extern int omp_test_nest_lock_target(
282    TARGET_TYPE target_type,
283    int target_number,
284    omp_nest_lock_target_t *lock
285);
286
287#ifdef __cplusplus
288} /* extern "C" */
289
290/* Namespace for the shared_allocator. */
291namespace __offload {
292  /* This follows the specification for std::allocator. */
293  /* Forward declaration of the class template. */
294  template <typename T>
295  class shared_allocator;
296
297  /* Specialization for shared_allocator<void>. */
298  template <>
299  class shared_allocator<void> {
300  public:
301    typedef void       *pointer;
302    typedef const void *const_pointer;
303    typedef void        value_type;
304    template <class U> struct rebind { typedef shared_allocator<U> other; };
305  };
306
307  /* Definition of shared_allocator<T>. */
308  template <class T>
309  class shared_allocator {
310  public:
311    typedef size_t     size_type;
312    typedef ptrdiff_t  difference_type;
313    typedef T         *pointer;
314    typedef const T   *const_pointer;
315    typedef T         &reference;
316    typedef const T   &const_reference;
317    typedef T          value_type;
318    template <class U> struct rebind { typedef shared_allocator<U> other; };
319    shared_allocator() throw() { }
320    shared_allocator(const shared_allocator&) throw() { }
321    template <class U> shared_allocator(const shared_allocator<U>&) throw() { }
322    ~shared_allocator() throw() { }
323    pointer address(reference x) const { return &x; }
324    const_pointer address(const_reference x) const { return &x; }
325    pointer allocate(
326      size_type, shared_allocator<void>::const_pointer hint = 0);
327    void deallocate(pointer p, size_type n);
328    size_type max_size() const throw() {
329      return size_type(-1)/sizeof(T);
330    } /* max_size */
331    void construct(pointer p, const T& arg) {
332      ::new (p) T(arg);
333    } /* construct */
334    void destroy(pointer p) {
335      p->~T();
336    } /* destroy */
337  };
338
339  /* Definition for allocate. */
340  template <class T>
341  typename shared_allocator<T>::pointer
342  shared_allocator<T>::allocate(shared_allocator<T>::size_type s,
343                                shared_allocator<void>::const_pointer) {
344    /* Allocate from shared memory. */
345    void *ptr = _Offload_shared_malloc(s*sizeof(T));
346    if (ptr == 0) std::__throw_bad_alloc();
347    return static_cast<pointer>(ptr);
348  } /* allocate */
349
350  template <class T>
351  void shared_allocator<T>::deallocate(pointer p,
352                                       shared_allocator<T>::size_type) {
353    /* Free the shared memory. */
354    _Offload_shared_free(p);
355  } /* deallocate */
356
357  template <typename _T1, typename _T2>
358  inline bool operator==(const shared_allocator<_T1> &,
359                         const shared_allocator<_T2> &) throw() {
360    return true;
361  }  /* operator== */
362
363  template <typename _T1, typename _T2>
364  inline bool operator!=(const shared_allocator<_T1> &,
365                         const shared_allocator<_T2> &) throw() {
366    return false;
367  }  /* operator!= */
368}  /* __offload */
369#endif /* __cplusplus */
370
371#endif /* OFFLOAD_H_INCLUDED */
372