diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -2989,6 +2989,15 @@ 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 @@ /* 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; diff --git a/openmp/runtime/src/kmp_global.cpp b/openmp/runtime/src/kmp_global.cpp --- a/openmp/runtime/src/kmp_global.cpp +++ b/openmp/runtime/src/kmp_global.cpp @@ -442,6 +442,7 @@ 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 diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp --- a/openmp/runtime/src/kmp_runtime.cpp +++ b/openmp/runtime/src/kmp_runtime.cpp @@ -3669,11 +3669,16 @@ __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 @@ __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