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