kmp_taskdeps.h revision 345231
1/* 2 * kmp_taskdeps.h 3 */ 4 5 6//===----------------------------------------------------------------------===// 7// 8// The LLVM Compiler Infrastructure 9// 10// This file is dual licensed under the MIT and the University of Illinois Open 11// Source Licenses. See LICENSE.txt for details. 12// 13//===----------------------------------------------------------------------===// 14 15 16#ifndef KMP_TASKDEPS_H 17#define KMP_TASKDEPS_H 18 19#include "kmp.h" 20 21#if OMP_40_ENABLED 22 23#define KMP_ACQUIRE_DEPNODE(gtid, n) __kmp_acquire_lock(&(n)->dn.lock, (gtid)) 24#define KMP_RELEASE_DEPNODE(gtid, n) __kmp_release_lock(&(n)->dn.lock, (gtid)) 25 26static inline void __kmp_node_deref(kmp_info_t *thread, kmp_depnode_t *node) { 27 if (!node) 28 return; 29 30 kmp_int32 n = KMP_ATOMIC_DEC(&node->dn.nrefs) - 1; 31 if (n == 0) { 32 KMP_ASSERT(node->dn.nrefs == 0); 33#if USE_FAST_MEMORY 34 __kmp_fast_free(thread, node); 35#else 36 __kmp_thread_free(thread, node); 37#endif 38 } 39} 40 41static inline void __kmp_depnode_list_free(kmp_info_t *thread, 42 kmp_depnode_list *list) { 43 kmp_depnode_list *next; 44 45 for (; list; list = next) { 46 next = list->next; 47 48 __kmp_node_deref(thread, list->node); 49#if USE_FAST_MEMORY 50 __kmp_fast_free(thread, list); 51#else 52 __kmp_thread_free(thread, list); 53#endif 54 } 55} 56 57static inline void __kmp_dephash_free_entries(kmp_info_t *thread, 58 kmp_dephash_t *h) { 59 for (size_t i = 0; i < h->size; i++) { 60 if (h->buckets[i]) { 61 kmp_dephash_entry_t *next; 62 for (kmp_dephash_entry_t *entry = h->buckets[i]; entry; entry = next) { 63 next = entry->next_in_bucket; 64 __kmp_depnode_list_free(thread, entry->last_ins); 65 __kmp_depnode_list_free(thread, entry->last_mtxs); 66 __kmp_node_deref(thread, entry->last_out); 67 if (entry->mtx_lock) { 68 __kmp_destroy_lock(entry->mtx_lock); 69 __kmp_free(entry->mtx_lock); 70 } 71#if USE_FAST_MEMORY 72 __kmp_fast_free(thread, entry); 73#else 74 __kmp_thread_free(thread, entry); 75#endif 76 } 77 h->buckets[i] = 0; 78 } 79 } 80} 81 82static inline void __kmp_dephash_free(kmp_info_t *thread, kmp_dephash_t *h) { 83 __kmp_dephash_free_entries(thread, h); 84#if USE_FAST_MEMORY 85 __kmp_fast_free(thread, h); 86#else 87 __kmp_thread_free(thread, h); 88#endif 89} 90 91static inline void __kmp_release_deps(kmp_int32 gtid, kmp_taskdata_t *task) { 92 kmp_info_t *thread = __kmp_threads[gtid]; 93 kmp_depnode_t *node = task->td_depnode; 94 95 if (task->td_dephash) { 96 KA_TRACE( 97 40, ("__kmp_release_deps: T#%d freeing dependencies hash of task %p.\n", 98 gtid, task)); 99 __kmp_dephash_free(thread, task->td_dephash); 100 task->td_dephash = NULL; 101 } 102 103 if (!node) 104 return; 105 106 KA_TRACE(20, ("__kmp_release_deps: T#%d notifying successors of task %p.\n", 107 gtid, task)); 108 109 KMP_ACQUIRE_DEPNODE(gtid, node); 110 node->dn.task = 111 NULL; // mark this task as finished, so no new dependencies are generated 112 KMP_RELEASE_DEPNODE(gtid, node); 113 114 kmp_depnode_list_t *next; 115 for (kmp_depnode_list_t *p = node->dn.successors; p; p = next) { 116 kmp_depnode_t *successor = p->node; 117 kmp_int32 npredecessors = KMP_ATOMIC_DEC(&successor->dn.npredecessors) - 1; 118 119 // successor task can be NULL for wait_depends or because deps are still 120 // being processed 121 if (npredecessors == 0) { 122 KMP_MB(); 123 if (successor->dn.task) { 124 KA_TRACE(20, ("__kmp_release_deps: T#%d successor %p of %p scheduled " 125 "for execution.\n", 126 gtid, successor->dn.task, task)); 127 __kmp_omp_task(gtid, successor->dn.task, false); 128 } 129 } 130 131 next = p->next; 132 __kmp_node_deref(thread, p->node); 133#if USE_FAST_MEMORY 134 __kmp_fast_free(thread, p); 135#else 136 __kmp_thread_free(thread, p); 137#endif 138 } 139 140 __kmp_node_deref(thread, node); 141 142 KA_TRACE( 143 20, 144 ("__kmp_release_deps: T#%d all successors of %p notified of completion\n", 145 gtid, task)); 146} 147 148#endif // OMP_40_ENABLED 149 150#endif // KMP_TASKDEPS_H 151