/* * kmp_threadprivate.cpp -- OpenMP threadprivate support library */ //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "kmp.h" #include "kmp_i18n.h" #include "kmp_itt.h" #define USE_CHECKS_COMMON #define KMP_INLINE_SUBR … void kmp_threadprivate_insert_private_data(int gtid, void *pc_addr, void *data_addr, size_t pc_size); struct private_common *kmp_threadprivate_insert(int gtid, void *pc_addr, void *data_addr, size_t pc_size); struct shared_table __kmp_threadprivate_d_table; static #ifdef KMP_INLINE_SUBR __forceinline #endif struct private_common * __kmp_threadprivate_find_task_common(struct common_table *tbl, int gtid, void *pc_addr) { … } static #ifdef KMP_INLINE_SUBR __forceinline #endif struct shared_common * __kmp_find_shared_task_common(struct shared_table *tbl, int gtid, void *pc_addr) { … } // Create a template for the data initialized storage. Either the template is // NULL indicating zero fill, or the template is a copy of the original data. static struct private_data *__kmp_init_common_data(void *pc_addr, size_t pc_size) { … } // Initialize the data area from the template. static void __kmp_copy_common_data(void *pc_addr, struct private_data *d) { … } /* we are called from __kmp_serial_initialize() with __kmp_initz_lock held. */ void __kmp_common_initialize(void) { … } /* Call all destructors for threadprivate data belonging to all threads. Currently unused! */ void __kmp_common_destroy(void) { … } /* Call all destructors for threadprivate data belonging to this thread */ void __kmp_common_destroy_gtid(int gtid) { … } #ifdef KMP_TASK_COMMON_DEBUG static void dump_list(void) { int p, q; for (p = 0; p < __kmp_all_nth; ++p) { if (!__kmp_threads[p]) continue; for (q = 0; q < KMP_HASH_TABLE_SIZE; ++q) { if (__kmp_threads[p]->th.th_pri_common->data[q]) { struct private_common *tn; KC_TRACE(10, ("\tdump_list: gtid:%d addresses\n", p)); for (tn = __kmp_threads[p]->th.th_pri_common->data[q]; tn; tn = tn->next) { KC_TRACE(10, ("\tdump_list: THREADPRIVATE: Serial %p -> Parallel %p\n", tn->gbl_addr, tn->par_addr)); } } } } } #endif /* KMP_TASK_COMMON_DEBUG */ // NOTE: this routine is to be called only from the serial part of the program. void kmp_threadprivate_insert_private_data(int gtid, void *pc_addr, void *data_addr, size_t pc_size) { … } struct private_common *kmp_threadprivate_insert(int gtid, void *pc_addr, void *data_addr, size_t pc_size) { … } /* ------------------------------------------------------------------------ */ /* We are currently parallel, and we know the thread id. */ /* ------------------------------------------------------------------------ */ /*! @ingroup THREADPRIVATE @param loc source location information @param data pointer to data being privatized @param ctor pointer to constructor function for data @param cctor pointer to copy constructor function for data @param dtor pointer to destructor function for data Register constructors and destructors for thread private data. This function is called when executing in parallel, when we know the thread id. */ void __kmpc_threadprivate_register(ident_t *loc, void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor) { … } void *__kmpc_threadprivate(ident_t *loc, kmp_int32 global_tid, void *data, size_t size) { … } static kmp_cached_addr_t *__kmp_find_cache(void *data) { … } /*! @ingroup THREADPRIVATE @param loc source location information @param global_tid global thread number @param data pointer to data to privatize @param size size of data to privatize @param cache pointer to cache @return pointer to private storage Allocate private storage for threadprivate data. */ void * __kmpc_threadprivate_cached(ident_t *loc, kmp_int32 global_tid, // gtid. void *data, // Pointer to original global variable. size_t size, // Size of original global variable. void ***cache) { … } // This function should only be called when both __kmp_tp_cached_lock and // kmp_forkjoin_lock are held. void __kmp_threadprivate_resize_cache(int newCapacity) { … } /*! @ingroup THREADPRIVATE @param loc source location information @param data pointer to data being privatized @param ctor pointer to constructor function for data @param cctor pointer to copy constructor function for data @param dtor pointer to destructor function for data @param vector_length length of the vector (bytes or elements?) Register vector constructors and destructors for thread private data. */ void __kmpc_threadprivate_register_vec(ident_t *loc, void *data, kmpc_ctor_vec ctor, kmpc_cctor_vec cctor, kmpc_dtor_vec dtor, size_t vector_length) { … } void __kmp_cleanup_threadprivate_caches() { … }