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((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); 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(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(&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 // Preview of target memory support 354 omp_allocator_handle_t const llvm_omp_target_host_mem_alloc = 355 (omp_allocator_handle_t const)100; 356 omp_allocator_handle_t const llvm_omp_target_shared_mem_alloc = 357 (omp_allocator_handle_t const)101; 358 omp_allocator_handle_t const llvm_omp_target_device_mem_alloc = 359 (omp_allocator_handle_t const)102; 360 361 omp_memspace_handle_t const omp_default_mem_space = 362 (omp_memspace_handle_t const)0; 363 omp_memspace_handle_t const omp_large_cap_mem_space = 364 (omp_memspace_handle_t const)1; 365 omp_memspace_handle_t const omp_const_mem_space = 366 (omp_memspace_handle_t const)2; 367 omp_memspace_handle_t const omp_high_bw_mem_space = 368 (omp_memspace_handle_t const)3; 369 omp_memspace_handle_t const omp_low_lat_mem_space = 370 (omp_memspace_handle_t const)4; 371 // Preview of target memory support 372 omp_memspace_handle_t const llvm_omp_target_host_mem_space = 373 (omp_memspace_handle_t const)100; 374 omp_memspace_handle_t const llvm_omp_target_shared_mem_space = 375 (omp_memspace_handle_t const)101; 376 omp_memspace_handle_t const llvm_omp_target_device_mem_space = 377 (omp_memspace_handle_t const)102; 378 #endif /* KMP_OS_WINDOWS */ 379 380 void *omp_alloc(size_t size, omp_allocator_handle_t allocator) { 381 i; 382 void *res; 383 #if KMP_OS_WINDOWS 384 // Returns a pointer to the memory block, or NULL if failed. 385 // Sets errno to ENOMEM or EINVAL if memory allocation failed or parameter 386 // validation failed. 387 res = _aligned_malloc(size, 1); 388 #else 389 res = malloc(size); 390 #endif 391 return res; 392 } 393 394 void *omp_aligned_alloc(size_t a, size_t size, omp_allocator_handle_t al) { 395 i; 396 int err; 397 void *res; 398 #if KMP_OS_WINDOWS 399 res = _aligned_malloc(size, a); 400 #else 401 if (err = posix_memalign(&res, a, size)) { 402 errno = err; // can be EINVAL or ENOMEM 403 res = NULL; 404 } 405 #endif 406 return res; 407 } 408 409 void *omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t al) { 410 i; 411 void *res; 412 #if KMP_OS_WINDOWS 413 res = _aligned_recalloc(NULL, nmemb, size, 1); 414 #else 415 res = calloc(nmemb, size); 416 #endif 417 return res; 418 } 419 420 void *omp_aligned_calloc(size_t a, size_t nmemb, size_t size, 421 omp_allocator_handle_t al) { 422 i; 423 int err; 424 void *res; 425 #if KMP_OS_WINDOWS 426 res = _aligned_recalloc(NULL, nmemb, size, a); 427 #else 428 if (err = posix_memalign(&res, a, nmemb * size)) { 429 errno = err; // can be EINVAL or ENOMEM 430 res = NULL; 431 } 432 memset(res, 0x00, size); 433 #endif 434 return res; 435 } 436 437 void *omp_realloc(void *ptr, size_t size, omp_allocator_handle_t al, 438 omp_allocator_handle_t free_al) { 439 i; 440 void *res; 441 #if KMP_OS_WINDOWS 442 res = _aligned_realloc(ptr, size, 1); 443 #else 444 res = realloc(ptr, size); 445 #endif 446 return res; 447 } 448 449 void omp_free(void *ptr, omp_allocator_handle_t allocator) { 450 i; 451 #if KMP_OS_WINDOWS 452 _aligned_free(ptr); 453 #else 454 free(ptr); 455 #endif 456 } 457 458 /* OpenMP 5.0 Affinity Format */ 459 void omp_set_affinity_format(char const *format) { i; } 460 size_t omp_get_affinity_format(char *buffer, size_t size) { 461 i; 462 return 0; 463 } 464 void omp_display_affinity(char const *format) { i; } 465 size_t omp_capture_affinity(char *buffer, size_t buf_size, char const *format) { 466 i; 467 return 0; 468 } 469 470 // end of file // 471