teak-llvm/openmp/runtime/test/tasking/kmp_taskloop.c
Roman Lebedev 781a0896b0 [OpenMP] Fixes for LIBOMP_OMP_VERSION=45/40
Summary:
I have discovered this because i wanted to experiment with
building static libomp (with openmp-4.0 support only)
for debugging purposes.

There are three kinds of problems here:
1. `__kmp_compare_and_store_acq()` simply does not exist.
   It was added in D47903 by @jlpeyton.
   I'm guessing `__kmp_atomic_compare_store_acq()` was meant.
2. In `__kmp_is_ticket_lock_initialized()`,
   `lck->lk.initialized` is `std::atomic<bool>`,
   while `lck` is `kmp_ticket_lock_t *`.
   Naturally, they can't be equality-compared.
   Either, it should return the value read from `lck->lk.initialized`,
   or do what `__kmp_is_queuing_lock_initialized()` does,
   compare the passed pointer with the field in the struct
   pointed by the pointer. I think the latter is correct-er choice here.
3. Tests were not versioned.
   They assume that `LIBOMP_OMP_VERSION` is at the latest version.

This does not touch LIBOMP_OMP_VERSION=30. That is still broken.

Reviewers: jlpeyton, Hahnfeld, AndreyChurbanov

Reviewed By: AndreyChurbanov

Subscribers: guansong, jfb, openmp-commits, jlpeyton

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D55496

llvm-svn: 349260
2018-12-15 09:23:39 +00:00

161 lines
4.1 KiB
C

// RUN: %libomp-compile-and-run
// RUN: %libomp-compile && env KMP_TASKLOOP_MIN_TASKS=1 %libomp-run
// REQUIRES: openmp-4.5
#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;
}