// RUN: %libomp-compile-and-run // RUN: %libomp-compile && env KMP_TASKLOOP_MIN_TASKS=1 %libomp-run #include #include #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; ishareds; 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