1 //****************************************************************************** 2 // include files 3 //****************************************************************************** 4 5 #include "kmp.h" 6 #include "ompt-internal.h" 7 #include "ompt-specific.h" 8 9 //****************************************************************************** 10 // macros 11 //****************************************************************************** 12 13 #define GTID_TO_OMPT_THREAD_ID(id) ((ompt_thread_id_t) (id >=0) ? id + 1: 0) 14 15 #define LWT_FROM_TEAM(team) (team)->t.ompt_serialized_team_info; 16 17 #define OMPT_THREAD_ID_BITS 16 18 19 // 2013 08 24 - John Mellor-Crummey 20 // ideally, a thread should assign its own ids based on thread private data. 21 // however, the way the intel runtime reinitializes thread data structures 22 // when it creates teams makes it difficult to maintain persistent thread 23 // data. using a shared variable instead is simple. I leave it to intel to 24 // sort out how to implement a higher performance version in their runtime. 25 26 // when using fetch_and_add to generate the IDs, there isn't any reason to waste 27 // bits for thread id. 28 #if 0 29 #define NEXT_ID(id_ptr,tid) \ 30 ((KMP_TEST_THEN_INC64(id_ptr) << OMPT_THREAD_ID_BITS) | (tid)) 31 #else 32 #define NEXT_ID(id_ptr,tid) (KMP_TEST_THEN_INC64((volatile kmp_int64 *)id_ptr)) 33 #endif 34 35 //****************************************************************************** 36 // private operations 37 //****************************************************************************** 38 39 //---------------------------------------------------------- 40 // traverse the team and task hierarchy 41 // note: __ompt_get_teaminfo and __ompt_get_taskinfo 42 // traverse the hierarchy similarly and need to be 43 // kept consistent 44 //---------------------------------------------------------- 45 46 ompt_team_info_t * 47 __ompt_get_teaminfo(int depth, int *size) 48 { 49 kmp_info_t *thr = ompt_get_thread(); 50 51 if (thr) { 52 kmp_team *team = thr->th.th_team; 53 if (team == NULL) return NULL; 54 55 ompt_lw_taskteam_t *lwt = LWT_FROM_TEAM(team); 56 57 while(depth > 0) { 58 // next lightweight team (if any) 59 if (lwt) lwt = lwt->parent; 60 61 // next heavyweight team (if any) after 62 // lightweight teams are exhausted 63 if (!lwt && team) { 64 team=team->t.t_parent; 65 if (team) { 66 lwt = LWT_FROM_TEAM(team); 67 } 68 } 69 70 depth--; 71 } 72 73 if (lwt) { 74 // lightweight teams have one task 75 if (size) *size = 1; 76 77 // return team info for lightweight team 78 return &lwt->ompt_team_info; 79 } else if (team) { 80 // extract size from heavyweight team 81 if (size) *size = team->t.t_nproc; 82 83 // return team info for heavyweight team 84 return &team->t.ompt_team_info; 85 } 86 } 87 88 return NULL; 89 } 90 91 92 ompt_task_info_t * 93 __ompt_get_taskinfo(int depth) 94 { 95 ompt_task_info_t *info = NULL; 96 kmp_info_t *thr = ompt_get_thread(); 97 98 if (thr) { 99 kmp_taskdata_t *taskdata = thr->th.th_current_task; 100 ompt_lw_taskteam_t *lwt = LWT_FROM_TEAM(taskdata->td_team); 101 102 while (depth > 0) { 103 // next lightweight team (if any) 104 if (lwt) lwt = lwt->parent; 105 106 // next heavyweight team (if any) after 107 // lightweight teams are exhausted 108 if (!lwt && taskdata) { 109 taskdata = taskdata->td_parent; 110 if (taskdata) { 111 lwt = LWT_FROM_TEAM(taskdata->td_team); 112 } 113 } 114 depth--; 115 } 116 117 if (lwt) { 118 info = &lwt->ompt_task_info; 119 } else if (taskdata) { 120 info = &taskdata->ompt_task_info; 121 } 122 } 123 124 return info; 125 } 126 127 128 129 //****************************************************************************** 130 // interface operations 131 //****************************************************************************** 132 133 //---------------------------------------------------------- 134 // thread support 135 //---------------------------------------------------------- 136 137 ompt_parallel_id_t 138 __ompt_thread_id_new() 139 { 140 static uint64_t ompt_thread_id = 1; 141 return NEXT_ID(&ompt_thread_id, 0); 142 } 143 144 void 145 __ompt_thread_begin(ompt_thread_type_t thread_type, int gtid) 146 { 147 ompt_callbacks.ompt_callback(ompt_event_thread_begin)( 148 thread_type, GTID_TO_OMPT_THREAD_ID(gtid)); 149 } 150 151 152 void 153 __ompt_thread_end(ompt_thread_type_t thread_type, int gtid) 154 { 155 ompt_callbacks.ompt_callback(ompt_event_thread_end)( 156 thread_type, GTID_TO_OMPT_THREAD_ID(gtid)); 157 } 158 159 160 ompt_thread_id_t 161 __ompt_get_thread_id_internal() 162 { 163 // FIXME 164 // until we have a better way of assigning ids, use __kmp_get_gtid 165 // since the return value might be negative, we need to test that before 166 // assigning it to an ompt_thread_id_t, which is unsigned. 167 int id = __kmp_get_gtid(); 168 assert(id >= 0); 169 170 return GTID_TO_OMPT_THREAD_ID(id); 171 } 172 173 //---------------------------------------------------------- 174 // state support 175 //---------------------------------------------------------- 176 177 void 178 __ompt_thread_assign_wait_id(void *variable) 179 { 180 int gtid = __kmp_gtid_get_specific(); 181 kmp_info_t *ti = ompt_get_thread_gtid(gtid); 182 183 ti->th.ompt_thread_info.wait_id = (ompt_wait_id_t) variable; 184 } 185 186 ompt_state_t 187 __ompt_get_state_internal(ompt_wait_id_t *ompt_wait_id) 188 { 189 kmp_info_t *ti = ompt_get_thread(); 190 191 if (ti) { 192 if (ompt_wait_id) 193 *ompt_wait_id = ti->th.ompt_thread_info.wait_id; 194 return ti->th.ompt_thread_info.state; 195 } 196 return ompt_state_undefined; 197 } 198 199 //---------------------------------------------------------- 200 // idle frame support 201 //---------------------------------------------------------- 202 203 void * 204 __ompt_get_idle_frame_internal(void) 205 { 206 kmp_info_t *ti = ompt_get_thread(); 207 return ti ? ti->th.ompt_thread_info.idle_frame : NULL; 208 } 209 210 211 //---------------------------------------------------------- 212 // parallel region support 213 //---------------------------------------------------------- 214 215 ompt_parallel_id_t 216 __ompt_parallel_id_new(int gtid) 217 { 218 static uint64_t ompt_parallel_id = 1; 219 return gtid >= 0 ? NEXT_ID(&ompt_parallel_id, gtid) : 0; 220 } 221 222 223 void * 224 __ompt_get_parallel_function_internal(int depth) 225 { 226 ompt_team_info_t *info = __ompt_get_teaminfo(depth, NULL); 227 void *function = info ? info->microtask : NULL; 228 return function; 229 } 230 231 232 ompt_parallel_id_t 233 __ompt_get_parallel_id_internal(int depth) 234 { 235 ompt_team_info_t *info = __ompt_get_teaminfo(depth, NULL); 236 ompt_parallel_id_t id = info ? info->parallel_id : 0; 237 return id; 238 } 239 240 241 int 242 __ompt_get_parallel_team_size_internal(int depth) 243 { 244 // initialize the return value with the error value. 245 // if there is a team at the specified depth, the default 246 // value will be overwritten the size of that team. 247 int size = -1; 248 (void) __ompt_get_teaminfo(depth, &size); 249 return size; 250 } 251 252 253 //---------------------------------------------------------- 254 // lightweight task team support 255 //---------------------------------------------------------- 256 257 void 258 __ompt_lw_taskteam_init(ompt_lw_taskteam_t *lwt, kmp_info_t *thr, 259 int gtid, void *microtask, 260 ompt_parallel_id_t ompt_pid) 261 { 262 lwt->ompt_team_info.parallel_id = ompt_pid; 263 lwt->ompt_team_info.microtask = microtask; 264 lwt->ompt_task_info.task_id = 0; 265 lwt->ompt_task_info.frame.reenter_runtime_frame = NULL; 266 lwt->ompt_task_info.frame.exit_runtime_frame = NULL; 267 lwt->ompt_task_info.function = NULL; 268 lwt->parent = 0; 269 } 270 271 272 void 273 __ompt_lw_taskteam_link(ompt_lw_taskteam_t *lwt, kmp_info_t *thr) 274 { 275 ompt_lw_taskteam_t *my_parent = thr->th.th_team->t.ompt_serialized_team_info; 276 lwt->parent = my_parent; 277 thr->th.th_team->t.ompt_serialized_team_info = lwt; 278 } 279 280 281 ompt_lw_taskteam_t * 282 __ompt_lw_taskteam_unlink(kmp_info_t *thr) 283 { 284 ompt_lw_taskteam_t *lwtask = thr->th.th_team->t.ompt_serialized_team_info; 285 if (lwtask) thr->th.th_team->t.ompt_serialized_team_info = lwtask->parent; 286 return lwtask; 287 } 288 289 290 //---------------------------------------------------------- 291 // task support 292 //---------------------------------------------------------- 293 294 ompt_task_id_t 295 __ompt_task_id_new(int gtid) 296 { 297 static uint64_t ompt_task_id = 1; 298 return NEXT_ID(&ompt_task_id, gtid); 299 } 300 301 302 ompt_task_id_t 303 __ompt_get_task_id_internal(int depth) 304 { 305 ompt_task_info_t *info = __ompt_get_taskinfo(depth); 306 ompt_task_id_t task_id = info ? info->task_id : 0; 307 return task_id; 308 } 309 310 311 void * 312 __ompt_get_task_function_internal(int depth) 313 { 314 ompt_task_info_t *info = __ompt_get_taskinfo(depth); 315 void *function = info ? info->function : NULL; 316 return function; 317 } 318 319 320 ompt_frame_t * 321 __ompt_get_task_frame_internal(int depth) 322 { 323 ompt_task_info_t *info = __ompt_get_taskinfo(depth); 324 ompt_frame_t *frame = info ? frame = &info->frame : NULL; 325 return frame; 326 } 327 328 329 //---------------------------------------------------------- 330 // team support 331 //---------------------------------------------------------- 332 333 void 334 __ompt_team_assign_id(kmp_team_t *team, ompt_parallel_id_t ompt_pid) 335 { 336 team->t.ompt_team_info.parallel_id = ompt_pid; 337 } 338