diff options
Diffstat (limited to 'openmp/runtime/src/kmp_gsupport.cpp')
| -rw-r--r-- | openmp/runtime/src/kmp_gsupport.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/openmp/runtime/src/kmp_gsupport.cpp b/openmp/runtime/src/kmp_gsupport.cpp index fd1e6b212c8..c63cbda350c 100644 --- a/openmp/runtime/src/kmp_gsupport.cpp +++ b/openmp/runtime/src/kmp_gsupport.cpp @@ -1413,6 +1413,137 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TEAMS)(unsigned int num_teams, } #endif // OMP_40_ENABLED +#if OMP_45_ENABLED + +// Task duplication function which copies src to dest (both are +// preallocated task structures) +static void __kmp_gomp_task_dup(kmp_task_t *dest, kmp_task_t *src, + kmp_int32 last_private) { + kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(src); + if (taskdata->td_copy_func) { + (taskdata->td_copy_func)(dest->shareds, src->shareds); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif + +template <typename T> +void __GOMP_taskloop(void (*func)(void *), void *data, + void (*copy_func)(void *, void *), long arg_size, + long arg_align, unsigned gomp_flags, + unsigned long num_tasks, int priority, T start, T end, + T step) { + typedef void (*p_task_dup_t)(kmp_task_t *, kmp_task_t *, kmp_int32); + MKLOC(loc, "GOMP_taskloop"); + int sched; + T *loop_bounds; + int gtid = __kmp_entry_gtid(); + kmp_int32 flags = 0; + int if_val = gomp_flags & (1u << 10); + int nogroup = gomp_flags & (1u << 11); + int up = gomp_flags & (1u << 8); + p_task_dup_t task_dup = NULL; + kmp_tasking_flags_t *input_flags = (kmp_tasking_flags_t *)&flags; +#ifdef KMP_DEBUG + { + const char *buff; + buff = __kmp_str_format( + "GOMP_taskloop: T#%%d: func:%%p data:%%p copy_func:%%p " + "arg_size:%%ld arg_align:%%ld gomp_flags:0x%%x num_tasks:%%lu " + "priority:%%d start:%%%s end:%%%s step:%%%s\n", + traits_t<T>::spec, traits_t<T>::spec, traits_t<T>::spec); + KA_TRACE(20, (buff, gtid, func, data, copy_func, arg_size, arg_align, + gomp_flags, num_tasks, priority, start, end, step)); + __kmp_str_free(&buff); + } +#endif + KMP_ASSERT((size_t)arg_size >= 2 * sizeof(T)); + KMP_ASSERT(arg_align > 0); + // The low-order bit is the "untied" flag + if (!(gomp_flags & 1)) { + input_flags->tiedness = 1; + } + // The second low-order bit is the "final" flag + if (gomp_flags & 2) { + input_flags->final = 1; + } + // Negative step flag + if (!up) { + // If step is flagged as negative, but isn't properly sign extended + // Then manually sign extend it. Could be a short, int, char embedded + // in a long. So cannot assume any cast. + if (step > 0) { + for (int i = sizeof(T) * CHAR_BIT - 1; i >= 0L; --i) { + // break at the first 1 bit + if (step & ((T)1 << i)) + break; + step |= ((T)1 << i); + } + } + } + input_flags->native = 1; + // Figure out if none/grainsize/num_tasks clause specified + if (num_tasks > 0) { + if (gomp_flags & (1u << 9)) + sched = 1; // grainsize specified + else + sched = 2; // num_tasks specified + // neither grainsize nor num_tasks specified + } else { + sched = 0; + } + + // __kmp_task_alloc() sets up all other flags + kmp_task_t *task = + __kmp_task_alloc(&loc, gtid, input_flags, sizeof(kmp_task_t), + arg_size + arg_align - 1, (kmp_routine_entry_t)func); + kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(task); + taskdata->td_copy_func = copy_func; + taskdata->td_size_loop_bounds = sizeof(T); + + // re-align shareds if needed and setup firstprivate copy constructors + // through the task_dup mechanism + task->shareds = (void *)((((size_t)task->shareds) + arg_align - 1) / + arg_align * arg_align); + if (copy_func) { + task_dup = __kmp_gomp_task_dup; + } + KMP_MEMCPY(task->shareds, data, arg_size); + + loop_bounds = (T *)task->shareds; + loop_bounds[0] = start; + loop_bounds[1] = end + (up ? -1 : 1); + __kmpc_taskloop(&loc, gtid, task, if_val, (kmp_uint64 *)&(loop_bounds[0]), + (kmp_uint64 *)&(loop_bounds[1]), (kmp_int64)step, nogroup, + sched, (kmp_uint64)num_tasks, (void *)task_dup); +} + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASKLOOP)( + void (*func)(void *), void *data, void (*copy_func)(void *, void *), + long arg_size, long arg_align, unsigned gomp_flags, unsigned long num_tasks, + int priority, long start, long end, long step) { + __GOMP_taskloop<long>(func, data, copy_func, arg_size, arg_align, gomp_flags, + num_tasks, priority, start, end, step); +} + +void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASKLOOP_ULL)( + void (*func)(void *), void *data, void (*copy_func)(void *, void *), + long arg_size, long arg_align, unsigned gomp_flags, unsigned long num_tasks, + int priority, unsigned long long start, unsigned long long end, + unsigned long long step) { + __GOMP_taskloop<unsigned long long>(func, data, copy_func, arg_size, + arg_align, gomp_flags, num_tasks, + priority, start, end, step); +} + +#endif + /* The following sections of code create aliases for the GOMP_* functions, then create versioned symbols using the assembler directive .symver. This is only pertinent for ELF .so library. The KMP_VERSION_SYMBOL macro is defined in @@ -1521,6 +1652,11 @@ KMP_VERSION_SYMBOL(KMP_API_NAME_GOMP_TARGET_UPDATE, 40, "GOMP_4.0"); KMP_VERSION_SYMBOL(KMP_API_NAME_GOMP_TEAMS, 40, "GOMP_4.0"); #endif +#if OMP_45_ENABLED +KMP_VERSION_SYMBOL(KMP_API_NAME_GOMP_TASKLOOP, 45, "GOMP_4.5"); +KMP_VERSION_SYMBOL(KMP_API_NAME_GOMP_TASKLOOP_ULL, 45, "GOMP_4.5"); +#endif + #endif // KMP_USE_VERSION_SYMBOLS #ifdef __cplusplus |

