1 /*
2  * kmp_stub.cpp -- stub versions of user-callable OpenMP RT functions.
3  */
4 
5 //===----------------------------------------------------------------------===//
6 //
7 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8 // See https://llvm.org/LICENSE.txt for license information.
9 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include <errno.h>
14 #include <limits.h>
15 #include <stdlib.h>
16 
17 #define __KMP_IMP
18 #include "omp.h" // omp_* declarations, must be included before "kmp.h"
19 #include "kmp.h" // KMP_DEFAULT_STKSIZE
20 #include "kmp_stub.h"
21 
22 #if KMP_OS_WINDOWS
23 #include <windows.h>
24 #else
25 #include <sys/time.h>
26 #endif
27 
28 // Moved from omp.h
29 #define omp_set_max_active_levels ompc_set_max_active_levels
30 #define omp_set_schedule ompc_set_schedule
31 #define omp_get_ancestor_thread_num ompc_get_ancestor_thread_num
32 #define omp_get_team_size ompc_get_team_size
33 
34 #define omp_set_num_threads ompc_set_num_threads
35 #define omp_set_dynamic ompc_set_dynamic
36 #define omp_set_nested ompc_set_nested
37 #define omp_set_affinity_format ompc_set_affinity_format
38 #define omp_get_affinity_format ompc_get_affinity_format
39 #define omp_display_affinity ompc_display_affinity
40 #define omp_capture_affinity ompc_capture_affinity
41 #define kmp_set_stacksize kmpc_set_stacksize
42 #define kmp_set_stacksize_s kmpc_set_stacksize_s
43 #define kmp_set_blocktime kmpc_set_blocktime
44 #define kmp_set_library kmpc_set_library
45 #define kmp_set_defaults kmpc_set_defaults
46 #define kmp_set_disp_num_buffers kmpc_set_disp_num_buffers
47 #define kmp_malloc kmpc_malloc
48 #define kmp_aligned_malloc kmpc_aligned_malloc
49 #define kmp_calloc kmpc_calloc
50 #define kmp_realloc kmpc_realloc
51 #define kmp_free kmpc_free
52 
53 #if KMP_OS_WINDOWS
54 static double frequency = 0.0;
55 #endif
56 
57 // Helper functions.
58 static size_t __kmps_init() {
59   static int initialized = 0;
60   static size_t dummy = 0;
61   if (!initialized) {
62     // TODO: Analyze KMP_VERSION environment variable, print
63     // __kmp_version_copyright and __kmp_version_build_time.
64     // WARNING: Do not use "fprintf(stderr, ...)" because it will cause
65     // unresolved "__iob" symbol (see C70080). We need to extract __kmp_printf()
66     // stuff from kmp_runtime.cpp and use it.
67 
68     // Trick with dummy variable forces linker to keep __kmp_version_copyright
69     // and __kmp_version_build_time strings in executable file (in case of
70     // static linkage). When KMP_VERSION analysis is implemented, dummy
71     // variable should be deleted, function should return void.
72     dummy = __kmp_version_copyright - __kmp_version_build_time;
73 
74 #if KMP_OS_WINDOWS
75     LARGE_INTEGER freq;
76     BOOL status = QueryPerformanceFrequency(&freq);
77     if (status) {
78       frequency = double(freq.QuadPart);
79     }
80 #endif
81 
82     initialized = 1;
83   }
84   return dummy;
85 } // __kmps_init
86 
87 #define i __kmps_init();
88 
89 /* set API functions */
90 void omp_set_num_threads(omp_int_t num_threads) { i; }
91 void omp_set_dynamic(omp_int_t dynamic) {
92   i;
93   __kmps_set_dynamic(dynamic);
94 }
95 void omp_set_nested(omp_int_t nested) {
96   i;
97   __kmps_set_nested(nested);
98 }
99 void omp_set_max_active_levels(omp_int_t max_active_levels) { i; }
100 void omp_set_schedule(omp_sched_t kind, omp_int_t modifier) {
101   i;
102   __kmps_set_schedule((kmp_sched_t)kind, modifier);
103 }
104 int omp_get_ancestor_thread_num(omp_int_t level) {
105   i;
106   return (level) ? (-1) : (0);
107 }
108 int omp_get_team_size(omp_int_t level) {
109   i;
110   return (level) ? (-1) : (1);
111 }
112 int kmpc_set_affinity_mask_proc(int proc, void **mask) {
113   i;
114   return -1;
115 }
116 int kmpc_unset_affinity_mask_proc(int proc, void **mask) {
117   i;
118   return -1;
119 }
120 int kmpc_get_affinity_mask_proc(int proc, void **mask) {
121   i;
122   return -1;
123 }
124 
125 /* kmp API functions */
126 void kmp_set_stacksize(omp_int_t arg) {
127   i;
128   __kmps_set_stacksize(arg);
129 }
130 void kmp_set_stacksize_s(size_t arg) {
131   i;
132   __kmps_set_stacksize(arg);
133 }
134 void kmp_set_blocktime(omp_int_t arg) {
135   i;
136   __kmps_set_blocktime(arg);
137 }
138 void kmp_set_library(omp_int_t arg) {
139   i;
140   __kmps_set_library(arg);
141 }
142 void kmp_set_defaults(char const *str) { i; }
143 void kmp_set_disp_num_buffers(omp_int_t arg) { i; }
144 
145 /* KMP memory management functions. */
146 void *kmp_malloc(size_t size) {
147   i;
148   void *res;
149 #if KMP_OS_WINDOWS
150   // If succesfull returns a pointer to the memory block, otherwise returns
151   // NULL.
152   // Sets errno to ENOMEM or EINVAL if memory allocation failed or parameter
153   // validation failed.
154   res = _aligned_malloc(size, 1);
155 #else
156   res = malloc(size);
157 #endif
158   return res;
159 }
160 void *kmp_aligned_malloc(size_t sz, size_t a) {
161   i;
162   int err;
163   void *res;
164 #if KMP_OS_WINDOWS
165   res = _aligned_malloc(sz, a);
166 #else
167   if (err = posix_memalign(&res, a, sz)) {
168     errno = err; // can be EINVAL or ENOMEM
169     res = NULL;
170   }
171 #endif
172   return res;
173 }
174 void *kmp_calloc(size_t nelem, size_t elsize) {
175   i;
176   void *res;
177 #if KMP_OS_WINDOWS
178   res = _aligned_recalloc(NULL, nelem, elsize, 1);
179 #else
180   res = calloc(nelem, elsize);
181 #endif
182   return res;
183 }
184 void *kmp_realloc(void *ptr, size_t size) {
185   i;
186   void *res;
187 #if KMP_OS_WINDOWS
188   res = _aligned_realloc(ptr, size, 1);
189 #else
190   res = realloc(ptr, size);
191 #endif
192   return res;
193 }
194 void kmp_free(void *ptr) {
195   i;
196 #if KMP_OS_WINDOWS
197   _aligned_free(ptr);
198 #else
199   free(ptr);
200 #endif
201 }
202 
203 static int __kmps_blocktime = INT_MAX;
204 
205 void __kmps_set_blocktime(int arg) {
206   i;
207   __kmps_blocktime = arg;
208 } // __kmps_set_blocktime
209 
210 int __kmps_get_blocktime(void) {
211   i;
212   return __kmps_blocktime;
213 } // __kmps_get_blocktime
214 
215 static int __kmps_dynamic = 0;
216 
217 void __kmps_set_dynamic(int arg) {
218   i;
219   __kmps_dynamic = arg;
220 } // __kmps_set_dynamic
221 
222 int __kmps_get_dynamic(void) {
223   i;
224   return __kmps_dynamic;
225 } // __kmps_get_dynamic
226 
227 static int __kmps_library = 1000;
228 
229 void __kmps_set_library(int arg) {
230   i;
231   __kmps_library = arg;
232 } // __kmps_set_library
233 
234 int __kmps_get_library(void) {
235   i;
236   return __kmps_library;
237 } // __kmps_get_library
238 
239 static int __kmps_nested = 0;
240 
241 void __kmps_set_nested(int arg) {
242   i;
243   __kmps_nested = arg;
244 } // __kmps_set_nested
245 
246 int __kmps_get_nested(void) {
247   i;
248   return __kmps_nested;
249 } // __kmps_get_nested
250 
251 static size_t __kmps_stacksize = KMP_DEFAULT_STKSIZE;
252 
253 void __kmps_set_stacksize(int arg) {
254   i;
255   __kmps_stacksize = arg;
256 } // __kmps_set_stacksize
257 
258 int __kmps_get_stacksize(void) {
259   i;
260   return __kmps_stacksize;
261 } // __kmps_get_stacksize
262 
263 static kmp_sched_t __kmps_sched_kind = kmp_sched_default;
264 static int __kmps_sched_modifier = 0;
265 
266 void __kmps_set_schedule(kmp_sched_t kind, int modifier) {
267   i;
268   __kmps_sched_kind = kind;
269   __kmps_sched_modifier = modifier;
270 } // __kmps_set_schedule
271 
272 void __kmps_get_schedule(kmp_sched_t *kind, int *modifier) {
273   i;
274   *kind = __kmps_sched_kind;
275   *modifier = __kmps_sched_modifier;
276 } // __kmps_get_schedule
277 
278 #if OMP_40_ENABLED
279 
280 static kmp_proc_bind_t __kmps_proc_bind = proc_bind_false;
281 
282 void __kmps_set_proc_bind(kmp_proc_bind_t arg) {
283   i;
284   __kmps_proc_bind = arg;
285 } // __kmps_set_proc_bind
286 
287 kmp_proc_bind_t __kmps_get_proc_bind(void) {
288   i;
289   return __kmps_proc_bind;
290 } // __kmps_get_proc_bind
291 
292 #endif /* OMP_40_ENABLED */
293 
294 double __kmps_get_wtime(void) {
295   // Elapsed wall clock time (in second) from "sometime in the past".
296   double wtime = 0.0;
297   i;
298 #if KMP_OS_WINDOWS
299   if (frequency > 0.0) {
300     LARGE_INTEGER now;
301     BOOL status = QueryPerformanceCounter(&now);
302     if (status) {
303       wtime = double(now.QuadPart) / frequency;
304     }
305   }
306 #else
307   // gettimeofday() returns seconds and microseconds since the Epoch.
308   struct timeval tval;
309   int rc;
310   rc = gettimeofday(&tval, NULL);
311   if (rc == 0) {
312     wtime = (double)(tval.tv_sec) + 1.0E-06 * (double)(tval.tv_usec);
313   } else {
314     // TODO: Assert or abort here.
315   }
316 #endif
317   return wtime;
318 } // __kmps_get_wtime
319 
320 double __kmps_get_wtick(void) {
321   // Number of seconds between successive clock ticks.
322   double wtick = 0.0;
323   i;
324 #if KMP_OS_WINDOWS
325   {
326     DWORD increment;
327     DWORD adjustment;
328     BOOL disabled;
329     BOOL rc;
330     rc = GetSystemTimeAdjustment(&adjustment, &increment, &disabled);
331     if (rc) {
332       wtick = 1.0E-07 * (double)(disabled ? increment : adjustment);
333     } else {
334       // TODO: Assert or abort here.
335       wtick = 1.0E-03;
336     }
337   }
338 #else
339   // TODO: gettimeofday() returns in microseconds, but what the precision?
340   wtick = 1.0E-06;
341 #endif
342   return wtick;
343 } // __kmps_get_wtick
344 
345 #if OMP_50_ENABLED
346 /* OpenMP 5.0 Memory Management */
347 #if KMP_OS_WINDOWS
348 omp_allocator_handle_t const omp_null_allocator = 0;
349 omp_allocator_handle_t const omp_default_mem_alloc =
350     (omp_allocator_handle_t const)1;
351 omp_allocator_handle_t const omp_large_cap_mem_alloc =
352     (omp_allocator_handle_t const)2;
353 omp_allocator_handle_t const omp_const_mem_alloc =
354     (omp_allocator_handle_t const)3;
355 omp_allocator_handle_t const omp_high_bw_mem_alloc =
356     (omp_allocator_handle_t const)4;
357 omp_allocator_handle_t const omp_low_lat_mem_alloc =
358     (omp_allocator_handle_t const)5;
359 omp_allocator_handle_t const omp_cgroup_mem_alloc =
360     (omp_allocator_handle_t const)6;
361 omp_allocator_handle_t const omp_pteam_mem_alloc =
362     (omp_allocator_handle_t const)7;
363 omp_allocator_handle_t const omp_thread_mem_alloc =
364     (omp_allocator_handle_t const)8;
365 
366 omp_memspace_handle_t const omp_default_mem_space =
367     (omp_memspace_handle_t const)0;
368 omp_memspace_handle_t const omp_large_cap_mem_space =
369     (omp_memspace_handle_t const)1;
370 omp_memspace_handle_t const omp_const_mem_space =
371     (omp_memspace_handle_t const)2;
372 omp_memspace_handle_t const omp_high_bw_mem_space =
373     (omp_memspace_handle_t const)3;
374 omp_memspace_handle_t const omp_low_lat_mem_space =
375     (omp_memspace_handle_t const)4;
376 #endif /* KMP_OS_WINDOWS */
377 void *omp_alloc(size_t size, const omp_allocator_handle_t allocator) {
378   i;
379   return malloc(size);
380 }
381 void omp_free(void *ptr, const omp_allocator_handle_t allocator) {
382   i;
383   free(ptr);
384 }
385 /* OpenMP 5.0 Affinity Format */
386 void omp_set_affinity_format(char const *format) { i; }
387 size_t omp_get_affinity_format(char *buffer, size_t size) {
388   i;
389   return 0;
390 }
391 void omp_display_affinity(char const *format) { i; }
392 size_t omp_capture_affinity(char *buffer, size_t buf_size, char const *format) {
393   i;
394   return 0;
395 }
396 #endif /* OMP_50_ENABLED */
397 
398 // end of file //
399