/* { dg-do run } */ /* { dg-set-target-env-var OMP_CANCELLATION "true" } */ #include #include struct T { struct T *children[2]; int val; }; struct T * search (struct T *tree, int val, int lvl) { if (tree == NULL || tree->val == val) return tree; struct T *ret = NULL; int i; for (i = 0; i < 2; i++) #pragma omp task shared(ret) if(lvl < 10) { struct T *r = search (tree->children[i], val, lvl + 1); if (r) { #pragma omp atomic write ret = r; #pragma omp cancel taskgroup } } #pragma omp taskwait return ret; } struct T * searchp (struct T *tree, int val) { struct T *ret; #pragma omp parallel shared(ret) firstprivate (tree, val) #pragma omp single #pragma omp taskgroup ret = search (tree, val, 0); return ret; } int main () { /* Must be power of two minus 1. */ int size = 0x7ffff; struct T *trees = (struct T *) malloc (size * sizeof (struct T)); if (trees == NULL) return 0; int i, l = 1, b = 0; for (i = 0; i < size; i++) { if (i == l) { b = l; l = l * 2 + 1; } trees[i].val = i; trees[i].children[0] = l == size ? NULL : &trees[l + (i - b) * 2]; trees[i].children[1] = l == size ? NULL : &trees[l + (i - b) * 2 + 1]; } for (i = 0; i < 50; i++) { int v = random () & size; if (searchp (&trees[0], v) != &trees[v]) abort (); } free (trees); return 0; }