blob: f680d1ac97cfa835c16499d71a12219c884174fd [file] [log] [blame]
Jim Cownie181b4bb2013-12-23 17:28:57 +00001
2//===----------------------------------------------------------------------===//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.txt for details.
8//
9//===----------------------------------------------------------------------===//
10
11
12#include "kmp.h"
13#include "kmp_i18n.h"
14#include "kmp_io.h"
15#include "kmp_str.h"
16
17#if OMP_40_ENABLED
18
19/*!
20@ingroup CANCELLATION
21@param loc_ref location of the original task directive
22@param gtid Global thread ID of encountering thread
23@param cncl_kind Cancellation kind (parallel, for, sections, taskgroup)
24
Jonathan Peyton30419822017-05-12 18:01:32 +000025@return returns true if the cancellation request has been activated and the
26execution thread needs to proceed to the end of the canceled region.
Jim Cownie181b4bb2013-12-23 17:28:57 +000027
28Request cancellation of the binding OpenMP region.
29*/
Jonathan Peyton30419822017-05-12 18:01:32 +000030kmp_int32 __kmpc_cancel(ident_t *loc_ref, kmp_int32 gtid, kmp_int32 cncl_kind) {
31 kmp_info_t *this_thr = __kmp_threads[gtid];
Jonathan Peyton61118492016-05-20 19:03:38 +000032
Jonathan Peyton30419822017-05-12 18:01:32 +000033 KC_TRACE(10, ("__kmpc_cancel: T#%d request %d OMP_CANCELLATION=%d\n", gtid,
34 cncl_kind, __kmp_omp_cancellation));
Jim Cownie181b4bb2013-12-23 17:28:57 +000035
Jonathan Peyton30419822017-05-12 18:01:32 +000036 KMP_DEBUG_ASSERT(cncl_kind != cancel_noreq);
37 KMP_DEBUG_ASSERT(cncl_kind == cancel_parallel || cncl_kind == cancel_loop ||
38 cncl_kind == cancel_sections ||
39 cncl_kind == cancel_taskgroup);
40 KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
Jim Cownie181b4bb2013-12-23 17:28:57 +000041
Jonathan Peyton30419822017-05-12 18:01:32 +000042 if (__kmp_omp_cancellation) {
43 switch (cncl_kind) {
44 case cancel_parallel:
45 case cancel_loop:
46 case cancel_sections:
47 // cancellation requests for parallel and worksharing constructs
48 // are handled through the team structure
49 {
50 kmp_team_t *this_team = this_thr->th.th_team;
51 KMP_DEBUG_ASSERT(this_team);
52 kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(
53 &(this_team->t.t_cancel_request), cancel_noreq, cncl_kind);
54 if (old == cancel_noreq || old == cncl_kind) {
55 // printf("__kmpc_cancel: this_team->t.t_cancel_request=%d @ %p\n",
56 // this_team->t.t_cancel_request,
57 // &(this_team->t.t_cancel_request));
58 // we do not have a cancellation request in this team or we do have
59 // one that matches the current request -> cancel
60 return 1 /* true */;
Jim Cownie181b4bb2013-12-23 17:28:57 +000061 }
Jonathan Peyton30419822017-05-12 18:01:32 +000062 break;
63 }
64 case cancel_taskgroup:
65 // cancellation requests for a task group
66 // are handled through the taskgroup structure
67 {
68 kmp_taskdata_t *task;
69 kmp_taskgroup_t *taskgroup;
Jim Cownie181b4bb2013-12-23 17:28:57 +000070
Jonathan Peyton30419822017-05-12 18:01:32 +000071 task = this_thr->th.th_current_task;
72 KMP_DEBUG_ASSERT(task);
73
74 taskgroup = task->td_taskgroup;
75 if (taskgroup) {
76 kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(
77 &(taskgroup->cancel_request), cancel_noreq, cncl_kind);
78 if (old == cancel_noreq || old == cncl_kind) {
79 // we do not have a cancellation request in this taskgroup or we do
80 // have one that matches the current request -> cancel
81 return 1 /* true */;
82 }
83 } else {
84 // TODO: what needs to happen here?
85 // the specification disallows cancellation w/o taskgroups
86 // so we might do anything here, let's abort for now
87 KMP_ASSERT(0 /* false */);
88 }
89 }
90 break;
91 default:
92 KMP_ASSERT(0 /* false */);
93 }
94 }
95
96 // ICV OMP_CANCELLATION=false, so we ignored this cancel request
97 KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
98 return 0 /* false */;
Jim Cownie181b4bb2013-12-23 17:28:57 +000099}
100
101/*!
102@ingroup CANCELLATION
103@param loc_ref location of the original task directive
104@param gtid Global thread ID of encountering thread
105@param cncl_kind Cancellation kind (parallel, for, sections, taskgroup)
106
Jonathan Peyton30419822017-05-12 18:01:32 +0000107@return returns true if a matching cancellation request has been flagged in the
108RTL and the encountering thread has to cancel..
Jim Cownie181b4bb2013-12-23 17:28:57 +0000109
110Cancellation point for the encountering thread.
111*/
Jonathan Peyton30419822017-05-12 18:01:32 +0000112kmp_int32 __kmpc_cancellationpoint(ident_t *loc_ref, kmp_int32 gtid,
113 kmp_int32 cncl_kind) {
114 kmp_info_t *this_thr = __kmp_threads[gtid];
Jim Cownie181b4bb2013-12-23 17:28:57 +0000115
Jonathan Peyton30419822017-05-12 18:01:32 +0000116 KC_TRACE(10,
117 ("__kmpc_cancellationpoint: T#%d request %d OMP_CANCELLATION=%d\n",
118 gtid, cncl_kind, __kmp_omp_cancellation));
Jim Cownie181b4bb2013-12-23 17:28:57 +0000119
Jonathan Peyton30419822017-05-12 18:01:32 +0000120 KMP_DEBUG_ASSERT(cncl_kind != cancel_noreq);
121 KMP_DEBUG_ASSERT(cncl_kind == cancel_parallel || cncl_kind == cancel_loop ||
122 cncl_kind == cancel_sections ||
123 cncl_kind == cancel_taskgroup);
124 KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
Jim Cownie181b4bb2013-12-23 17:28:57 +0000125
Jonathan Peyton30419822017-05-12 18:01:32 +0000126 if (__kmp_omp_cancellation) {
127 switch (cncl_kind) {
128 case cancel_parallel:
129 case cancel_loop:
130 case cancel_sections:
131 // cancellation requests for parallel and worksharing constructs
132 // are handled through the team structure
133 {
134 kmp_team_t *this_team = this_thr->th.th_team;
135 KMP_DEBUG_ASSERT(this_team);
136 if (this_team->t.t_cancel_request) {
137 if (cncl_kind == this_team->t.t_cancel_request) {
138 // the request in the team structure matches the type of
139 // cancellation point so we can cancel
140 return 1 /* true */;
141 }
142 KMP_ASSERT(0 /* false */);
143 } else {
144 // we do not have a cancellation request pending, so we just
145 // ignore this cancellation point
146 return 0;
Jim Cownie181b4bb2013-12-23 17:28:57 +0000147 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000148 break;
149 }
150 case cancel_taskgroup:
151 // cancellation requests for a task group
152 // are handled through the taskgroup structure
153 {
154 kmp_taskdata_t *task;
155 kmp_taskgroup_t *taskgroup;
Jim Cownie181b4bb2013-12-23 17:28:57 +0000156
Jonathan Peyton30419822017-05-12 18:01:32 +0000157 task = this_thr->th.th_current_task;
158 KMP_DEBUG_ASSERT(task);
159
160 taskgroup = task->td_taskgroup;
161 if (taskgroup) {
162 // return the current status of cancellation for the taskgroup
163 return !!taskgroup->cancel_request;
164 } else {
165 // if a cancellation point is encountered by a task that does not
166 // belong to a taskgroup, it is OK to ignore it
167 return 0 /* false */;
168 }
169 }
170 default:
171 KMP_ASSERT(0 /* false */);
172 }
173 }
174
175 // ICV OMP_CANCELLATION=false, so we ignore the cancellation point
176 KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
177 return 0 /* false */;
Jim Cownie181b4bb2013-12-23 17:28:57 +0000178}
179
180/*!
181@ingroup CANCELLATION
182@param loc_ref location of the original task directive
183@param gtid Global thread ID of encountering thread
184
Jonathan Peyton30419822017-05-12 18:01:32 +0000185@return returns true if a matching cancellation request has been flagged in the
186RTL and the encountering thread has to cancel..
Jim Cownie181b4bb2013-12-23 17:28:57 +0000187
188Barrier with cancellation point to send threads from the barrier to the
Jonathan Peyton61118492016-05-20 19:03:38 +0000189end of the parallel region. Needs a special code pattern as documented
Jim Cownie181b4bb2013-12-23 17:28:57 +0000190in the design document for the cancellation feature.
191*/
Jonathan Peyton30419822017-05-12 18:01:32 +0000192kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 gtid) {
193 int ret = 0 /* false */;
194 kmp_info_t *this_thr = __kmp_threads[gtid];
195 kmp_team_t *this_team = this_thr->th.th_team;
Jim Cownie181b4bb2013-12-23 17:28:57 +0000196
Jonathan Peyton30419822017-05-12 18:01:32 +0000197 KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
Jim Cownie181b4bb2013-12-23 17:28:57 +0000198
Jonathan Peyton30419822017-05-12 18:01:32 +0000199 // call into the standard barrier
200 __kmpc_barrier(loc, gtid);
Jim Cownie181b4bb2013-12-23 17:28:57 +0000201
Jonathan Peyton30419822017-05-12 18:01:32 +0000202 // if cancellation is active, check cancellation flag
203 if (__kmp_omp_cancellation) {
204 // depending on which construct to cancel, check the flag and
205 // reset the flag
206 switch (this_team->t.t_cancel_request) {
207 case cancel_parallel:
208 ret = 1;
209 // ensure that threads have checked the flag, when
210 // leaving the above barrier
211 __kmpc_barrier(loc, gtid);
212 this_team->t.t_cancel_request = cancel_noreq;
213 // the next barrier is the fork/join barrier, which
214 // synchronizes the threads leaving here
215 break;
216 case cancel_loop:
217 case cancel_sections:
218 ret = 1;
219 // ensure that threads have checked the flag, when
220 // leaving the above barrier
221 __kmpc_barrier(loc, gtid);
222 this_team->t.t_cancel_request = cancel_noreq;
223 // synchronize the threads again to make sure we do not have any run-away
224 // threads that cause a race on the cancellation flag
225 __kmpc_barrier(loc, gtid);
226 break;
227 case cancel_taskgroup:
228 // this case should not occur
229 KMP_ASSERT(0 /* false */);
230 break;
231 case cancel_noreq:
232 // do nothing
233 break;
234 default:
235 KMP_ASSERT(0 /* false */);
Jim Cownie181b4bb2013-12-23 17:28:57 +0000236 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000237 }
Jonathan Peyton61118492016-05-20 19:03:38 +0000238
Jonathan Peyton30419822017-05-12 18:01:32 +0000239 return ret;
Jim Cownie181b4bb2013-12-23 17:28:57 +0000240}
241
242/*!
243@ingroup CANCELLATION
244@param loc_ref location of the original task directive
245@param gtid Global thread ID of encountering thread
246
Jonathan Peyton30419822017-05-12 18:01:32 +0000247@return returns true if a matching cancellation request has been flagged in the
248RTL and the encountering thread has to cancel..
Jim Cownie181b4bb2013-12-23 17:28:57 +0000249
250Query function to query the current status of cancellation requests.
251Can be used to implement the following pattern:
Jonathan Peyton61118492016-05-20 19:03:38 +0000252
Jim Cownie181b4bb2013-12-23 17:28:57 +0000253if (kmp_get_cancellation_status(kmp_cancel_parallel)) {
254 perform_cleanup();
Jonathan Peyton61118492016-05-20 19:03:38 +0000255 #pragma omp cancellation point parallel
Jim Cownie181b4bb2013-12-23 17:28:57 +0000256}
257*/
258int __kmp_get_cancellation_status(int cancel_kind) {
Jonathan Peyton30419822017-05-12 18:01:32 +0000259 if (__kmp_omp_cancellation) {
260 kmp_info_t *this_thr = __kmp_entry_thread();
Jonathan Peyton61118492016-05-20 19:03:38 +0000261
Jonathan Peyton30419822017-05-12 18:01:32 +0000262 switch (cancel_kind) {
263 case cancel_parallel:
264 case cancel_loop:
265 case cancel_sections: {
266 kmp_team_t *this_team = this_thr->th.th_team;
267 return this_team->t.t_cancel_request == cancel_kind;
Jim Cownie181b4bb2013-12-23 17:28:57 +0000268 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000269 case cancel_taskgroup: {
270 kmp_taskdata_t *task;
271 kmp_taskgroup_t *taskgroup;
272 task = this_thr->th.th_current_task;
273 taskgroup = task->td_taskgroup;
274 return taskgroup && taskgroup->cancel_request;
275 }
276 }
277 }
Jim Cownie181b4bb2013-12-23 17:28:57 +0000278
Jonathan Peyton30419822017-05-12 18:01:32 +0000279 return 0 /* false */;
Jim Cownie181b4bb2013-12-23 17:28:57 +0000280}
281
282#endif