Intel® OpenMP* Runtime Library
 All Classes Functions Variables Typedefs Enumerations Enumerator Groups Pages
kmp_cancel.cpp
1 /* <copyright>
2  Copyright (c) 1997-2015 Intel Corporation. All Rights Reserved.
3 
4  Redistribution and use in source and binary forms, with or without
5  modification, are permitted provided that the following conditions
6  are met:
7 
8  * Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright
11  notice, this list of conditions and the following disclaimer in the
12  documentation and/or other materials provided with the distribution.
13  * Neither the name of Intel Corporation nor the names of its
14  contributors may be used to endorse or promote products derived
15  from this software without specific prior written permission.
16 
17  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 </copyright> */
30 
31 #include "kmp.h"
32 #include "kmp_i18n.h"
33 #include "kmp_io.h"
34 #include "kmp_str.h"
35 
36 #if OMP_40_ENABLED
37 
49 kmp_int32 __kmpc_cancel(ident_t* loc_ref, kmp_int32 gtid, kmp_int32 cncl_kind) {
50  kmp_info_t *this_thr = __kmp_threads [ gtid ];
51 
52  KC_TRACE( 10, ("__kmpc_cancel: T#%d request %d OMP_CANCELLATION=%d\n", gtid, cncl_kind, __kmp_omp_cancellation) );
53 
54  KMP_DEBUG_ASSERT(cncl_kind != cancel_noreq);
55  KMP_DEBUG_ASSERT(cncl_kind == cancel_parallel || cncl_kind == cancel_loop ||
56  cncl_kind == cancel_sections || cncl_kind == cancel_taskgroup);
57  KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
58 
59  if (__kmp_omp_cancellation) {
60  switch (cncl_kind) {
61  case cancel_parallel:
62  case cancel_loop:
63  case cancel_sections:
64  // cancellation requests for parallel and worksharing constructs
65  // are handled through the team structure
66  {
67  kmp_team_t *this_team = this_thr->th.th_team;
68  KMP_DEBUG_ASSERT(this_team);
69  kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(&(this_team->t.t_cancel_request), cancel_noreq, cncl_kind);
70  if (old == cancel_noreq || old == cncl_kind) {
71  //printf("__kmpc_cancel: this_team->t.t_cancel_request=%d @ %p\n",
72  // this_team->t.t_cancel_request, &(this_team->t.t_cancel_request));
73  // we do not have a cancellation request in this team or we do have one
74  // that matches the current request -> cancel
75  return 1 /* true */;
76  }
77  break;
78  }
79  case cancel_taskgroup:
80  // cancellation requests for parallel and worksharing constructs
81  // are handled through the taskgroup structure
82  {
83  kmp_taskdata_t* task;
84  kmp_taskgroup_t* taskgroup;
85 
86  task = this_thr->th.th_current_task;
87  KMP_DEBUG_ASSERT( task );
88 
89  taskgroup = task->td_taskgroup;
90  if (taskgroup) {
91  kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(&(taskgroup->cancel_request), cancel_noreq, cncl_kind);
92  if (old == cancel_noreq || old == cncl_kind) {
93  // we do not have a cancellation request in this taskgroup or we do have one
94  // that matches the current request -> cancel
95  return 1 /* true */;
96  }
97  }
98  else {
99  // TODO: what needs to happen here?
100  // the specification disallows cancellation w/o taskgroups
101  // so we might do anything here, let's abort for now
102  KMP_ASSERT( 0 /* false */);
103  }
104  }
105  break;
106  default:
107  KMP_ASSERT (0 /* false */);
108  }
109  }
110 
111  // ICV OMP_CANCELLATION=false, so we ignored this cancel request
112  KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
113  return 0 /* false */;
114 }
115 
127 kmp_int32 __kmpc_cancellationpoint(ident_t* loc_ref, kmp_int32 gtid, kmp_int32 cncl_kind) {
128  kmp_info_t *this_thr = __kmp_threads [ gtid ];
129 
130  KC_TRACE( 10, ("__kmpc_cancellationpoint: T#%d request %d OMP_CANCELLATION=%d\n", gtid, cncl_kind, __kmp_omp_cancellation) );
131 
132  KMP_DEBUG_ASSERT(cncl_kind != cancel_noreq);
133  KMP_DEBUG_ASSERT(cncl_kind == cancel_parallel || cncl_kind == cancel_loop ||
134  cncl_kind == cancel_sections || cncl_kind == cancel_taskgroup);
135  KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
136 
137  if (__kmp_omp_cancellation) {
138  switch (cncl_kind) {
139  case cancel_parallel:
140  case cancel_loop:
141  case cancel_sections:
142  // cancellation requests for parallel and worksharing constructs
143  // are handled through the team structure
144  {
145  kmp_team_t *this_team = this_thr->th.th_team;
146  KMP_DEBUG_ASSERT(this_team);
147  if (this_team->t.t_cancel_request) {
148  if (cncl_kind == this_team->t.t_cancel_request) {
149  // the request in the team structure matches the type of
150  // cancellation point so we can cancel
151  return 1 /* true */;
152  }
153  KMP_ASSERT( 0 /* false */);
154  }
155  else {
156  // we do not have a cancellation request pending, so we just
157  // ignore this cancellation point
158  return 0;
159  }
160  break;
161  }
162  case cancel_taskgroup:
163  // cancellation requests for parallel and worksharing constructs
164  // are handled through the taskgroup structure
165  {
166  kmp_taskdata_t* task;
167  kmp_taskgroup_t* taskgroup;
168 
169  task = this_thr->th.th_current_task;
170  KMP_DEBUG_ASSERT( task );
171 
172  taskgroup = task->td_taskgroup;
173  if (taskgroup) {
174  // return the current status of cancellation for the
175  // taskgroup
176  return !!taskgroup->cancel_request;
177  }
178  else {
179  // if a cancellation point is encountered by a task
180  // that does not belong to a taskgroup, it is OK
181  // to ignore it
182  return 0 /* false */;
183  }
184  }
185  default:
186  KMP_ASSERT (0 /* false */);
187  }
188  }
189 
190  // ICV OMP_CANCELLATION=false, so we ignore the cancellation point
191  KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
192  return 0 /* false */;
193 }
194 
207 kmp_int32
208 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 gtid) {
209  int ret = 0 /* false */;
210  kmp_info_t *this_thr = __kmp_threads [ gtid ];
211  kmp_team_t *this_team = this_thr->th.th_team;
212 
213  KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
214 
215  // call into the standard barrier
216  __kmpc_barrier(loc, gtid);
217 
218  // if cancellation is active, check cancellation flag
219  if (__kmp_omp_cancellation) {
220  // depending on which construct to cancel, check the flag and
221  // reset the flag
222  switch (this_team->t.t_cancel_request) {
223  case cancel_parallel:
224  ret = 1;
225  // ensure that threads have checked the flag, when
226  // leaving the above barrier
227  __kmpc_barrier(loc, gtid);
228  this_team->t.t_cancel_request = cancel_noreq;
229  // the next barrier is the fork/join barrier, which
230  // synchronizes the threads leaving here
231  break;
232  case cancel_loop:
233  case cancel_sections:
234  ret = 1;
235  // ensure that threads have checked the flag, when
236  // leaving the above barrier
237  __kmpc_barrier(loc, gtid);
238  this_team->t.t_cancel_request = cancel_noreq;
239  // synchronize the threads again to make sure we
240  // do not have any run-away threads that cause a race
241  // on the cancellation flag
242  __kmpc_barrier(loc, gtid);
243  break;
244  case cancel_taskgroup:
245  // this case should not occur
246  KMP_ASSERT (0 /* false */ );
247  break;
248  case cancel_noreq:
249  // do nothing
250  break;
251  default:
252  KMP_ASSERT ( 0 /* false */);
253  }
254  }
255 
256  return ret;
257 }
258 
275 int __kmp_get_cancellation_status(int cancel_kind) {
276  if (__kmp_omp_cancellation) {
277  kmp_info_t *this_thr = __kmp_entry_thread();
278 
279  switch (cancel_kind) {
280  case cancel_parallel:
281  case cancel_loop:
282  case cancel_sections:
283  {
284  kmp_team_t *this_team = this_thr->th.th_team;
285  return this_team->t.t_cancel_request == cancel_kind;
286  }
287  case cancel_taskgroup:
288  {
289  kmp_taskdata_t* task;
290  kmp_taskgroup_t* taskgroup;
291  task = this_thr->th.th_current_task;
292  taskgroup = task->td_taskgroup;
293  return taskgroup && taskgroup->cancel_request;
294  }
295  }
296  }
297 
298  return 0 /* false */;
299 }
300 
301 #endif
Definition: kmp.h:218
KMP_EXPORT void __kmpc_barrier(ident_t *, kmp_int32 global_tid)
Definition: kmp_csupport.c:672