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