Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,131 @@
// RUN: %libomp-compile -lpthread && %libomp-run
// The runtime currently does not get dependency information from GCC.
// UNSUPPORTED: gcc
#include <stdio.h>
#include <omp.h>
#include <pthread.h>
#include "omp_my_sleep.h"
/*
With task dependencies one can generate proxy tasks from an explicit task
being executed by a serial task team. The OpenMP runtime library didn't
expect that and tries to free the explicit task that is the parent of the
proxy task still working in background. It therefore has incomplete children
which triggers a debugging assertion.
*/
// Compiler-generated code (emulation)
typedef long kmp_intptr_t;
typedef int kmp_int32;
typedef char bool;
typedef struct ident {
kmp_int32 reserved_1; /**< might be used in Fortran; see above */
kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; KMP_IDENT_KMPC identifies this union member */
kmp_int32 reserved_2; /**< not really used in Fortran any more; see above */
#if USE_ITT_BUILD
/* but currently used for storing region-specific ITT */
/* contextual information. */
#endif /* USE_ITT_BUILD */
kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for C++ */
char const *psource; /**< String describing the source location.
The string is composed of semi-colon separated fields which describe the source file,
the function and a pair of line numbers that delimit the construct.
*/
} ident_t;
typedef struct kmp_depend_info {
kmp_intptr_t base_addr;
size_t len;
struct {
bool in:1;
bool out:1;
} flags;
} kmp_depend_info_t;
struct kmp_task;
typedef kmp_int32 (* kmp_routine_entry_t)( kmp_int32, struct kmp_task * );
typedef struct kmp_task { /* GEH: Shouldn't this be aligned somehow? */
void * shareds; /**< pointer to block of pointers to shared vars */
kmp_routine_entry_t routine; /**< pointer to routine to call for executing task */
kmp_int32 part_id; /**< part id for the task */
} kmp_task_t;
#ifdef __cplusplus
extern "C" {
#endif
kmp_int32 __kmpc_global_thread_num ( ident_t * );
kmp_task_t*
__kmpc_omp_task_alloc( ident_t *loc_ref, kmp_int32 gtid, kmp_int32 flags,
size_t sizeof_kmp_task_t, size_t sizeof_shareds,
kmp_routine_entry_t task_entry );
void __kmpc_proxy_task_completed_ooo ( kmp_task_t *ptask );
kmp_int32 __kmpc_omp_task_with_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task,
kmp_int32 ndeps, kmp_depend_info_t *dep_list,
kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list );
kmp_int32
__kmpc_omp_task( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task );
#ifdef __cplusplus
}
#endif
void *target(void *task)
{
my_sleep( 0.1 );
__kmpc_proxy_task_completed_ooo((kmp_task_t*) task);
return NULL;
}
pthread_t target_thread;
// User's code
int task_entry(kmp_int32 gtid, kmp_task_t *task)
{
pthread_create(&target_thread, NULL, &target, task);
return 0;
}
int main()
{
int dep;
#pragma omp taskgroup
{
/*
* Corresponds to:
#pragma omp target nowait depend(out: dep)
{
my_sleep( 0.1 );
}
*/
kmp_depend_info_t dep_info;
dep_info.base_addr = (long) &dep;
dep_info.len = sizeof(int);
// out = inout per spec and runtime expects this
dep_info.flags.in = 1;
dep_info.flags.out = 1;
kmp_int32 gtid = __kmpc_global_thread_num(NULL);
kmp_task_t *proxy_task = __kmpc_omp_task_alloc(NULL,gtid,17,sizeof(kmp_task_t),0,&task_entry);
__kmpc_omp_task_with_deps(NULL,gtid,proxy_task,1,&dep_info,0,NULL);
#pragma omp task depend(in: dep)
{
/*
* Corresponds to:
#pragma omp target nowait
{
my_sleep( 0.1 );
}
*/
kmp_task_t *nested_proxy_task = __kmpc_omp_task_alloc(NULL,gtid,17,sizeof(kmp_task_t),0,&task_entry);
__kmpc_omp_task(NULL,gtid,nested_proxy_task);
}
}
// only check that it didn't crash
return 0;
}

View File

@@ -0,0 +1,134 @@
// RUN: %libomp-compile -lpthread && %libomp-run
// The runtime currently does not get dependency information from GCC.
// UNSUPPORTED: gcc
#include <stdio.h>
#include <omp.h>
#include <pthread.h>
#include "omp_my_sleep.h"
/*
An explicit task can have a dependency on a target task. If it is not
directly satisfied, the runtime should not wait but resume execution.
*/
// Compiler-generated code (emulation)
typedef long kmp_intptr_t;
typedef int kmp_int32;
typedef char bool;
typedef struct ident {
kmp_int32 reserved_1; /**< might be used in Fortran; see above */
kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; KMP_IDENT_KMPC identifies this union member */
kmp_int32 reserved_2; /**< not really used in Fortran any more; see above */
#if USE_ITT_BUILD
/* but currently used for storing region-specific ITT */
/* contextual information. */
#endif /* USE_ITT_BUILD */
kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for C++ */
char const *psource; /**< String describing the source location.
The string is composed of semi-colon separated fields which describe the source file,
the function and a pair of line numbers that delimit the construct.
*/
} ident_t;
typedef struct kmp_depend_info {
kmp_intptr_t base_addr;
size_t len;
struct {
bool in:1;
bool out:1;
} flags;
} kmp_depend_info_t;
struct kmp_task;
typedef kmp_int32 (* kmp_routine_entry_t)( kmp_int32, struct kmp_task * );
typedef struct kmp_task { /* GEH: Shouldn't this be aligned somehow? */
void * shareds; /**< pointer to block of pointers to shared vars */
kmp_routine_entry_t routine; /**< pointer to routine to call for executing task */
kmp_int32 part_id; /**< part id for the task */
} kmp_task_t;
#ifdef __cplusplus
extern "C" {
#endif
kmp_int32 __kmpc_global_thread_num ( ident_t * );
kmp_task_t*
__kmpc_omp_task_alloc( ident_t *loc_ref, kmp_int32 gtid, kmp_int32 flags,
size_t sizeof_kmp_task_t, size_t sizeof_shareds,
kmp_routine_entry_t task_entry );
void __kmpc_proxy_task_completed_ooo ( kmp_task_t *ptask );
kmp_int32 __kmpc_omp_task_with_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task,
kmp_int32 ndeps, kmp_depend_info_t *dep_list,
kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list );
kmp_int32
__kmpc_omp_task( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task );
#ifdef __cplusplus
}
#endif
void *target(void *task)
{
my_sleep( 0.1 );
__kmpc_proxy_task_completed_ooo((kmp_task_t*) task);
return NULL;
}
pthread_t target_thread;
// User's code
int task_entry(kmp_int32 gtid, kmp_task_t *task)
{
pthread_create(&target_thread, NULL, &target, task);
return 0;
}
int main()
{
int dep;
/*
* Corresponds to:
#pragma omp target nowait depend(out: dep)
{
my_sleep( 0.1 );
}
*/
kmp_depend_info_t dep_info;
dep_info.base_addr = (long) &dep;
dep_info.len = sizeof(int);
// out = inout per spec and runtime expects this
dep_info.flags.in = 1;
dep_info.flags.out = 1;
kmp_int32 gtid = __kmpc_global_thread_num(NULL);
kmp_task_t *proxy_task = __kmpc_omp_task_alloc(NULL,gtid,17,sizeof(kmp_task_t),0,&task_entry);
__kmpc_omp_task_with_deps(NULL,gtid,proxy_task,1,&dep_info,0,NULL);
int first_task_finished = 0;
#pragma omp task shared(first_task_finished) depend(inout: dep)
{
first_task_finished = 1;
}
int second_task_finished = 0;
#pragma omp task shared(second_task_finished) depend(in: dep)
{
second_task_finished = 1;
}
// check that execution has been resumed and the runtime has not waited
// for the dependencies to be satisfied.
int error = (first_task_finished == 1);
error += (second_task_finished == 1);
#pragma omp taskwait
// by now all tasks should have finished
error += (first_task_finished != 1);
error += (second_task_finished != 1);
return error;
}

View File

@@ -0,0 +1,16 @@
// RUN: %libomp-compile-and-run
/*
GCC failed this test because __kmp_get_gtid() instead of __kmp_entry_gtid()
was called in xexpand(KMP_API_NAME_GOMP_TASKGROUP_START)(void).
__kmp_entry_gtid() will initialize the runtime if not yet done which does not
happen with __kmp_get_gtid().
*/
int main()
{
#pragma omp taskgroup
{ }
return 0;
}

View File

@@ -0,0 +1,376 @@
// RUN: %libomp-cxx-compile-and-run
// RUN: %libomp-cxx-compile -DFLG=1 && %libomp-run
// GCC-5 is needed for OpenMP 4.0 support (taskgroup)
// XFAIL: gcc-4
#include <cstdio>
#include <cmath>
#include <cassert>
#include <omp.h>
// Total number of loop iterations, should be multiple of T for this test
#define N 10000
// Flag to request lazy (1) or eager (0) allocation of reduction objects
#ifndef FLG
#define FLG 0
#endif
/*
// initial user's code that corresponds to pseudo code of the test
#pragma omp taskgroup task_reduction(+:i,j) task_reduction(*:x)
{
for( int l = 0; l < N; ++l ) {
#pragma omp task firstprivate(l) in_reduction(+:i) in_reduction(*:x)
{
i += l;
if( l%2 )
x *= 1.0 / (l + 1);
else
x *= (l + 1);
}
}
#pragma omp taskgroup task_reduction(-:i,k) task_reduction(+:y)
{
for( int l = 0; l < N; ++l ) {
#pragma omp task firstprivate(l) in_reduction(+:j,y) \
in_reduction(*:x) in_reduction(-:k)
{
j += l;
k -= l;
y += (double)l;
if( l%2 )
x *= 1.0 / (l + 1);
else
x *= (l + 1);
}
#pragma omp task firstprivate(l) in_reduction(+:y) in_reduction(-:i,k)
{
i -= l;
k -= l;
y += (double)l;
}
#pragma omp task firstprivate(l) in_reduction(+:j) in_reduction(*:x)
{
j += l;
if( l%2 )
x *= 1.0 / (l + 1);
else
x *= (l + 1);
}
}
} // inner reduction
for( int l = 0; l < N; ++l ) {
#pragma omp task firstprivate(l) in_reduction(+:j)
j += l;
}
} // outer reduction
*/
//------------------------------------------------
// OpenMP runtime library routines
#ifdef __cplusplus
extern "C" {
#endif
extern void* __kmpc_task_reduction_get_th_data(int gtid, void* tg, void* item);
extern void* __kmpc_task_reduction_init(int gtid, int num, void* data);
extern int __kmpc_global_thread_num(void*);
#ifdef __cplusplus
}
#endif
//------------------------------------------------
// Compiler-generated code
typedef struct _task_red_item {
void *shar; // shared reduction item
size_t size; // size of data item
void *f_init; // data initialization routine
void *f_fini; // data finalization routine
void *f_comb; // data combiner routine
unsigned flags;
} _task_red_item_t;
// int:+ no need in init/fini callbacks, valid for subtraction
void __red_int_add_comb(void *lhs, void *rhs) // combiner
{ *(int*)lhs += *(int*)rhs; }
// long long:+ no need in init/fini callbacks, valid for subtraction
void __red_llong_add_comb(void *lhs, void *rhs) // combiner
{ *(long long*)lhs += *(long long*)rhs; }
// double:* no need in fini callback
void __red_dbl_mul_init(void *data) // initializer
{ *(double*)data = 1.0; }
void __red_dbl_mul_comb(void *lhs, void *rhs) // combiner
{ *(double*)lhs *= *(double*)rhs; }
// double:+ no need in init/fini callbacks
void __red_dbl_add_comb(void *lhs, void *rhs) // combiner
{ *(double*)lhs += *(double*)rhs; }
// ==============================
void calc_serial(int *pi, long long *pj, double *px, long long *pk, double *py)
{
for( int l = 0; l < N; ++l ) {
*pi += l;
if( l%2 )
*px *= 1.0 / (l + 1);
else
*px *= (l + 1);
}
for( int l = 0; l < N; ++l ) {
*pj += l;
*pk -= l;
*py += (double)l;
if( l%2 )
*px *= 1.0 / (l + 1);
else
*px *= (l + 1);
*pi -= l;
*pk -= l;
*py += (double)l;
*pj += l;
if( l%2 )
*px *= 1.0 / (l + 1);
else
*px *= (l + 1);
}
for( int l = 0; l < N; ++l ) {
*pj += l;
}
}
//------------------------------------------------
// Test case
int main()
{
int nthreads = omp_get_max_threads();
int err = 0;
void** ptrs = (void**)malloc(nthreads*sizeof(void*));
// user's code ======================================
// variables for serial calculations:
int is = 3;
long long js = -9999999;
double xs = 99999.0;
long long ks = 99999999;
double ys = -99999999.0;
// variables for parallel calculations:
int ip = 3;
long long jp = -9999999;
double xp = 99999.0;
long long kp = 99999999;
double yp = -99999999.0;
calc_serial(&is, &js, &xs, &ks, &ys);
// ==================================================
for (int i = 0; i < nthreads; ++i)
ptrs[i] = NULL;
#pragma omp parallel
{
#pragma omp single nowait
{
// outer taskgroup reduces (i,j,x)
#pragma omp taskgroup // task_reduction(+:i,j) task_reduction(*:x)
{
_task_red_item_t red_data[3];
red_data[0].shar = &ip;
red_data[0].size = sizeof(ip);
red_data[0].f_init = NULL; // RTL will zero thread-specific objects
red_data[0].f_fini = NULL; // no destructors needed
red_data[0].f_comb = (void*)&__red_int_add_comb;
red_data[0].flags = FLG;
red_data[1].shar = &jp;
red_data[1].size = sizeof(jp);
red_data[1].f_init = NULL; // RTL will zero thread-specific objects
red_data[1].f_fini = NULL; // no destructors needed
red_data[1].f_comb = (void*)&__red_llong_add_comb;
red_data[1].flags = FLG;
red_data[2].shar = &xp;
red_data[2].size = sizeof(xp);
red_data[2].f_init = (void*)&__red_dbl_mul_init;
red_data[2].f_fini = NULL; // no destructors needed
red_data[2].f_comb = (void*)&__red_dbl_mul_comb;
red_data[2].flags = FLG;
int gtid = __kmpc_global_thread_num(NULL);
void* tg1 = __kmpc_task_reduction_init(gtid, 3, red_data);
for( int l = 0; l < N; l += 2 ) {
// 2 iterations per task to get correct x value; actually any even
// number of iters per task will work, otherwise x looses precision
#pragma omp task firstprivate(l) //in_reduction(+:i) in_reduction(*:x)
{
int gtid = __kmpc_global_thread_num(NULL);
int *p_ip = (int*)__kmpc_task_reduction_get_th_data(gtid, tg1, &ip);
double *p_xp = (double*)__kmpc_task_reduction_get_th_data(
gtid, tg1, &xp);
if (!ptrs[gtid]) ptrs[gtid] = p_xp;
// user's pseudo-code ==============================
*p_ip += l;
*p_xp *= (l + 1);
*p_ip += l + 1;
*p_xp *= 1.0 / (l + 2);
// ==================================================
}
}
// inner taskgroup reduces (i,k,y), i is same object as in outer one
#pragma omp taskgroup // task_reduction(-:i,k) task_reduction(+:y)
{
_task_red_item_t red_data[3];
red_data[0].shar = &ip;
red_data[0].size = sizeof(ip);
red_data[0].f_init = NULL; // RTL will zero thread-specific objects
red_data[0].f_fini = NULL; // no destructors needed
red_data[0].f_comb = (void*)&__red_int_add_comb;
red_data[0].flags = FLG;
red_data[1].shar = &kp;
red_data[1].size = sizeof(kp);
red_data[1].f_init = NULL; // RTL will zero thread-specific objects
red_data[1].f_fini = NULL; // no destructors needed
red_data[1].f_comb = (void*)&__red_llong_add_comb; // same for + and -
red_data[1].flags = FLG;
red_data[2].shar = &yp;
red_data[2].size = sizeof(yp);
red_data[2].f_init = NULL; // RTL will zero thread-specific objects
red_data[2].f_fini = NULL; // no destructors needed
red_data[2].f_comb = (void*)&__red_dbl_add_comb;
red_data[2].flags = FLG;
int gtid = __kmpc_global_thread_num(NULL);
void* tg2 = __kmpc_task_reduction_init(gtid, 3, red_data);
for( int l = 0; l < N; l += 2 ) {
#pragma omp task firstprivate(l)
// in_reduction(+:j,y) in_reduction(*:x) in_reduction(-:k)
{
int gtid = __kmpc_global_thread_num(NULL);
long long *p_jp = (long long*)__kmpc_task_reduction_get_th_data(
gtid, tg1, &jp);
long long *p_kp = (long long*)__kmpc_task_reduction_get_th_data(
gtid, tg2, &kp);
double *p_xp = (double*)__kmpc_task_reduction_get_th_data(
gtid, tg1, &xp);
double *p_yp = (double*)__kmpc_task_reduction_get_th_data(
gtid, tg2, &yp);
// user's pseudo-code ==============================
*p_jp += l;
*p_kp -= l;
*p_yp += (double)l;
*p_xp *= (l + 1);
*p_jp += l + 1;
*p_kp -= l + 1;
*p_yp += (double)(l + 1);
*p_xp *= 1.0 / (l + 2);
// =================================================
{
// the following code is here just to check __kmpc_task_reduction_get_th_data:
int tid = omp_get_thread_num();
void *addr1;
void *addr2;
addr1 = __kmpc_task_reduction_get_th_data(gtid, tg1, &xp); // from shared
addr2 = __kmpc_task_reduction_get_th_data(gtid, tg1, addr1); // from private
if (addr1 != addr2) {
#pragma omp atomic
++err;
printf("Wrong thread-specific addresses %d s:%p p:%p\n", tid, addr1, addr2);
}
// from neighbour w/o taskgroup (should start lookup from current tg2)
if (tid > 0) {
if (ptrs[tid-1]) {
addr2 = __kmpc_task_reduction_get_th_data(gtid, NULL, ptrs[tid-1]);
if (addr1 != addr2) {
#pragma omp atomic
++err;
printf("Wrong thread-specific addresses %d s:%p n:%p\n",
tid, addr1, addr2);
}
}
} else {
if (ptrs[nthreads-1]) {
addr2 = __kmpc_task_reduction_get_th_data(gtid, NULL, ptrs[nthreads-1]);
if (addr1 != addr2) {
#pragma omp atomic
++err;
printf("Wrong thread-specific addresses %d s:%p n:%p\n",
tid, addr1, addr2);
}
}
}
// ----------------------------------------------
}
}
#pragma omp task firstprivate(l)
// in_reduction(+:y) in_reduction(-:i,k)
{
int gtid = __kmpc_global_thread_num(NULL);
int *p_ip = (int*)__kmpc_task_reduction_get_th_data(
gtid, tg2, &ip);
long long *p_kp = (long long*)__kmpc_task_reduction_get_th_data(
gtid, tg2, &kp);
double *p_yp = (double*)__kmpc_task_reduction_get_th_data(
gtid, tg2, &yp);
// user's pseudo-code ==============================
*p_ip -= l;
*p_kp -= l;
*p_yp += (double)l;
*p_ip -= l + 1;
*p_kp -= l + 1;
*p_yp += (double)(l + 1);
// =================================================
}
#pragma omp task firstprivate(l)
// in_reduction(+:j) in_reduction(*:x)
{
int gtid = __kmpc_global_thread_num(NULL);
long long *p_jp = (long long*)__kmpc_task_reduction_get_th_data(
gtid, tg1, &jp);
double *p_xp = (double*)__kmpc_task_reduction_get_th_data(
gtid, tg1, &xp);
// user's pseudo-code ==============================
*p_jp += l;
*p_xp *= (l + 1);
*p_jp += l + 1;
*p_xp *= 1.0 / (l + 2);
// =================================================
}
}
} // inner reduction
for( int l = 0; l < N; l += 2 ) {
#pragma omp task firstprivate(l) // in_reduction(+:j)
{
int gtid = __kmpc_global_thread_num(NULL);
long long *p_jp = (long long*)__kmpc_task_reduction_get_th_data(
gtid, tg1, &jp);
// user's pseudo-code ==============================
*p_jp += l;
*p_jp += l + 1;
// =================================================
}
}
} // outer reduction
} // end single
} // end parallel
// check results
#if _DEBUG
printf("reduction flags = %u\n", FLG);
#endif
if (ip == is && jp == js && ks == kp &&
fabs(xp - xs) < 0.01 && fabs(yp - ys) < 0.01)
printf("passed\n");
else
printf("failed,\n ser:(%d %lld %f %lld %f)\n par:(%d %lld %f %lld %f)\n",
is, js, xs, ks, ys,
ip, jp, xp, kp, yp);
return 0;
}

View File

@@ -0,0 +1,159 @@
// 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 GRAIN 10
#define STRIDE 3
// globals
int th_counter[N];
int counter;
// Compiler-generated code (emulation)
typedef struct ident {
void* dummy;
} ident_t;
typedef struct shar {
int(*pth_counter)[N];
int *pcounter;
int *pj;
} *pshareds;
typedef struct task {
pshareds shareds;
int(* routine)(int,struct task*);
int part_id;
// privates:
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(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, 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;
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);
__kmpc_atomic_fixed4_add(NULL,gtid,&((*pshar->pth_counter)[task->th]),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;
}
int main()
{
int i, j, gtid = __kmpc_global_thread_num(NULL);
ptask task;
pshareds psh;
omp_set_dynamic(0);
counter = 0;
for( i=0; i<N; ++i )
th_counter[i] = 0;
#pragma omp parallel num_threads(N)
{
#pragma omp master
{
int gtid = __kmpc_global_thread_num(NULL);
/*
* This is what the OpenMP runtime calls correspond to:
#pragma omp taskloop num_tasks(N) lastprivate(j)
for( i=0; i<N*GRAIN*STRIDE-1; i+=STRIDE )
{
int th = omp_get_thread_num();
#pragma omp atomic
counter++;
#pragma omp atomic
th_counter[th]++;
j = i;
}
*/
task = __kmpc_omp_task_alloc(NULL,gtid,1,sizeof(struct task),sizeof(struct shar),&task_entry);
psh = task->shareds;
psh->pth_counter = &th_counter;
psh->pcounter = &counter;
psh->pj = &j;
task->lb = 0;
task->ub = N*GRAIN*STRIDE-2;
task->st = STRIDE;
__kmpc_taskloop(
NULL, // location
gtid, // gtid
task, // task structure
1, // if clause value
&task->lb, // lower bound
&task->ub, // upper bound
STRIDE, // loop increment
0, // 1 if nogroup specified
2, // schedule type: 0-none, 1-grainsize, 2-num_tasks
N, // schedule value (ignored for type 0)
(void*)&__task_dup_entry // tasks duplication routine
);
} // end master
} // end parallel
// check results
if( j != N*GRAIN*STRIDE-STRIDE ) {
printf("Error in lastprivate, %d != %d\n",j,N*GRAIN*STRIDE-STRIDE);
return 1;
}
if( counter != N*GRAIN ) {
printf("Error, counter %d != %d\n",counter,N*GRAIN);
return 1;
}
for( i=0; i<N; ++i ) {
if( th_counter[i] % GRAIN ) {
printf("Error, th_counter[%d] = %d\n",i,th_counter[i]);
return 1;
}
}
printf("passed\n");
return 0;
}

View File

@@ -0,0 +1,32 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <omp.h>
/*
* This test would hang when level instead of active level
* used to push task state.
*/
int main()
{
// If num_threads is changed to a value greater than 1, then the test passes
#pragma omp parallel num_threads(1)
{
#pragma omp parallel
printf("Hello World from thread %d\n", omp_get_thread_num());
}
printf("omp_num_threads: %d\n", omp_get_max_threads());
#pragma omp parallel
{
#pragma omp master
#pragma omp task default(none)
{
printf("%d is executing this task\n", omp_get_thread_num());
}
}
printf("pass\n");
return 0;
}

View File

@@ -0,0 +1,35 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <omp.h>
#include "omp_my_sleep.h"
/*
* This test creates tasks that themselves create a new task.
* The runtime has to take care that they are correctly freed.
*/
int main()
{
#pragma omp task
{
#pragma omp task
{
my_sleep( 0.1 );
}
}
#pragma omp parallel num_threads(2)
{
#pragma omp single
#pragma omp task
{
#pragma omp task
{
my_sleep( 0.1 );
}
}
}
printf("pass\n");
return 0;
}

View File

@@ -0,0 +1,52 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"
#include "omp_my_sleep.h"
int test_omp_task()
{
int tids[NUM_TASKS];
int i;
#pragma omp parallel
{
#pragma omp single
{
for (i = 0; i < NUM_TASKS; i++) {
/* First we have to store the value of the loop index in a new variable
* which will be private for each task because otherwise it will be overwritten
* if the execution of the task takes longer than the time which is needed to
* enter the next step of the loop!
*/
int myi;
myi = i;
#pragma omp task
{
my_sleep (SLEEPTIME);
tids[myi] = omp_get_thread_num();
} /* end of omp task */
} /* end of for */
} /* end of single */
} /*end of parallel */
/* Now we ckeck if more than one thread executed the tasks. */
for (i = 1; i < NUM_TASKS; i++) {
if (tids[0] != tids[i])
return 1;
}
return 0;
} /* end of check_parallel_for_private */
int main()
{
int i;
int num_failed=0;
for(i = 0; i < REPETITIONS; i++) {
if(!test_omp_task()) {
num_failed++;
}
}
return num_failed;
}

View File

@@ -0,0 +1,65 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"
#include "omp_my_sleep.h"
int test_omp_task_final()
{
int tids[NUM_TASKS];
int includedtids[NUM_TASKS];
int i;
int error = 0;
#pragma omp parallel
{
#pragma omp single
{
for (i = 0; i < NUM_TASKS; i++) {
/* First we have to store the value of the loop index in a new variable
* which will be private for each task because otherwise it will be overwritten
* if the execution of the task takes longer than the time which is needed to
* enter the next step of the loop!
*/
int myi;
myi = i;
#pragma omp task final(i>=10)
{
tids[myi] = omp_get_thread_num();
/* we generate included tasks for final tasks */
if(myi >= 10) {
int included = myi;
#pragma omp task
{
my_sleep (SLEEPTIME);
includedtids[included] = omp_get_thread_num();
} /* end of omp included task of the final task */
my_sleep (SLEEPTIME);
} /* end of if it is a final task*/
} /* end of omp task */
} /* end of for */
} /* end of single */
} /*end of parallel */
/* Now we ckeck if more than one thread executed the final task and its included task. */
for (i = 10; i < NUM_TASKS; i++) {
if (tids[i] != includedtids[i]) {
error++;
}
}
return (error==0);
} /* end of check_paralel_for_private */
int main()
{
int i;
int num_failed=0;
for(i = 0; i < REPETITIONS; i++) {
if(!test_omp_task_final()) {
num_failed++;
}
}
return num_failed;
}

View File

@@ -0,0 +1,51 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"
int test_omp_task_firstprivate()
{
int i;
int sum = 1234;
int known_sum;
int result = 0; /* counts the wrong sums from tasks */
known_sum = 1234 + (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
#pragma omp parallel
{
#pragma omp single
{
for (i = 0; i < NUM_TASKS; i++) {
#pragma omp task firstprivate(sum)
{
int j;
for (j = 0; j <= LOOPCOUNT; j++) {
#pragma omp flush
sum += j;
}
/* check if calculated sum was right */
if (sum != known_sum) {
#pragma omp critical
{ result++; }
}
} /* omp task */
} /* for loop */
} /* omp single */
} /* omp parallel */
return (result == 0);
}
int main()
{
int i;
int num_failed=0;
for(i = 0; i < REPETITIONS; i++) {
if(!test_omp_task_firstprivate()) {
num_failed++;
}
}
return num_failed;
}

View File

@@ -0,0 +1,43 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"
#include "omp_my_sleep.h"
int test_omp_task_if()
{
int condition_false;
int count;
int result;
count=0;
condition_false = (count == 1);
#pragma omp parallel
{
#pragma omp single
{
#pragma omp task if (condition_false) shared(count, result)
{
my_sleep (SLEEPTIME);
#pragma omp critical
result = (0 == count);
} /* end of omp task */
#pragma omp critical
count = 1;
} /* end of single */
} /*end of parallel */
return result;
}
int main()
{
int i;
int num_failed=0;
for(i = 0; i < REPETITIONS; i++) {
if(!test_omp_task_if()) {
num_failed++;
}
}
return num_failed;
}

View File

@@ -0,0 +1,47 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"
/* Utility function do spend some time in a loop */
int test_omp_task_imp_firstprivate()
{
int i=5;
int k = 0;
int result = 0;
int task_result = 1;
#pragma omp parallel firstprivate(i)
{
#pragma omp single
{
for (k = 0; k < NUM_TASKS; k++) {
#pragma omp task shared(result , task_result)
{
int j;
//check if i is private
if(i != 5)
task_result = 0;
for(j = 0; j < NUM_TASKS; j++)
i++;
//this should be firstprivate implicitly
}
}
#pragma omp taskwait
result = (task_result && i==5);
}
}
return result;
}
int main()
{
int i;
int num_failed=0;
for(i = 0; i < REPETITIONS; i++) {
if(!test_omp_task_imp_firstprivate()) {
num_failed++;
}
}
return num_failed;
}

View File

@@ -0,0 +1,22 @@
// RUN: %libomp-compile && env OMP_MAX_TASK_PRIORITY=42 %libomp-run
// Test OMP 4.5 task priorities
// Currently only API function and envirable parsing implemented.
// Test environment sets envirable: OMP_MAX_TASK_PRIORITY=42 as tested below.
#include <stdio.h>
#include <omp.h>
int main (void) {
int passed;
passed = (omp_get_max_task_priority() == 42);
printf("Got %d\n", omp_get_max_task_priority());
if (passed) {
printf("passed\n");
return 0;
}
printf("failed\n");
return 1;
}

View File

@@ -0,0 +1,53 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"
/* Utility function do spend some time in a loop */
int test_omp_task_private()
{
int i;
int known_sum;
int sum = 0;
int result = 0; /* counts the wrong sums from tasks */
known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
#pragma omp parallel
{
#pragma omp single
{
for (i = 0; i < NUM_TASKS; i++) {
#pragma omp task private(sum) shared(result, known_sum)
{
int j;
//if sum is private, initialize to 0
sum = 0;
for (j = 0; j <= LOOPCOUNT; j++) {
#pragma omp flush
sum += j;
}
/* check if calculated sum was right */
if (sum != known_sum) {
#pragma omp critical
result++;
}
} /* end of omp task */
} /* end of for */
} /* end of single */
} /* end of parallel*/
return (result == 0);
}
int main()
{
int i;
int num_failed=0;
for(i = 0; i < REPETITIONS; i++) {
if(!test_omp_task_private()) {
num_failed++;
}
}
return num_failed;
}

View File

@@ -0,0 +1,41 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"
/* Utility function do spend some time in a loop */
int test_omp_task_imp_shared()
{
int i;
int k = 0;
int result = 0;
i=0;
#pragma omp parallel
{
#pragma omp single
for (k = 0; k < NUM_TASKS; k++) {
#pragma omp task shared(i)
{
#pragma omp atomic
i++;
//this should be shared implicitly
}
}
}
result = i;
return ((result == NUM_TASKS));
}
int main()
{
int i;
int num_failed=0;
for(i = 0; i < REPETITIONS; i++) {
if(!test_omp_task_imp_shared()) {
num_failed++;
}
}
return num_failed;
}

View File

@@ -0,0 +1,109 @@
// RUN: %libomp-compile-and-run
// RUN: %libomp-compile && env KMP_TASKLOOP_MIN_TASKS=1 %libomp-run
// UNSUPPORTED: gcc
// We do not yet have the GOMP interface for taskloop
/*
* Test for taskloop
* Method: caculate how many times the iteration space is dispatched
* and judge if each dispatch has the requested grainsize
* It is possible for two adjacent chunks are executed by the same thread
*/
#include <stdio.h>
#include <omp.h>
#include <stdlib.h>
#include "omp_testsuite.h"
#define CFDMAX_SIZE 1120
int test_omp_taskloop_grainsize()
{
int result = 0;
int i, grainsize, count, tmp_count, num_off;
int *tmp, *tids, *tidsArray;
tidsArray = (int *)malloc(sizeof(int) * CFDMAX_SIZE);
tids = tidsArray;
for (grainsize = 1; grainsize < 48; ++grainsize) {
fprintf(stderr, "Grainsize %d\n", grainsize);
count = tmp_count = num_off = 0;
for (i = 0; i < CFDMAX_SIZE; ++i) {
tids[i] = -1;
}
#pragma omp parallel shared(tids)
{
#pragma omp master
#pragma omp taskloop grainsize(grainsize)
for (i = 0; i < CFDMAX_SIZE; i++) {
tids[i] = omp_get_thread_num();
}
}
for (i = 0; i < CFDMAX_SIZE; ++i) {
if (tids[i] == -1) {
fprintf(stderr, " Iteration %d not touched!\n", i);
result++;
}
}
for (i = 0; i < CFDMAX_SIZE - 1; ++i) {
if (tids[i] != tids[i + 1]) {
count++;
}
}
tmp = (int *)malloc(sizeof(int) * (count + 1));
tmp[0] = 1;
for (i = 0; i < CFDMAX_SIZE - 1; ++i) {
if (tmp_count > count) {
printf("--------------------\nTestinternal Error: List too "
"small!!!\n--------------------\n");
break;
}
if (tids[i] != tids[i + 1]) {
tmp_count++;
tmp[tmp_count] = 1;
} else {
tmp[tmp_count]++;
}
}
// is grainsize statement working?
int num_tasks = CFDMAX_SIZE / grainsize;
int multiple1 = CFDMAX_SIZE / num_tasks;
int multiple2 = CFDMAX_SIZE / num_tasks + 1;
for (i = 0; i < count; i++) {
// it is possible for 2 adjacent chunks assigned to a same thread
if (tmp[i] % multiple1 != 0 && tmp[i] % multiple2 != 0) {
num_off++;
}
}
if (num_off > 1) {
fprintf(stderr, " The number of bad chunks is %d\n", num_off);
result++;
} else {
fprintf(stderr, " Everything ok\n");
}
free(tmp);
}
free(tidsArray);
return (result==0);
}
int main()
{
int i;
int num_failed=0;
for (i = 0; i < REPETITIONS; i++) {
if (!test_omp_taskloop_grainsize()) {
num_failed++;
}
}
return num_failed;
}

View File

@@ -0,0 +1,69 @@
// RUN: %libomp-compile-and-run
// RUN: %libomp-compile && env KMP_TASKLOOP_MIN_TASKS=1 %libomp-run
// UNSUPPORTED: gcc
// We do not yet have the GOMP interface for taskloop
/*
* Test for taskloop
* Method: caculate how many times the iteration space is dispatched
* and judge if each dispatch has the requested grainsize
* It is possible for two adjacent chunks are executed by the same thread
*/
#include <stdio.h>
#include <omp.h>
#include <stdlib.h>
#include "omp_testsuite.h"
#define CFDMAX_SIZE 1120
int test_omp_taskloop_num_tasks()
{
int i;
int *tids;
int *tidsArray;
int count;
int result = 0;
int num_tasks;
for (num_tasks = 1; num_tasks < 120; ++num_tasks) {
count = 0;
tidsArray = (int *)malloc(sizeof(int) * CFDMAX_SIZE);
tids = tidsArray;
#pragma omp parallel shared(tids)
{
int i;
#pragma omp master
#pragma omp taskloop num_tasks(num_tasks)
for (i = 0; i < CFDMAX_SIZE; i++) {
tids[i] = omp_get_thread_num();
}
}
for (i = 0; i < CFDMAX_SIZE - 1; ++i) {
if (tids[i] != tids[i + 1]) {
count++;
}
}
if (count > num_tasks) {
fprintf(stderr, "counted too many tasks: (wanted %d, got %d)\n",
num_tasks, count);
result++;
}
}
return (result==0);
}
int main()
{
int i;
int num_failed=0;
for (i = 0; i < REPETITIONS; i++) {
if (!test_omp_taskloop_num_tasks()) {
num_failed++;
}
}
return num_failed;
}

View File

@@ -0,0 +1,74 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"
#include "omp_my_sleep.h"
int test_omp_taskwait()
{
int result1 = 0; /* Stores number of not finished tasks after the taskwait */
int result2 = 0; /* Stores number of wrong array elements at the end */
int array[NUM_TASKS];
int i;
/* fill array */
for (i = 0; i < NUM_TASKS; i++)
array[i] = 0;
#pragma omp parallel
{
#pragma omp single
{
for (i = 0; i < NUM_TASKS; i++) {
/* First we have to store the value of the loop index in a new variable
* which will be private for each task because otherwise it will be overwritten
* if the execution of the task takes longer than the time which is needed to
* enter the next step of the loop!
*/
int myi;
myi = i;
#pragma omp task
{
my_sleep (SLEEPTIME);
array[myi] = 1;
} /* end of omp task */
} /* end of for */
#pragma omp taskwait
/* check if all tasks were finished */
for (i = 0; i < NUM_TASKS; i++)
if (array[i] != 1)
result1++;
/* generate some more tasks which now shall overwrite
* the values in the tids array */
for (i = 0; i < NUM_TASKS; i++) {
int myi;
myi = i;
#pragma omp task
{
array[myi] = 2;
} /* end of omp task */
} /* end of for */
} /* end of single */
} /*end of parallel */
/* final check, if all array elements contain the right values: */
for (i = 0; i < NUM_TASKS; i++) {
if (array[i] != 2)
result2++;
}
return ((result1 == 0) && (result2 == 0));
}
int main()
{
int i;
int num_failed=0;
for(i = 0; i < REPETITIONS; i++) {
if(!test_omp_taskwait()) {
num_failed++;
}
}
return num_failed;
}

View File

@@ -0,0 +1,58 @@
// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"
#include "omp_my_sleep.h"
int test_omp_taskyield()
{
int i;
int count = 0;
int start_tid[NUM_TASKS];
int current_tid[NUM_TASKS];
for (i=0; i< NUM_TASKS; i++) {
start_tid[i]=0;
current_tid[i]=0;
}
#pragma omp parallel
{
#pragma omp single
{
for (i = 0; i < NUM_TASKS; i++) {
int myi = i;
#pragma omp task untied
{
my_sleep(SLEEPTIME);
start_tid[myi] = omp_get_thread_num();
#pragma omp taskyield
if((start_tid[myi] %2) ==0){
my_sleep(SLEEPTIME);
current_tid[myi] = omp_get_thread_num();
} /*end of if*/
} /* end of omp task */
} /* end of for */
} /* end of single */
} /* end of parallel */
for (i=0;i<NUM_TASKS; i++) {
//printf("start_tid[%d]=%d, current_tid[%d]=%d\n",
//i, start_tid[i], i , current_tid[i]);
if (current_tid[i] == start_tid[i])
count++;
}
return (count<NUM_TASKS);
}
int main()
{
int i;
int num_failed=0;
for(i = 0; i < REPETITIONS; i++) {
if(!test_omp_taskyield()) {
num_failed++;
}
}
return num_failed;
}