1 // RUN: %libomp-compile-and-run 2 // RUN: %libomp-compile && env KMP_TASKLOOP_MIN_TASKS=1 %libomp-run 3 4 #include <stdio.h> 5 #include <omp.h> 6 #include "omp_my_sleep.h" 7 8 #define N 4 9 #define ST 3 10 #define UB 118 11 #define LB 0 12 13 // globals 14 int counter; 15 int task_count; 16 17 // Compiler-generated code (emulation) 18 typedef struct ident { 19 void* dummy; 20 } ident_t; 21 22 typedef struct shar { 23 int *pcounter; 24 int *pj; 25 int *ptask_count; 26 } *pshareds; 27 28 typedef struct task { 29 pshareds shareds; 30 int(* routine)(int,struct task*); 31 int part_id; 32 unsigned long long lb; // library always uses ULONG 33 unsigned long long ub; 34 int st; 35 int last; 36 int i; 37 int j; 38 int th; 39 } *ptask, kmp_task_t; 40 41 typedef int(* task_entry_t)( int, ptask ); 42 43 void 44 __task_dup_entry(ptask task_dst, ptask task_src, int lastpriv) 45 { 46 // setup lastprivate flag 47 task_dst->last = lastpriv; 48 // could be constructor calls here... 49 } 50 51 // OpenMP RTL interfaces 52 typedef unsigned long long kmp_uint64; 53 typedef long long kmp_int64; 54 55 #ifdef __cplusplus 56 extern "C" { 57 #endif 58 void 59 __kmpc_taskloop_5(ident_t *loc, int gtid, kmp_task_t *task, int if_val, 60 kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, 61 int nogroup, int sched, kmp_int64 grainsize, int modifier, 62 void *task_dup); 63 ptask 64 __kmpc_omp_task_alloc(ident_t *loc, int gtid, int flags, 65 size_t sizeof_kmp_task_t, size_t sizeof_shareds, 66 task_entry_t task_entry); 67 void __kmpc_atomic_fixed4_add(void *id_ref, int gtid, int * lhs, int rhs); 68 int __kmpc_global_thread_num(void *id_ref); 69 #ifdef __cplusplus 70 } 71 #endif 72 73 // User's code 74 int task_entry(int gtid, ptask task) 75 { 76 pshareds pshar = task->shareds; 77 __kmpc_atomic_fixed4_add(NULL, gtid, pshar->ptask_count, 1); 78 79 for (task->i = task->lb; task->i <= (int)task->ub; task->i += task->st) { 80 task->th = omp_get_thread_num(); 81 __kmpc_atomic_fixed4_add(NULL,gtid,pshar->pcounter,1); 82 task->j = task->i; 83 } 84 my_sleep( 0.1 ); // sleep 100 ms in order to allow other threads to steal tasks 85 if (task->last) { 86 *(pshar->pj) = task->j; // lastprivate 87 } 88 return 0; 89 } 90 91 void task_loop(int sched_type, int sched_val, int modifier) 92 { 93 int i, j, gtid = __kmpc_global_thread_num(NULL); 94 ptask task; 95 pshareds psh; 96 omp_set_dynamic(0); 97 counter = 0; 98 task_count = 0; 99 #pragma omp parallel num_threads(N) 100 { 101 #pragma omp master 102 { 103 int gtid = __kmpc_global_thread_num(NULL); 104 task = __kmpc_omp_task_alloc(NULL, gtid, 1, sizeof(struct task), 105 sizeof(struct shar), &task_entry); 106 psh = task->shareds; 107 psh->pcounter = &counter; 108 psh->ptask_count = &task_count; 109 psh->pj = &j; 110 task->lb = LB; 111 task->ub = UB; 112 task->st = ST; 113 114 __kmpc_taskloop_5( 115 NULL, // location 116 gtid, // gtid 117 task, // task structure 118 1, // if clause value 119 &task->lb, // lower bound 120 &task->ub, // upper bound 121 ST, // loop increment 122 0, // 1 if nogroup specified 123 sched_type, // schedule type: 0-none, 1-grainsize, 2-num_tasks 124 sched_val, // schedule value (ignored for type 0) 125 modifier, // strict modifier 126 (void*)&__task_dup_entry // tasks duplication routine 127 ); 128 } // end master 129 } // end parallel 130 // check results 131 int tc; 132 if (ST == 1) { // most common case 133 tc = UB - LB + 1; 134 } else if (ST < 0) { 135 tc = (LB - UB) / (-ST) + 1; 136 } else { // ST > 0 137 tc = (UB - LB) / ST + 1; 138 } 139 int count; 140 if (sched_type == 1) { 141 count = (sched_val > tc) ? 1 : (tc + sched_val - 1) / sched_val; 142 } else { 143 count = (sched_val > tc) ? tc : sched_val; 144 } 145 if (j != LB + (tc - 1) * ST) { 146 printf("Error in lastprivate, %d != %d\n", j, LB + (tc - 1) * ST); 147 exit(1); 148 } 149 if (counter != tc) { 150 printf("Error, counter %d != %d\n", counter, tc); 151 exit(1); 152 } 153 if (task_count != count) { 154 printf("Error, task count %d != %d\n", task_count, count); 155 exit(1); 156 } 157 } 158 159 int main(int argc, char *argv[]) { 160 task_loop(1, 6, 1); // create 7 tasks 161 task_loop(2, 6, 1); // create 6 tasks 162 task_loop(1, 50, 1); // create 1 task 163 task_loop(2, 50, 1); // create 40 tasks 164 165 printf("Test passed\n"); 166 return 0; 167 } 168