193 lines · cpp
1/*2 * z_Windows_NT-586_util.cpp -- platform specific routines.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-exception10//11//===----------------------------------------------------------------------===//12 13#include "kmp.h"14 15#if (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_ARM)16/* Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to17 use compare_and_store for these routines */18 19kmp_int8 __kmp_test_then_or8(volatile kmp_int8 *p, kmp_int8 d) {20 kmp_int8 old_value, new_value;21 22 old_value = TCR_1(*p);23 new_value = old_value | d;24 25 while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {26 KMP_CPU_PAUSE();27 old_value = TCR_1(*p);28 new_value = old_value | d;29 }30 return old_value;31}32 33kmp_int8 __kmp_test_then_and8(volatile kmp_int8 *p, kmp_int8 d) {34 kmp_int8 old_value, new_value;35 36 old_value = TCR_1(*p);37 new_value = old_value & d;38 39 while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {40 KMP_CPU_PAUSE();41 old_value = TCR_1(*p);42 new_value = old_value & d;43 }44 return old_value;45}46 47kmp_uint32 __kmp_test_then_or32(volatile kmp_uint32 *p, kmp_uint32 d) {48 kmp_uint32 old_value, new_value;49 50 old_value = TCR_4(*p);51 new_value = old_value | d;52 53 while (!KMP_COMPARE_AND_STORE_REL32((volatile kmp_int32 *)p, old_value,54 new_value)) {55 KMP_CPU_PAUSE();56 old_value = TCR_4(*p);57 new_value = old_value | d;58 }59 return old_value;60}61 62kmp_uint32 __kmp_test_then_and32(volatile kmp_uint32 *p, kmp_uint32 d) {63 kmp_uint32 old_value, new_value;64 65 old_value = TCR_4(*p);66 new_value = old_value & d;67 68 while (!KMP_COMPARE_AND_STORE_REL32((volatile kmp_int32 *)p, old_value,69 new_value)) {70 KMP_CPU_PAUSE();71 old_value = TCR_4(*p);72 new_value = old_value & d;73 }74 return old_value;75}76 77#if KMP_ARCH_X86 || KMP_ARCH_X86_6478kmp_int8 __kmp_test_then_add8(volatile kmp_int8 *p, kmp_int8 d) {79 kmp_int64 old_value, new_value;80 81 old_value = TCR_1(*p);82 new_value = old_value + d;83 while (!__kmp_compare_and_store8(p, old_value, new_value)) {84 KMP_CPU_PAUSE();85 old_value = TCR_1(*p);86 new_value = old_value + d;87 }88 return old_value;89}90 91#if KMP_ARCH_X8692kmp_int64 __kmp_test_then_add64(volatile kmp_int64 *p, kmp_int64 d) {93 kmp_int64 old_value, new_value;94 95 old_value = TCR_8(*p);96 new_value = old_value + d;97 while (!__kmp_compare_and_store64(p, old_value, new_value)) {98 KMP_CPU_PAUSE();99 old_value = TCR_8(*p);100 new_value = old_value + d;101 }102 return old_value;103}104#endif /* KMP_ARCH_X86 */105#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */106 107kmp_uint64 __kmp_test_then_or64(volatile kmp_uint64 *p, kmp_uint64 d) {108 kmp_uint64 old_value, new_value;109 110 old_value = TCR_8(*p);111 new_value = old_value | d;112 while (!KMP_COMPARE_AND_STORE_REL64((volatile kmp_int64 *)p, old_value,113 new_value)) {114 KMP_CPU_PAUSE();115 old_value = TCR_8(*p);116 new_value = old_value | d;117 }118 119 return old_value;120}121 122kmp_uint64 __kmp_test_then_and64(volatile kmp_uint64 *p, kmp_uint64 d) {123 kmp_uint64 old_value, new_value;124 125 old_value = TCR_8(*p);126 new_value = old_value & d;127 while (!KMP_COMPARE_AND_STORE_REL64((volatile kmp_int64 *)p, old_value,128 new_value)) {129 KMP_CPU_PAUSE();130 old_value = TCR_8(*p);131 new_value = old_value & d;132 }133 134 return old_value;135}136 137#if KMP_ARCH_AARCH64 && KMP_COMPILER_MSVC138// For !KMP_COMPILER_MSVC, this function is provided in assembly form139// by z_Linux_asm.S.140int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,141 void *p_argv[]142#if OMPT_SUPPORT143 ,144 void **exit_frame_ptr145#endif146) {147#if OMPT_SUPPORT148 *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0);149#endif150 151 switch (argc) {152 case 0:153 (*pkfn)(>id, &tid);154 break;155 case 1:156 (*pkfn)(>id, &tid, p_argv[0]);157 break;158 case 2:159 (*pkfn)(>id, &tid, p_argv[0], p_argv[1]);160 break;161 case 3:162 (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2]);163 break;164 case 4:165 (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3]);166 break;167 case 5:168 (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4]);169 break;170 default: {171 // p_argv[6] and onwards must be passed on the stack since 8 registers are172 // already used.173 size_t len = (argc - 6) * sizeof(void *);174 void *argbuf = alloca(len);175 memcpy(argbuf, &p_argv[6], len);176 }177 [[fallthrough]];178 case 6:179 (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],180 p_argv[5]);181 break;182 }183 184#if OMPT_SUPPORT185 *exit_frame_ptr = 0;186#endif187 188 return 1;189}190#endif191 192#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_ARM */193