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) 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 138 int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc, 139 void *p_argv[] 140 #if OMPT_SUPPORT 141 , 142 void **exit_frame_ptr 143 #endif 144 ) { 145 #if OMPT_SUPPORT 146 *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0); 147 #endif 148 149 switch (argc) { 150 case 0: 151 (*pkfn)(>id, &tid); 152 break; 153 case 1: 154 (*pkfn)(>id, &tid, p_argv[0]); 155 break; 156 case 2: 157 (*pkfn)(>id, &tid, p_argv[0], p_argv[1]); 158 break; 159 case 3: 160 (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2]); 161 break; 162 case 4: 163 (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3]); 164 break; 165 case 5: 166 (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4]); 167 break; 168 default: { 169 // p_argv[6] and onwards must be passed on the stack since 8 registers are 170 // already used. 171 size_t len = (argc - 6) * sizeof(void *); 172 void *argbuf = alloca(len); 173 memcpy(argbuf, &p_argv[6], len); 174 } 175 [[fallthrough]]; 176 case 6: 177 (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], 178 p_argv[5]); 179 break; 180 } 181 182 #if OMPT_SUPPORT 183 *exit_frame_ptr = 0; 184 #endif 185 186 return 1; 187 } 188 #endif 189 190 #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 */ 191