Skip to content

Commit ac97562

Browse files
authored
[OpenMP][AIX]Define struct kmp_base_tas_lock with the order of two members swapped for big-endian (#79188)
The direct lock data structure has bit `0` (the least significant bit) of the first 32-bit word set to `1` to indicate it is a direct lock. On the other hand, the first word (in 32-bit mode) or first two words (in 64-bit mode) of an indirect lock are the address of the entry allocated from the indirect lock table. The runtime checks bit `0` of the first 32-bit word to tell if this is a direct or an indirect lock. This works fine for 32-bit and 64-bit little-endian because its memory layout of a 64-bit address is (`low word`, `high word`). However, this causes problems for big-endian where the memory layout of a 64-bit address is (`high word`, `low word`). If an address of the indirect lock table entry is something like `0x110035300`, i.e., (`0x1`, `0x10035300`), it is treated as a direct lock. This patch defines `struct kmp_base_tas_lock` with the ordering of the two 32-bit members flipped for big-endian PPC64 so that when checking/setting tags in member `poll`, the second word (the low word) is used. This patch also changes places where `poll` is not already explicitly specified for checking/setting tags.
1 parent ec0aa16 commit ac97562

File tree

4 files changed

+20
-10
lines changed

4 files changed

+20
-10
lines changed

openmp/runtime/src/kmp_csupport.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -1533,8 +1533,9 @@ void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
15331533
kmp_dyna_lockseq_t lockseq = __kmp_map_hint_to_lock(hint);
15341534
if (*lk == 0) {
15351535
if (KMP_IS_D_LOCK(lockseq)) {
1536-
KMP_COMPARE_AND_STORE_ACQ32((volatile kmp_int32 *)crit, 0,
1537-
KMP_GET_D_TAG(lockseq));
1536+
KMP_COMPARE_AND_STORE_ACQ32(
1537+
(volatile kmp_int32 *)&((kmp_base_tas_lock_t *)crit)->poll, 0,
1538+
KMP_GET_D_TAG(lockseq));
15381539
} else {
15391540
__kmp_init_indirect_csptr(crit, loc, global_tid, KMP_GET_I_TAG(lockseq));
15401541
}

openmp/runtime/src/kmp_gsupport.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_BARRIER)(void) {
144144

145145
// Mutual exclusion
146146

147-
// The symbol that icc/ifort generates for unnamed for unnamed critical sections
147+
// The symbol that icc/ifort generates for unnamed critical sections
148148
// - .gomp_critical_user_ - is defined using .comm in any objects reference it.
149149
// We can't reference it directly here in C code, as the symbol contains a ".".
150150
//

openmp/runtime/src/kmp_lock.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -2689,7 +2689,7 @@ void __kmp_spin_backoff(kmp_backoff_t *boff) {
26892689
// lock word.
26902690
static void __kmp_init_direct_lock(kmp_dyna_lock_t *lck,
26912691
kmp_dyna_lockseq_t seq) {
2692-
TCW_4(*lck, KMP_GET_D_TAG(seq));
2692+
TCW_4(((kmp_base_tas_lock_t *)lck)->poll, KMP_GET_D_TAG(seq));
26932693
KA_TRACE(
26942694
20,
26952695
("__kmp_init_direct_lock: initialized direct lock with type#%d\n", seq));
@@ -3180,8 +3180,8 @@ kmp_indirect_lock_t *__kmp_allocate_indirect_lock(void **user_lock,
31803180
lck->type = tag;
31813181

31823182
if (OMP_LOCK_T_SIZE < sizeof(void *)) {
3183-
*((kmp_lock_index_t *)user_lock) = idx
3184-
<< 1; // indirect lock word must be even
3183+
*(kmp_lock_index_t *)&(((kmp_base_tas_lock_t *)user_lock)->poll) =
3184+
idx << 1; // indirect lock word must be even
31853185
} else {
31863186
*((kmp_indirect_lock_t **)user_lock) = lck;
31873187
}

openmp/runtime/src/kmp_lock.h

+13-4
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ typedef struct ident ident_t;
5050
// recent versions), but we are bounded by the pointer-sized chunks that
5151
// the Intel compiler allocates.
5252

53-
#if KMP_OS_LINUX && defined(KMP_GOMP_COMPAT)
53+
#if (KMP_OS_LINUX || KMP_OS_AIX) && defined(KMP_GOMP_COMPAT)
5454
#define OMP_LOCK_T_SIZE sizeof(int)
5555
#define OMP_NEST_LOCK_T_SIZE sizeof(void *)
5656
#else
@@ -120,8 +120,15 @@ extern void __kmp_validate_locks(void);
120120

121121
struct kmp_base_tas_lock {
122122
// KMP_LOCK_FREE(tas) => unlocked; locked: (gtid+1) of owning thread
123+
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __LP64__
124+
// Flip the ordering of the high and low 32-bit member to be consistent
125+
// with the memory layout of the address in 64-bit big-endian.
126+
kmp_int32 depth_locked; // depth locked, for nested locks only
127+
std::atomic<kmp_int32> poll;
128+
#else
123129
std::atomic<kmp_int32> poll;
124130
kmp_int32 depth_locked; // depth locked, for nested locks only
131+
#endif
125132
};
126133

127134
typedef struct kmp_base_tas_lock kmp_base_tas_lock_t;
@@ -1138,11 +1145,13 @@ extern int (**__kmp_indirect_test)(kmp_user_lock_p, kmp_int32);
11381145

11391146
// Extracts direct lock tag from a user lock pointer
11401147
#define KMP_EXTRACT_D_TAG(l) \
1141-
(*((kmp_dyna_lock_t *)(l)) & ((1 << KMP_LOCK_SHIFT) - 1) & \
1142-
-(*((kmp_dyna_lock_t *)(l)) & 1))
1148+
((kmp_dyna_lock_t)((kmp_base_tas_lock_t *)(l))->poll & \
1149+
((1 << KMP_LOCK_SHIFT) - 1) & \
1150+
-((kmp_dyna_lock_t)((kmp_tas_lock_t *)(l))->lk.poll & 1))
11431151

11441152
// Extracts indirect lock index from a user lock pointer
1145-
#define KMP_EXTRACT_I_INDEX(l) (*(kmp_lock_index_t *)(l) >> 1)
1153+
#define KMP_EXTRACT_I_INDEX(l) \
1154+
((kmp_lock_index_t)((kmp_base_tas_lock_t *)(l))->poll >> 1)
11461155

11471156
// Returns function pointer to the direct lock function with l (kmp_dyna_lock_t
11481157
// *) and op (operation type).

0 commit comments

Comments
 (0)