This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp3] Implement new OpenMP 3.0 omp_* entrypoints in libgomp
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 23 Oct 2007 16:06:10 -0400
- Subject: [gomp3] Implement new OpenMP 3.0 omp_* entrypoints in libgomp
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
Tested on x86_64-linux, committed to gomp-3_0-branch.
2007-10-23 Jakub Jelinek <jakub@redhat.com>
* libgomp.h (gomp_schedule_type): Reorder enum to match
omp_sched_t.
(struct gomp_team_state): Add level field.
* team.c (gomp_thread_start): Clear ts.level.
(gomp_team_start): Initialize ts.level.
* parallel.c (omp_in_parallel): Update comment.
(omp_get_level, omp_get_ancestor_thread_num,
omp_get_team_size, omp_get_active_level): New functions,
add ialias.
* env.c (omp_set_schedule, omp_get_schedule, omp_get_thread_limit,
omp_set_max_active_levels, omp_get_max_active_levels): New functions,
add ialias.
* omp_lib.f90.in (omp_get_ancestor_thread_num): Handle
integer (8) argument.
* fortran.c (omp_set_schedule, omp_get_schedule,
omp_get_thread_limit, omp_set_max_active_levels,
omp_get_max_active_levels, omp_get_level,
omp_get_ancestor_thread_num, omp_get_team_size,
omp_get_active_level): New ialias_redirect.
(omp_set_schedule_, omp_set_schedule_8_,
omp_get_schedule_, omp_get_schedule_8_, omp_get_thread_limit_,
omp_set_max_active_levels_, omp_set_max_active_levels_8_,
omp_get_max_active_levels_, omp_get_level_,
omp_get_ancestor_thread_num_, omp_get_ancestor_thread_num_8_,
omp_get_team_size_, omp_get_team_size_8_, omp_get_active_level_):
New functions.
* libgomp.map (omp_set_schedule, omp_get_schedule,
omp_get_thread_limit, omp_set_max_active_levels,
omp_get_max_active_levels, omp_get_level,
omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level,
omp_set_schedule_, omp_set_schedule_8_,
omp_get_schedule_, omp_get_schedule_8_, omp_get_thread_limit_,
omp_set_max_active_levels_, omp_set_max_active_levels_8_,
omp_get_max_active_levels_, omp_get_level_,
omp_get_ancestor_thread_num_, omp_get_ancestor_thread_num_8_,
omp_get_team_size_, omp_get_team_size_8_, omp_get_active_level_):
New exports @@OMP_3.0.
* testsuite/libgomp.fortran/nested1.f90: New test.
* testsuite/libgomp.fortran/lib4.f90: New test.
* testsuite/libgomp.c/lib-2.c: New test.
* testsuite/libgomp.c/nested-3.c: New test.
--- libgomp/parallel.c.jj 2007-10-22 22:11:45.000000000 +0200
+++ libgomp/parallel.c 2007-10-23 20:41:32.000000000 +0200
@@ -102,11 +102,12 @@ omp_get_thread_num (void)
return gomp_thread ()->ts.team_id;
}
-/* ??? This isn't right. The definition of this function is false if any
- of the IF clauses for any of the parallels is false. Which is not the
- same thing as any outer team having more than one thread. */
+/* This wasn't right for OpenMP 2.5. Active region used to be
+ one where IF clause doesn't evaluate to false, starting with
+ 3.0 it is one with more than one thread in the team. */
-int omp_in_parallel (void)
+int
+omp_in_parallel (void)
{
struct gomp_team *team = gomp_thread ()->ts.team;
@@ -120,7 +121,58 @@ int omp_in_parallel (void)
return false;
}
+int
+omp_get_level (void)
+{
+ return gomp_thread ()->ts.level;
+}
+
+int
+omp_get_ancestor_thread_num (int level)
+{
+ struct gomp_team_state *ts = &gomp_thread ()->ts;
+ if (level < 0 || level > ts->level)
+ return -1;
+ for (level = ts->level - level; level > 0; --level)
+ ts = &ts->team->prev_ts;
+ return ts->team_id;
+}
+
+int
+omp_get_team_size (int level)
+{
+ struct gomp_team_state *ts = &gomp_thread ()->ts;
+ if (level < 0 || level > ts->level)
+ return -1;
+ for (level = ts->level - level; level > 0; --level)
+ ts = &ts->team->prev_ts;
+ if (ts->team == NULL)
+ return 1;
+ else
+ return ts->team->nthreads;
+}
+
+int
+omp_get_active_level (void)
+{
+ struct gomp_team *team = gomp_thread ()->ts.team;
+ int active = 0;
+
+ while (team)
+ {
+ if (team->nthreads > 1)
+ ++active;
+ team = team->prev_ts.team;
+ }
+
+ return active;
+}
+
ialias (omp_get_num_threads)
ialias (omp_get_max_threads)
ialias (omp_get_thread_num)
ialias (omp_in_parallel)
+ialias (omp_get_level)
+ialias (omp_get_ancestor_thread_num)
+ialias (omp_get_team_size)
+ialias (omp_get_active_level)
--- libgomp/team.c.jj 2007-10-22 22:11:45.000000000 +0200
+++ libgomp/team.c 2007-10-23 17:42:30.000000000 +0200
@@ -115,6 +115,7 @@ gomp_thread_start (void *xdata)
thr->ts.team = NULL;
thr->ts.work_share = NULL;
thr->ts.team_id = 0;
+ thr->ts.level = 0;
thr->ts.work_share_generation = 0;
thr->ts.static_trip = 0;
@@ -198,6 +199,7 @@ gomp_team_start (void (*fn) (void *), vo
thr->ts.team = team;
thr->ts.work_share = work_share;
thr->ts.team_id = 0;
+ ++thr->ts.level;
thr->ts.work_share_generation = 0;
thr->ts.static_trip = 0;
@@ -243,6 +245,7 @@ gomp_team_start (void (*fn) (void *), vo
nthr->ts.team = team;
nthr->ts.work_share = work_share;
nthr->ts.team_id = i;
+ nthr->ts.level = team->prev_ts.level + 1;
nthr->ts.work_share_generation = 0;
nthr->ts.static_trip = 0;
nthr->fn = fn;
@@ -289,6 +292,7 @@ gomp_team_start (void (*fn) (void *), vo
start_data->ts.team = team;
start_data->ts.work_share = work_share;
start_data->ts.team_id = i;
+ start_data->ts.level = team->prev_ts.level + 1;
start_data->ts.work_share_generation = 0;
start_data->ts.static_trip = 0;
start_data->fn = fn;
--- libgomp/libgomp.h.jj 2007-10-22 22:39:59.000000000 +0200
+++ libgomp/libgomp.h 2007-10-23 17:31:24.000000000 +0200
@@ -57,10 +57,10 @@
enum gomp_schedule_type
{
+ GFS_RUNTIME,
GFS_STATIC,
GFS_DYNAMIC,
GFS_GUIDED,
- GFS_RUNTIME,
GFS_AUTO
};
@@ -143,6 +143,9 @@ struct gomp_team_state
threads in the team. */
unsigned team_id;
+ /* Nesting level. */
+ unsigned level;
+
/* The work share "generation" is a number that increases by one for
each work share construct encountered in the dynamic flow of the
program. It is used to find the control data for the work share
--- libgomp/omp_lib.f90.in.jj 2007-10-23 15:24:22.000000000 +0200
+++ libgomp/omp_lib.f90.in 2007-10-23 18:07:13.000000000 +0200
@@ -259,11 +259,17 @@
end function omp_get_level
end interface
- interface
- function omp_get_ancestor_thread_num ()
+ interface omp_get_ancestor_thread_num
+ function omp_get_ancestor_thread_num (level)
use omp_lib_kinds
+ integer (4), intent (in) :: level
integer (omp_integer_kind) :: omp_get_ancestor_thread_num
end function omp_get_ancestor_thread_num
+ function omp_get_ancestor_thread_num_8 (level)
+ use omp_lib_kinds
+ integer (8), intent (in) :: level
+ integer (omp_integer_kind) :: omp_get_ancestor_thread_num
+ end function omp_get_ancestor_thread_num_8
end interface
interface omp_get_team_size
--- libgomp/fortran.c.jj 2007-10-22 22:11:45.000000000 +0200
+++ libgomp/fortran.c 2007-10-23 19:25:42.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2007 Free Software Foundation, Inc.
Contributed by Jakub Jelinek <jakub@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -60,6 +60,15 @@ ialias_redirect (omp_get_num_threads)
ialias_redirect (omp_get_thread_num)
ialias_redirect (omp_get_wtick)
ialias_redirect (omp_get_wtime)
+ialias_redirect (omp_set_schedule)
+ialias_redirect (omp_get_schedule)
+ialias_redirect (omp_get_thread_limit)
+ialias_redirect (omp_set_max_active_levels)
+ialias_redirect (omp_get_max_active_levels)
+ialias_redirect (omp_get_level)
+ialias_redirect (omp_get_ancestor_thread_num)
+ialias_redirect (omp_get_team_size)
+ialias_redirect (omp_get_active_level)
#endif
void
@@ -225,3 +234,97 @@ omp_get_wtime_ (void)
{
return omp_get_wtime ();
}
+
+void
+omp_set_schedule_ (const int32_t *kind, const int32_t *modifier)
+{
+ omp_set_schedule (*kind, *modifier);
+}
+
+void
+omp_set_schedule_8_ (const int32_t *kind, const int64_t *modifier)
+{
+ omp_set_schedule (*kind, *modifier);
+}
+
+int32_t
+omp_get_schedule_ (int32_t *kind, int32_t *modifier)
+{
+ omp_sched_t k;
+ int m, r;
+ r = omp_get_schedule (&k, &m);
+ *kind = k;
+ *modifier = m;
+ return r;
+}
+
+int32_t
+omp_get_schedule_8_ (int32_t *kind, int64_t *modifier)
+{
+ omp_sched_t k;
+ int m, r;
+ r = omp_get_schedule (&k, &m);
+ *kind = k;
+ *modifier = m;
+ return r;
+}
+
+int32_t
+omp_get_thread_limit_ (void)
+{
+ return omp_get_thread_limit ();
+}
+
+void
+omp_set_max_active_levels_ (const int32_t *levels)
+{
+ omp_set_max_active_levels (*levels);
+}
+
+void
+omp_set_max_active_levels_8_ (const int64_t *levels)
+{
+ omp_set_max_active_levels (*levels);
+}
+
+int32_t
+omp_get_max_active_levels_ (void)
+{
+ return omp_get_max_active_levels ();
+}
+
+int32_t
+omp_get_level_ (void)
+{
+ return omp_get_level ();
+}
+
+int32_t
+omp_get_ancestor_thread_num_ (const int32_t *level)
+{
+ return omp_get_ancestor_thread_num (*level);
+}
+
+int32_t
+omp_get_ancestor_thread_num_8_ (const int64_t *level)
+{
+ return omp_get_ancestor_thread_num (*level);
+}
+
+int32_t
+omp_get_team_size_ (const int32_t *level)
+{
+ return omp_get_team_size (*level);
+}
+
+int32_t
+omp_get_team_size_8_ (const int64_t *level)
+{
+ return omp_get_team_size (*level);
+}
+
+int32_t
+omp_get_active_level_ (void)
+{
+ return omp_get_active_level ();
+}
--- libgomp/env.c.jj 2007-10-22 23:01:18.000000000 +0200
+++ libgomp/env.c 2007-10-23 19:26:58.000000000 +0200
@@ -13,7 +13,7 @@
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details.
- You should have received a copy of the GNU Lesser General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with libgomp; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
@@ -45,8 +45,8 @@ unsigned long gomp_run_sched_chunk = 1;
unsigned short *gomp_cpu_affinity;
bool gomp_active_wait_policy = false;
size_t gomp_cpu_affinity_len;
-unsigned long gomp_max_active_levels_var = -1;
-unsigned long gomp_thread_limit_var = -1;
+unsigned long gomp_max_active_levels_var = INT_MAX;
+unsigned long gomp_thread_limit_var = INT_MAX;
/* Parse the OMP_SCHEDULE environment variable. */
@@ -216,7 +216,7 @@ parse_stacksize (const char *name, unsig
return false;
}
-/* Parse a boolean value for environment variable NAME and store the
+/* Parse a boolean value for environment variable NAME and store the
result in VALUE. */
static void
@@ -248,7 +248,7 @@ parse_boolean (const char *name, bool *v
gomp_error ("Invalid value for environment variable %s", name);
}
-/* Parse the OMP_WAIT_POLICY environment variable and store the
+/* Parse the OMP_WAIT_POLICY environment variable and store the
result in gomp_active_wait_policy. */
static void
@@ -451,8 +451,61 @@ omp_get_nested (void)
return gomp_nest_var;
}
+void
+omp_set_schedule (omp_sched_t kind, int modifier)
+{
+ switch (kind)
+ {
+ case omp_sched_static:
+ case omp_sched_dynamic:
+ case omp_sched_guided:
+ if (modifier < 1)
+ modifier = 1;
+ gomp_run_sched_chunk = modifier;
+ break;
+ case omp_sched_auto:
+ break;
+ default:
+ return;
+ }
+ gomp_run_sched_var = kind;
+}
+
+int
+omp_get_schedule (omp_sched_t *kind, int *modifier)
+{
+ *kind = gomp_run_sched_var;
+ *modifier = gomp_run_sched_chunk;
+ /* FIXME: What is this supposed to return? */
+ return 0;
+}
+
+int
+omp_get_thread_limit (void)
+{
+ return gomp_thread_limit_var;
+}
+
+void
+omp_set_max_active_levels (int max_levels)
+{
+ if (max_levels > 0)
+ gomp_max_active_levels_var = max_levels;
+}
+
+int
+omp_get_max_active_levels (void)
+{
+ return gomp_max_active_levels_var;
+}
+
ialias (omp_set_dynamic)
ialias (omp_set_nested)
ialias (omp_set_num_threads)
ialias (omp_get_dynamic)
ialias (omp_get_nested)
+ialias (omp_set_schedule)
+ialias (omp_get_schedule)
+ialias (omp_get_thread_limit)
+ialias (omp_set_max_active_levels)
+ialias (omp_get_max_active_levels)
--- libgomp/libgomp.map.jj 2007-10-22 22:11:45.000000000 +0200
+++ libgomp/libgomp.map 2007-10-23 18:07:26.000000000 +0200
@@ -55,6 +55,33 @@ OMP_2.0 {
omp_get_wtime_;
} OMP_1.0;
+OMP_3.0 {
+ global:
+ omp_set_schedule;
+ omp_set_schedule_;
+ omp_set_schedule_8_;
+ omp_get_schedule;
+ omp_get_schedule_;
+ omp_get_schedule_8_;
+ omp_get_thread_limit;
+ omp_get_thread_limit_;
+ omp_set_max_active_levels;
+ omp_set_max_active_levels_;
+ omp_set_max_active_levels_8_;
+ omp_get_max_active_levels;
+ omp_get_max_active_levels_;
+ omp_get_level;
+ omp_get_level_;
+ omp_get_ancestor_thread_num;
+ omp_get_ancestor_thread_num_;
+ omp_get_ancestor_thread_num_8_;
+ omp_get_team_size;
+ omp_get_team_size_;
+ omp_get_team_size_8_;
+ omp_get_active_level;
+ omp_get_active_level_;
+} OMP_2.0;
+
GOMP_1.0 {
global:
GOMP_atomic_end;
--- libgomp/testsuite/libgomp.fortran/nested1.f90.jj 2007-10-23 20:44:16.000000000 +0200
+++ libgomp/testsuite/libgomp.fortran/nested1.f90 2007-10-23 21:09:26.000000000 +0200
@@ -0,0 +1,87 @@
+! { dg-do run }
+program nested1
+ use omp_lib
+ integer :: e1, e2, e3, e
+ integer :: tn1, tn2, tn3
+ e1 = 0
+ e2 = 0
+ e3 = 0
+ call omp_set_nested (.true.)
+ call omp_set_dynamic (.false.)
+ if (omp_in_parallel ()) call abort
+ if (omp_get_num_threads ().ne.1) call abort
+ if (omp_get_level ().ne.0) call abort
+ if (omp_get_ancestor_thread_num (0).ne.0) call abort
+ if (omp_get_ancestor_thread_num (-1).ne.-1) call abort
+ if (omp_get_ancestor_thread_num (1).ne.-1) call abort
+ if (omp_get_team_size (0).ne.1) call abort
+ if (omp_get_team_size (-1).ne.-1) call abort
+ if (omp_get_team_size (1).ne.-1) call abort
+ if (omp_get_active_level ().ne.0) call abort
+!$omp parallel num_threads (4) private (e, tn1)
+ e = 0
+ tn1 = omp_get_thread_num ()
+ if (.not.omp_in_parallel ()) e = e + 1
+ if (omp_get_num_threads ().ne.4) e = e + 1
+ if (tn1.lt.0.or.tn1.ge.4) e = e + 1
+ if (omp_get_level ().ne.1) e = e + 1
+ if (omp_get_ancestor_thread_num (0).ne.0) e = e + 1
+ if (omp_get_ancestor_thread_num (1).ne.tn1) e = e + 1
+ if (omp_get_ancestor_thread_num (-1).ne.-1) e = e + 1
+ if (omp_get_ancestor_thread_num (2).ne.-1) e = e + 1
+ if (omp_get_team_size (0).ne.1) e = e + 1
+ if (omp_get_team_size (1).ne.4) e = e + 1
+ if (omp_get_team_size (-1).ne.-1) e = e + 1
+ if (omp_get_team_size (2).ne.-1) e = e + 1
+ if (omp_get_active_level ().ne.1) e = e + 1
+ !$omp atomic
+ e1 = e1 + e
+!$omp parallel num_threads (5) if (.false.) firstprivate (tn1) &
+!$omp& private (e, tn2)
+ e = 0
+ tn2 = omp_get_thread_num ()
+ if (.not.omp_in_parallel ()) e = e + 1
+ if (omp_get_num_threads ().ne.1) e = e + 1
+ if (tn2.ne.0) e = e + 1
+ if (omp_get_level ().ne.2) e = e + 1
+ if (omp_get_ancestor_thread_num (0).ne.0) e = e + 1
+ if (omp_get_ancestor_thread_num (1).ne.tn1) e = e + 1
+ if (omp_get_ancestor_thread_num (2).ne.tn2) e = e + 1
+ if (omp_get_ancestor_thread_num (-1).ne.-1) e = e + 1
+ if (omp_get_ancestor_thread_num (3).ne.-1) e = e + 1
+ if (omp_get_team_size (0).ne.1) e = e + 1
+ if (omp_get_team_size (1).ne.4) e = e + 1
+ if (omp_get_team_size (2).ne.1) e = e + 1
+ if (omp_get_team_size (-1).ne.-1) e = e + 1
+ if (omp_get_team_size (3).ne.-1) e = e + 1
+ if (omp_get_active_level ().ne.1) e = e + 1
+ !$omp atomic
+ e2 = e2 + e
+!$omp parallel num_threads (2) firstprivate (tn1, tn2) &
+!$omp& private (e, tn3)
+ e = 0
+ tn3 = omp_get_thread_num ()
+ if (.not.omp_in_parallel ()) e = e + 1
+ if (omp_get_num_threads ().ne.2) e = e + 1
+ if (tn3.lt.0.or.tn3.ge.2) e = e + 1
+ if (omp_get_level ().ne.3) e = e + 1
+ if (omp_get_ancestor_thread_num (0).ne.0) e = e + 1
+ if (omp_get_ancestor_thread_num (1).ne.tn1) e = e + 1
+ if (omp_get_ancestor_thread_num (2).ne.tn2) e = e + 1
+ if (omp_get_ancestor_thread_num (3).ne.tn3) e = e + 1
+ if (omp_get_ancestor_thread_num (-1).ne.-1) e = e + 1
+ if (omp_get_ancestor_thread_num (4).ne.-1) e = e + 1
+ if (omp_get_team_size (0).ne.1) e = e + 1
+ if (omp_get_team_size (1).ne.4) e = e + 1
+ if (omp_get_team_size (2).ne.1) e = e + 1
+ if (omp_get_team_size (3).ne.2) e = e + 1
+ if (omp_get_team_size (-1).ne.-1) e = e + 1
+ if (omp_get_team_size (4).ne.-1) e = e + 1
+ if (omp_get_active_level ().ne.2) e = e + 1
+ !$omp atomic
+ e3 = e3 + e
+!$omp end parallel
+!$omp end parallel
+!$omp end parallel
+ if (e1.ne.0.or.e2.ne.0.or.e3.ne.0) call abort
+end program nested1
--- libgomp/testsuite/libgomp.fortran/lib4.f90.jj 2007-10-23 21:29:04.000000000 +0200
+++ libgomp/testsuite/libgomp.fortran/lib4.f90 2007-10-23 21:35:58.000000000 +0200
@@ -0,0 +1,16 @@
+! { dg-do run }
+
+program lib4
+ use omp_lib
+ integer (omp_sched_kind) :: kind
+ integer :: modifier
+ call omp_set_schedule (omp_sched_static, 32)
+ call omp_get_schedule (kind, modifier)
+ if (kind.ne.omp_sched_static.or.modifier.ne.32) call abort
+ call omp_set_schedule (omp_sched_dynamic, 4)
+ call omp_get_schedule (kind, modifier)
+ if (kind.ne.omp_sched_dynamic.or.modifier.ne.4) call abort
+ if (omp_get_thread_limit ().lt.0) call abort
+ call omp_set_max_active_levels (6)
+ if (omp_get_max_active_levels ().ne.6) call abort
+end program lib4
--- libgomp/testsuite/libgomp.c/lib-2.c.jj 2007-10-23 21:28:15.000000000 +0200
+++ libgomp/testsuite/libgomp.c/lib-2.c 2007-10-23 21:28:06.000000000 +0200
@@ -0,0 +1,25 @@
+#include <stdlib.h>
+#include <omp.h>
+
+int
+main (void)
+{
+ omp_sched_t kind;
+ int modifier;
+
+ omp_set_schedule (omp_sched_static, 32);
+ omp_get_schedule (&kind, &modifier);
+ if (kind != omp_sched_static || modifier != 32)
+ abort ();
+ omp_set_schedule (omp_sched_guided, 4);
+ omp_get_schedule (&kind, &modifier);
+ if (kind != omp_sched_guided || modifier != 4)
+ abort ();
+ if (omp_get_thread_limit () < 0)
+ abort ();
+ omp_set_max_active_levels (6);
+ if (omp_get_max_active_levels () != 6)
+ abort ();
+
+ return 0;
+}
--- libgomp/testsuite/libgomp.c/nested-3.c.jj 2007-10-23 20:37:09.000000000 +0200
+++ libgomp/testsuite/libgomp.c/nested-3.c 2007-10-23 21:13:26.000000000 +0200
@@ -0,0 +1,89 @@
+#include <omp.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main (void)
+{
+ int e[3];
+
+ memset (e, '\0', sizeof (e));
+ omp_set_nested (1);
+ omp_set_dynamic (0);
+ if (omp_in_parallel ()
+ || omp_get_level () != 0
+ || omp_get_ancestor_thread_num (0) != 0
+ || omp_get_ancestor_thread_num (-1) != -1
+ || omp_get_ancestor_thread_num (1) != -1
+ || omp_get_team_size (0) != 1
+ || omp_get_team_size (-1) != -1
+ || omp_get_team_size (1) != -1
+ || omp_get_active_level () != 0)
+ abort ();
+#pragma omp parallel num_threads (4)
+ {
+ int tn1 = omp_get_thread_num ();
+ if (omp_in_parallel () != 1
+ || omp_get_num_threads () != 4
+ || tn1 >= 4 || tn1 < 0
+ || omp_get_level () != 1
+ || omp_get_ancestor_thread_num (0) != 0
+ || omp_get_ancestor_thread_num (1) != tn1
+ || omp_get_ancestor_thread_num (-1) != -1
+ || omp_get_ancestor_thread_num (2) != -1
+ || omp_get_team_size (0) != 1
+ || omp_get_team_size (1) != omp_get_num_threads ()
+ || omp_get_team_size (-1) != -1
+ || omp_get_team_size (2) != -1
+ || omp_get_active_level () != 1)
+ #pragma omp atomic
+ e[0] += 1;
+ #pragma omp parallel if (0) num_threads(5) firstprivate(tn1)
+ {
+ int tn2 = omp_get_thread_num ();
+ if (omp_in_parallel () != 1
+ || omp_get_num_threads () != 1
+ || tn2 != 0
+ || omp_get_level () != 2
+ || omp_get_ancestor_thread_num (0) != 0
+ || omp_get_ancestor_thread_num (1) != tn1
+ || omp_get_ancestor_thread_num (2) != tn2
+ || omp_get_ancestor_thread_num (-1) != -1
+ || omp_get_ancestor_thread_num (3) != -1
+ || omp_get_team_size (0) != 1
+ || omp_get_team_size (1) != 4
+ || omp_get_team_size (2) != 1
+ || omp_get_team_size (-1) != -1
+ || omp_get_team_size (3) != -1
+ || omp_get_active_level () != 1)
+ #pragma omp atomic
+ e[1] += 1;
+ #pragma omp parallel num_threads(2) firstprivate(tn1, tn2)
+ {
+ int tn3 = omp_get_thread_num ();
+ if (omp_in_parallel () != 1
+ || omp_get_num_threads () != 2
+ || tn3 > 1 || tn3 < 0
+ || omp_get_level () != 3
+ || omp_get_ancestor_thread_num (0) != 0
+ || omp_get_ancestor_thread_num (1) != tn1
+ || omp_get_ancestor_thread_num (2) != tn2
+ || omp_get_ancestor_thread_num (3) != tn3
+ || omp_get_ancestor_thread_num (-1) != -1
+ || omp_get_ancestor_thread_num (4) != -1
+ || omp_get_team_size (0) != 1
+ || omp_get_team_size (1) != 4
+ || omp_get_team_size (2) != 1
+ || omp_get_team_size (3) != 2
+ || omp_get_team_size (-1) != -1
+ || omp_get_team_size (4) != -1
+ || omp_get_active_level () != 2)
+ #pragma omp atomic
+ e[2] += 1;
+ }
+ }
+ }
+ if (e[0] || e[1] || e[2])
+ abort ();
+ return 0;
+}
Jakub