kmp_taskdeps.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * kmp_taskdeps.h
  3. */
  4. //===----------------------------------------------------------------------===//
  5. //
  6. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  7. // See https://llvm.org/LICENSE.txt for license information.
  8. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  9. //
  10. //===----------------------------------------------------------------------===//
  11. #ifndef KMP_TASKDEPS_H
  12. #define KMP_TASKDEPS_H
  13. #include "kmp.h"
  14. #define KMP_ACQUIRE_DEPNODE(gtid, n) __kmp_acquire_lock(&(n)->dn.lock, (gtid))
  15. #define KMP_RELEASE_DEPNODE(gtid, n) __kmp_release_lock(&(n)->dn.lock, (gtid))
  16. static inline void __kmp_node_deref(kmp_info_t *thread, kmp_depnode_t *node) {
  17. if (!node)
  18. return;
  19. kmp_int32 n = KMP_ATOMIC_DEC(&node->dn.nrefs) - 1;
  20. KMP_DEBUG_ASSERT(n >= 0);
  21. if (n == 0) {
  22. #if USE_ITT_BUILD && USE_ITT_NOTIFY
  23. __itt_sync_destroy(node);
  24. #endif
  25. KMP_ASSERT(node->dn.nrefs == 0);
  26. #if USE_FAST_MEMORY
  27. __kmp_fast_free(thread, node);
  28. #else
  29. __kmp_thread_free(thread, node);
  30. #endif
  31. }
  32. }
  33. static inline void __kmp_depnode_list_free(kmp_info_t *thread,
  34. kmp_depnode_list *list) {
  35. kmp_depnode_list *next;
  36. for (; list; list = next) {
  37. next = list->next;
  38. __kmp_node_deref(thread, list->node);
  39. #if USE_FAST_MEMORY
  40. __kmp_fast_free(thread, list);
  41. #else
  42. __kmp_thread_free(thread, list);
  43. #endif
  44. }
  45. }
  46. static inline void __kmp_dephash_free_entries(kmp_info_t *thread,
  47. kmp_dephash_t *h) {
  48. for (size_t i = 0; i < h->size; i++) {
  49. if (h->buckets[i]) {
  50. kmp_dephash_entry_t *next;
  51. for (kmp_dephash_entry_t *entry = h->buckets[i]; entry; entry = next) {
  52. next = entry->next_in_bucket;
  53. __kmp_depnode_list_free(thread, entry->last_set);
  54. __kmp_depnode_list_free(thread, entry->prev_set);
  55. __kmp_node_deref(thread, entry->last_out);
  56. if (entry->mtx_lock) {
  57. __kmp_destroy_lock(entry->mtx_lock);
  58. __kmp_free(entry->mtx_lock);
  59. }
  60. #if USE_FAST_MEMORY
  61. __kmp_fast_free(thread, entry);
  62. #else
  63. __kmp_thread_free(thread, entry);
  64. #endif
  65. }
  66. h->buckets[i] = 0;
  67. }
  68. }
  69. __kmp_node_deref(thread, h->last_all);
  70. h->last_all = NULL;
  71. }
  72. static inline void __kmp_dephash_free(kmp_info_t *thread, kmp_dephash_t *h) {
  73. __kmp_dephash_free_entries(thread, h);
  74. #if USE_FAST_MEMORY
  75. __kmp_fast_free(thread, h);
  76. #else
  77. __kmp_thread_free(thread, h);
  78. #endif
  79. }
  80. extern void __kmpc_give_task(kmp_task_t *ptask, kmp_int32 start);
  81. static inline void __kmp_release_deps(kmp_int32 gtid, kmp_taskdata_t *task) {
  82. kmp_info_t *thread = __kmp_threads[gtid];
  83. kmp_depnode_t *node = task->td_depnode;
  84. // Check mutexinoutset dependencies, release locks
  85. if (UNLIKELY(node && (node->dn.mtx_num_locks < 0))) {
  86. // negative num_locks means all locks were acquired
  87. node->dn.mtx_num_locks = -node->dn.mtx_num_locks;
  88. for (int i = node->dn.mtx_num_locks - 1; i >= 0; --i) {
  89. KMP_DEBUG_ASSERT(node->dn.mtx_locks[i] != NULL);
  90. __kmp_release_lock(node->dn.mtx_locks[i], gtid);
  91. }
  92. }
  93. if (task->td_dephash) {
  94. KA_TRACE(
  95. 40, ("__kmp_release_deps: T#%d freeing dependencies hash of task %p.\n",
  96. gtid, task));
  97. __kmp_dephash_free(thread, task->td_dephash);
  98. task->td_dephash = NULL;
  99. }
  100. if (!node)
  101. return;
  102. KA_TRACE(20, ("__kmp_release_deps: T#%d notifying successors of task %p.\n",
  103. gtid, task));
  104. KMP_ACQUIRE_DEPNODE(gtid, node);
  105. node->dn.task =
  106. NULL; // mark this task as finished, so no new dependencies are generated
  107. KMP_RELEASE_DEPNODE(gtid, node);
  108. kmp_depnode_list_t *next;
  109. kmp_taskdata_t *next_taskdata;
  110. for (kmp_depnode_list_t *p = node->dn.successors; p; p = next) {
  111. kmp_depnode_t *successor = p->node;
  112. #if USE_ITT_BUILD && USE_ITT_NOTIFY
  113. __itt_sync_releasing(successor);
  114. #endif
  115. kmp_int32 npredecessors = KMP_ATOMIC_DEC(&successor->dn.npredecessors) - 1;
  116. // successor task can be NULL for wait_depends or because deps are still
  117. // being processed
  118. if (npredecessors == 0) {
  119. #if USE_ITT_BUILD && USE_ITT_NOTIFY
  120. __itt_sync_acquired(successor);
  121. #endif
  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. // If a regular task depending on a hidden helper task, when the
  128. // hidden helper task is done, the regular task should be executed by
  129. // its encountering team.
  130. if (KMP_HIDDEN_HELPER_THREAD(gtid)) {
  131. // Hidden helper thread can only execute hidden helper tasks
  132. KMP_ASSERT(task->td_flags.hidden_helper);
  133. next_taskdata = KMP_TASK_TO_TASKDATA(successor->dn.task);
  134. // If the dependent task is a regular task, we need to push to its
  135. // encountering thread's queue; otherwise, it can be pushed to its own
  136. // queue.
  137. if (!next_taskdata->td_flags.hidden_helper) {
  138. kmp_int32 encountering_gtid =
  139. next_taskdata->td_alloc_thread->th.th_info.ds.ds_gtid;
  140. kmp_int32 encountering_tid = __kmp_tid_from_gtid(encountering_gtid);
  141. __kmpc_give_task(successor->dn.task, encountering_tid);
  142. } else {
  143. __kmp_omp_task(gtid, successor->dn.task, false);
  144. }
  145. } else {
  146. __kmp_omp_task(gtid, successor->dn.task, false);
  147. }
  148. }
  149. }
  150. next = p->next;
  151. __kmp_node_deref(thread, p->node);
  152. #if USE_FAST_MEMORY
  153. __kmp_fast_free(thread, p);
  154. #else
  155. __kmp_thread_free(thread, p);
  156. #endif
  157. }
  158. __kmp_node_deref(thread, node);
  159. KA_TRACE(
  160. 20,
  161. ("__kmp_release_deps: T#%d all successors of %p notified of completion\n",
  162. gtid, task));
  163. }
  164. #endif // KMP_TASKDEPS_H