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(arg: dynamic); |
94 | } |
95 | void omp_set_nested(omp_int_t nested) { |
96 | i; |
97 | __kmps_set_nested(arg: 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(kind: (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: (size_t)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 successful 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: size); |
157 | #endif |
158 | return res; |
159 | } |
160 | void *kmp_aligned_malloc(size_t sz, size_t a) { |
161 | i; |
162 | void *res; |
163 | #if KMP_OS_WINDOWS |
164 | res = _aligned_malloc(sz, a); |
165 | #else |
166 | int err; |
167 | if ((err = posix_memalign(memptr: &res, alignment: a, size: 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(nmemb: nelem, size: 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: ptr, size: 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: 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(size_t arg) { |
254 | i; |
255 | __kmps_stacksize = arg; |
256 | } // __kmps_set_stacksize |
257 | |
258 | size_t __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 | kmp_proc_bind_t __kmps_get_proc_bind(void) { |
279 | i; |
280 | return proc_bind_false; |
281 | } // __kmps_get_proc_bind |
282 | |
283 | double __kmps_get_wtime(void) { |
284 | // Elapsed wall clock time (in second) from "sometime in the past". |
285 | double wtime = 0.0; |
286 | i; |
287 | #if KMP_OS_WINDOWS |
288 | if (frequency > 0.0) { |
289 | LARGE_INTEGER now; |
290 | BOOL status = QueryPerformanceCounter(&now); |
291 | if (status) { |
292 | wtime = double(now.QuadPart) / frequency; |
293 | } |
294 | } |
295 | #else |
296 | // gettimeofday() returns seconds and microseconds since the Epoch. |
297 | struct timeval tval; |
298 | int rc; |
299 | rc = gettimeofday(tv: &tval, NULL); |
300 | if (rc == 0) { |
301 | wtime = (double)(tval.tv_sec) + 1.0E-06 * (double)(tval.tv_usec); |
302 | } else { |
303 | // TODO: Assert or abort here. |
304 | } |
305 | #endif |
306 | return wtime; |
307 | } // __kmps_get_wtime |
308 | |
309 | double __kmps_get_wtick(void) { |
310 | // Number of seconds between successive clock ticks. |
311 | double wtick = 0.0; |
312 | i; |
313 | #if KMP_OS_WINDOWS |
314 | { |
315 | DWORD increment; |
316 | DWORD adjustment; |
317 | BOOL disabled; |
318 | BOOL rc; |
319 | rc = GetSystemTimeAdjustment(&adjustment, &increment, &disabled); |
320 | if (rc) { |
321 | wtick = 1.0E-07 * (double)(disabled ? increment : adjustment); |
322 | } else { |
323 | // TODO: Assert or abort here. |
324 | wtick = 1.0E-03; |
325 | } |
326 | } |
327 | #else |
328 | // TODO: gettimeofday() returns in microseconds, but what the precision? |
329 | wtick = 1.0E-06; |
330 | #endif |
331 | return wtick; |
332 | } // __kmps_get_wtick |
333 | |
334 | /* OpenMP 5.0 Memory Management */ |
335 | #if KMP_OS_WINDOWS |
336 | omp_allocator_handle_t const omp_null_allocator = 0; |
337 | omp_allocator_handle_t const omp_default_mem_alloc = |
338 | (omp_allocator_handle_t const)1; |
339 | omp_allocator_handle_t const omp_large_cap_mem_alloc = |
340 | (omp_allocator_handle_t const)2; |
341 | omp_allocator_handle_t const omp_const_mem_alloc = |
342 | (omp_allocator_handle_t const)3; |
343 | omp_allocator_handle_t const omp_high_bw_mem_alloc = |
344 | (omp_allocator_handle_t const)4; |
345 | omp_allocator_handle_t const omp_low_lat_mem_alloc = |
346 | (omp_allocator_handle_t const)5; |
347 | omp_allocator_handle_t const omp_cgroup_mem_alloc = |
348 | (omp_allocator_handle_t const)6; |
349 | omp_allocator_handle_t const omp_pteam_mem_alloc = |
350 | (omp_allocator_handle_t const)7; |
351 | omp_allocator_handle_t const omp_thread_mem_alloc = |
352 | (omp_allocator_handle_t const)8; |
353 | omp_allocator_handle_t const llvm_omp_target_host_mem_alloc = |
354 | (omp_allocator_handle_t const)100; |
355 | omp_allocator_handle_t const llvm_omp_target_shared_mem_alloc = |
356 | (omp_allocator_handle_t const)101; |
357 | omp_allocator_handle_t const llvm_omp_target_device_mem_alloc = |
358 | (omp_allocator_handle_t const)102; |
359 | |
360 | omp_memspace_handle_t const omp_default_mem_space = |
361 | (omp_memspace_handle_t const)0; |
362 | omp_memspace_handle_t const omp_large_cap_mem_space = |
363 | (omp_memspace_handle_t const)1; |
364 | omp_memspace_handle_t const omp_const_mem_space = |
365 | (omp_memspace_handle_t const)2; |
366 | omp_memspace_handle_t const omp_high_bw_mem_space = |
367 | (omp_memspace_handle_t const)3; |
368 | omp_memspace_handle_t const omp_low_lat_mem_space = |
369 | (omp_memspace_handle_t const)4; |
370 | omp_memspace_handle_t const llvm_omp_target_host_mem_space = |
371 | (omp_memspace_handle_t const)100; |
372 | omp_memspace_handle_t const llvm_omp_target_shared_mem_space = |
373 | (omp_memspace_handle_t const)101; |
374 | omp_memspace_handle_t const llvm_omp_target_device_mem_space = |
375 | (omp_memspace_handle_t const)102; |
376 | #endif /* KMP_OS_WINDOWS */ |
377 | |
378 | void *omp_alloc(size_t size, omp_allocator_handle_t allocator) { |
379 | i; |
380 | void *res; |
381 | #if KMP_OS_WINDOWS |
382 | // Returns a pointer to the memory block, or NULL if failed. |
383 | // Sets errno to ENOMEM or EINVAL if memory allocation failed or parameter |
384 | // validation failed. |
385 | res = _aligned_malloc(size, 1); |
386 | #else |
387 | res = malloc(size: size); |
388 | #endif |
389 | return res; |
390 | } |
391 | |
392 | void *omp_aligned_alloc(size_t a, size_t size, omp_allocator_handle_t al) { |
393 | i; |
394 | void *res; |
395 | #if KMP_OS_WINDOWS |
396 | res = _aligned_malloc(size, a); |
397 | #else |
398 | int err; |
399 | if ((err = posix_memalign(memptr: &res, alignment: a, size: size))) { |
400 | errno = err; // can be EINVAL or ENOMEM |
401 | res = NULL; |
402 | } |
403 | #endif |
404 | return res; |
405 | } |
406 | |
407 | void *omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t al) { |
408 | i; |
409 | void *res; |
410 | #if KMP_OS_WINDOWS |
411 | res = _aligned_recalloc(NULL, nmemb, size, 1); |
412 | #else |
413 | res = calloc(nmemb: nmemb, size: size); |
414 | #endif |
415 | return res; |
416 | } |
417 | |
418 | void *omp_aligned_calloc(size_t a, size_t nmemb, size_t size, |
419 | omp_allocator_handle_t al) { |
420 | i; |
421 | void *res; |
422 | #if KMP_OS_WINDOWS |
423 | res = _aligned_recalloc(NULL, nmemb, size, a); |
424 | #else |
425 | int err; |
426 | if ((err = posix_memalign(memptr: &res, alignment: a, size: nmemb * size))) { |
427 | errno = err; // can be EINVAL or ENOMEM |
428 | res = NULL; |
429 | } |
430 | memset(s: res, c: 0x00, n: size); |
431 | #endif |
432 | return res; |
433 | } |
434 | |
435 | void *omp_realloc(void *ptr, size_t size, omp_allocator_handle_t al, |
436 | omp_allocator_handle_t free_al) { |
437 | i; |
438 | void *res; |
439 | #if KMP_OS_WINDOWS |
440 | res = _aligned_realloc(ptr, size, 1); |
441 | #else |
442 | res = realloc(ptr: ptr, size: size); |
443 | #endif |
444 | return res; |
445 | } |
446 | |
447 | void omp_free(void *ptr, omp_allocator_handle_t allocator) { |
448 | i; |
449 | #if KMP_OS_WINDOWS |
450 | _aligned_free(ptr); |
451 | #else |
452 | free(ptr: ptr); |
453 | #endif |
454 | } |
455 | |
456 | /* OpenMP 5.0 Affinity Format */ |
457 | void omp_set_affinity_format(char const *format) { i; } |
458 | size_t omp_get_affinity_format(char *buffer, size_t size) { |
459 | i; |
460 | return 0; |
461 | } |
462 | void omp_display_affinity(char const *format) { i; } |
463 | size_t omp_capture_affinity(char *buffer, size_t buf_size, char const *format) { |
464 | i; |
465 | return 0; |
466 | } |
467 | |
468 | // end of file // |
469 | |