/* Call all destructors for threadprivate data belonging to all threads. Currently unused! */ void __kmp_common_destroy( void ) { if( TCR_4(__kmp_init_common) ) { int q; TCW_4(__kmp_init_common, FALSE); for (q = 0; q < KMP_HASH_TABLE_SIZE; ++q) { int gtid; struct private_common *tn; struct shared_common *d_tn; /* C++ destructors need to be called once per thread before exiting */ /* don't call destructors for master thread though unless we used copy constructor */ for (d_tn = __kmp_threadprivate_d_table.data[ q ]; d_tn; d_tn = d_tn->next) { if (d_tn->is_vec) { if (d_tn->dt.dtorv != 0) { for (gtid = 0; gtid < __kmp_all_nth; ++gtid) { if( __kmp_threads[gtid] ) { if( (__kmp_foreign_tp) ? (! KMP_INITIAL_GTID (gtid)) : (! KMP_UBER_GTID (gtid)) ) { tn = __kmp_threadprivate_find_task_common( __kmp_threads[ gtid ]->th.th_pri_common, gtid, d_tn->gbl_addr ); if (tn) { (*d_tn->dt.dtorv) (tn->par_addr, d_tn->vec_len); } } } } if (d_tn->obj_init != 0) { (*d_tn->dt.dtorv) (d_tn->obj_init, d_tn->vec_len); } } } else { if (d_tn->dt.dtor != 0) { for (gtid = 0; gtid < __kmp_all_nth; ++gtid) { if( __kmp_threads[gtid] ) { if( (__kmp_foreign_tp) ? (! KMP_INITIAL_GTID (gtid)) : (! KMP_UBER_GTID (gtid)) ) { tn = __kmp_threadprivate_find_task_common( __kmp_threads[ gtid ]->th.th_pri_common, gtid, d_tn->gbl_addr ); if (tn) { (*d_tn->dt.dtor) (tn->par_addr); } } } } if (d_tn->obj_init != 0) { (*d_tn->dt.dtor) (d_tn->obj_init); } } } } __kmp_threadprivate_d_table.data[ q ] = 0; } } }
void __ompt_init_internal() { if (ompt_status & ompt_status_track) { // initialize initial thread for OMPT kmp_info_t *root_thread = ompt_get_thread(); __kmp_task_init_ompt( root_thread->th.th_team->t.t_implicit_task_taskdata, 0); __kmp_task_init_ompt( root_thread->th.th_serial_team->t.t_implicit_task_taskdata, 0); // make mandatory callback for creation of initial thread // this needs to occur here rather than in __kmp_register_root because // __kmp_register_root is called before ompt_initialize int gtid = __kmp_get_gtid(); if (KMP_UBER_GTID(gtid)) { // initialize the initial thread's idle frame and state root_thread->th.ompt_thread_info.idle_frame = 0; root_thread->th.ompt_thread_info.state = ompt_state_overhead; if ((ompt_status == ompt_status_track_callback) && ompt_callbacks.ompt_callback(ompt_event_thread_begin)) { __ompt_thread_begin(ompt_thread_initial, gtid); } root_thread->th.ompt_thread_info.state = ompt_state_work_serial; } } }
/* Call all destructors for threadprivate data belonging to this thread */ void __kmp_common_destroy_gtid( int gtid ) { struct private_common *tn; struct shared_common *d_tn; KC_TRACE( 10, ("__kmp_common_destroy_gtid: T#%d called\n", gtid ) ); if( (__kmp_foreign_tp) ? (! KMP_INITIAL_GTID (gtid)) : (! KMP_UBER_GTID (gtid)) ) { if( TCR_4(__kmp_init_common) ) { #if KMP_THREADPRIVATE_TLS for(d_tn = kmpc_threadprivate_d_table_data_head_local; d_tn != NULL; d_tn = d_tn->next) { // call destructor if (d_tn->dt.dtor) d_tn->dt.dtor(NULL); } #else /* Cannot do this here since not all threads have destroyed their data */ /* TCW_4(__kmp_init_common, FALSE); */ for (tn = __kmp_threads[ gtid ]->th.th_pri_head; tn; tn = tn->link) { d_tn = __kmp_find_shared_task_common( &__kmp_threadprivate_d_table, gtid, tn->gbl_addr ); KMP_DEBUG_ASSERT( d_tn ); if (d_tn->is_vec) { if (d_tn->dt.dtorv != 0) { (void) (*d_tn->dt.dtorv) (tn->par_addr, d_tn->vec_len); } if (d_tn->obj_init != 0) { (void) (*d_tn->dt.dtorv) (d_tn->obj_init, d_tn->vec_len); } } else { if (d_tn->dt.dtor != 0) { (void) (*d_tn->dt.dtor) (tn->par_addr); } if (d_tn->obj_init != 0) { (void) (*d_tn->dt.dtor) (d_tn->obj_init); } } } #endif KC_TRACE( 30, ("__kmp_common_destroy_gtid: T#%d threadprivate destructors complete\n", gtid ) ); } } }
struct private_common * kmp_threadprivate_insert( int gtid, void *pc_addr, void *data_addr, size_t pc_size ) { struct private_common *tn, **tt; struct shared_common *d_tn; /* +++++++++ START OF CRITICAL SECTION +++++++++ */ __kmp_acquire_lock( & __kmp_global_lock, gtid ); tn = (struct private_common *) __kmp_allocate( sizeof (struct private_common) ); tn->gbl_addr = pc_addr; d_tn = __kmp_find_shared_task_common( &__kmp_threadprivate_d_table, gtid, pc_addr ); /* Only the MASTER data table exists. */ if (d_tn != 0) { /* This threadprivate variable has already been seen. */ if ( d_tn->pod_init == 0 && d_tn->obj_init == 0 ) { d_tn->cmn_size = pc_size; if (d_tn->is_vec) { if (d_tn->ct.ctorv != 0) { /* Construct from scratch so no prototype exists */ d_tn->obj_init = 0; } else if (d_tn->cct.cctorv != 0) { /* Now data initialize the prototype since it was previously registered */ d_tn->obj_init = (void *) __kmp_allocate( d_tn->cmn_size ); (void) (*d_tn->cct.cctorv) (d_tn->obj_init, pc_addr, d_tn->vec_len); } else { d_tn->pod_init = __kmp_init_common_data( data_addr, d_tn->cmn_size ); } } else { if (d_tn->ct.ctor != 0) { /* Construct from scratch so no prototype exists */ d_tn->obj_init = 0; } else if (d_tn->cct.cctor != 0) { /* Now data initialize the prototype since it was previously registered */ d_tn->obj_init = (void *) __kmp_allocate( d_tn->cmn_size ); (void) (*d_tn->cct.cctor) (d_tn->obj_init, pc_addr); } else { d_tn->pod_init = __kmp_init_common_data( data_addr, d_tn->cmn_size ); } } } } else { struct shared_common **lnk_tn; d_tn = (struct shared_common *) __kmp_allocate( sizeof( struct shared_common ) ); d_tn->gbl_addr = pc_addr; d_tn->cmn_size = pc_size; d_tn->pod_init = __kmp_init_common_data( data_addr, pc_size ); /* d_tn->obj_init = 0; // AC: commented out because __kmp_allocate zeroes the memory d_tn->ct.ctor = 0; d_tn->cct.cctor = 0; d_tn->dt.dtor = 0; d_tn->is_vec = FALSE; d_tn->vec_len = 0L; */ lnk_tn = &(__kmp_threadprivate_d_table.data[ KMP_HASH(pc_addr) ]); d_tn->next = *lnk_tn; *lnk_tn = d_tn; } tn->cmn_size = d_tn->cmn_size; if ( (__kmp_foreign_tp) ? (KMP_INITIAL_GTID (gtid)) : (KMP_UBER_GTID (gtid)) ) { tn->par_addr = (void *) pc_addr; } else { tn->par_addr = (void *) __kmp_allocate( tn->cmn_size ); } __kmp_release_lock( & __kmp_global_lock, gtid ); /* +++++++++ END OF CRITICAL SECTION +++++++++ */ #ifdef USE_CHECKS_COMMON if (pc_size > d_tn->cmn_size) { KC_TRACE( 10, ( "__kmp_threadprivate_insert: THREADPRIVATE: %p (%" KMP_UINTPTR_SPEC " ,%" KMP_UINTPTR_SPEC ")\n", pc_addr, pc_size, d_tn->cmn_size ) ); KMP_FATAL( TPCommonBlocksInconsist ); } #endif /* USE_CHECKS_COMMON */ tt = &(__kmp_threads[ gtid ]->th.th_pri_common->data[ KMP_HASH(pc_addr) ]); #ifdef KMP_TASK_COMMON_DEBUG if (*tt != 0) { KC_TRACE( 10, ( "__kmp_threadprivate_insert: WARNING! thread#%d: collision on %p\n", gtid, pc_addr ) ); } #endif tn->next = *tt; *tt = tn; #ifdef KMP_TASK_COMMON_DEBUG KC_TRACE( 10, ( "__kmp_threadprivate_insert: thread#%d, inserted node %p on list\n", gtid, pc_addr ) ); dump_list( ); #endif /* Link the node into a simple list */ tn->link = __kmp_threads[ gtid ]->th.th_pri_head; __kmp_threads[ gtid ]->th.th_pri_head = tn; #ifdef BUILD_TV __kmp_tv_threadprivate_store( __kmp_threads[ gtid ], tn->gbl_addr, tn->par_addr ); #endif if( (__kmp_foreign_tp) ? (KMP_INITIAL_GTID (gtid)) : (KMP_UBER_GTID (gtid)) ) return tn; /* * if C++ object with copy constructor, use it; * else if C++ object with constructor, use it for the non-master copies only; * else use pod_init and memcpy * * C++ constructors need to be called once for each non-master thread on allocate * C++ copy constructors need to be called once for each thread on allocate */ /* * C++ object with constructors/destructors; * don't call constructors for master thread though */ if (d_tn->is_vec) { if ( d_tn->ct.ctorv != 0) { (void) (*d_tn->ct.ctorv) (tn->par_addr, d_tn->vec_len); } else if (d_tn->cct.cctorv != 0) { (void) (*d_tn->cct.cctorv) (tn->par_addr, d_tn->obj_init, d_tn->vec_len); } else if (tn->par_addr != tn->gbl_addr) { __kmp_copy_common_data( tn->par_addr, d_tn->pod_init ); } } else { if ( d_tn->ct.ctor != 0 ) { (void) (*d_tn->ct.ctor) (tn->par_addr); } else if (d_tn->cct.cctor != 0) { (void) (*d_tn->cct.cctor) (tn->par_addr, d_tn->obj_init); } else if (tn->par_addr != tn->gbl_addr) { __kmp_copy_common_data( tn->par_addr, d_tn->pod_init ); } } /* !BUILD_OPENMP_C if (tn->par_addr != tn->gbl_addr) __kmp_copy_common_data( tn->par_addr, d_tn->pod_init ); */ return tn; }