aboutsummaryrefslogtreecommitdiff
path: root/libgomp
diff options
context:
space:
mode:
authorjakub <>2011-08-02 16:13:29 +0000
committerjakub <>2011-08-02 16:13:29 +0000
commit293eb20ff0caab9e84acb4907bfd52777ae546af (patch)
tree2f3013a777c51a67a52b10f839e1bd56903dc5ba /libgomp
parentd2613009c227dfcb01f0eaea011f3e8a2ea72934 (diff)
Merge from gomp-3_1-branch branch:
2011-08-02 Jakub Jelinek <jakub@redhat.com> gcc/ * c-parser.c (enum c_parser_prec): New enum, moved from within c_parser_binary_expression. (c_parser_binary_expression): Add PREC argument. Stop parsing if operator has lower or equal precedence than PREC. (c_parser_conditional_expression, c_parser_omp_for_loop): Adjust callers. (c_parser_omp_atomic): Handle parsing OpenMP 3.1 atomics. Adjust c_finish_omp_atomic caller. (c_parser_omp_taskyield): New function. (c_parser_pragma): Handle PRAGMA_OMP_TASKYIELD. (c_parser_omp_clause_name): Handle final and mergeable clauses. (c_parser_omp_clause_final, c_parser_omp_clause_mergeable): New functions. (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FINAL and PRAGMA_OMP_CLAUSE_MERGEABLE. (OMP_TASK_CLAUSE_MASK): Allow final and mergeable clauses. (c_parser_omp_clause_reduction): Handle min and max. * c-typeck.c (c_finish_omp_clauses): Don't complain about const qualified predetermined vars in firstprivate clause. andle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. Handle MIN_EXPR and MAX_EXPR. * tree-pretty-print.c (dump_omp_clause): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. (dump_generic_node): Handle OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD and OMP_ATOMIC_CAPTURE_NEW. * tree.c (omp_clause_num_ops): Add OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. (omp_clause_code_name): Likewise. (walk_tree_1): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. * tree.h (enum omp_clause_code): Add OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. (OMP_CLAUSE_FINAL_EXPR): Define. * omp-low.c (scan_sharing_clauses): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. (expand_task_call): Likewise. (expand_omp_atomic_load, expand_omp_atomic_store): New functions. (expand_omp_atomic_fetch_op): Handle cases where old or new value is needed afterwards. (expand_omp_atomic): Call expand_omp_atomic_load resp. expand_omp_atomic_store. * gimplify.c (gimplify_omp_atomic, gimplify_expr): Handle OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD and OMP_ATOMIC_CAPTURE_NEW. (gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. * tree-nested.c (convert_nonlocal_omp_clauses, convert_local_omp_clauses): Likewise. * tree.def (OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD, OMP_ATOMIC_CAPTURE_NEW): New. * gimple.h (GF_OMP_ATOMIC_NEED_VALUE): New. (gimple_omp_atomic_need_value_p, gimple_omp_atomic_set_need_value): New inlines. * omp-builtins.def (BUILT_IN_GOMP_TASKYIELD): New builtin. * doc/generic.texi: Mention OMP_CLAUSE_COLLAPSE, OMP_CLAUSE_UNTIED, OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. gcc/c-family/ * c-common.h (c_finish_omp_atomic): Adjust prototype. (c_finish_omp_taskyield): New prototype. * c-omp.c (c_finish_omp_atomic): Add OPCODE, V, LHS1 and RHS1 arguments. Handle OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD and OMP_ATOMIC_CAPTURE_NEW in addition to OMP_ATOMIC. If LHS1 or RHS1 have side-effects, evaluate those too in the right spot, if it is a decl and LHS is also a decl, error out if they aren't the same. (c_finish_omp_taskyield): New function. * c-cppbuiltin.c (c_cpp_builtins): Change _OPENMP to 201107. * c-pragma.c (omp_pragmas): Add taskyield. * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_TASKYIELD. (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_FINAL and PRAGMA_OMP_CLAUSE_MERGEABLE. gcc/cp/ * cp-tree.h (finish_omp_atomic): Adjust prototype. (cxx_omp_const_qual_no_mutable): New prototype. (finish_omp_taskyield): New prototype. * parser.c (cp_parser_omp_atomic): (cp_parser_omp_atomic): Handle parsing OpenMP 3.1 atomics. Adjust finish_omp_atomic caller. (cp_parser_omp_clause_name): Handle final and mergeable clauses. (cp_parser_omp_clause_final, cp_parser_omp_clause_mergeable): New functions. (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FINAL and PRAGMA_OMP_CLAUSE_MERGEABLE. (OMP_TASK_CLAUSE_MASK): Allow final and mergeable clauses. (cp_parser_omp_taskyield): New function. (cp_parser_pragma): Handle PRAGMA_OMP_TASKYIELD. (cp_parser_omp_clause_reduction): Handle min and max. * pt.c (tsubst_expr) <case OMP_ATOMIC>: Handle OpenMP 3.1 atomics. (tsubst_omp_clauses): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. * semantics.c (finish_omp_atomic): Add OPCODE, V, LHS1 and RHS1 arguments. Handle OpenMP 3.1 atomics. Adjust c_finish_omp_atomic caller. (finish_omp_clauses): Don't complain about const qualified predetermined vars and static data members in firstprivate clause. Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. Handle MIN_EXPR and MAX_EXPR. (finish_omp_taskyield): New function. * cp-gimplify.c (cxx_omp_const_qual_no_mutable): New function. (cxx_omp_predetermined_sharing): Use it. gcc/fortran/ PR fortran/46752 * cpp.c (cpp_define_builtins): Change _OPENMP to 201107. * openmp.c (gfc_free_omp_clauses): Free also final_expr. (OMP_CLAUSE_FINAL, OMP_CLAUSE_MERGEABLE): Define. (gfc_match_omp_clauses): Handle parsing final and mergeable clauses. (OMP_TASK_CLAUSES): Allow final and mergeable clauses. (gfc_match_omp_taskyield): New function. (resolve_omp_clauses): Resolve final clause. Allow POINTERs and Cray pointers in clauses other than REDUCTION. (gfc_match_omp_atomic): Match optional read/write/update/capture keywords after !$omp atomic. (resolve_omp_atomic): Handle all OpenMP 3.1 atomic forms. * dump-parse-tree.c (show_omp_node): Handle EXEC_OMP_TASKYIELD, print final and mergeable clauses. (show_code_node): Handle EXEC_OMP_TASKYIELD. * trans-openmp.c (gfc_trans_omp_clauses): Handle final and mergeable clauses. (gfc_trans_omp_taskyield): New function. (gfc_trans_omp_directive): Handle EXEC_OMP_TASKYIELD. (gfc_trans_omp_atomic): Handle all OpenMP 3.1 atomic forms. (gfc_omp_clause_copy_ctor): Handle non-allocated allocatable. (gfc_omp_predetermined_sharing): Adjust comment. * gfortran.h (gfc_statement): Add ST_OMP_TASKYIELD and ST_OMP_END_ATOMIC. (gfc_omp_clauses): Add final_expr and mergeable fields. (gfc_exec_op): Add EXEC_OMP_TASKYIELD. (gfc_omp_atomic_op): New enum typedef. (struct gfc_code): Add ext.omp_atomic. * trans.c (trans_code): Handle EXEC_OMP_TASKYIELD. * frontend-passes.c (gfc_code_walker): Also walk final_expr. * resolve.c (gfc_resolve_blocks, resolve_code): Handle EXEC_OMP_TASKYIELD. * st.c (gfc_free_statement): Likewise. * match.h (gfc_match_omp_taskyield): New prototype. * parse.c (decode_omp_directive): Handle taskyield directive. Handle !$omp end atomic. (case_executable): Add ST_OMP_TASKYIELD case. (gfc_ascii_statement): Handle ST_OMP_TASKYIELD. (parse_omp_atomic): Return gfc_statement instead of void. For !$omp atomic capture parse two assignments instead of just one and require !$omp end atomic afterwards, for other !$omp atomic forms just allow !$omp end atomic at the end. (parse_omp_structured_block, parse_executable): Adjust parse_omp_atomic callers. 2011-08-02 Tobias Burnus <burnus@net-b.de> * intrinsic.c (OMP_LIB): Updated openmp_version's value to 201107. * gfortran.texi (OpenMP): Update ref to OpenMP 3.1. * intrinsic.texi (OpenMP Modules): Update ref to OpenMP 3.1; remove deleted omp_integer_kind and omp_logical_kind constants. gcc/testsuite/ PR fortran/46752 * gcc.dg/gomp/atomic-5.c: Adjust expected diagnostics. * gcc.dg/gomp/atomic-15.c: New test. * g++.dg/gomp/atomic-5.C: Adjust expected diagnostics. * g++.dg/gomp/atomic-15.C: New test. * g++.dg/gomp/private-1.C: New test. * g++.dg/gomp/sharing-2.C: New test. * gfortran.dg/gomp/crayptr1.f90: Don't expect error about Cray pointer in FIRSTPRIVATE/LASTPRIVATE. * gfortran.dg/gomp/omp_atomic2.f90: New test. libgomp/ PR fortran/42041 PR fortran/46752 * omp.h.in (omp_in_final): New prototype. * omp_lib.f90.in (omp_in_final): New interface. (omp_integer_kind, omp_logical_kind): Remove and replace all its uses in the module with 4. (openmp_version): Change to 201107. * omp_lib.h.in (omp_sched_static, omp_sched_dynamic, omp_sched_guided, omp_sched_auto): Use omp_sched_kind kind for the parameters. (omp_in_final): New external. (openmp_version): Change to 201107. * task.c (omp_in_final): New function. (gomp_init_task): Initialize final_task. (GOMP_task): Remove unused attribute from flags. Handle final tasks. (GOMP_taskyield): New function. (omp_in_final): Return true if if (false) or final (true) task or descendant of final (true). * fortran.c (omp_in_final_): New function. * libgomp.map (OMP_3.1): Export omp_in_final and omp_in_final_. (GOMP_3.0): Export GOMP_taskyield. * env.c (gomp_nthreads_var_list, gomp_nthreads_var_list_len): New variables. (parse_unsigned_long_list): New function. (initialize_env): Use it for OMP_NUM_THREADS. Call parse_boolean with "OMP_PROC_BIND". If OMP_PROC_BIND=true, call gomp_init_affinity even if parse_affinity returned false. * config/linux/affinity.c (gomp_init_affinity): Handle gomp_cpu_affinity_len == 0. * libgomp_g.h (GOMP_taskyield): New prototype. * libgomp.h (struct gomp_task): Add final_task field. (gomp_nthreads_var_list, gomp_nthreads_var_list_len): New externs. * team.c (gomp_team_start): Override new task's nthreads_var icv if list form OMP_NUM_THREADS has been used and it has value for the new nesting level. * testsuite/libgomp.c/atomic-11.c: New test. * testsuite/libgomp.c/atomic-12.c: New test. * testsuite/libgomp.c/atomic-13.c: New test. * testsuite/libgomp.c/atomic-14.c: New test. * testsuite/libgomp.c/reduction-6.c: New test. * testsuite/libgomp.c/task-5.c: New test. * testsuite/libgomp.c++/atomic-2.C: New test. * testsuite/libgomp.c++/atomic-3.C: New test. * testsuite/libgomp.c++/atomic-4.C: New test. * testsuite/libgomp.c++/atomic-5.C: New test. * testsuite/libgomp.c++/atomic-6.C: New test. * testsuite/libgomp.c++/atomic-7.C: New test. * testsuite/libgomp.c++/atomic-8.C: New test. * testsuite/libgomp.c++/atomic-9.C: New test. * testsuite/libgomp.c++/task-8.C: New test. * testsuite/libgomp.c++/reduction-4.C: New test. * testsuite/libgomp.fortran/allocatable7.f90: New test. * testsuite/libgomp.fortran/allocatable8.f90: New test. * testsuite/libgomp.fortran/crayptr3.f90: New test. * testsuite/libgomp.fortran/omp_atomic3.f90: New test. * testsuite/libgomp.fortran/omp_atomic4.f90: New test. * testsuite/libgomp.fortran/pointer1.f90: New test. * testsuite/libgomp.fortran/pointer2.f90: New test. * testsuite/libgomp.fortran/task4.f90: New test. 2011-08-02 Tobias Burnus <burnus@net-b.de> * libgomp.texi: Update OpenMP spec references to 3.1. (omp_in_final,OMP_PROC_BIND): New sections. (OMP_NUM_THREADS): Document that the value can be now a list. (GOMP_STACKSIZE,GOMP_CPU_AFFINITY): Update @ref.
Diffstat (limited to 'libgomp')
-rw-r--r--libgomp/ChangeLog71
-rw-r--r--libgomp/config/linux/affinity.c38
-rw-r--r--libgomp/env.c100
-rw-r--r--libgomp/fortran.c7
-rw-r--r--libgomp/libgomp.h5
-rw-r--r--libgomp/libgomp.map11
-rw-r--r--libgomp/libgomp.texi161
-rw-r--r--libgomp/libgomp_g.h3
-rw-r--r--libgomp/omp.h.in4
-rw-r--r--libgomp/omp_lib.f90.in47
-rw-r--r--libgomp/omp_lib.h.in12
-rw-r--r--libgomp/task.c26
-rw-r--r--libgomp/team.c11
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-2.C156
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-3.C74
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-4.C166
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-5.C79
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-6.C58
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-7.C63
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-8.C137
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-9.C148
-rw-r--r--libgomp/testsuite/libgomp.c++/reduction-4.C54
-rw-r--r--libgomp/testsuite/libgomp.c++/task-8.C44
-rw-r--r--libgomp/testsuite/libgomp.c/atomic-11.c156
-rw-r--r--libgomp/testsuite/libgomp.c/atomic-12.c98
-rw-r--r--libgomp/testsuite/libgomp.c/atomic-13.c59
-rw-r--r--libgomp/testsuite/libgomp.c/atomic-14.c137
-rw-r--r--libgomp/testsuite/libgomp.c/reduction-6.c29
-rw-r--r--libgomp/testsuite/libgomp.c/task-5.c45
-rw-r--r--libgomp/testsuite/libgomp.fortran/allocatable7.f9016
-rw-r--r--libgomp/testsuite/libgomp.fortran/allocatable8.f9014
-rw-r--r--libgomp/testsuite/libgomp.fortran/crayptr3.f9036
-rw-r--r--libgomp/testsuite/libgomp.fortran/omp_atomic3.f9058
-rw-r--r--libgomp/testsuite/libgomp.fortran/omp_atomic4.f9037
-rw-r--r--libgomp/testsuite/libgomp.fortran/pointer1.f9077
-rw-r--r--libgomp/testsuite/libgomp.fortran/pointer2.f9028
-rw-r--r--libgomp/testsuite/libgomp.fortran/task4.f9045
37 files changed, 2208 insertions, 102 deletions
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index efd0c04c71b..b26dcd54cd6 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,74 @@
+2011-08-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR fortran/42041
+ PR fortran/46752
+ * omp.h.in (omp_in_final): New prototype.
+ * omp_lib.f90.in (omp_in_final): New interface.
+ (omp_integer_kind, omp_logical_kind): Remove
+ and replace all its uses in the module with 4.
+ (openmp_version): Change to 201107.
+ * omp_lib.h.in (omp_sched_static, omp_sched_dynamic,
+ omp_sched_guided, omp_sched_auto): Use omp_sched_kind
+ kind for the parameters.
+ (omp_in_final): New external.
+ (openmp_version): Change to 201107.
+ * task.c (omp_in_final): New function.
+ (gomp_init_task): Initialize final_task.
+ (GOMP_task): Remove unused attribute from flags. Handle final
+ tasks.
+ (GOMP_taskyield): New function.
+ (omp_in_final): Return true if if (false) or final (true) task
+ or descendant of final (true).
+ * fortran.c (omp_in_final_): New function.
+ * libgomp.map (OMP_3.1): Export omp_in_final and omp_in_final_.
+ (GOMP_3.0): Export GOMP_taskyield.
+ * env.c (gomp_nthreads_var_list, gomp_nthreads_var_list_len): New
+ variables.
+ (parse_unsigned_long_list): New function.
+ (initialize_env): Use it for OMP_NUM_THREADS. Call parse_boolean
+ with "OMP_PROC_BIND". If OMP_PROC_BIND=true, call gomp_init_affinity
+ even if parse_affinity returned false.
+ * config/linux/affinity.c (gomp_init_affinity): Handle
+ gomp_cpu_affinity_len == 0.
+ * libgomp_g.h (GOMP_taskyield): New prototype.
+ * libgomp.h (struct gomp_task): Add final_task field.
+ (gomp_nthreads_var_list, gomp_nthreads_var_list_len): New externs.
+ * team.c (gomp_team_start): Override new task's nthreads_var icv
+ if list form OMP_NUM_THREADS has been used and it has value for
+ the new nesting level.
+
+ * testsuite/libgomp.c/atomic-11.c: New test.
+ * testsuite/libgomp.c/atomic-12.c: New test.
+ * testsuite/libgomp.c/atomic-13.c: New test.
+ * testsuite/libgomp.c/atomic-14.c: New test.
+ * testsuite/libgomp.c/reduction-6.c: New test.
+ * testsuite/libgomp.c/task-5.c: New test.
+ * testsuite/libgomp.c++/atomic-2.C: New test.
+ * testsuite/libgomp.c++/atomic-3.C: New test.
+ * testsuite/libgomp.c++/atomic-4.C: New test.
+ * testsuite/libgomp.c++/atomic-5.C: New test.
+ * testsuite/libgomp.c++/atomic-6.C: New test.
+ * testsuite/libgomp.c++/atomic-7.C: New test.
+ * testsuite/libgomp.c++/atomic-8.C: New test.
+ * testsuite/libgomp.c++/atomic-9.C: New test.
+ * testsuite/libgomp.c++/task-8.C: New test.
+ * testsuite/libgomp.c++/reduction-4.C: New test.
+ * testsuite/libgomp.fortran/allocatable7.f90: New test.
+ * testsuite/libgomp.fortran/allocatable8.f90: New test.
+ * testsuite/libgomp.fortran/crayptr3.f90: New test.
+ * testsuite/libgomp.fortran/omp_atomic3.f90: New test.
+ * testsuite/libgomp.fortran/omp_atomic4.f90: New test.
+ * testsuite/libgomp.fortran/pointer1.f90: New test.
+ * testsuite/libgomp.fortran/pointer2.f90: New test.
+ * testsuite/libgomp.fortran/task4.f90: New test.
+
+2011-08-02 Tobias Burnus <burnus@net-b.de>
+
+ * libgomp.texi: Update OpenMP spec references to 3.1.
+ (omp_in_final,OMP_PROC_BIND): New sections.
+ (OMP_NUM_THREADS): Document that the value can be now a list.
+ (GOMP_STACKSIZE,GOMP_CPU_AFFINITY): Update @ref.
+
2011-08-02 H.J. Lu <hongjiu.lu@intel.com>
* config/linux/x86/futex.h: Check __x86_64__ instead of
diff --git a/libgomp/config/linux/affinity.c b/libgomp/config/linux/affinity.c
index da9f3d8fdcb..d8d575628ff 100644
--- a/libgomp/config/linux/affinity.c
+++ b/libgomp/config/linux/affinity.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+/* Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
+ Free Software Foundation, Inc.
Contributed by Jakub Jelinek <jakub@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -53,17 +54,36 @@ gomp_init_affinity (void)
}
CPU_ZERO (&cpusetnew);
- for (widx = idx = 0; idx < gomp_cpu_affinity_len; idx++)
- if (gomp_cpu_affinity[idx] < CPU_SETSIZE
- && CPU_ISSET (gomp_cpu_affinity[idx], &cpuset))
- {
- if (! CPU_ISSET (gomp_cpu_affinity[idx], &cpusetnew))
+ if (gomp_cpu_affinity_len == 0)
+ {
+ unsigned long count = CPU_COUNT (&cpuset);
+ if (count >= 65536)
+ count = 65536;
+ gomp_cpu_affinity = malloc (count * sizeof (unsigned short));
+ if (gomp_cpu_affinity == NULL)
+ {
+ gomp_error ("not enough memory to store CPU affinity list");
+ return;
+ }
+ for (widx = idx = 0; widx < count && idx < 65536; idx++)
+ if (CPU_ISSET (idx, &cpuset))
{
cpus++;
- CPU_SET (gomp_cpu_affinity[idx], &cpusetnew);
+ gomp_cpu_affinity[widx++] = idx;
}
- gomp_cpu_affinity[widx++] = gomp_cpu_affinity[idx];
- }
+ }
+ else
+ for (widx = idx = 0; idx < gomp_cpu_affinity_len; idx++)
+ if (gomp_cpu_affinity[idx] < CPU_SETSIZE
+ && CPU_ISSET (gomp_cpu_affinity[idx], &cpuset))
+ {
+ if (! CPU_ISSET (gomp_cpu_affinity[idx], &cpusetnew))
+ {
+ cpus++;
+ CPU_SET (gomp_cpu_affinity[idx], &cpusetnew);
+ }
+ gomp_cpu_affinity[widx++] = gomp_cpu_affinity[idx];
+ }
if (widx == 0)
{
diff --git a/libgomp/env.c b/libgomp/env.c
index 0ca9a1c9e00..aff7490a8b7 100644
--- a/libgomp/env.c
+++ b/libgomp/env.c
@@ -67,6 +67,7 @@ gomp_mutex_t gomp_remaining_threads_lock;
#endif
unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
+unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
/* Parse the OMP_SCHEDULE environment variable. */
@@ -184,6 +185,95 @@ parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
return false;
}
+/* Parse an unsigned long list environment variable. Return true if one was
+ present and it was successfully parsed. */
+
+static bool
+parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
+ unsigned long **pvalues,
+ unsigned long *pnvalues)
+{
+ char *env, *end;
+ unsigned long value, *values = NULL;
+
+ env = getenv (name);
+ if (env == NULL)
+ return false;
+
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == '\0')
+ goto invalid;
+
+ errno = 0;
+ value = strtoul (env, &end, 10);
+ if (errno || (long) value <= 0)
+ goto invalid;
+
+ while (isspace ((unsigned char) *end))
+ ++end;
+ if (*end != '\0')
+ {
+ if (*end == ',')
+ {
+ unsigned long nvalues = 0, nalloced = 0;
+
+ do
+ {
+ env = end + 1;
+ if (nvalues == nalloced)
+ {
+ unsigned long *n;
+ nalloced = nalloced ? nalloced * 2 : 16;
+ n = realloc (values, nalloced * sizeof (unsigned long));
+ if (n == NULL)
+ {
+ free (values);
+ gomp_error ("Out of memory while trying to parse"
+ " environment variable %s", name);
+ return false;
+ }
+ values = n;
+ if (nvalues == 0)
+ values[nvalues++] = value;
+ }
+
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == '\0')
+ goto invalid;
+
+ errno = 0;
+ value = strtoul (env, &end, 10);
+ if (errno || (long) value <= 0)
+ goto invalid;
+
+ values[nvalues++] = value;
+ while (isspace ((unsigned char) *end))
+ ++end;
+ if (*end == '\0')
+ break;
+ if (*end != ',')
+ goto invalid;
+ }
+ while (1);
+ *p1stvalue = values[0];
+ *pvalues = values;
+ *pnvalues = nvalues;
+ return true;
+ }
+ goto invalid;
+ }
+
+ *p1stvalue = value;
+ return true;
+
+ invalid:
+ free (values);
+ gomp_error ("Invalid value for environment variable %s", name);
+ return false;
+}
+
/* Parse the OMP_STACKSIZE environment varible. Return true if one was
present and it was successfully parsed. */
@@ -481,6 +571,7 @@ initialize_env (void)
{
unsigned long stacksize;
int wait_policy;
+ bool bind_var = false;
/* Do a compile time check that mkomp_h.pl did good job. */
omp_check_defines ();
@@ -488,6 +579,7 @@ initialize_env (void)
parse_schedule ();
parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
+ parse_boolean ("OMP_PROC_BIND", &bind_var);
parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
true);
parse_unsigned_long ("OMP_THREAD_LIMIT", &gomp_thread_limit_var, false);
@@ -498,10 +590,12 @@ initialize_env (void)
#endif
gomp_init_num_threads ();
gomp_available_cpus = gomp_global_icv.nthreads_var;
- if (!parse_unsigned_long ("OMP_NUM_THREADS", &gomp_global_icv.nthreads_var,
- false))
+ if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
+ &gomp_global_icv.nthreads_var,
+ &gomp_nthreads_var_list,
+ &gomp_nthreads_var_list_len))
gomp_global_icv.nthreads_var = gomp_available_cpus;
- if (parse_affinity ())
+ if (parse_affinity () || bind_var)
gomp_init_affinity ();
wait_policy = parse_wait_policy ();
if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
diff --git a/libgomp/fortran.c b/libgomp/fortran.c
index 39bd7486b07..de806f8aba4 100644
--- a/libgomp/fortran.c
+++ b/libgomp/fortran.c
@@ -69,6 +69,7 @@ ialias_redirect (omp_get_level)
ialias_redirect (omp_get_ancestor_thread_num)
ialias_redirect (omp_get_team_size)
ialias_redirect (omp_get_active_level)
+ialias_redirect (omp_in_final)
#endif
#ifndef LIBGOMP_GNU_SYMBOL_VERSIONING
@@ -428,3 +429,9 @@ omp_get_active_level_ (void)
{
return omp_get_active_level ();
}
+
+int32_t
+omp_in_final_ (void)
+{
+ return omp_in_final ();
+}
diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h
index aa2f580ca5b..9cf9d3221c5 100644
--- a/libgomp/libgomp.h
+++ b/libgomp/libgomp.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
+ Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -226,6 +227,7 @@ extern gomp_mutex_t gomp_remaining_threads_lock;
extern unsigned long gomp_max_active_levels_var;
extern unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
extern unsigned long gomp_available_cpus, gomp_managed_threads;
+extern unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
enum gomp_task_kind
{
@@ -251,6 +253,7 @@ struct gomp_task
enum gomp_task_kind kind;
bool in_taskwait;
bool in_tied_task;
+ bool final_task;
gomp_sem_t taskwait_sem;
};
diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index d95693dbdde..7b051f96aab 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -107,6 +107,12 @@ OMP_3.0 {
omp_unset_nest_lock_;
} OMP_2.0;
+OMP_3.1 {
+ global:
+ omp_in_final;
+ omp_in_final_;
+} OMP_3.0;
+
GOMP_1.0 {
global:
GOMP_atomic_end;
@@ -173,3 +179,8 @@ GOMP_2.0 {
GOMP_loop_ull_static_next;
GOMP_loop_ull_static_start;
} GOMP_1.0;
+
+GOMP_3.0 {
+ global:
+ GOMP_taskyield;
+} GOMP_2.0;
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index 58199437a5f..29c078b668e 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -116,7 +116,7 @@ arranges for automatic linking of the OpenMP runtime library
A complete description of all OpenMP directives accepted may be found in
the @uref{http://www.openmp.org, OpenMP Application Program Interface} manual,
-version 3.0.
+version 3.1.
@c ---------------------------------------------------------------------
@@ -127,7 +127,7 @@ version 3.0.
@chapter Runtime Library Routines
The runtime routines described here are defined by section 3 of the OpenMP
-specifications in version 3.0. The routines are structured in following
+specifications in version 3.1. The routines are structured in following
three parts:
Control threads, processors and the parallel environment.
@@ -147,6 +147,7 @@ Control threads, processors and the parallel environment.
* omp_get_thread_limit:: Maximum number of threads
* omp_get_thread_num:: Current thread ID
* omp_in_parallel:: Whether a parallel region is active
+* omp_in_final:: Whether in final or included task region
* omp_set_dynamic:: Enable/disable dynamic teams
* omp_set_max_active_levels:: Limits the number of active parallel regions
* omp_set_nested:: Enable/disable nested parallel regions
@@ -199,7 +200,7 @@ which enclose the calling call.
@ref{omp_get_level}, @ref{omp_get_max_active_levels}, @ref{omp_set_max_active_levels}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.19.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.19.
@end table
@@ -228,7 +229,7 @@ zero to @code{omp_get_level} -1 is returned; if @var{level} is
@ref{omp_get_level}, @ref{omp_get_thread_num}, @ref{omp_get_team_size}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.17.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.17.
@end table
@@ -260,7 +261,7 @@ disabled by default.
@ref{omp_set_dynamic}, @ref{OMP_DYNAMIC}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.8.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.8.
@end table
@@ -286,7 +287,7 @@ which enclose the calling call.
@ref{omp_get_active_level}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.16.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.16.
@end table
@@ -311,7 +312,7 @@ This function obtains the maximum allowed number of nested, active parallel regi
@ref{omp_set_max_active_levels}, @ref{omp_get_active_level}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.14.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.15.
@end table
@@ -337,7 +338,7 @@ that does not use the clause @code{num_threads}.
@ref{omp_set_num_threads}, @ref{omp_set_dynamic}, @ref{omp_get_thread_limit}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.3.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.3.
@end table
@@ -369,7 +370,7 @@ disabled by default.
@ref{omp_set_nested}, @ref{OMP_NESTED}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.10.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.10.
@end table
@@ -391,7 +392,7 @@ Returns the number of processors online.
@end multitable
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.5.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.5.
@end table
@@ -424,7 +425,7 @@ one thread per CPU online is used.
@ref{omp_get_max_threads}, @ref{omp_set_num_threads}, @ref{OMP_NUM_THREADS}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.2.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.2.
@end table
@@ -440,7 +441,7 @@ set to the value @code{omp_sched_static}, @code{omp_sched_dynamic},
@item @emph{C/C++}
@multitable @columnfractions .20 .80
-@item @emph{Prototype}: @tab @code{omp_schedule(omp_sched_t *kind, int *modifier);}
+@item @emph{Prototype}: @tab @code{void omp_schedule(omp_sched_t *kind, int *modifier);}
@end multitable
@item @emph{Fortran}:
@@ -454,7 +455,7 @@ set to the value @code{omp_sched_static}, @code{omp_sched_dynamic},
@ref{omp_set_schedule}, @ref{OMP_SCHEDULE}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.12.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.12.
@end table
@@ -484,7 +485,7 @@ to @code{omp_get_num_threads}.
@ref{omp_get_num_threads}, @ref{omp_get_level}, @ref{omp_get_ancestor_thread_num}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.18.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.18.
@end table
@@ -509,7 +510,7 @@ Return the maximum number of threads of the program.
@ref{omp_get_max_threads}, @ref{OMP_THREAD_LIMIT}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.13.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.13.
@end table
@@ -538,7 +539,7 @@ value of the master thread of a team is always 0.
@ref{omp_get_num_threads}, @ref{omp_get_ancestor_thread_num}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.4.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.4.
@end table
@@ -562,7 +563,30 @@ their language-specific counterparts.
@end multitable
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.6.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.6.
+@end table
+
+
+@node omp_in_final
+@section @code{omp_in_final} -- Whether in final or included task region
+@table @asis
+@item @emph{Description}:
+This function returns @code{true} if currently running in a final
+or included task region, @code{false} otherwise. Here, @code{true}
+and @code{false} represent their language-specific counterparts.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{int omp_in_final(void);}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{logical function omp_in_final()}
+@end multitable
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.20.
@end table
@@ -590,7 +614,7 @@ adjustment of team sizes and @code{false} disables it.
@ref{OMP_DYNAMIC}, @ref{omp_get_dynamic}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.7.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.7.
@end table
@@ -617,7 +641,7 @@ parallel regions.
@ref{omp_get_max_active_levels}, @ref{omp_get_active_level}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.14.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.14.
@end table
@@ -646,7 +670,7 @@ dynamic adjustment of team sizes and @code{false} disables it.
@ref{OMP_NESTED}, @ref{omp_get_nested}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.9.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.9.
@end table
@@ -674,7 +698,7 @@ argument of @code{omp_set_num_threads} shall be a positive integer.
@ref{OMP_NUM_THREADS}, @ref{omp_get_num_threads}, @ref{omp_get_max_threads}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.1.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.1.
@end table
@@ -692,7 +716,7 @@ For @code{omp_sched_auto} the @var{modifier} argument is ignored.
@item @emph{C/C++}
@multitable @columnfractions .20 .80
-@item @emph{Prototype}: @tab @code{int omp_set_schedule(omp_sched_t *kind, int *modifier);}
+@item @emph{Prototype}: @tab @code{void omp_set_schedule(omp_sched_t *kind, int *modifier);}
@end multitable
@item @emph{Fortran}:
@@ -707,7 +731,7 @@ For @code{omp_sched_auto} the @var{modifier} argument is ignored.
@ref{OMP_SCHEDULE}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.11.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.11.
@end table
@@ -734,7 +758,7 @@ an unlocked state.
@ref{omp_destroy_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.1.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.1.
@end table
@@ -763,7 +787,7 @@ a deadlock occurs.
@ref{omp_init_lock}, @ref{omp_test_lock}, @ref{omp_unset_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.3.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.3.
@end table
@@ -785,8 +809,7 @@ does not block if the lock is not available. This function returns
@item @emph{Fortran}:
@multitable @columnfractions .20 .80
-@item @emph{Interface}: @tab @code{subroutine omp_test_lock(lock)}
-@item @tab @code{logical(omp_logical_kind) :: omp_test_lock}
+@item @emph{Interface}: @tab @code{logical function omp_test_lock(lock)}
@item @tab @code{integer(omp_lock_kind), intent(inout) :: lock}
@end multitable
@@ -794,7 +817,7 @@ does not block if the lock is not available. This function returns
@ref{omp_init_lock}, @ref{omp_set_lock}, @ref{omp_set_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.5.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.5.
@end table
@@ -807,7 +830,7 @@ A simple lock about to be unset must have been locked by @code{omp_set_lock}
or @code{omp_test_lock} before. In addition, the lock must be held by the
thread calling @code{omp_unset_lock}. Then, the lock becomes unlocked. If one
or more threads attempted to set the lock before, one of them is chosen to,
-again, set the lock for itself.
+again, set the lock to itself.
@item @emph{C/C++}:
@multitable @columnfractions .20 .80
@@ -824,7 +847,7 @@ again, set the lock for itself.
@ref{omp_set_lock}, @ref{omp_test_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.4.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.4.
@end table
@@ -851,7 +874,7 @@ in the unlocked state.
@ref{omp_init_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.2.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.2.
@end table
@@ -878,7 +901,7 @@ an unlocked state and the nesting count is set to zero.
@ref{omp_destroy_nest_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.1.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.1.
@end table
@@ -889,7 +912,7 @@ an unlocked state and the nesting count is set to zero.
Before setting a nested lock, the lock variable must be initialized by
@code{omp_init_nest_lock}. The calling thread is blocked until the lock
is available. If the lock is already held by the current thread, the
-nesting count for the lock in incremented.
+nesting count for the lock is incremented.
@item @emph{C/C++}:
@multitable @columnfractions .20 .80
@@ -906,7 +929,7 @@ nesting count for the lock in incremented.
@ref{omp_init_nest_lock}, @ref{omp_unset_nest_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.3.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.3.
@end table
@@ -928,8 +951,7 @@ is returned. Otherwise, the return value equals zero.
@item @emph{Fortran}:
@multitable @columnfractions .20 .80
-@item @emph{Interface}: @tab @code{integer function omp_test_nest_lock(lock)}
-@item @tab @code{integer(omp_integer_kind) :: omp_test_nest_lock}
+@item @emph{Interface}: @tab @code{logical function omp_test_nest_lock(lock)}
@item @tab @code{integer(omp_nest_lock_kind), intent(inout) :: lock}
@end multitable
@@ -938,7 +960,7 @@ is returned. Otherwise, the return value equals zero.
@ref{omp_init_lock}, @ref{omp_set_lock}, @ref{omp_set_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.5.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.5.
@end table
@@ -951,7 +973,7 @@ A nested lock about to be unset must have been locked by @code{omp_set_nested_lo
or @code{omp_test_nested_lock} before. In addition, the lock must be held by the
thread calling @code{omp_unset_nested_lock}. If the nesting count drops to zero, the
lock becomes unlocked. If one ore more threads attempted to set the lock before,
-one of them is chosen to, again, set the lock for itself.
+one of them is chosen to, again, set the lock to itself.
@item @emph{C/C++}:
@multitable @columnfractions .20 .80
@@ -968,7 +990,7 @@ one of them is chosen to, again, set the lock for itself.
@ref{omp_set_nest_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.4.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.4.
@end table
@@ -995,7 +1017,7 @@ in the unlocked state and its nesting count must equal zero.
@ref{omp_init_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.2.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.2.
@end table
@@ -1021,7 +1043,7 @@ successive clock ticks.
@ref{omp_get_wtime}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.4.2.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.4.2.
@end table
@@ -1049,7 +1071,7 @@ guaranteed not to change during the execution of the program.
@ref{omp_get_wtick}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.4.1.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.4.1.
@end table
@@ -1064,7 +1086,7 @@ guaranteed not to change during the execution of the program.
The variables @env{OMP_DYNAMIC}, @env{OMP_MAX_ACTIVE_LEVELS},
@env{OMP_NESTED}, @env{OMP_NUM_THREADS}, @env{OMP_SCHEDULE},
@env{OMP_STACKSIZE},@env{OMP_THREAD_LIMIT} and @env{OMP_WAIT_POLICY}
-are defined by section 4 of the OpenMP specifications in version 3.0,
+are defined by section 4 of the OpenMP specifications in version 3.1,
while @env{GOMP_CPU_AFFINITY} and @env{GOMP_STACKSIZE} are GNU
extensions.
@@ -1077,6 +1099,7 @@ extensions.
* OMP_SCHEDULE:: How threads are scheduled
* OMP_THREAD_LIMIT:: Set the maximum number of threads
* OMP_WAIT_POLICY:: How waiting threads are handled
+* OMP_PROC_BIND:: Whether theads may be moved between CPUs
* GOMP_CPU_AFFINITY:: Bind threads to specific CPUs
* GOMP_STACKSIZE:: Set default thread stack size
@end menu
@@ -1096,7 +1119,7 @@ disabled by default.
@ref{omp_set_dynamic}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 4.3
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.3
@end table
@@ -1107,14 +1130,14 @@ disabled by default.
@table @asis
@item @emph{Description}:
Specifies the initial value for the maximum number of nested parallel
-regions. The value of this variable shall be positive integer.
+regions. The value of this variable shall be a positive integer.
If undefined, the number of active levels is unlimited.
@item @emph{See also}:
@ref{omp_set_max_active_levels}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 4.7
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.8
@end table
@@ -1134,7 +1157,7 @@ regions are disabled by default.
@ref{omp_set_nested}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 4.4
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.5
@end table
@@ -1146,14 +1169,15 @@ regions are disabled by default.
@table @asis
@item @emph{Description}:
Specifies the default number of threads to use in parallel regions. The
-value of this variable shall be a positive integer. If undefined one thread
-per CPU is used.
+value of this variable shall be a comma-separated list of positive integers;
+the value specified the number of threads to use for the corresponding nested
+level. If undefined one thread per CPU is used.
@item @emph{See also}:
@ref{omp_set_num_threads}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 4.2
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.2
@end table
@@ -1174,7 +1198,7 @@ dynamic scheduling and a chunk size of 1 is used.
@ref{omp_set_schedule}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, sections 2.5.1 and 4.1
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, sections 2.5.1 and 4.1
@end table
@@ -1188,13 +1212,13 @@ Set the default thread stack size in kilobytes, unless the number
is suffixed by @code{B}, @code{K}, @code{M} or @code{G}, in which
case the size is, respectively, in bytes, kilobytes, megabytes
or gigabytes. This is different from @code{pthread_attr_setstacksize}
-which gets the number of bytes as an argument. If the stacksize cannot
+which gets the number of bytes as an argument. If the stack size cannot
be set due to system constraints, an error is reported and the initial
-stacksize is left unchanged. If undefined, the stack size is system
+stack size is left unchanged. If undefined, the stack size is system
dependent.
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, sections 4.5
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, sections 4.6
@end table
@@ -1213,7 +1237,7 @@ the number of threads is not limited.
@ref{omp_get_thread_limit}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 4.8
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.9
@end table
@@ -1229,7 +1253,25 @@ power while waiting; while the value is @code{ACTIVE} specifies that
they should.
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, sections 4.6
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, sections 4.7
+@end table
+
+
+
+@node OMP_PROC_BIND
+@section @env{OMP_PROC_BIND} -- Whether theads may be moved between CPUs
+@cindex Environment Variable
+@table @asis
+@item @emph{Description}:
+Specifies whether threads may be moved between processors. If set to
+@code{true}, OpenMP theads should not be moved, if set to @code{false}
+they may be moved.
+
+@item @emph{See also}:
+@ref{GOMP_CPU_AFFINITY}
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, sections 4.4
@end table
@@ -1258,6 +1300,9 @@ or disabled during the runtime of the application.
If this environment variable is omitted, the host system will handle the
assignment of threads to CPUs.
+
+@item @emph{See also}:
+@ref{OMP_PROC_BIND}
@end table
@@ -1270,8 +1315,8 @@ assignment of threads to CPUs.
@item @emph{Description}:
Set the default thread stack size in kilobytes. This is different from
@code{pthread_attr_setstacksize} which gets the number of bytes as an
-argument. If the stacksize cannot be set due to system constraints, an
-error is reported and the initial stacksize is left unchanged. If undefined,
+argument. If the stack size cannot be set due to system constraints, an
+error is reported and the initial stack size is left unchanged. If undefined,
the stack size is system dependent.
@item @emph{See also}:
diff --git a/libgomp/libgomp_g.h b/libgomp/libgomp_g.h
index 18f69bc1e31..8a7c31f0d2a 100644
--- a/libgomp/libgomp_g.h
+++ b/libgomp/libgomp_g.h
@@ -158,11 +158,12 @@ extern void GOMP_ordered_end (void);
extern void GOMP_parallel_start (void (*) (void *), void *, unsigned);
extern void GOMP_parallel_end (void);
-/* team.c */
+/* task.c */
extern void GOMP_task (void (*) (void *), void *, void (*) (void *, void *),
long, long, bool, unsigned);
extern void GOMP_taskwait (void);
+extern void GOMP_taskyield (void);
/* sections.c */
diff --git a/libgomp/omp.h.in b/libgomp/omp.h.in
index 0198b8fd7ec..f2d7ba4e115 100644
--- a/libgomp/omp.h.in
+++ b/libgomp/omp.h.in
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -98,6 +98,8 @@ int omp_get_ancestor_thread_num (int) __GOMP_NOTHROW;
int omp_get_team_size (int) __GOMP_NOTHROW;
int omp_get_active_level (void) __GOMP_NOTHROW;
+int omp_in_final (void) __GOMP_NOTHROW;
+
#ifdef __cplusplus
}
#endif
diff --git a/libgomp/omp_lib.f90.in b/libgomp/omp_lib.f90.in
index 6b0b7aa26ca..d00fa0551f6 100644
--- a/libgomp/omp_lib.f90.in
+++ b/libgomp/omp_lib.f90.in
@@ -1,4 +1,4 @@
-! Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+! Copyright (C) 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
! Contributed by Jakub Jelinek <jakub@redhat.com>.
! This file is part of the GNU OpenMP Library (libgomp).
@@ -24,8 +24,6 @@
module omp_lib_kinds
implicit none
- integer, parameter :: omp_integer_kind = 4
- integer, parameter :: omp_logical_kind = 4
integer, parameter :: omp_lock_kind = @OMP_LOCK_KIND@
integer, parameter :: omp_nest_lock_kind = @OMP_NEST_LOCK_KIND@
integer, parameter :: omp_sched_kind = 4
@@ -34,7 +32,7 @@
module omp_lib
use omp_lib_kinds
implicit none
- integer, parameter :: openmp_version = 200805
+ integer, parameter :: openmp_version = 201107
integer (omp_sched_kind), parameter :: omp_sched_static = 1
integer (omp_sched_kind), parameter :: omp_sched_dynamic = 2
integer (omp_sched_kind), parameter :: omp_sched_guided = 3
@@ -126,28 +124,28 @@
interface
function omp_get_dynamic ()
use omp_lib_kinds
- logical (omp_logical_kind) :: omp_get_dynamic
+ logical (4) :: omp_get_dynamic
end function omp_get_dynamic
end interface
interface
function omp_get_nested ()
use omp_lib_kinds
- logical (omp_logical_kind) :: omp_get_nested
+ logical (4) :: omp_get_nested
end function omp_get_nested
end interface
interface
function omp_in_parallel ()
use omp_lib_kinds
- logical (omp_logical_kind) :: omp_in_parallel
+ logical (4) :: omp_in_parallel
end function omp_in_parallel
end interface
interface
function omp_test_lock (lock)
use omp_lib_kinds
- logical (omp_logical_kind) :: omp_test_lock
+ logical (4) :: omp_test_lock
integer (omp_lock_kind), intent (inout) :: lock
end function omp_test_lock
end interface
@@ -155,35 +153,35 @@
interface
function omp_get_max_threads ()
use omp_lib_kinds
- integer (omp_integer_kind) :: omp_get_max_threads
+ integer (4) :: omp_get_max_threads
end function omp_get_max_threads
end interface
interface
function omp_get_num_procs ()
use omp_lib_kinds
- integer (omp_integer_kind) :: omp_get_num_procs
+ integer (4) :: omp_get_num_procs
end function omp_get_num_procs
end interface
interface
function omp_get_num_threads ()
use omp_lib_kinds
- integer (omp_integer_kind) :: omp_get_num_threads
+ integer (4) :: omp_get_num_threads
end function omp_get_num_threads
end interface
interface
function omp_get_thread_num ()
use omp_lib_kinds
- integer (omp_integer_kind) :: omp_get_thread_num
+ integer (4) :: omp_get_thread_num
end function omp_get_thread_num
end interface
interface
function omp_test_nest_lock (lock)
use omp_lib_kinds
- integer (omp_integer_kind) :: omp_test_nest_lock
+ integer (4) :: omp_test_nest_lock
integer (omp_nest_lock_kind), intent (inout) :: lock
end function omp_test_nest_lock
end interface
@@ -229,7 +227,7 @@
interface
function omp_get_thread_limit ()
use omp_lib_kinds
- integer (omp_integer_kind) :: omp_get_thread_limit
+ integer (4) :: omp_get_thread_limit
end function omp_get_thread_limit
end interface
@@ -247,14 +245,14 @@
interface
function omp_get_max_active_levels ()
use omp_lib_kinds
- integer (omp_integer_kind) :: omp_get_max_active_levels
+ integer (4) :: omp_get_max_active_levels
end function omp_get_max_active_levels
end interface
interface
function omp_get_level ()
use omp_lib_kinds
- integer (omp_integer_kind) :: omp_get_level
+ integer (4) :: omp_get_level
end function omp_get_level
end interface
@@ -262,12 +260,12 @@
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
+ integer (4) :: 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_8
+ integer (4) :: omp_get_ancestor_thread_num_8
end function omp_get_ancestor_thread_num_8
end interface
@@ -275,20 +273,27 @@
function omp_get_team_size (level)
use omp_lib_kinds
integer (4), intent (in) :: level
- integer (omp_integer_kind) :: omp_get_team_size
+ integer (4) :: omp_get_team_size
end function omp_get_team_size
function omp_get_team_size_8 (level)
use omp_lib_kinds
integer (8), intent (in) :: level
- integer (omp_integer_kind) :: omp_get_team_size_8
+ integer (4) :: omp_get_team_size_8
end function omp_get_team_size_8
end interface
interface
function omp_get_active_level ()
use omp_lib_kinds
- integer (omp_integer_kind) :: omp_get_active_level
+ integer (4) :: omp_get_active_level
end function omp_get_active_level
end interface
+ interface
+ function omp_in_final ()
+ use omp_lib_kinds
+ logical (4) :: omp_in_final
+ end function omp_in_final
+ end interface
+
end module omp_lib
diff --git a/libgomp/omp_lib.h.in b/libgomp/omp_lib.h.in
index 2ff7a42fa8f..c583ba3d24a 100644
--- a/libgomp/omp_lib.h.in
+++ b/libgomp/omp_lib.h.in
@@ -1,4 +1,4 @@
-! Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+! Copyright (C) 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
! Contributed by Jakub Jelinek <jakub@redhat.com>.
! This file is part of the GNU OpenMP Library (libgomp).
@@ -23,16 +23,17 @@
! <http://www.gnu.org/licenses/>.
integer omp_lock_kind, omp_nest_lock_kind, openmp_version
- integer omp_sched_kind, omp_sched_static, omp_sched_dynamic
- integer omp_sched_guided, omp_sched_auto
parameter (omp_lock_kind = @OMP_LOCK_KIND@)
parameter (omp_nest_lock_kind = @OMP_NEST_LOCK_KIND@)
+ integer omp_sched_kind
parameter (omp_sched_kind = 4)
+ integer (omp_sched_kind) omp_sched_static, omp_sched_dynamic
+ integer (omp_sched_kind) omp_sched_guided, omp_sched_auto
parameter (omp_sched_static = 1)
parameter (omp_sched_dynamic = 2)
parameter (omp_sched_guided = 3)
parameter (omp_sched_auto = 4)
- parameter (openmp_version = 200805)
+ parameter (openmp_version = 201107)
external omp_init_lock, omp_init_nest_lock
external omp_destroy_lock, omp_destroy_nest_lock
@@ -64,3 +65,6 @@
integer(4) omp_get_thread_limit, omp_get_max_active_levels
integer(4) omp_get_level, omp_get_ancestor_thread_num
integer(4) omp_get_team_size, omp_get_active_level
+
+ external omp_in_final
+ logical(4) omp_in_final
diff --git a/libgomp/task.c b/libgomp/task.c
index 95f163d53cd..b93f77a3816 100644
--- a/libgomp/task.c
+++ b/libgomp/task.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -41,6 +41,7 @@ gomp_init_task (struct gomp_task *task, struct gomp_task *parent_task,
task->kind = GOMP_TASK_IMPLICIT;
task->in_taskwait = false;
task->in_tied_task = false;
+ task->final_task = false;
task->children = NULL;
gomp_sem_init (&task->taskwait_sem, 0);
}
@@ -77,8 +78,7 @@ gomp_clear_parent (struct gomp_task *children)
void
GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
- long arg_size, long arg_align, bool if_clause,
- unsigned flags __attribute__((unused)))
+ long arg_size, long arg_align, bool if_clause, unsigned flags)
{
struct gomp_thread *thr = gomp_thread ();
struct gomp_team *team = thr->ts.team;
@@ -95,12 +95,14 @@ GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
#endif
if (!if_clause || team == NULL
+ || (thr->task && thr->task->final_task)
|| team->task_count > 64 * team->nthreads)
{
struct gomp_task task;
gomp_init_task (&task, thr->task, gomp_icv (false));
task.kind = GOMP_TASK_IFFALSE;
+ task.final_task = (thr->task && thr->task->final_task) || (flags & 2);
if (thr->task)
task.in_tied_task = thr->task->in_tied_task;
thr->task = &task;
@@ -145,6 +147,7 @@ GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
task->fn = fn;
task->fn_data = arg;
task->in_tied_task = true;
+ task->final_task = (flags & 2) >> 1;
gomp_mutex_lock (&team->task_lock);
if (parent->children)
{
@@ -362,3 +365,20 @@ GOMP_taskwait (void)
}
}
}
+
+/* Called when encountering a taskyield directive. */
+
+void
+GOMP_taskyield (void)
+{
+ /* Nothing at the moment. */
+}
+
+int
+omp_in_final (void)
+{
+ struct gomp_thread *thr = gomp_thread ();
+ return thr->task && thr->task->final_task;
+}
+
+ialias (omp_in_final)
diff --git a/libgomp/team.c b/libgomp/team.c
index 44ffd56095f..633902ca567 100644
--- a/libgomp/team.c
+++ b/libgomp/team.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2011
+ Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -260,6 +261,7 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
struct gomp_thread_pool *pool;
unsigned i, n, old_threads_used = 0;
pthread_attr_t thread_attr, *attr;
+ unsigned long nthreads_var;
thr = gomp_thread ();
nested = thr->ts.team != NULL;
@@ -289,7 +291,12 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
#endif
thr->ts.static_trip = 0;
thr->task = &team->implicit_task[0];
+ nthreads_var = icv->nthreads_var;
+ if (__builtin_expect (gomp_nthreads_var_list != NULL, 0)
+ && thr->ts.level < gomp_nthreads_var_list_len)
+ nthreads_var = gomp_nthreads_var_list[thr->ts.level];
gomp_init_task (thr->task, task, icv);
+ team->implicit_task[0].icv.nthreads_var = nthreads_var;
if (nthreads == 1)
return;
@@ -342,6 +349,7 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
nthr->ts.static_trip = 0;
nthr->task = &team->implicit_task[i];
gomp_init_task (nthr->task, task, icv);
+ team->implicit_task[i].icv.nthreads_var = nthreads_var;
nthr->fn = fn;
nthr->data = data;
team->ordered_release[i] = &nthr->release;
@@ -413,6 +421,7 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
start_data->ts.static_trip = 0;
start_data->task = &team->implicit_task[i];
gomp_init_task (start_data->task, task, icv);
+ team->implicit_task[i].icv.nthreads_var = nthreads_var;
start_data->thread_pool = pool;
start_data->nested = nested;
diff --git a/libgomp/testsuite/libgomp.c++/atomic-2.C b/libgomp/testsuite/libgomp.c++/atomic-2.C
new file mode 100644
index 00000000000..e7217590a36
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-2.C
@@ -0,0 +1,156 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+int x = 6;
+float y;
+
+int
+main (void)
+{
+ int v;
+ float f;
+ #pragma omp atomic read
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic write
+ x = 17;
+ #pragma omp atomic read
+ v = x;
+ if (v != 17)
+ abort ();
+ #pragma omp atomic update
+ x++;
+ #pragma omp atomic read
+ v = x;
+ if (v != 18)
+ abort ();
+ #pragma omp atomic capture
+ v = x++;
+ if (v != 18)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 19)
+ abort ();
+ #pragma omp atomic capture
+ v = ++x;
+ if (v != 20)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 20)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x *= 3; }
+ if (v != 20)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 60)
+ abort ();
+ #pragma omp atomic capture
+ {
+ x |= 2;
+ v = x;
+ }
+ if (v != 62)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 62)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x++; }
+ if (v != 62)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; ++x; }
+ if (v != 63)
+ abort ();
+ #pragma omp atomic capture
+ {
+ ++x;
+ v = x;
+ }
+ if (v != 65)
+ abort ();
+#pragma omp atomic capture
+{x++;v=x;}if (v != 66)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 66)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x--; }
+ if (v != 66)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; --x; }
+ if (v != 65)
+ abort ();
+ #pragma omp atomic capture
+ {
+ --x;
+ v = x;
+ }
+ if (v != 63)
+ abort ();
+ #pragma omp atomic capture
+ { x--; v = x; } if (v != 62)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 62)
+ abort ();
+ #pragma omp atomic write
+ y = 17.5f;
+ #pragma omp atomic read
+ f = y;
+ if (f != 17.5)
+ abort ();
+ #pragma omp atomic update
+ y *= 2.0f;
+ #pragma omp atomic read
+ f = y;
+ if (y != 35.0)
+ abort ();
+ #pragma omp atomic capture
+ f = y *= 2.0f;
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic capture
+ f = y++;
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic read
+ f = y;
+ if (f != 71.0)
+ abort ();
+ #pragma omp atomic capture
+ f = --y;
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic read
+ f = y;
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic capture
+ { f = y; y /= 2.0f; }
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic read
+ f = y;
+ if (f != 35.0)
+ abort ();
+ #pragma omp atomic capture
+ { y /= 2.0f; f = y; }
+ if (f != 17.5)
+ abort ();
+ #pragma omp atomic read
+ f = y;
+ if (f != 17.5)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-3.C b/libgomp/testsuite/libgomp.c++/atomic-3.C
new file mode 100644
index 00000000000..660b260e19f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-3.C
@@ -0,0 +1,74 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+bool v, x1, x2, x3, x4, x5, x6;
+
+void
+foo ()
+{
+ #pragma omp atomic capture
+ v = ++x1;
+ if (!v)
+ abort ();
+ #pragma omp atomic capture
+ v = x2++;
+ if (v)
+ abort ();
+ #pragma omp atomic read
+ v = x3;
+ if (!v)
+ abort ();
+ #pragma omp atomic read
+ v = x4;
+ if (!v)
+ abort ();
+ #pragma omp atomic capture
+ { v = x5; x5 |= 1; }
+ if (v)
+ abort ();
+ #pragma omp atomic capture
+ { x6 |= 1; v = x6; }
+ if (!v)
+ abort ();
+}
+
+void
+bar ()
+{
+ #pragma omp atomic write
+ x1 = false;
+ #pragma omp atomic write
+ x2 = false;
+ #pragma omp atomic capture
+ { ++x1; v = x1; }
+ if (!v)
+ abort ();
+ #pragma omp atomic capture
+ { v = x2; x2++; }
+ if (v)
+ abort ();
+ #pragma omp atomic write
+ x1 = false;
+ #pragma omp atomic write
+ x2 = false;
+ #pragma omp atomic capture
+ { x1++; v = x1; }
+ if (!v)
+ abort ();
+ #pragma omp atomic capture
+ { v = x2; ++x2; }
+ if (v)
+ abort ();
+}
+
+int
+main ()
+{
+ #pragma omp atomic write
+ x3 = true;
+ #pragma omp atomic write
+ x4 = true;
+ foo ();
+ bar ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-4.C b/libgomp/testsuite/libgomp.c++/atomic-4.C
new file mode 100644
index 00000000000..82439df2bb2
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-4.C
@@ -0,0 +1,166 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+template <typename T, typename T2>
+int
+foo (void)
+{
+ extern T x;
+ extern T2 y;
+ T v;
+ T2 f;
+ #pragma omp atomic read
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic write
+ x = 17;
+ #pragma omp atomic read
+ v = x;
+ if (v != 17)
+ abort ();
+ #pragma omp atomic update
+ x++;
+ #pragma omp atomic read
+ v = x;
+ if (v != 18)
+ abort ();
+ #pragma omp atomic capture
+ v = x++;
+ if (v != 18)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 19)
+ abort ();
+ #pragma omp atomic capture
+ v = ++x;
+ if (v != 20)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 20)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x *= 3; }
+ if (v != 20)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 60)
+ abort ();
+ #pragma omp atomic capture
+ {
+ x |= 2;
+ v = x;
+ }
+ if (v != 62)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 62)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x++; }
+ if (v != 62)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; ++x; }
+ if (v != 63)
+ abort ();
+ #pragma omp atomic capture
+ {
+ ++x;
+ v = x;
+ }
+ if (v != 65)
+ abort ();
+#pragma omp atomic capture
+{x++;v=x;}if (v != 66)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 66)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x--; }
+ if (v != 66)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; --x; }
+ if (v != 65)
+ abort ();
+ #pragma omp atomic capture
+ {
+ --x;
+ v = x;
+ }
+ if (v != 63)
+ abort ();
+ #pragma omp atomic capture
+ { x--; v = x; } if (v != 62)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 62)
+ abort ();
+ #pragma omp atomic write
+ y = 17.5f;
+ #pragma omp atomic read
+ f = y;
+ if (f != 17.5)
+ abort ();
+ #pragma omp atomic update
+ y *= 2.0f;
+ #pragma omp atomic read
+ f = y;
+ if (y != 35.0)
+ abort ();
+ #pragma omp atomic capture
+ f = y *= 2.0f;
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic capture
+ f = y++;
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic read
+ f = y;
+ if (f != 71.0)
+ abort ();
+ #pragma omp atomic capture
+ f = --y;
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic read
+ f = y;
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic capture
+ { f = y; y /= 2.0f; }
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic read
+ f = y;
+ if (f != 35.0)
+ abort ();
+ #pragma omp atomic capture
+ { y /= 2.0f; f = y; }
+ if (f != 17.5)
+ abort ();
+ #pragma omp atomic read
+ f = y;
+ if (f != 17.5)
+ abort ();
+ return 0;
+}
+
+int x = 6;
+float y;
+
+int
+main ()
+{
+ foo <int, float> ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-5.C b/libgomp/testsuite/libgomp.c++/atomic-5.C
new file mode 100644
index 00000000000..e9bd2cc1cbd
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-5.C
@@ -0,0 +1,79 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+
+template <typename T>
+void
+foo ()
+{
+ extern T v, x1, x2, x3, x4, x5, x6;
+ #pragma omp atomic capture
+ v = ++x1;
+ if (!v)
+ abort ();
+ #pragma omp atomic capture
+ v = x2++;
+ if (v)
+ abort ();
+ #pragma omp atomic read
+ v = x3;
+ if (!v)
+ abort ();
+ #pragma omp atomic read
+ v = x4;
+ if (!v)
+ abort ();
+ #pragma omp atomic capture
+ { v = x5; x5 |= 1; }
+ if (v)
+ abort ();
+ #pragma omp atomic capture
+ { x6 |= 1; v = x6; }
+ if (!v)
+ abort ();
+}
+
+template <typename T>
+void
+bar ()
+{
+ extern T v, x1, x2;
+ #pragma omp atomic write
+ x1 = false;
+ #pragma omp atomic write
+ x2 = false;
+ #pragma omp atomic capture
+ { ++x1; v = x1; }
+ if (!v)
+ abort ();
+ #pragma omp atomic capture
+ { v = x2; x2++; }
+ if (v)
+ abort ();
+ #pragma omp atomic write
+ x1 = false;
+ #pragma omp atomic write
+ x2 = false;
+ #pragma omp atomic capture
+ { x1++; v = x1; }
+ if (!v)
+ abort ();
+ #pragma omp atomic capture
+ { v = x2; ++x2; }
+ if (v)
+ abort ();
+}
+
+bool v, x1, x2, x3, x4, x5, x6;
+
+int
+main ()
+{
+ #pragma omp atomic write
+ x3 = true;
+ #pragma omp atomic write
+ x4 = true;
+ foo <bool> ();
+ bar <bool> ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-6.C b/libgomp/testsuite/libgomp.c++/atomic-6.C
new file mode 100644
index 00000000000..d7d0eb981f7
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-6.C
@@ -0,0 +1,58 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+long long l, m;
+int i, j;
+
+void
+foo (void)
+{
+ #pragma omp atomic read
+ i = l;
+ #pragma omp atomic read
+ m = j;
+ if (i != 77 || m != 88)
+ abort ();
+ #pragma omp atomic write
+ l = 1 + i + 6 * 1;
+ #pragma omp atomic write
+ j = 170 - 170 + m + 1 * 7;
+ #pragma omp atomic capture
+ i = l += 4;
+ #pragma omp atomic capture
+ m = j += 4;
+ if (i != 88 || m != 99)
+ abort ();
+ #pragma omp atomic capture
+ {
+ i = l;
+ l += 4;
+ }
+ #pragma omp atomic capture
+ {
+ m = j;
+ j += 4;
+ }
+ if (i != 88 || m != 99)
+ abort ();
+ #pragma omp atomic capture
+ {
+ l += 4;
+ i = l;
+ }
+ #pragma omp atomic capture
+ {
+ j += 4;
+ m = j;
+ }
+ if (i != 96 || m != 107)
+ abort ();
+}
+
+int
+main ()
+{
+ l = 77;
+ j = 88;
+ foo ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-7.C b/libgomp/testsuite/libgomp.c++/atomic-7.C
new file mode 100644
index 00000000000..fe1b4d7aa9e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-7.C
@@ -0,0 +1,63 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+
+template <typename S, typename T>
+void
+foo (void)
+{
+ extern S l, m;
+ extern T i, j;
+
+ #pragma omp atomic read
+ i = l;
+ #pragma omp atomic read
+ m = j;
+ if (i != 77 || m != 88)
+ abort ();
+ #pragma omp atomic write
+ l = 1 + i + 6 * 1;
+ #pragma omp atomic write
+ j = 170 - 170 + m + 1 * 7;
+ #pragma omp atomic capture
+ i = l += 4;
+ #pragma omp atomic capture
+ m = j += 4;
+ if (i != 88 || m != 99)
+ abort ();
+ #pragma omp atomic capture
+ {
+ i = l;
+ l += 4;
+ }
+ #pragma omp atomic capture
+ {
+ m = j;
+ j += 4;
+ }
+ if (i != 88 || m != 99)
+ abort ();
+ #pragma omp atomic capture
+ {
+ l += 4;
+ i = l;
+ }
+ #pragma omp atomic capture
+ {
+ j += 4;
+ m = j;
+ }
+ if (i != 96 || m != 107)
+ abort ();
+}
+
+long long l, m;
+int i, j;
+
+int
+main ()
+{
+ l = 77;
+ j = 88;
+ foo <long long, int> ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-8.C b/libgomp/testsuite/libgomp.c++/atomic-8.C
new file mode 100644
index 00000000000..744b3409c97
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-8.C
@@ -0,0 +1,137 @@
+// { dg-do run }
+
+extern "C" void abort ();
+int x = 6, cnt;
+
+int
+foo ()
+{
+ return cnt++;
+}
+
+int
+main ()
+{
+ int v, *p;
+ #pragma omp atomic update
+ x = x + 7;
+ #pragma omp atomic
+ x = x + 7 + 6;
+ #pragma omp atomic update
+ x = x + 2 * 3;
+ #pragma omp atomic
+ x = x * (2 - 1);
+ #pragma omp atomic read
+ v = x;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic write
+ x = 0;
+ #pragma omp atomic capture
+ {
+ v = x;
+ x = x | 1 ^ 2;
+ }
+ if (v != 0)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = x;
+ x = x | 4 | 2;
+ }
+ if (v != 3)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 7)
+ abort ();
+ #pragma omp atomic capture
+ {
+ x = x ^ 6 & 2;
+ v = x;
+ }
+ if (v != 5)
+ abort ();
+ #pragma omp atomic capture
+ { x = x - (6 + 4); v = x; }
+ if (v != -5)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = x - (1 | 2); }
+ if (v != -5)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic
+ x = x * -4 / 2;
+ #pragma omp atomic read
+ v = x;
+ if (v != 16)
+ abort ();
+ p = &x;
+ #pragma omp atomic update
+ p[foo (), 0] = p[foo (), 0] - 16;
+ #pragma omp atomic read
+ v = x;
+ if (cnt != 2 || v != 0)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[foo (), 0] += 6;
+ v = p[foo (), 0];
+ }
+ if (cnt != 4 || v != 6)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0];
+ p[foo (), 0] += 6;
+ }
+ if (cnt != 6 || v != 6)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 12)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[foo (), 0] = p[foo (), 0] + 6;
+ v = p[foo (), 0];
+ }
+ if (cnt != 9 || v != 18)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0];
+ p[foo (), 0] = p[foo (), 0] + 6;
+ }
+ if (cnt != 12 || v != 18)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 24)
+ abort ();
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; p[foo (), 0]++; }
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; ++p[foo (), 0]; }
+ #pragma omp atomic capture
+ { p[foo (), 0]++; v = p[foo (), 0]; }
+ #pragma omp atomic capture
+ { ++p[foo (), 0]; v = p[foo (), 0]; }
+ if (cnt != 20 || v != 28)
+ abort ();
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; p[foo (), 0]--; }
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; --p[foo (), 0]; }
+ #pragma omp atomic capture
+ { p[foo (), 0]--; v = p[foo (), 0]; }
+ #pragma omp atomic capture
+ { --p[foo (), 0]; v = p[foo (), 0]; }
+ if (cnt != 28 || v != 24)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-9.C b/libgomp/testsuite/libgomp.c++/atomic-9.C
new file mode 100644
index 00000000000..ece1bf3f029
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-9.C
@@ -0,0 +1,148 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+int cnt;
+
+int
+foo ()
+{
+ return cnt++;
+}
+
+template <typename T>
+void
+bar ()
+{
+ extern T x;
+ T v, *p;
+ #pragma omp atomic update
+ x = x + 7;
+ #pragma omp atomic
+ x = x + 7 + 6;
+ #pragma omp atomic update
+ x = x + 2 * 3;
+ #pragma omp atomic
+ x = x * (2 - 1);
+ #pragma omp atomic read
+ v = x;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic write
+ x = 0;
+ #pragma omp atomic capture
+ {
+ v = x;
+ x = x | 1 ^ 2;
+ }
+ if (v != 0)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = x;
+ x = x | 4 | 2;
+ }
+ if (v != 3)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 7)
+ abort ();
+ #pragma omp atomic capture
+ {
+ x = x ^ 6 & 2;
+ v = x;
+ }
+ if (v != 5)
+ abort ();
+ #pragma omp atomic capture
+ { x = x - (6 + 4); v = x; }
+ if (v != -5)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = x - (1 | 2); }
+ if (v != -5)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic
+ x = x * -4 / 2;
+ #pragma omp atomic read
+ v = x;
+ if (v != 16)
+ abort ();
+ p = &x;
+ #pragma omp atomic update
+ p[foo (), 0] = p[foo (), 0] - 16;
+ #pragma omp atomic read
+ v = x;
+ if (cnt != 2 || v != 0)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[foo (), 0] += 6;
+ v = p[foo (), 0];
+ }
+ if (cnt != 4 || v != 6)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0];
+ p[foo (), 0] += 6;
+ }
+ if (cnt != 6 || v != 6)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 12)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[foo (), 0] = p[foo (), 0] + 6;
+ v = p[foo (), 0];
+ }
+ if (cnt != 9 || v != 18)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0];
+ p[foo (), 0] = p[foo (), 0] + 6;
+ }
+ if (cnt != 12 || v != 18)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 24)
+ abort ();
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; p[foo (), 0]++; }
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; ++p[foo (), 0]; }
+ #pragma omp atomic capture
+ { p[foo (), 0]++; v = p[foo (), 0]; }
+ #pragma omp atomic capture
+ { ++p[foo (), 0]; v = p[foo (), 0]; }
+ if (cnt != 20 || v != 28)
+ abort ();
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; p[foo (), 0]--; }
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; --p[foo (), 0]; }
+ #pragma omp atomic capture
+ { p[foo (), 0]--; v = p[foo (), 0]; }
+ #pragma omp atomic capture
+ { --p[foo (), 0]; v = p[foo (), 0]; }
+ if (cnt != 28 || v != 24)
+ abort ();
+}
+
+int x = 6;
+
+int
+main ()
+{
+ bar <int> ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/reduction-4.C b/libgomp/testsuite/libgomp.c++/reduction-4.C
new file mode 100644
index 00000000000..e7ef8a13c2a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/reduction-4.C
@@ -0,0 +1,54 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+
+template <typename I, typename F>
+void
+foo ()
+{
+ I j = -10000;
+ F f = 1024.0;
+ int i;
+ #pragma omp parallel for reduction (min:f) reduction (max:j)
+ for (i = 0; i < 4; i++)
+ switch (i)
+ {
+ case 0:
+ if (j < -16) j = -16; break;
+ case 1:
+ if (f > -2.0) f = -2.0; break;
+ case 2:
+ if (j < 8) j = 8; if (f > 9.0) f = 9.0; break;
+ case 3:
+ break;
+ }
+ if (j != 8 || f != -2.0)
+ abort ();
+}
+
+int
+main ()
+{
+ int j = -10000;
+ float f = 1024.0;
+ int i;
+ #pragma omp parallel for reduction (min:f) reduction (max:j)
+ for (i = 0; i < 4; i++)
+ switch (i)
+ {
+ case 0:
+ if (j < -16) j = -16; break;
+ case 1:
+ if (f > -2.0) f = -2.0; break;
+ case 2:
+ if (j < 8) j = 8; if (f > 9.0) f = 9.0; break;
+ case 3:
+ break;
+ }
+ if (j != 8 || f != -2.0)
+ abort ();
+ foo <int, float> ();
+ foo <long, double> ();
+ foo <long long, long double> ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-8.C b/libgomp/testsuite/libgomp.c++/task-8.C
new file mode 100644
index 00000000000..3e1b4696b08
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-8.C
@@ -0,0 +1,44 @@
+// { dg-do run }
+
+#include <omp.h>
+#include <cstdlib>
+
+int err;
+
+int
+main ()
+{
+ int e;
+#pragma omp parallel shared(err)
+ {
+ if (omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ #pragma omp task if (0) shared(err)
+ {
+ if (omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ #pragma omp task if (0) shared(err)
+ if (omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ }
+ #pragma omp task final (1) shared(err)
+ {
+ if (!omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ #pragma omp taskyield
+ #pragma omp taskwait
+ #pragma omp task shared(err)
+ if (!omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ }
+ }
+ #pragma omp atomic read
+ e = err;
+ if (e)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c/atomic-11.c b/libgomp/testsuite/libgomp.c/atomic-11.c
new file mode 100644
index 00000000000..d1d6ca53a30
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/atomic-11.c
@@ -0,0 +1,156 @@
+/* { dg-do run } */
+
+extern void abort (void);
+int x = 6;
+float y;
+
+int
+main (void)
+{
+ int v;
+ float f;
+ #pragma omp atomic read
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic write
+ x = 17;
+ #pragma omp atomic read
+ v = x;
+ if (v != 17)
+ abort ();
+ #pragma omp atomic update
+ x++;
+ #pragma omp atomic read
+ v = x;
+ if (v != 18)
+ abort ();
+ #pragma omp atomic capture
+ v = x++;
+ if (v != 18)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 19)
+ abort ();
+ #pragma omp atomic capture
+ v = ++x;
+ if (v != 20)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 20)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x *= 3; }
+ if (v != 20)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 60)
+ abort ();
+ #pragma omp atomic capture
+ {
+ x |= 2;
+ v = x;
+ }
+ if (v != 62)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 62)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x++; }
+ if (v != 62)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; ++x; }
+ if (v != 63)
+ abort ();
+ #pragma omp atomic capture
+ {
+ ++x;
+ v = x;
+ }
+ if (v != 65)
+ abort ();
+#pragma omp atomic capture
+{x++;v=x;}if (v != 66)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 66)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x--; }
+ if (v != 66)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; --x; }
+ if (v != 65)
+ abort ();
+ #pragma omp atomic capture
+ {
+ --x;
+ v = x;
+ }
+ if (v != 63)
+ abort ();
+ #pragma omp atomic capture
+ { x--; v = x; } if (v != 62)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 62)
+ abort ();
+ #pragma omp atomic write
+ y = 17.5f;
+ #pragma omp atomic read
+ f = y;
+ if (f != 17.5)
+ abort ();
+ #pragma omp atomic update
+ y *= 2.0f;
+ #pragma omp atomic read
+ f = y;
+ if (y != 35.0)
+ abort ();
+ #pragma omp atomic capture
+ f = y *= 2.0f;
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic capture
+ f = y++;
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic read
+ f = y;
+ if (f != 71.0)
+ abort ();
+ #pragma omp atomic capture
+ f = --y;
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic read
+ f = y;
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic capture
+ { f = y; y /= 2.0f; }
+ if (f != 70.0)
+ abort ();
+ #pragma omp atomic read
+ f = y;
+ if (f != 35.0)
+ abort ();
+ #pragma omp atomic capture
+ { y /= 2.0f; f = y; }
+ if (f != 17.5)
+ abort ();
+ #pragma omp atomic read
+ f = y;
+ if (f != 17.5)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/atomic-12.c b/libgomp/testsuite/libgomp.c/atomic-12.c
new file mode 100644
index 00000000000..a9fe5606538
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/atomic-12.c
@@ -0,0 +1,98 @@
+/* { dg-do run } */
+
+extern void abort (void);
+_Bool v, x1, x2, x3, x4, x5, x6;
+
+void
+foo (void)
+{
+ #pragma omp atomic capture
+ v = ++x1;
+ if (!v)
+ abort ();
+ #pragma omp atomic capture
+ v = x2++;
+ if (v)
+ abort ();
+ #pragma omp atomic capture
+ v = --x3;
+ if (v)
+ abort ();
+ #pragma omp atomic capture
+ v = x4--;
+ if (!v)
+ abort ();
+ #pragma omp atomic capture
+ { v = x5; x5 |= 1; }
+ if (v)
+ abort ();
+ #pragma omp atomic capture
+ { x6 |= 1; v = x6; }
+ if (!v)
+ abort ();
+}
+
+void
+bar (void)
+{
+ #pragma omp atomic write
+ x1 = 0;
+ #pragma omp atomic write
+ x2 = 0;
+ #pragma omp atomic write
+ x3 = 1;
+ #pragma omp atomic write
+ x4 = 1;
+ #pragma omp atomic capture
+ { ++x1; v = x1; }
+ if (!v)
+ abort ();
+ #pragma omp atomic capture
+ { v = x2; x2++; }
+ if (v)
+ abort ();
+ #pragma omp atomic capture
+ { --x3; v = x3; }
+ if (v)
+ abort ();
+ #pragma omp atomic capture
+ { v = x4; x4--; }
+ if (!v)
+ abort ();
+ #pragma omp atomic write
+ x1 = 0;
+ #pragma omp atomic write
+ x2 = 0;
+ #pragma omp atomic write
+ x3 = 1;
+ #pragma omp atomic write
+ x4 = 1;
+ #pragma omp atomic capture
+ { x1++; v = x1; }
+ if (!v)
+ abort ();
+ #pragma omp atomic capture
+ { v = x2; ++x2; }
+ if (v)
+ abort ();
+ #pragma omp atomic capture
+ { x3--; v = x3; }
+ if (v)
+ abort ();
+ #pragma omp atomic capture
+ { v = x4; --x4; }
+ if (!v)
+ abort ();
+}
+
+int
+main ()
+{
+ #pragma omp atomic write
+ x3 = 1;
+ #pragma omp atomic write
+ x4 = 1;
+ foo ();
+ bar ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/atomic-13.c b/libgomp/testsuite/libgomp.c/atomic-13.c
new file mode 100644
index 00000000000..52800fc7192
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/atomic-13.c
@@ -0,0 +1,59 @@
+/* { dg-do run } */
+
+extern void abort (void);
+long long l, m;
+int i, j;
+
+void
+foo (void)
+{
+ #pragma omp atomic read
+ i = l;
+ #pragma omp atomic read
+ m = j;
+ if (i != 77 || m != 88)
+ abort ();
+ #pragma omp atomic write
+ l = 1 + i + 6 * 1;
+ #pragma omp atomic write
+ j = 170 - 170 + m + 1 * 7;
+ #pragma omp atomic capture
+ i = l += 4;
+ #pragma omp atomic capture
+ m = j += 4;
+ if (i != 88 || m != 99)
+ abort ();
+ #pragma omp atomic capture
+ {
+ i = l;
+ l += 4;
+ }
+ #pragma omp atomic capture
+ {
+ m = j;
+ j += 4;
+ }
+ if (i != 88 || m != 99)
+ abort ();
+ #pragma omp atomic capture
+ {
+ l += 4;
+ i = l;
+ }
+ #pragma omp atomic capture
+ {
+ j += 4;
+ m = j;
+ }
+ if (i != 96 || m != 107)
+ abort ();
+}
+
+int
+main ()
+{
+ l = 77;
+ j = 88;
+ foo ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/atomic-14.c b/libgomp/testsuite/libgomp.c/atomic-14.c
new file mode 100644
index 00000000000..593665046c5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/atomic-14.c
@@ -0,0 +1,137 @@
+/* { dg-do run } */
+
+extern void abort (void);
+int x = 6, cnt;
+
+int
+foo (void)
+{
+ return cnt++;
+}
+
+int
+main ()
+{
+ int v, *p;
+ #pragma omp atomic update
+ x = x + 7;
+ #pragma omp atomic
+ x = x + 7 + 6;
+ #pragma omp atomic update
+ x = x + 2 * 3;
+ #pragma omp atomic
+ x = x * (2 - 1);
+ #pragma omp atomic read
+ v = x;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic write
+ x = 0;
+ #pragma omp atomic capture
+ {
+ v = x;
+ x = x | 1 ^ 2;
+ }
+ if (v != 0)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = x;
+ x = x | 4 | 2;
+ }
+ if (v != 3)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 7)
+ abort ();
+ #pragma omp atomic capture
+ {
+ x = x ^ 6 & 2;
+ v = x;
+ }
+ if (v != 5)
+ abort ();
+ #pragma omp atomic capture
+ { x = x - (6 + 4); v = x; }
+ if (v != -5)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = x - (1 | 2); }
+ if (v != -5)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic
+ x = x * -4 / 2;
+ #pragma omp atomic read
+ v = x;
+ if (v != 16)
+ abort ();
+ p = &x;
+ #pragma omp atomic update
+ p[foo (), 0] = p[foo (), 0] - 16;
+ #pragma omp atomic read
+ v = x;
+ if (cnt != 2 || v != 0)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[foo (), 0] += 6;
+ v = p[foo (), 0];
+ }
+ if (cnt != 4 || v != 6)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0];
+ p[foo (), 0] += 6;
+ }
+ if (cnt != 6 || v != 6)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 12)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[foo (), 0] = p[foo (), 0] + 6;
+ v = p[foo (), 0];
+ }
+ if (cnt != 9 || v != 18)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0];
+ p[foo (), 0] = p[foo (), 0] + 6;
+ }
+ if (cnt != 12 || v != 18)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 24)
+ abort ();
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; p[foo (), 0]++; }
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; ++p[foo (), 0]; }
+ #pragma omp atomic capture
+ { p[foo (), 0]++; v = p[foo (), 0]; }
+ #pragma omp atomic capture
+ { ++p[foo (), 0]; v = p[foo (), 0]; }
+ if (cnt != 20 || v != 28)
+ abort ();
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; p[foo (), 0]--; }
+ #pragma omp atomic capture
+ { v = p[foo (), 0]; --p[foo (), 0]; }
+ #pragma omp atomic capture
+ { p[foo (), 0]--; v = p[foo (), 0]; }
+ #pragma omp atomic capture
+ { --p[foo (), 0]; v = p[foo (), 0]; }
+ if (cnt != 28 || v != 24)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/reduction-6.c b/libgomp/testsuite/libgomp.c/reduction-6.c
new file mode 100644
index 00000000000..d378bad9a6a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/reduction-6.c
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+
+extern void abort (void);
+int j;
+float f;
+
+int
+main ()
+{
+ j = -10000;
+ f = 1024.0;
+ int i;
+ #pragma omp parallel for reduction (min:f) reduction (max:j)
+ for (i = 0; i < 4; i++)
+ switch (i)
+ {
+ case 0:
+ if (j < -16) j = -16; break;
+ case 1:
+ if (f > -2.0) f = -2.0; break;
+ case 2:
+ if (j < 8) j = 8; if (f > 9.0) f = 9.0; break;
+ case 3:
+ break;
+ }
+ if (j != 8 || f != -2.0)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/task-5.c b/libgomp/testsuite/libgomp.c/task-5.c
new file mode 100644
index 00000000000..b1523712760
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/task-5.c
@@ -0,0 +1,45 @@
+/* { dg-do run } */
+
+#include <omp.h>
+#include <stdlib.h>
+
+int err;
+
+int
+main ()
+{
+ int e;
+#pragma omp parallel shared(err)
+ {
+ if (omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ #pragma omp task if (0) shared(err)
+ {
+ if (omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ #pragma omp task if (0) shared(err)
+ if (omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ }
+ #pragma omp task final (1) shared(err)
+ {
+ if (!omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ #pragma omp taskyield
+ #pragma omp taskwait
+ #pragma omp task shared(err)
+ if (!omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ }
+ }
+ #pragma omp atomic read
+ e = err;
+ if (e)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.fortran/allocatable7.f90 b/libgomp/testsuite/libgomp.fortran/allocatable7.f90
new file mode 100644
index 00000000000..dc68baa7542
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/allocatable7.f90
@@ -0,0 +1,16 @@
+! { dg-do run }
+
+ integer, allocatable :: a(:)
+ logical :: l
+ l = .false.
+!$omp parallel firstprivate (a) reduction (.or.:l)
+ l = allocated (a)
+ allocate (a(10))
+ l = l .or. .not. allocated (a)
+ a = 10
+ if (any (a .ne. 10)) l = .true.
+ deallocate (a)
+ l = l .or. allocated (a)
+!$omp end parallel
+ if (l) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/allocatable8.f90 b/libgomp/testsuite/libgomp.fortran/allocatable8.f90
new file mode 100644
index 00000000000..209378259e3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/allocatable8.f90
@@ -0,0 +1,14 @@
+! { dg-do run }
+! { dg-require-effective-target tls_runtime }
+!$ use omp_lib
+
+ integer, save, allocatable :: a(:, :)
+ logical :: l
+!$omp threadprivate (a)
+ if (allocated (a)) call abort
+ l = .false.
+!$omp parallel copyin (a) num_threads (4) reduction(.or.:l)
+ l = l.or.allocated (a)
+!$omp end parallel
+ if (l.or.allocated (a)) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/crayptr3.f90 b/libgomp/testsuite/libgomp.fortran/crayptr3.f90
new file mode 100644
index 00000000000..9777c6b22cc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/crayptr3.f90
@@ -0,0 +1,36 @@
+! { dg-do run }
+! { dg-options "-fopenmp -fcray-pointer" }
+
+ use omp_lib
+ integer :: a, b, c, i, p
+ logical :: l
+ pointer (ip, p)
+ a = 1
+ b = 2
+ c = 3
+ l = .false.
+ ip = loc (a)
+
+!$omp parallel num_threads (2) reduction (.or.:l) firstprivate (ip)
+ l = p .ne. 1
+ ip = loc (b)
+ if (omp_get_thread_num () .eq. 1) ip = loc (c)
+ l = l .or. (p .ne. (2 + omp_get_thread_num ()))
+!$omp end parallel
+
+ if (l) call abort
+
+ l = .false.
+ ip = loc (a)
+!$omp parallel do num_threads (2) reduction (.or.:l) &
+!$omp & firstprivate (ip) lastprivate (ip)
+ do i = 0, 1
+ l = l .or. (p .ne. 1)
+ ip = loc (b)
+ if (i .eq. 1) ip = loc (c)
+ l = l .or. (p .ne. (2 + i))
+ end do
+
+ if (l) call abort
+ if (p .ne. 3) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/omp_atomic3.f90 b/libgomp/testsuite/libgomp.fortran/omp_atomic3.f90
new file mode 100644
index 00000000000..e8923d1f214
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/omp_atomic3.f90
@@ -0,0 +1,58 @@
+! { dg-do run }
+ integer (kind = 4) :: a, a2
+ integer (kind = 2) :: b, b2
+ real :: c, f
+ double precision :: d, d2, c2
+ integer, dimension (10) :: e
+!$omp atomic write
+ a = 1
+!$omp atomic write
+ b = 2
+!$omp end atomic
+!$omp atomic write
+ c = 3
+!$omp atomic write
+ d = 1 + 2 + 3 - 2
+ e = 5
+!$omp atomic write
+ f = 6
+!$omp end atomic
+!$omp atomic
+ a = a + 4
+!$omp end atomic
+!$omp atomic update
+ b = 4 - b
+!$omp atomic
+ c = c * 2
+!$omp atomic update
+ d = 2 / d
+!$omp end atomic
+!$omp atomic read
+ a2 = a
+!$omp atomic read
+ b2 = b
+!$omp end atomic
+!$omp atomic read
+ c2 = c
+!$omp atomic read
+ d2 = d
+ if (a2 .ne. 5 .or. b2 .ne. 2 .or. c2 .ne. 6 .or. d2 .ne. 0.5) call abort
+!$omp atomic write
+ d = 1.2
+!$omp atomic
+ a = a + c + d
+!$omp atomic
+ b = b - (a + c + d)
+ if (a .ne. 12 .or. b .ne. -17) call abort
+!$omp atomic
+ a = c + d + a
+!$omp atomic
+ b = a + c + d - b
+ if (a .ne. 19 .or. b .ne. 43) call abort
+!$omp atomic
+ b = (a + c + d) - b
+ a = 32
+!$omp atomic
+ a = a / 3.4
+ if (a .ne. 9 .or. b .ne. -16) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/omp_atomic4.f90 b/libgomp/testsuite/libgomp.fortran/omp_atomic4.f90
new file mode 100644
index 00000000000..725a3bc24ee
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/omp_atomic4.f90
@@ -0,0 +1,37 @@
+! { dg-do run }
+ integer (kind = 4) :: a, a2
+ integer (kind = 2) :: b, b2
+ real :: c
+ double precision :: d, d2, c2
+ integer, dimension (10) :: e
+!$omp atomic write
+ a = 1
+!$omp atomic write
+ b = 2
+!$omp atomic write
+ c = 3
+!$omp atomic write
+ d = 4
+!$omp atomic capture
+ a2 = a
+ a = a + 4
+!$omp end atomic
+!$omp atomic capture
+ b = b - 18
+ b2 = b
+!$omp end atomic
+!$omp atomic capture
+ c2 = c
+ c = 2.0 * c
+!$omp end atomic
+!$omp atomic capture
+ d = d / 2.0
+ d2 = d
+!$omp end atomic
+ if (a2 .ne. 1 .or. b2 .ne. -16 .or. c2 .ne. 3 .or. d2 .ne. 2) call abort
+!$omp atomic read
+ a2 = a
+!$omp atomic read
+ c2 = c
+ if (a2 .ne. 5 .or. b2 .ne. -16 .or. c2 .ne. 6 .or. d2 .ne. 2) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/pointer1.f90 b/libgomp/testsuite/libgomp.fortran/pointer1.f90
new file mode 100644
index 00000000000..d55ef35f4a5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/pointer1.f90
@@ -0,0 +1,77 @@
+! { dg-do run }
+ integer, pointer :: a, c(:)
+ integer, target :: b, d(10)
+ b = 0
+ a => b
+ d = 0
+ c => d
+ call foo (a, c)
+ b = 0
+ d = 0
+ call bar (a, c)
+contains
+ subroutine foo (a, c)
+ integer, pointer :: a, c(:), b, d(:)
+ integer :: r, r2
+ r = 0
+ !$omp parallel firstprivate (a, c) reduction (+:r)
+ !$omp atomic
+ a = a + 1
+ !$omp atomic
+ c(1) = c(1) + 1
+ r = r + 1
+ !$omp end parallel
+ if (a.ne.r.or.c(1).ne.r) call abort
+ r2 = r
+ b => a
+ d => c
+ r = 0
+ !$omp parallel firstprivate (b, d) reduction (+:r)
+ !$omp atomic
+ b = b + 1
+ !$omp atomic
+ d(1) = d(1) + 1
+ r = r + 1
+ !$omp end parallel
+ if (b.ne.r+r2.or.d(1).ne.r+r2) call abort
+ end subroutine foo
+ subroutine bar (a, c)
+ integer, pointer :: a, c(:), b, d(:)
+ integer, target :: q, r(5)
+ integer :: i
+ q = 17
+ r = 21
+ b => a
+ d => c
+ !$omp parallel do firstprivate (a, c) lastprivate (a, c)
+ do i = 1, 100
+ !$omp atomic
+ a = a + 1
+ !$omp atomic
+ c((i+9)/10) = c((i+9)/10) + 1
+ if (i.eq.100) then
+ a => q
+ c => r
+ end if
+ end do
+ !$omp end parallel do
+ if (b.ne.100.or.any(d.ne.10)) call abort
+ if (a.ne.17.or.any(c.ne.21)) call abort
+ a => b
+ c => d
+ !$omp parallel do firstprivate (b, d) lastprivate (b, d)
+ do i = 1, 100
+ !$omp atomic
+ b = b + 1
+ !$omp atomic
+ d((i+9)/10) = d((i+9)/10) + 1
+ if (i.eq.100) then
+ b => q
+ d => r
+ end if
+ end do
+ !$omp end parallel do
+ if (a.ne.200.or.any(c.ne.20)) call abort
+ if (b.ne.17.or.any(d.ne.21)) call abort
+ end subroutine bar
+end
diff --git a/libgomp/testsuite/libgomp.fortran/pointer2.f90 b/libgomp/testsuite/libgomp.fortran/pointer2.f90
new file mode 100644
index 00000000000..f172aed4b12
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/pointer2.f90
@@ -0,0 +1,28 @@
+! { dg-do run }
+! { dg-require-effective-target tls_runtime }
+ integer, pointer, save :: thr(:)
+!$omp threadprivate (thr)
+ integer, target :: s(3), t(3), u(3)
+ integer :: i
+ logical :: l
+ s = 2
+ t = 7
+ u = 13
+ thr => t
+ l = .false.
+ i = 0
+!$omp parallel copyin (thr) reduction(.or.:l) reduction(+:i)
+ if (any (thr.ne.7)) l = .true.
+ thr => s
+!$omp master
+ thr => u
+!$omp end master
+!$omp atomic
+ thr(1) = thr(1) + 1
+ i = i + 1
+!$omp end parallel
+ if (l) call abort
+ if (thr(1).ne.14) call abort
+ if (s(1).ne.1+i) call abort
+ if (u(1).ne.14) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/task4.f90 b/libgomp/testsuite/libgomp.fortran/task4.f90
new file mode 100644
index 00000000000..9fa67d95baa
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/task4.f90
@@ -0,0 +1,45 @@
+! { dg-do run }
+
+ use omp_lib
+ integer :: err, e
+
+!$omp atomic write
+ err = 0
+!$omp parallel shared(err) private(e)
+ if (omp_in_final ()) then
+!$omp atomic write
+ err = 1
+ endif
+!$omp task if (.false.) shared(err)
+ if (omp_in_final ()) then
+!$omp atomic write
+ err = 1
+ endif
+!$omp task if (.false.) shared(err)
+ if (omp_in_final ()) then
+!$omp atomic write
+ err = 1
+ endif
+!$omp end task
+!$omp end task
+!$omp atomic read
+ e = err
+!$omp task final (e .eq. 0) shared(err)
+ if (.not.omp_in_final ()) then
+!$omp atomic write
+ err = 1
+ endif
+!$omp taskyield
+!$omp taskwait
+!$omp task shared(err)
+ if (.not.omp_in_final ()) then
+!$omp atomic write
+ err = 1
+ endif
+!$omp end task
+!$omp end task
+!$omp end parallel
+!$omp atomic read
+ e = err
+ if (e .ne. 0) call abort
+end