blob: d1eb00c6649785281085c0cc4662c63c72bd492e [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
25@return returns true if the cancellation request has been activated and the execution thread
26needs to proceed to the end of the canceled region.
27
28Request cancellation of the binding OpenMP region.
29*/
30kmp_int32 __kmpc_cancel(ident_t* loc_ref, kmp_int32 gtid, kmp_int32 cncl_kind) {
31 kmp_info_t *this_thr = __kmp_threads [ gtid ];
32
33 KC_TRACE( 10, ("__kmpc_cancel: T#%d request %d OMP_CANCELLATION=%d\n", gtid, cncl_kind, __kmp_omp_cancellation) );
34
35 KMP_DEBUG_ASSERT(cncl_kind != cancel_noreq);
36 KMP_DEBUG_ASSERT(cncl_kind == cancel_parallel || cncl_kind == cancel_loop ||
37 cncl_kind == cancel_sections || cncl_kind == cancel_taskgroup);
38 KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
39
40 if (__kmp_omp_cancellation) {
41 switch (cncl_kind) {
42 case cancel_parallel:
43 case cancel_loop:
44 case cancel_sections:
45 // cancellation requests for parallel and worksharing constructs
46 // are handled through the team structure
47 {
48 kmp_team_t *this_team = this_thr->th.th_team;
49 KMP_DEBUG_ASSERT(this_team);
50 kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(&(this_team->t.t_cancel_request), cancel_noreq, cncl_kind);
51 if (old == cancel_noreq || old == cncl_kind) {
52 //printf("__kmpc_cancel: this_team->t.t_cancel_request=%d @ %p\n",
53 // this_team->t.t_cancel_request, &(this_team->t.t_cancel_request));
54 // we do not have a cancellation request in this team or we do have one
55 // that matches the current request -> cancel
56 return 1 /* true */;
57 }
58 break;
59 }
60 case cancel_taskgroup:
Jonathan Peyton45be4502015-08-11 21:36:41 +000061 // cancellation requests for a task group
Jim Cownie181b4bb2013-12-23 17:28:57 +000062 // are handled through the taskgroup structure
63 {
64 kmp_taskdata_t* task;
65 kmp_taskgroup_t* taskgroup;
66
67 task = this_thr->th.th_current_task;
68 KMP_DEBUG_ASSERT( task );
69
70 taskgroup = task->td_taskgroup;
71 if (taskgroup) {
72 kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(&(taskgroup->cancel_request), cancel_noreq, cncl_kind);
73 if (old == cancel_noreq || old == cncl_kind) {
74 // we do not have a cancellation request in this taskgroup or we do have one
75 // that matches the current request -> cancel
76 return 1 /* true */;
77 }
78 }
79 else {
80 // TODO: what needs to happen here?
81 // the specification disallows cancellation w/o taskgroups
82 // so we might do anything here, let's abort for now
83 KMP_ASSERT( 0 /* false */);
84 }
85 }
86 break;
87 default:
88 KMP_ASSERT (0 /* false */);
89 }
90 }
91
92 // ICV OMP_CANCELLATION=false, so we ignored this cancel request
93 KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
94 return 0 /* false */;
95}
96
97/*!
98@ingroup CANCELLATION
99@param loc_ref location of the original task directive
100@param gtid Global thread ID of encountering thread
101@param cncl_kind Cancellation kind (parallel, for, sections, taskgroup)
102
103@return returns true if a matching cancellation request has been flagged in the RTL and the
104encountering thread has to cancel..
105
106Cancellation point for the encountering thread.
107*/
108kmp_int32 __kmpc_cancellationpoint(ident_t* loc_ref, kmp_int32 gtid, kmp_int32 cncl_kind) {
109 kmp_info_t *this_thr = __kmp_threads [ gtid ];
110
111 KC_TRACE( 10, ("__kmpc_cancellationpoint: T#%d request %d OMP_CANCELLATION=%d\n", gtid, cncl_kind, __kmp_omp_cancellation) );
112
113 KMP_DEBUG_ASSERT(cncl_kind != cancel_noreq);
114 KMP_DEBUG_ASSERT(cncl_kind == cancel_parallel || cncl_kind == cancel_loop ||
115 cncl_kind == cancel_sections || cncl_kind == cancel_taskgroup);
116 KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
117
118 if (__kmp_omp_cancellation) {
119 switch (cncl_kind) {
120 case cancel_parallel:
121 case cancel_loop:
122 case cancel_sections:
123 // cancellation requests for parallel and worksharing constructs
124 // are handled through the team structure
125 {
126 kmp_team_t *this_team = this_thr->th.th_team;
127 KMP_DEBUG_ASSERT(this_team);
128 if (this_team->t.t_cancel_request) {
129 if (cncl_kind == this_team->t.t_cancel_request) {
130 // the request in the team structure matches the type of
131 // cancellation point so we can cancel
132 return 1 /* true */;
133 }
134 KMP_ASSERT( 0 /* false */);
135 }
136 else {
137 // we do not have a cancellation request pending, so we just
138 // ignore this cancellation point
139 return 0;
140 }
141 break;
142 }
143 case cancel_taskgroup:
Jonathan Peyton45be4502015-08-11 21:36:41 +0000144 // cancellation requests for a task group
Jim Cownie181b4bb2013-12-23 17:28:57 +0000145 // are handled through the taskgroup structure
146 {
147 kmp_taskdata_t* task;
148 kmp_taskgroup_t* taskgroup;
149
150 task = this_thr->th.th_current_task;
151 KMP_DEBUG_ASSERT( task );
152
153 taskgroup = task->td_taskgroup;
154 if (taskgroup) {
155 // return the current status of cancellation for the
156 // taskgroup
157 return !!taskgroup->cancel_request;
158 }
159 else {
160 // if a cancellation point is encountered by a task
161 // that does not belong to a taskgroup, it is OK
162 // to ignore it
163 return 0 /* false */;
164 }
165 }
166 default:
167 KMP_ASSERT (0 /* false */);
168 }
169 }
170
171 // ICV OMP_CANCELLATION=false, so we ignore the cancellation point
172 KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
173 return 0 /* false */;
174}
175
176/*!
177@ingroup CANCELLATION
178@param loc_ref location of the original task directive
179@param gtid Global thread ID of encountering thread
180
181@return returns true if a matching cancellation request has been flagged in the RTL and the
182encountering thread has to cancel..
183
184Barrier with cancellation point to send threads from the barrier to the
185end of the parallel region. Needs a special code pattern as documented
186in the design document for the cancellation feature.
187*/
188kmp_int32
189__kmpc_cancel_barrier(ident_t *loc, kmp_int32 gtid) {
190 int ret = 0 /* false */;
191 kmp_info_t *this_thr = __kmp_threads [ gtid ];
192 kmp_team_t *this_team = this_thr->th.th_team;
193
194 KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
195
196 // call into the standard barrier
197 __kmpc_barrier(loc, gtid);
198
199 // if cancellation is active, check cancellation flag
200 if (__kmp_omp_cancellation) {
201 // depending on which construct to cancel, check the flag and
202 // reset the flag
203 switch (this_team->t.t_cancel_request) {
204 case cancel_parallel:
205 ret = 1;
206 // ensure that threads have checked the flag, when
207 // leaving the above barrier
208 __kmpc_barrier(loc, gtid);
209 this_team->t.t_cancel_request = cancel_noreq;
210 // the next barrier is the fork/join barrier, which
211 // synchronizes the threads leaving here
212 break;
213 case cancel_loop:
214 case cancel_sections:
215 ret = 1;
216 // ensure that threads have checked the flag, when
217 // leaving the above barrier
218 __kmpc_barrier(loc, gtid);
219 this_team->t.t_cancel_request = cancel_noreq;
220 // synchronize the threads again to make sure we
221 // do not have any run-away threads that cause a race
222 // on the cancellation flag
223 __kmpc_barrier(loc, gtid);
224 break;
225 case cancel_taskgroup:
226 // this case should not occur
227 KMP_ASSERT (0 /* false */ );
228 break;
229 case cancel_noreq:
230 // do nothing
231 break;
232 default:
233 KMP_ASSERT ( 0 /* false */);
234 }
235 }
236
237 return ret;
238}
239
240/*!
241@ingroup CANCELLATION
242@param loc_ref location of the original task directive
243@param gtid Global thread ID of encountering thread
244
245@return returns true if a matching cancellation request has been flagged in the RTL and the
246encountering thread has to cancel..
247
248Query function to query the current status of cancellation requests.
249Can be used to implement the following pattern:
250
251if (kmp_get_cancellation_status(kmp_cancel_parallel)) {
252 perform_cleanup();
253 #pragma omp cancellation point parallel
254}
255*/
256int __kmp_get_cancellation_status(int cancel_kind) {
257 if (__kmp_omp_cancellation) {
258 kmp_info_t *this_thr = __kmp_entry_thread();
259
260 switch (cancel_kind) {
261 case cancel_parallel:
262 case cancel_loop:
263 case cancel_sections:
264 {
265 kmp_team_t *this_team = this_thr->th.th_team;
266 return this_team->t.t_cancel_request == cancel_kind;
267 }
268 case cancel_taskgroup:
269 {
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 }
278
279 return 0 /* false */;
280}
281
282#endif