LLVM OpenMP* Runtime Library
kmp_cancel.cpp
1 
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 
30 kmp_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:
61  // cancellation requests for parallel and worksharing constructs
62  // 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 
108 kmp_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:
144  // cancellation requests for parallel and worksharing constructs
145  // 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 
188 kmp_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 
256 int __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
Definition: kmp.h:198
KMP_EXPORT void __kmpc_barrier(ident_t *, kmp_int32 global_tid)
Definition: kmp_csupport.c:653