forked from OSchip/llvm-project
168 lines
4.2 KiB
C
168 lines
4.2 KiB
C
// RUN: %libomp-compile-and-run
|
|
// RUN: %libomp-compile && env KMP_TASKLOOP_MIN_TASKS=1 %libomp-run
|
|
|
|
#include <stdio.h>
|
|
#include <omp.h>
|
|
#include "omp_my_sleep.h"
|
|
|
|
#define N 4
|
|
#define ST 3
|
|
#define UB 118
|
|
#define LB 0
|
|
|
|
// globals
|
|
int counter;
|
|
int task_count;
|
|
|
|
// Compiler-generated code (emulation)
|
|
typedef struct ident {
|
|
void* dummy;
|
|
} ident_t;
|
|
|
|
typedef struct shar {
|
|
int *pcounter;
|
|
int *pj;
|
|
int *ptask_count;
|
|
} *pshareds;
|
|
|
|
typedef struct task {
|
|
pshareds shareds;
|
|
int(* routine)(int,struct task*);
|
|
int part_id;
|
|
unsigned long long lb; // library always uses ULONG
|
|
unsigned long long ub;
|
|
int st;
|
|
int last;
|
|
int i;
|
|
int j;
|
|
int th;
|
|
} *ptask, kmp_task_t;
|
|
|
|
typedef int(* task_entry_t)( int, ptask );
|
|
|
|
void
|
|
__task_dup_entry(ptask task_dst, ptask task_src, int lastpriv)
|
|
{
|
|
// setup lastprivate flag
|
|
task_dst->last = lastpriv;
|
|
// could be constructor calls here...
|
|
}
|
|
|
|
// OpenMP RTL interfaces
|
|
typedef unsigned long long kmp_uint64;
|
|
typedef long long kmp_int64;
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
void
|
|
__kmpc_taskloop_5(ident_t *loc, int gtid, kmp_task_t *task, int if_val,
|
|
kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st,
|
|
int nogroup, int sched, kmp_int64 grainsize, int modifier,
|
|
void *task_dup);
|
|
ptask
|
|
__kmpc_omp_task_alloc(ident_t *loc, int gtid, int flags,
|
|
size_t sizeof_kmp_task_t, size_t sizeof_shareds,
|
|
task_entry_t task_entry);
|
|
void __kmpc_atomic_fixed4_add(void *id_ref, int gtid, int * lhs, int rhs);
|
|
int __kmpc_global_thread_num(void *id_ref);
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
// User's code
|
|
int task_entry(int gtid, ptask task)
|
|
{
|
|
pshareds pshar = task->shareds;
|
|
__kmpc_atomic_fixed4_add(NULL, gtid, pshar->ptask_count, 1);
|
|
|
|
for (task->i = task->lb; task->i <= (int)task->ub; task->i += task->st) {
|
|
task->th = omp_get_thread_num();
|
|
__kmpc_atomic_fixed4_add(NULL,gtid,pshar->pcounter,1);
|
|
task->j = task->i;
|
|
}
|
|
my_sleep( 0.1 ); // sleep 100 ms in order to allow other threads to steal tasks
|
|
if (task->last) {
|
|
*(pshar->pj) = task->j; // lastprivate
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void task_loop(int sched_type, int sched_val, int modifier)
|
|
{
|
|
int i, j, gtid = __kmpc_global_thread_num(NULL);
|
|
ptask task;
|
|
pshareds psh;
|
|
omp_set_dynamic(0);
|
|
counter = 0;
|
|
task_count = 0;
|
|
#pragma omp parallel num_threads(N)
|
|
{
|
|
#pragma omp master
|
|
{
|
|
int gtid = __kmpc_global_thread_num(NULL);
|
|
task = __kmpc_omp_task_alloc(NULL, gtid, 1, sizeof(struct task),
|
|
sizeof(struct shar), &task_entry);
|
|
psh = task->shareds;
|
|
psh->pcounter = &counter;
|
|
psh->ptask_count = &task_count;
|
|
psh->pj = &j;
|
|
task->lb = LB;
|
|
task->ub = UB;
|
|
task->st = ST;
|
|
|
|
__kmpc_taskloop_5(
|
|
NULL, // location
|
|
gtid, // gtid
|
|
task, // task structure
|
|
1, // if clause value
|
|
&task->lb, // lower bound
|
|
&task->ub, // upper bound
|
|
ST, // loop increment
|
|
0, // 1 if nogroup specified
|
|
sched_type, // schedule type: 0-none, 1-grainsize, 2-num_tasks
|
|
sched_val, // schedule value (ignored for type 0)
|
|
modifier, // strict modifier
|
|
(void*)&__task_dup_entry // tasks duplication routine
|
|
);
|
|
} // end master
|
|
} // end parallel
|
|
// check results
|
|
int tc;
|
|
if (ST == 1) { // most common case
|
|
tc = UB - LB + 1;
|
|
} else if (ST < 0) {
|
|
tc = (LB - UB) / (-ST) + 1;
|
|
} else { // ST > 0
|
|
tc = (UB - LB) / ST + 1;
|
|
}
|
|
int count;
|
|
if (sched_type == 1) {
|
|
count = (sched_val > tc) ? 1 : (tc + sched_val - 1) / sched_val;
|
|
} else {
|
|
count = (sched_val > tc) ? tc : sched_val;
|
|
}
|
|
if (j != LB + (tc - 1) * ST) {
|
|
printf("Error in lastprivate, %d != %d\n", j, LB + (tc - 1) * ST);
|
|
exit(1);
|
|
}
|
|
if (counter != tc) {
|
|
printf("Error, counter %d != %d\n", counter, tc);
|
|
exit(1);
|
|
}
|
|
if (task_count != count) {
|
|
printf("Error, task count %d != %d\n", task_count, count);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
task_loop(1, 6, 1); // create 7 tasks
|
|
task_loop(2, 6, 1); // create 6 tasks
|
|
task_loop(1, 50, 1); // create 1 task
|
|
task_loop(2, 50, 1); // create 40 tasks
|
|
|
|
printf("Test passed\n");
|
|
return 0;
|
|
}
|