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-exception 10 // 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 to 17 use compare_and_store for these routines */ 18 19 kmp_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 33 kmp_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 47 kmp_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 62 kmp_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_64 78 kmp_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_X86 92 kmp_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 107 kmp_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 122 kmp_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_MSVC 138 // For !KMP_COMPILER_MSVC, this function is provided in assembly form 139 // by z_Linux_asm.S. 140 int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc, 141 void *p_argv[] 142 #if OMPT_SUPPORT 143 , 144 void **exit_frame_ptr 145 #endif 146 ) { 147 #if OMPT_SUPPORT 148 *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0); 149 #endif 150 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 are 172 // 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_SUPPORT 185 *exit_frame_ptr = 0; 186 #endif 187 188 return 1; 189 } 190 #endif 191 192 #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_ARM */ 193