diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-08-02 16:13:29 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-08-02 16:13:29 +0000 |
commit | 2169f33bdc9db9199850a22ce70730c68227b2db (patch) | |
tree | 2f3013a777c51a67a52b10f839e1bd56903dc5ba /libgomp | |
parent | f233ad1b4674f8b84008e794113d923ea6822dcf (diff) | |
download | gcc-2169f33bdc9db9199850a22ce70730c68227b2db.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@177194 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgomp')
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 |