forked from OSchip/llvm-project
[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: https://github.com/llvm/llvm-project/issues/54708 Differential Revision: https://reviews.llvm.org/D125013
This commit is contained in:
parent
1061511008
commit
b7b4986576
|
@ -2989,6 +2989,15 @@ struct fortran_inx_info {
|
|||
kmp_int32 data;
|
||||
};
|
||||
|
||||
// This list type exists to hold old __kmp_threads arrays so that
|
||||
// old references to them may complete while reallocation takes place when
|
||||
// expanding the array. The items in this list are kept alive until library
|
||||
// shutdown.
|
||||
typedef struct kmp_old_threads_list_t {
|
||||
kmp_info_t **threads;
|
||||
struct kmp_old_threads_list_t *next;
|
||||
} kmp_old_threads_list_t;
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
extern int __kmp_settings;
|
||||
|
@ -3270,6 +3279,8 @@ extern int __kmp_teams_thread_limit;
|
|||
/* the following are protected by the fork/join lock */
|
||||
/* write: lock read: anytime */
|
||||
extern kmp_info_t **__kmp_threads; /* Descriptors for the threads */
|
||||
/* Holds old arrays of __kmp_threads until library shutdown */
|
||||
extern kmp_old_threads_list_t *__kmp_old_threads_list;
|
||||
/* read/write: lock */
|
||||
extern volatile kmp_team_t *__kmp_team_pool;
|
||||
extern volatile kmp_info_t *__kmp_thread_pool;
|
||||
|
|
|
@ -442,6 +442,7 @@ kmp_uint64 __kmp_pause_init = 1; // for tpause
|
|||
KMP_ALIGN_CACHE
|
||||
kmp_info_t **__kmp_threads = NULL;
|
||||
kmp_root_t **__kmp_root = NULL;
|
||||
kmp_old_threads_list_t *__kmp_old_threads_list = NULL;
|
||||
|
||||
/* data read/written to often by primary threads */
|
||||
KMP_ALIGN_CACHE
|
||||
|
|
|
@ -3669,11 +3669,16 @@ static int __kmp_expand_threads(int nNeed) {
|
|||
__kmp_threads_capacity * sizeof(kmp_info_t *));
|
||||
KMP_MEMCPY(newRoot, __kmp_root,
|
||||
__kmp_threads_capacity * sizeof(kmp_root_t *));
|
||||
// Put old __kmp_threads array on a list. Any ongoing references to the old
|
||||
// list will be valid. This list is cleaned up at library shutdown.
|
||||
kmp_old_threads_list_t *node =
|
||||
(kmp_old_threads_list_t *)__kmp_allocate(sizeof(kmp_old_threads_list_t));
|
||||
node->threads = __kmp_threads;
|
||||
node->next = __kmp_old_threads_list;
|
||||
__kmp_old_threads_list = node;
|
||||
|
||||
kmp_info_t **temp_threads = __kmp_threads;
|
||||
*(kmp_info_t * *volatile *)&__kmp_threads = newThreads;
|
||||
*(kmp_root_t * *volatile *)&__kmp_root = newRoot;
|
||||
__kmp_free(temp_threads);
|
||||
added += newCapacity - __kmp_threads_capacity;
|
||||
*(volatile int *)&__kmp_threads_capacity = newCapacity;
|
||||
|
||||
|
@ -8101,6 +8106,15 @@ void __kmp_cleanup(void) {
|
|||
__kmp_root = NULL;
|
||||
__kmp_threads_capacity = 0;
|
||||
|
||||
// Free old __kmp_threads arrays if they exist.
|
||||
kmp_old_threads_list_t *ptr = __kmp_old_threads_list;
|
||||
while (ptr) {
|
||||
kmp_old_threads_list_t *next = ptr->next;
|
||||
__kmp_free(ptr->threads);
|
||||
__kmp_free(ptr);
|
||||
ptr = next;
|
||||
}
|
||||
|
||||
#if KMP_USE_DYNAMIC_LOCK
|
||||
__kmp_cleanup_indirect_user_locks();
|
||||
#else
|
||||
|
|
Loading…
Reference in New Issue