Skip to content

Commit b7b4986

Browse files
committed
[OpenMP][libomp] Hold old __kmp_threads arrays until library shutdown
When many nested teams are formed, __kmp_threads may be reallocated to accommodate new threads. This reallocation causes a data race when another existing team's thread simultaneously references __kmp_threads. This patch keeps the old thread arrays around until library shutdown so these lingering references can complete without issue and access to __kmp_threads remains a simple array reference. Fixes: #54708 Differential Revision: https://reviews.llvm.org/D125013
1 parent 1061511 commit b7b4986

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

openmp/runtime/src/kmp.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2989,6 +2989,15 @@ struct fortran_inx_info {
29892989
kmp_int32 data;
29902990
};
29912991

2992+
// This list type exists to hold old __kmp_threads arrays so that
2993+
// old references to them may complete while reallocation takes place when
2994+
// expanding the array. The items in this list are kept alive until library
2995+
// shutdown.
2996+
typedef struct kmp_old_threads_list_t {
2997+
kmp_info_t **threads;
2998+
struct kmp_old_threads_list_t *next;
2999+
} kmp_old_threads_list_t;
3000+
29923001
/* ------------------------------------------------------------------------ */
29933002

29943003
extern int __kmp_settings;
@@ -3270,6 +3279,8 @@ extern int __kmp_teams_thread_limit;
32703279
/* the following are protected by the fork/join lock */
32713280
/* write: lock read: anytime */
32723281
extern kmp_info_t **__kmp_threads; /* Descriptors for the threads */
3282+
/* Holds old arrays of __kmp_threads until library shutdown */
3283+
extern kmp_old_threads_list_t *__kmp_old_threads_list;
32733284
/* read/write: lock */
32743285
extern volatile kmp_team_t *__kmp_team_pool;
32753286
extern volatile kmp_info_t *__kmp_thread_pool;

openmp/runtime/src/kmp_global.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ kmp_uint64 __kmp_pause_init = 1; // for tpause
442442
KMP_ALIGN_CACHE
443443
kmp_info_t **__kmp_threads = NULL;
444444
kmp_root_t **__kmp_root = NULL;
445+
kmp_old_threads_list_t *__kmp_old_threads_list = NULL;
445446

446447
/* data read/written to often by primary threads */
447448
KMP_ALIGN_CACHE

openmp/runtime/src/kmp_runtime.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3669,11 +3669,16 @@ static int __kmp_expand_threads(int nNeed) {
36693669
__kmp_threads_capacity * sizeof(kmp_info_t *));
36703670
KMP_MEMCPY(newRoot, __kmp_root,
36713671
__kmp_threads_capacity * sizeof(kmp_root_t *));
3672+
// Put old __kmp_threads array on a list. Any ongoing references to the old
3673+
// list will be valid. This list is cleaned up at library shutdown.
3674+
kmp_old_threads_list_t *node =
3675+
(kmp_old_threads_list_t *)__kmp_allocate(sizeof(kmp_old_threads_list_t));
3676+
node->threads = __kmp_threads;
3677+
node->next = __kmp_old_threads_list;
3678+
__kmp_old_threads_list = node;
36723679

3673-
kmp_info_t **temp_threads = __kmp_threads;
36743680
*(kmp_info_t * *volatile *)&__kmp_threads = newThreads;
36753681
*(kmp_root_t * *volatile *)&__kmp_root = newRoot;
3676-
__kmp_free(temp_threads);
36773682
added += newCapacity - __kmp_threads_capacity;
36783683
*(volatile int *)&__kmp_threads_capacity = newCapacity;
36793684

@@ -8101,6 +8106,15 @@ void __kmp_cleanup(void) {
81018106
__kmp_root = NULL;
81028107
__kmp_threads_capacity = 0;
81038108

8109+
// Free old __kmp_threads arrays if they exist.
8110+
kmp_old_threads_list_t *ptr = __kmp_old_threads_list;
8111+
while (ptr) {
8112+
kmp_old_threads_list_t *next = ptr->next;
8113+
__kmp_free(ptr->threads);
8114+
__kmp_free(ptr);
8115+
ptr = next;
8116+
}
8117+
81048118
#if KMP_USE_DYNAMIC_LOCK
81058119
__kmp_cleanup_indirect_user_locks();
81068120
#else

0 commit comments

Comments
 (0)