summaryrefslogtreecommitdiff
path: root/libgomp/config
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2008-06-06 13:01:54 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2008-06-06 13:01:54 +0000
commitfd6481cf2e4413bca3ef43b1e504e1c78de6025d (patch)
tree5d5537ea17855b77cca7b9c90a262e584c441592 /libgomp/config
parentcbdcfa59ffeb7d51f7cbdfe64e1a99e43c82b2ac (diff)
downloadgcc-fd6481cf2e4413bca3ef43b1e504e1c78de6025d.tar.gz
* c-cppbuiltin.c (c_cpp_builtins): Change _OPENMP value to
200805. * langhooks.h (struct lang_hooks_for_decls): Add omp_finish_clause. Add omp_private_outer_ref hook, add another argument to omp_clause_default_ctor hook. * langhooks-def.h (LANG_HOOKS_OMP_FINISH_CLAUSE): Define. (LANG_HOOKS_OMP_PRIVATE_OUTER_REF): Define. (LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR): Change to hook_tree_tree_tree_tree_null. (LANG_HOOKS_DECLS): Add LANG_HOOKS_OMP_FINISH_CLAUSE and LANG_HOOKS_OMP_PRIVATE_OUTER_REF. * hooks.c (hook_tree_tree_tree_tree_null): New function. * hooks.h (hook_tree_tree_tree_tree_null): New prototype. * tree.def (OMP_TASK): New tree code. * tree.h (OMP_TASK_COPYFN, OMP_TASK_ARG_SIZE, OMP_TASK_ARG_ALIGN, OMP_CLAUSE_PRIVATE_OUTER_REF, OMP_CLAUSE_LASTPRIVATE_STMT, OMP_CLAUSE_COLLAPSE_ITERVAR, OMP_CLAUSE_COLLAPSE_COUNT, OMP_TASKREG_CHECK, OMP_TASKREG_BODY, OMP_TASKREG_CLAUSES, OMP_TASKREG_FN, OMP_TASKREG_DATA_ARG, OMP_TASK_BODY, OMP_TASK_CLAUSES, OMP_TASK_FN, OMP_TASK_DATA_ARG, OMP_CLAUSE_COLLAPSE_EXPR): Define. (enum omp_clause_default_kind): Add OMP_CLAUSE_DEFAULT_FIRSTPRIVATE. (OMP_DIRECTIVE_P): Add OMP_TASK. (OMP_CLAUSE_COLLAPSE, OMP_CLAUSE_UNTIED): New clause codes. (OMP_CLAUSE_SCHEDULE_AUTO): New schedule kind. * tree.c (omp_clause_code_name): Add OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED entries. (omp_clause_num_ops): Likewise. Increase OMP_CLAUSE_LASTPRIVATE num_ops to 2. (walk_tree_1): Handle OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. Walk OMP_CLAUSE_LASTPRIVATE_STMT. * tree-pretty-print.c (dump_omp_clause): Handle OMP_CLAUSE_SCHEDULE_AUTO, OMP_CLAUSE_UNTIED, OMP_CLAUSE_COLLAPSE, OMP_CLAUSE_DEFAULT_FIRSTPRIVATE. (dump_generic_node): Handle OMP_TASK and collapsed OMP_FOR loops. * c-omp.c (c_finish_omp_for): Allow pointer iterators. Remove warning about unsigned iterators. Change decl/init/cond/incr arguments to TREE_VECs, check arguments for all collapsed loops. (c_finish_omp_taskwait): New function. (c_split_parallel_clauses): Put OMP_CLAUSE_COLLAPSE clause to ws_clauses. * c-parser.c (c_parser_omp_for_loop): Parse collapsed loops. Call default_function_array_conversion on init. Add par_clauses argument. If decl is present in parallel's lastprivate clause, change it to shared and add lastprivate clause for decl to OMP_FOR_CLAUSES. Add clauses argument, on success set OMP_FOR_CLAUSES to it. Look up collapse count in clauses. (c_parser_omp_for, c_parser_omp_parallel): Adjust c_parser_omp_for_loop callers. (OMP_FOR_CLAUSE_MASK): Add 1 << PRAGMA_OMP_CLAUSE_COLLAPSE. (c_parser_pragma): Handle PRAGMA_OMP_TASKWAIT. (c_parser_omp_clause_name): Handle collapse and untied clauses. (c_parser_omp_clause_collapse, c_parser_omp_clause_untied): New functions. (c_parser_omp_clause_schedule): Handle schedule(auto). Include correct location in the error message. (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_COLLAPSE and PRAGMA_OMP_CLAUSE_UNTIED. (OMP_TASK_CLAUSE_MASK): Define. (c_parser_omp_task, c_parser_omp_taskwait): New functions. (c_parser_omp_construct): Handle PRAGMA_OMP_TASK. * tree-nested.c (convert_nonlocal_omp_clauses, convert_local_omp_clauses): Handle OMP_CLAUSE_LASTPRIVATE_STMT, OMP_CLAUSE_REDUCTION_INIT, OMP_CLAUSE_REDUCTION_MERGE, OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. Don't handle TREE_STATIC or DECL_EXTERNAL VAR_DECLs in OMP_CLAUSE_DECL. (conver_nonlocal_reference, convert_local_reference, convert_call_expr): Handle OMP_TASK the same as OMP_PARALLEL. Use OMP_TASKREG_* macros rather than OMP_PARALLEL_*. (walk_omp_for): Adjust for OMP_FOR_{INIT,COND,INCR} changes. * tree-gimple.c (is_gimple_stmt): Handle OMP_TASK. * c-tree.h (c_begin_omp_task, c_finish_omp_task): New prototypes. * c-pragma.h (PRAGMA_OMP_TASK, PRAGMA_OMP_TASKWAIT): New. (PRAGMA_OMP_CLAUSE_COLLAPSE, PRAGMA_OMP_CLAUSE_UNTIED): New. * c-typeck.c (c_begin_omp_task, c_finish_omp_task): New functions. (c_finish_omp_clauses): Handle OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. * c-pragma.c (init_pragma): Init omp task and omp taskwait pragmas. * c-common.h (c_finish_omp_taskwait): New prototype. * gimple-low.c (lower_stmt): Handle OMP_TASK. * tree-parloops.c (create_parallel_loop): Create 1 entry vectors for OMP_FOR_{INIT,COND,INCR}. * tree-cfg.c (remove_useless_stmts_1): Handle OMP_* containers. (make_edges): Handle OMP_TASK. * tree-ssa-operands.c (get_expr_operands): Handle collapsed OMP_FOR loops, adjust for OMP_FOR_{INIT,COND,INCR} changes. * tree-inline.c (estimate_num_insns_1): Handle OMP_TASK. * builtin-types.def (BT_PTR_ULONGLONG, BT_PTR_FN_VOID_PTR_PTR, BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR, BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR, BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT): New. * omp-builtins.def (BUILT_IN_GOMP_TASK, BUILT_IN_GOMP_TASKWAIT, BUILT_IN_GOMP_LOOP_ULL_STATIC_START, BUILT_IN_GOMP_LOOP_ULL_DYNAMIC_START, BUILT_IN_GOMP_LOOP_ULL_GUIDED_START, BUILT_IN_GOMP_LOOP_ULL_RUNTIME_START, BUILT_IN_GOMP_LOOP_ULL_ORDERED_STATIC_START, BUILT_IN_GOMP_LOOP_ULL_ORDERED_DYNAMIC_START, BUILT_IN_GOMP_LOOP_ULL_ORDERED_GUIDED_START, BUILT_IN_GOMP_LOOP_ULL_ORDERED_RUNTIME_START, BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT, BUILT_IN_GOMP_LOOP_ULL_DYNAMIC_NEXT, BUILT_IN_GOMP_LOOP_ULL_GUIDED_NEXT, BUILT_IN_GOMP_LOOP_ULL_RUNTIME_NEXT, BUILT_IN_GOMP_LOOP_ULL_ORDERED_STATIC_NEXT, BUILT_IN_GOMP_LOOP_ULL_ORDERED_DYNAMIC_NEXT, BUILT_IN_GOMP_LOOP_ULL_ORDERED_GUIDED_NEXT, BUILT_IN_GOMP_LOOP_ULL_ORDERED_RUNTIME_NEXT): New builtins. * gimplify.c (gimplify_omp_for): Allow pointer type for decl, handle POINTER_PLUS_EXPR. If loop counter has been replaced and original iterator is present in lastprivate clause or if collapse > 1, set OMP_CLAUSE_LASTPRIVATE_STMT. Handle collapsed OMP_FOR loops, adjust for OMP_FOR_{INIT,COND,INCR} changes. (gimplify_expr): Handle OMP_SECTIONS_SWITCH and OMP_TASK. (enum gimplify_omp_var_data): Add GOVD_PRIVATE_OUTER_REF. (omp_notice_variable): Set GOVD_PRIVATE_OUTER_REF if needed, if it is set, lookup var in outer contexts too. Handle OMP_CLAUSE_DEFAULT_FIRSTPRIVATE. Handle vars that are supposed to be implicitly determined firstprivate for task regions. (gimplify_scan_omp_clauses): Set GOVD_PRIVATE_OUTER_REF if needed, if it is set, lookup var in outer contexts too. Set OMP_CLAUSE_PRIVATE_OUTER_REF if GOVD_PRIVATE_OUTER_REF is set. Handle OMP_CLAUSE_LASTPRIVATE_STMT, OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. Take region_type as last argument instead of in_parallel and in_combined_parallel. (gimplify_omp_parallel, gimplify_omp_for, gimplify_omp_workshare): Adjust callers. (gimplify_adjust_omp_clauses_1): Set OMP_CLAUSE_PRIVATE_OUTER_REF if GOVD_PRIVATE_OUTER_REF is set. Call omp_finish_clause langhook. (new_omp_context): Set default_kind to OMP_CLAUSE_DEFAULT_UNSPECIFIED for OMP_TASK regions. (omp_region_type): New enum. (struct gimplify_omp_ctx): Remove is_parallel and is_combined_parallel fields, add region_type. (new_omp_context): Take region_type as argument instead of is_parallel and is_combined_parallel. (gimple_add_tmp_var, omp_firstprivatize_variable, omp_notice_variable, omp_is_private, omp_check_private): Adjust ctx->is_parallel and ctx->is_combined_parallel checks. (gimplify_omp_task): New function. (gimplify_adjust_omp_clauses): Handle OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. * omp-low.c (extract_omp_for_data): Use schedule(static) for schedule(auto). Handle pointer and unsigned iterators. Compute fd->iter_type. Handle POINTER_PLUS_EXPR increments. Add loops argument. Extract data for collapsed OMP_FOR loops. (expand_parallel_call): Assert sched_kind isn't auto, map runtime schedule to index 3. (struct omp_for_data_loop): New type. (struct omp_for_data): Remove v, n1, n2, step, cond_code fields. Add loop, loops, collapse and iter_type fields. (workshare_safe_to_combine_p): Disallow combined for if iter_type is unsigned long long. Don't combine collapse > 1 loops unless all bounds and steps are constant. Adjust extract_omp_for_data caller. (expand_omp_for_generic): Handle pointer, unsigned and long long iterators. Handle collapsed OMP_FOR loops. Adjust for struct omp_for_data changes. If libgomp function doesn't return boolean_type_node, add comparison of the return value with 0. (expand_omp_for_static_nochunk, expand_omp_for_static_chunk): Handle pointer, unsigned and long long iterators. Adjust for struct omp_for_data changes. (expand_omp_for): Assert sched_kind isn't auto, map runtime schedule to index 3. Use GOMP_loop_ull*{start,next} if iter_type is unsigned long long. Allocate loops array, pass it to extract_omp_for_data. For collapse > 1 loops use always expand_omp_for_generic. (omp_context): Add sfield_map and srecord_type fields. (is_task_ctx, lookup_sfield): New functions. (use_pointer_for_field): Use is_task_ctx helper. Change first argument's type from const_tree to tree. Clarify comment. In OMP_TASK disallow copy-in/out sharing. (build_sender_ref): Call lookup_sfield instead of lookup_field. (install_var_field): Add mask argument. Populate both record_type and srecord_type if needed. (delete_omp_context): Destroy sfield_map, clear DECL_ABSTRACT_ORIGIN in srecord_type. (fixup_child_record_type): Also remap FIELD_DECL's DECL_SIZE{,_UNIT} and DECL_FIELD_OFFSET. (scan_sharing_clauses): Adjust install_var_field callers. For firstprivate clauses on explicit tasks allocate the var by value in record_type unconditionally, rather than by reference. Handle OMP_CLAUSE_PRIVATE_OUTER_REF. Scan OMP_CLAUSE_LASTPRIVATE_STMT. Use is_taskreg_ctx instead of is_parallel_ctx. Handle OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. (create_omp_child_function_name): Add task_copy argument, use *_omp_cpyfn* names if it is true. (create_omp_child_function): Add task_copy argument, if true create *_omp_cpyfn* helper function. (scan_omp_parallel): Adjust create_omp_child_function callers. Rename parallel_nesting_level to taskreg_nesting_level. (scan_omp_task): New function. (lower_rec_input_clauses): Don't run constructors for firstprivate explicit task vars which are initialized by *_omp_cpyfn*. Pass outer var ref to omp_clause_default_ctor hook if OMP_CLAUSE_PRIVATE_OUTER_REF or OMP_CLAUSE_LASTPRIVATE. Replace OMP_CLAUSE_REDUCTION_PLACEHOLDER decls in OMP_CLAUSE_REDUCTION_INIT. (lower_send_clauses): Clear DECL_ABSTRACT_ORIGIN if in task to avoid duplicate setting of fields. Handle OMP_CLAUSE_PRIVATE_OUTER_REF. (lower_send_shared_vars): Use srecord_type if non-NULL. Don't copy-out if TREE_READONLY, only copy-in. (expand_task_copyfn): New function. (expand_task_call): New function. (struct omp_taskcopy_context): New type. (task_copyfn_copy_decl, task_copyfn_remap_type, create_task_copyfn): New functions. (lower_omp_parallel): Rename to... (lower_omp_taskreg): ... this. Use OMP_TASKREG_* macros where needed. Call create_task_copyfn if srecord_type is needed. Adjust sender_decl type. (task_shared_vars): New variable. (check_omp_nesting_restrictions): Warn if work-sharing, barrier, master or ordered region is closely nested inside OMP_TASK. Add warnings for barrier if closely nested inside of work-sharing, ordered, or master region. (scan_omp_1): Call check_omp_nesting_restrictions even for GOMP_barrier calls. Rename parallel_nesting_level to taskreg_nesting_level. Handle OMP_TASK. (lower_lastprivate_clauses): Even if some lastprivate is found on a work-sharing construct, continue looking for them on parent parallel construct. (lower_omp_for_lastprivate): Add lastprivate clauses to the beginning of dlist rather than end. Adjust for struct omp_for_data changes. (lower_omp_for): Add rec input clauses before OMP_FOR_PRE_BODY, not after it. Handle collapsed OMP_FOR loops, adjust for OMP_FOR_{INIT,COND,INCR} changes, adjust extract_omp_for_data caller. (get_ws_args_for): Adjust extract_omp_for_data caller. (scan_omp_for): Handle collapsed OMP_FOR loops, adjust for OMP_FOR_{INIT,COND,INCR} changes. (lower_omp_single_simple): If libgomp function doesn't return boolean_type_node, add comparison of the return value with 0. (diagnose_sb_1, diagnose_sb_2): Handle collapsed OMP_FOR loops, adjust for OMP_FOR_{INIT,COND,INCR} changes. Handle OMP_TASK. (parallel_nesting_level): Rename to... (taskreg_nesting_level): ... this. (is_taskreg_ctx): New function. (build_outer_var_ref, omp_copy_decl): Use is_taskreg_ctx instead of is_parallel_ctx. (execute_lower_omp): Rename parallel_nesting_level to taskreg_nesting_level. (expand_omp_parallel): Rename to... (expand_omp_taskreg): ... this. Use OMP_TASKREG_* macros where needed. Call omp_task_call for OMP_TASK regions. (expand_omp): Adjust caller, handle OMP_TASK. (lower_omp_1): Adjust lower_omp_taskreg caller, handle OMP_TASK. * bitmap.c (bitmap_default_obstack_depth): New variable. (bitmap_obstack_initialize, bitmap_obstack_release): Do nothing if argument is NULL and bitmap_default_obstack is already initialized. * ipa-struct-reorg.c (do_reorg_1): Call bitmap_obstack_release at the end. * matrix-reorg.c (matrix_reorg): Likewise. cp/ * cp-tree.h (cxx_omp_finish_clause, cxx_omp_create_clause_info, dependent_omp_for_p, begin_omp_task, finish_omp_task, finish_omp_taskwait): New prototypes. (cxx_omp_clause_default_ctor): Add outer argument. (finish_omp_for): Add new clauses argument. * cp-gimplify.c (cxx_omp_finish_clause): New function. (cxx_omp_predetermined_sharing): Moved from semantics.c, rewritten. (cxx_omp_clause_default_ctor): Add outer argument. (cp_genericize_r): Walk OMP_CLAUSE_LASTPRIVATE_STMT. * cp-objcp-common.h (LANG_HOOKS_OMP_FINISH_CLAUSE): Define. * parser.c (cp_parser_omp_for_loop): Parse collapsed for loops. Add par_clauses argument. If decl is present in parallel's lastprivate clause, change that clause to shared and add a lastprivate clause for decl to OMP_FOR_CLAUSES. Fix wording of error messages. Adjust finish_omp_for caller. Add clauses argument. Parse loops with random access iterators. (cp_parser_omp_clause_collapse, cp_parser_omp_clause_untied): New functions. (cp_parser_omp_for, cp_parser_omp_parallel): Adjust cp_parser_omp_for_loop callers. (cp_parser_omp_for_cond, cp_parser_omp_for_incr): New helper functions. (cp_parser_omp_clause_name): Handle collapse and untied clauses. (cp_parser_omp_clause_schedule): Handle auto schedule. (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_COLLAPSE and PRAGMA_OMP_CLAUSE_UNTIED. (OMP_FOR_CLAUSE_MASK): Add PRAGMA_OMP_CLAUSE_COLLAPSE. (OMP_TASK_CLAUSE_MASK): Define. (cp_parser_omp_task, cp_parser_omp_taskwait): New functions. (cp_parser_omp_construct): Handle PRAGMA_OMP_TASK. (cp_parser_pragma): Handle PRAGMA_OMP_TASK and PRAGMA_OMP_TASKWAIT. * pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_COLLAPSE and OMP_CLAUSE_UNTIED. Handle OMP_CLAUSE_LASTPRIVATE_STMT. (tsubst_omp_for_iterator): New function. (dependent_omp_for_p): New function. (tsubst_expr) <case OMP_FOR>: Use it. Handle collapsed OMP_FOR loops. Adjust finish_omp_for caller. Handle loops with random access iterators. Adjust for OMP_FOR_{INIT,COND,INCR} changes. (tsubst_expr): Handle OMP_TASK. * semantics.c (cxx_omp_create_clause_info): New function. (finish_omp_clauses): Call it. Handle OMP_CLAUSE_UNTIED and OMP_CLAUSE_COLLAPSE. (cxx_omp_predetermined_sharing): Removed. * semantics.c (finish_omp_for): Allow pointer iterators. Use handle_omp_for_class_iterator and dependent_omp_for_p. Handle collapsed for loops. Adjust c_finish_omp_for caller. Add new clauses argument. Fix check for type dependent cond or incr. Set OMP_FOR_CLAUSES to clauses. Use cp_convert instead of fold_convert to convert incr amount to difference_type. Only fold if not in template. If decl is mentioned in lastprivate clause, set OMP_CLAUSE_LASTPRIVATE_STMT. Handle loops with random access iterators. Adjust for OMP_FOR_{INIT,COND,INCR} changes. (finish_omp_threadprivate): Allow static class members of the current class. (handle_omp_for_class_iterator, begin_omp_task, finish_omp_task, finish_omp_taskwait): New functions. * parser.c (cp_parser_binary_expression): Add prec argument. (cp_parser_assignment_expression): Adjust caller. * cp-tree.h (outer_curly_brace_block): New prototype. * decl.c (outer_curly_brace_block): No longer static. fortran/ * scanner.c (skip_free_comments, skip_fixed_comments): Handle tabs. * parse.c (next_free): Allow tab after !$omp. (decode_omp_directive): Handle !$omp task, !$omp taskwait and !$omp end task. (case_executable): Add ST_OMP_TASKWAIT. (case_exec_markers): Add ST_OMP_TASK. (gfc_ascii_statement): Handle ST_OMP_TASK, ST_OMP_END_TASK and ST_OMP_TASKWAIT. (parse_omp_structured_block, parse_executable): Handle ST_OMP_TASK. * gfortran.h (gfc_find_sym_in_expr): New prototype. (gfc_statement): Add ST_OMP_TASK, ST_OMP_END_TASK and ST_OMP_TASKWAIT. (gfc_omp_clauses): Add OMP_SCHED_AUTO to sched_kind, OMP_DEFAULT_FIRSTPRIVATE to default_sharing. Add collapse and untied fields. (gfc_exec_op): Add EXEC_OMP_TASK and EXEC_OMP_TASKWAIT. * f95-lang.c (LANG_HOOKS_OMP_CLAUSE_COPY_CTOR, LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP, LANG_HOOKS_OMP_CLAUSE_DTOR, LANG_HOOKS_OMP_PRIVATE_OUTER_REF): Define. * trans.h (gfc_omp_clause_default_ctor): Add another argument. (gfc_omp_clause_copy_ctor, gfc_omp_clause_assign_op, gfc_omp_clause_dtor, gfc_omp_private_outer_ref): New prototypes. * types.def (BT_ULONGLONG, BT_PTR_ULONGLONG, BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR, BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR, BT_FN_VOID_PTR_PTR, BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT): New. (BT_BOOL): Use integer type with BOOL_TYPE_SIZE rather than boolean_type_node. * dump-parse-tree.c (gfc_show_omp_node): Handle EXEC_OMP_TASK, EXEC_OMP_TASKWAIT, OMP_SCHED_AUTO, OMP_DEFAULT_FIRSTPRIVATE, untied and collapse clauses. (gfc_show_code_node): Handle EXEC_OMP_TASK and EXEC_OMP_TASKWAIT. * trans.c (gfc_trans_code): Handle EXEC_OMP_TASK and EXEC_OMP_TASKWAIT. * st.c (gfc_free_statement): Likewise. * resolve.c (gfc_resolve_blocks, resolve_code): Likewise. (find_sym_in_expr): Rename to... (gfc_find_sym_in_expr): ... this. No longer static. (resolve_allocate_expr, resolve_ordinary_assign): Adjust caller. * match.h (gfc_match_omp_task, gfc_match_omp_taskwait): New prototypes. * openmp.c (resolve_omp_clauses): Allow allocatable arrays in firstprivate, lastprivate, reduction, copyprivate and copyin clauses. (omp_current_do_code): Made static. (omp_current_do_collapse): New variable. (gfc_resolve_omp_do_blocks): Compute omp_current_do_collapse, clear omp_current_do_code and omp_current_do_collapse on return. (gfc_resolve_do_iterator): Handle collapsed do loops. (resolve_omp_do): Likewise, diagnose errorneous collapsed do loops. (OMP_CLAUSE_COLLAPSE, OMP_CLAUSE_UNTIED): Define. (gfc_match_omp_clauses): Handle default (firstprivate), schedule (auto), untied and collapse (n) clauses. (OMP_DO_CLAUSES): Add OMP_CLAUSE_COLLAPSE. (OMP_TASK_CLAUSES): Define. (gfc_match_omp_task, gfc_match_omp_taskwait): New functions. * trans-openmp.c (gfc_omp_private_outer_ref): New function. (gfc_omp_clause_default_ctor): Add outer argument. For allocatable arrays allocate them with the bounds of the outer var if outer var is allocated. (gfc_omp_clause_copy_ctor, gfc_omp_clause_assign_op, gfc_omp_clause_dtor): New functions. (gfc_trans_omp_array_reduction): If decl is allocatable array, allocate it with outer var's bounds in OMP_CLAUSE_REDUCTION_INIT and deallocate it in OMP_CLAUSE_REDUCTION_MERGE. (gfc_omp_predetermined_sharing): Return OMP_CLAUSE_DEFAULT_SHARED for assumed-size arrays. (gfc_trans_omp_do): Add par_clauses argument. If dovar is present in lastprivate clause and do loop isn't simple, set OMP_CLAUSE_LASTPRIVATE_STMT. If dovar is present in parallel's lastprivate clause, change it to shared and add lastprivate clause to OMP_FOR_CLAUSES. Handle collapsed do loops. (gfc_trans_omp_directive): Adjust gfc_trans_omp_do callers. (gfc_trans_omp_parallel_do): Likewise. Move collapse clause to OMP_FOR from OMP_PARALLEL. (gfc_trans_omp_clauses): Handle OMP_SCHED_AUTO, OMP_DEFAULT_FIRSTPRIVATE, untied and collapse clauses. (gfc_trans_omp_task, gfc_trans_omp_taskwait): New functions. (gfc_trans_omp_directive): Handle EXEC_OMP_TASK and EXEC_OMP_TASKWAIT. gcc/testsuite/ * gcc.dg/gomp/collapse-1.c: New test. * gcc.dg/gomp/nesting-1.c: New test. * g++.dg/gomp/task-1.C: New test. * g++.dg/gomp/predetermined-1.C: New test. * g++.dg/gomp/tls-4.C: New test. * gfortran.dg/gomp/collapse1.f90: New test. * gfortran.dg/gomp/sharing-3.f90: New test. * gcc.dg/gomp/pr27499.c (foo): Remove is unsigned dg-warning. * g++.dg/gomp/pr27499.C (foo): Likewise. * g++.dg/gomp/for-16.C (foo): Likewise. * g++.dg/gomp/tls-3.C: Remove dg-error, add S::s definition. * g++.dg/gomp/pr34607.C: Adjust dg-error location. * g++.dg/gomp/for-16.C (foo): Add a new dg-error. * gcc.dg/gomp/appendix-a/a.35.4.c: Add dg-warning. * gcc.dg/gomp/appendix-a/a.35.6.c: Likewise. * gfortran.dg/gomp/appendix-a/a.35.4.f90: Likewise. * gfortran.dg/gomp/appendix-a/a.35.6.f90: Likewise. * gfortran.dg/gomp/omp_parse1.f90: Remove !$omp tab test. * gfortran.dg/gomp/appendix-a/a.33.4.f90: Remove dg-error about allocatable array. * gfortran.dg/gomp/reduction1.f90: Likewise. libgomp/ * configure.ac (LIBGOMP_GNU_SYMBOL_VERSIONING): New AC_DEFINE. Substitute also OMP_*LOCK_25*. * configure: Regenerated. * config.h.in: Regenerated. * Makefile.am (libgomp_la_SOURCES): Add loop_ull.c, iter_ull.c, ptrlock.c and task.c. * Makefile.in: Regenerated. * testsuite/Makefile.in: Regenerated. * task.c: New file. * loop_ull.c: New file. * iter_ull.c: New file. * libgomp.h: Include ptrlock.h. (enum gomp_task_kind): New type. (struct gomp_team): Add task_lock, task_queue, task_count, task_running_count, single_count fields. Add work_share_list_free_lock ifndef HAVE_SYNC_BUILTINS. Remove work_share_lock, generation_mask, oldest_live_gen, num_live_gen and init_work_shares fields, add work work_share_list_alloc, work_share_list_free and work_share_chunk fields. Change work_shares from pointer to pointers into an array. Change ordered_release field into gomp_sem_t ** from flexible array member. Add implicit_task and initial_work_shares fields. Move close to the end of the struct. (struct gomp_team_state): Add single_count, last_work_share, active_level and level fields, remove work_share_generation. (gomp_barrier_handle_tasks): New prototype. (gomp_finish_task): New inline function. (struct gomp_work_share): Move chunk_size, end, incr into transparent union/struct, add chunk_size_ull, end_ll, incr_ll and next_ll fields. Reshuffle fields. Add next_alloc, next_ws, next_free and inline_ordered_team_ids fields, change ordered_team_ids into pointer from flexible array member. Add mode field. Put lock and next into a different cache line from most of the write-once fields. (gomp_iter_ull_static_next, gomp_iter_ull_dynamic_next_locked, gomp_iter_ull_guided_next_locked, gomp_iter_ull_dynamic_next, gomp_iter_ull_guided_next): New prototypes. (gomp_new_icv): New prototype. (struct gomp_thread): Add thread_pool and task fields. (struct gomp_thread_pool): New type. (gomp_new_team): New prototype. (gomp_team_start): Change type of last argument. (gomp_new_work_share): Removed. (gomp_init_work_share, gomp_fini_work_share): New prototypes. (gomp_work_share_init_done): New static inline. (gomp_throttled_spin_count_var, gomp_available_cpus, gomp_managed_threads): New extern decls. (gomp_init_task): New prototype. (gomp_spin_count_var): New extern var decl. (LIBGOMP_GNU_SYMBOL_VERSIONING): Undef if no visibility or no alias support, or if not PIC. (gomp_init_lock_30, gomp_destroy_lock_30, gomp_set_lock_30, gomp_unset_lock_30, gomp_test_lock_30, gomp_init_nest_lock_30, gomp_destroy_nest_lock_30, gomp_set_nest_lock_30, gomp_unset_nest_lock_30, gomp_test_nest_lock_30, gomp_init_lock_25, gomp_destroy_lock_25, gomp_set_lock_25, gomp_unset_lock_25, gomp_test_lock_25, gomp_init_nest_lock_25, gomp_destroy_nest_lock_25, gomp_set_nest_lock_25, gomp_unset_nest_lock_25, gomp_test_nest_lock_25): New prototypes. (omp_lock_symver, strong_alias): Define. (gomp_remaining_threads_count, gomp_remaining_threads_lock): New decls. (gomp_end_task): New. (struct gomp_task_icv, gomp_global_icv): New. (gomp_thread_limit_var, gomp_max_active_levels_var): New. (struct gomp_task): New. (gomp_nthreads_var, gomp_dyn_var, gomp_nest_var, gomp_run_sched_var, gomp_run_sched_chunk): Remove. (gomp_icv): New. (gomp_schedule_type): Reorder enum to match omp_sched_t. * team.c (struct gomp_thread_start_data): Add thread_pool and task fields. (gomp_thread_start): Add gomp_team_barrier_wait call. For non-nested case remove clearing of docked thread thr fields. Use pool fields instead of global gomp_* variables. Use gomp_barrier_wait_last when needed. Initialize ts.active_level. Create tasks for each member thread. (free_team): Only destroy team barrier, task_lock here and free it. (gomp_free_thread): Free last_team if non-NULL. (gomp_team_end): Call gomp_team_barrier_wait instead of gomp_barrier_wait. For nested case call one extra gomp_barrier_wait. Move here some destruction from free_team. Call free_team on pool->last_team if any, rather than freeing current team. Destroy work_share_list_free_lock ifndef HAVE_SYNC_BUILTINS. (gomp_new_icv): New function. (gomp_threads, gomp_threads_size, gomp_threads_used, gomp_threads_dock): Removed. (gomp_thread_destructor): New variable. (gomp_new_thread_pool, gomp_free_pool_helper, gomp_free_thread): New functions. (gomp_team_start): Create new pool if current thread doesn't have one. Use pool fields instead of global gomp_* variables. Initialize thread_pool field for new threads. Clear single_count. Change last argument from ws to team, don't create new team, set ts.work_share to &team->work_shares[0] and clear ts.last_work_share. Don't clear ts.work_share_generation. If number of threads changed, adjust atomically gomp_managed_threads. Use gomp_init_task instead of gomp_new_task, set thr->task to the corresponding implicit_task array entry. Create tasks for each member thread. Initialize ts.level. (initialize_team): Call pthread_key_create on gomp_thread_destructor. (team_destructor): New function. (new_team): Removed. (gomp_new_team): New function. (free_team): Free gomp_work_share blocks chained through next_alloc, instead of freeing work_shares and destroying work_share_lock. (gomp_team_end): Call gomp_fini_work_share. If number of threads changed, adjust atomically gomp_managed_threads. Use gomp_end_task. * barrier.c (GOMP_barrier): Call gomp_team_barrier_wait instead of gomp_barrier_wait. * single.c (GOMP_single_copy_start): Call gomp_team_barrier_wait instead of gomp_barrier_wait. Call gomp_work_share_init_done if gomp_work_share_start returned true. Don't unlock ws->lock. (GOMP_single_copy_end): Call gomp_team_barrier_wait instead of gomp_barrier_wait. (GOMP_single_start): Rewritten if HAVE_SYNC_BUILTINS. Call gomp_work_share_init_done if gomp_work_share_start returned true. Don't unlock ws->lock. * work.c: Include stddef.h. (free_work_share): Use work_share_list_free_lock instead of atomic chaining ifndef HAVE_SYNC_BUILTINS. Add team argument. Call gomp_fini_work_share and then either free ws if orphaned, or put it into work_share_list_free list of the current team. (alloc_work_share, gomp_init_work_share, gomp_fini_work_share): New functions. (gomp_work_share_start, gomp_work_share_end, gomp_work_share_end_nowait): Rewritten. * omp_lib.f90.in Change some tabs to spaces to prevent warnings. (openmp_version): Set to 200805. (omp_sched_kind, omp_sched_static, omp_sched_dynamic, omp_sched_guided, omp_sched_auto): New parameters. (omp_set_schedule, omp_get_schedule, omp_get_thread_limit, omp_set_max_active_levels, omp_get_max_active_levels, omp_get_level, omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level): New interfaces. * omp_lib.h.in (openmp_version): Set to 200805. (omp_sched_kind, omp_sched_static, omp_sched_dynamic, omp_sched_guided, omp_sched_auto): New parameters. (omp_set_schedule, omp_get_schedule, omp_get_thread_limit, omp_set_max_active_levels, omp_get_max_active_levels, omp_get_level, omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level): New externals. * loop.c: Include limits.h. (GOMP_loop_runtime_next, GOMP_loop_ordered_runtime_next): Handle GFS_AUTO. (GOMP_loop_runtime_start, GOMP_loop_ordered_runtime_start): Likewise. Use gomp_icv. (gomp_loop_static_start, gomp_loop_dynamic_start): Clear ts.static_trip here. (gomp_loop_static_start, gomp_loop_ordered_static_start): Call gomp_work_share_init_done after gomp_loop_init. Don't unlock ws->lock. (gomp_loop_dynamic_start, gomp_loop_guided_start): Call gomp_work_share_init_done after gomp_loop_init. If HAVE_SYNC_BUILTINS, don't unlock ws->lock, otherwise lock it. (gomp_loop_ordered_dynamic_start, gomp_loop_ordered_guided_start): Call gomp_work_share_init_done after gomp_loop_init. Lock ws->lock. (gomp_parallel_loop_start): Call gomp_new_team instead of gomp_new_work_share. Call gomp_loop_init on &team->work_shares[0]. Adjust gomp_team_start caller. Pass 0 as second argument to gomp_resolve_num_threads. (gomp_loop_init): For GFS_DYNAMIC, multiply ws->chunk_size by incr. If adding ws->chunk_size nthreads + 1 times after end won't overflow, set ws->mode to 1. * libgomp_g.h (GOMP_loop_ull_static_start, GOMP_loop_ull_dynamic_start, GOMP_loop_ull_guided_start, GOMP_loop_ull_runtime_start, GOMP_loop_ull_ordered_static_start, GOMP_loop_ull_ordered_dynamic_start, GOMP_loop_ull_ordered_guided_start, GOMP_loop_ull_ordered_runtime_start, GOMP_loop_ull_static_next, GOMP_loop_ull_dynamic_next, GOMP_loop_ull_guided_next, GOMP_loop_ull_runtime_next, GOMP_loop_ull_ordered_static_next, GOMP_loop_ull_ordered_dynamic_next, GOMP_loop_ull_ordered_guided_next, GOMP_loop_ull_ordered_runtime_next, GOMP_task, GOMP_taskwait): New prototypes. * libgomp.map: Export lock routines also @@OMP_2.0. (GOMP_loop_ordered_dynamic_first, GOMP_loop_ordered_guided_first, GOMP_loop_ordered_runtime_first, GOMP_loop_ordered_static_first): Remove. (GOMP_loop_ull_dynamic_next, GOMP_loop_ull_dynamic_start, GOMP_loop_ull_guided_next, GOMP_loop_ull_guided_start, GOMP_loop_ull_ordered_dynamic_next, GOMP_loop_ull_ordered_dynamic_start, GOMP_loop_ull_ordered_guided_next, GOMP_loop_ull_ordered_guided_start, GOMP_loop_ull_ordered_runtime_next, GOMP_loop_ull_ordered_runtime_start, GOMP_loop_ull_ordered_static_next, GOMP_loop_ull_ordered_static_start, GOMP_loop_ull_runtime_next, GOMP_loop_ull_runtime_start, GOMP_loop_ull_static_next, GOMP_loop_ull_static_start, GOMP_task, GOMP_taskwait): Export @@GOMP_2.0. (omp_set_schedule, omp_get_schedule, omp_get_thread_limit, omp_set_max_active_levels, omp_get_max_active_levels, omp_get_level, omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level, omp_set_schedule_, omp_set_schedule_8_, omp_get_schedule_, omp_get_schedule_8_, omp_get_thread_limit_, omp_set_max_active_levels_, omp_set_max_active_levels_8_, omp_get_max_active_levels_, omp_get_level_, omp_get_ancestor_thread_num_, omp_get_ancestor_thread_num_8_, omp_get_team_size_, omp_get_team_size_8_, omp_get_active_level_): New exports @@OMP_3.0. * omp.h.in (omp_sched_t): New type. (omp_set_schedule, omp_get_schedule, omp_get_thread_limit, omp_set_max_active_levels, omp_get_max_active_levels, omp_get_level, omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level): New prototypes. * env.c (gomp_spin_count_var, gomp_throttled_spin_count_var, gomp_available_cpus, gomp_managed_threads, gomp_max_active_levels_var, gomp_thread_limit_var, gomp_remaining_threads_count, gomp_remaining_threads_lock): New variables. (parse_spincount): New function. (initialize_env): Call gomp_init_num_threads unconditionally. Initialize gomp_available_cpus. Call parse_spincount, initialize gomp_{,throttled_}spin_count_var depending on presence and value of OMP_WAIT_POLICY and GOMP_SPINCOUNT env vars. Handle GOMP_BLOCKTIME env var. Handle OMP_WAIT_POLICY, OMP_MAX_ACTIVE_LEVELS, OMP_THREAD_LIMIT, OMP_STACKSIZE env vars. Handle unit specification for GOMP_STACKSIZE. Initialize gomp_remaining_threads_count and gomp_remaining_threads_lock if needed. Use gomp_global_icv. (gomp_nthreads_var, gomp_dyn_var, gomp_nest_var, gomp_run_sched_var, gomp_run_sched_chunk): Remove. (gomp_global_icv): New. (parse_schedule): Use it. Parse "auto". (omp_set_num_threads): Use gomp_icv. (omp_set_dynamic, omp_get_dynamic, omp_set_nested, omp_get_nested): Likewise. (omp_get_max_threads): Move from parallel.c. (omp_set_schedule, omp_get_schedule, omp_get_thread_limit, omp_set_max_active_levels, omp_get_max_active_levels): New functions, add ialias. (parse_stacksize, parse_wait_policy): New functions. * fortran.c: Rewrite lock wrappers, if symbol versioning provide both wrappers for compatibility and new locks. (omp_set_schedule, omp_get_schedule, omp_get_thread_limit, omp_set_max_active_levels, omp_get_max_active_levels, omp_get_level, omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level): New ialias_redirect. (omp_set_schedule_, omp_set_schedule_8_, omp_get_schedule_, omp_get_schedule_8_, omp_get_thread_limit_, omp_set_max_active_levels_, omp_set_max_active_levels_8_, omp_get_max_active_levels_, omp_get_level_, omp_get_ancestor_thread_num_, omp_get_ancestor_thread_num_8_, omp_get_team_size_, omp_get_team_size_8_, omp_get_active_level_): New functions. * parallel.c: Include limits.h. (gomp_resolve_num_threads): Add count argument. Rewritten. (GOMP_parallel_start): Call gomp_new_team and pass that as last argument to gomp_team_start. Pass 0 as second argument to gomp_resolve_num_threads. (GOMP_parallel_end): Decrease gomp_remaining_threads_count if gomp_thread_limit_var != ULONG_MAX. (omp_in_parallel): Implement using ts.active_level. (omp_get_max_threads): Move to env.c. (omp_get_level, omp_get_ancestor_thread_num, omp_get_team_size, omp_get_active_level): New functions, add ialias. * sections.c (GOMP_sections_start): Call gomp_work_share_init_done after gomp_sections_init. If HAVE_SYNC_BUILTINS, call gomp_iter_dynamic_next instead of the _locked variant and don't take lock around it, otherwise acquire it before calling gomp_iter_dynamic_next_locked. (GOMP_sections_next): If HAVE_SYNC_BUILTINS, call gomp_iter_dynamic_next instead of the _locked variant and don't take lock around it. (GOMP_parallel_sections_start): Call gomp_new_team instead of gomp_new_work_share. Call gomp_sections_init on &team->work_shares[0]. Adjust gomp_team_start caller. Pass count as second argument to gomp_resolve_num_threads, don't adjust num_threads after the call. Use gomp_icv. * iter.c (gomp_iter_dynamic_next_locked): Don't multiply ws->chunk_size by incr. (gomp_iter_dynamic_next): Likewise. If ws->mode, use more efficient code. * libgomp_f.h.in (omp_lock_25_arg_t, omp_nest_lock_25_arg_t): New types. (omp_lock_25_arg, omp_nest_lock_25_arg): New macros. (omp_check_defines): Check even the compat defines. * config/linux/ptrlock.c: New file. * config/linux/ptrlock.h: New file. * config/linux/wait.h: New file. * config/posix/ptrlock.c: New file. * config/posix/ptrlock.h: New file. * config/linux/bar.h (gomp_team_barrier_wait, gomp_team_barrier_wait_end, gomp_team_barrier_wake): New prototypes. (gomp_team_barrier_set_task_pending, gomp_team_barrier_clear_task_pending, gomp_team_barrier_set_waiting_for_tasks, gomp_team_barrier_waiting_for_tasks, gomp_team_barrier_done): New inlines. (gomp_barrier_t): Rewritten. (gomp_barrier_state_t): New typedef. (gomp_barrier_init, gomp_barrier_reinit, gomp_barrier_destroy, gomp_barrier_wait_start): Rewritten. (gomp_barrier_wait_end): Change second argument to gomp_barrier_state_t. (gomp_barrier_last_thread, gomp_barrier_wait_last): New static inlines. * config/linux/bar.c: Include wait.h instead of libgomp.h and futex.h. (gomp_barrier_wait_end): Rewritten. (gomp_team_barrier_wait, gomp_team_barrier_wait_end, gomp_team_barrier_wake, gomp_barrier_wait_last): New functions. * config/posix/bar.h (gomp_barrier_t): Add generation field. (gomp_barrier_state_t): New typedef. (gomp_team_barrier_wait, gomp_team_barrier_wait_end, gomp_team_barrier_wake): New prototypes. (gomp_barrier_wait_start): Or all but low 2 bits from generation into the return value. Return gomp_barrier_state_t. (gomp_team_barrier_set_task_pending, gomp_team_barrier_clear_task_pending, gomp_team_barrier_set_waiting_for_tasks, gomp_team_barrier_waiting_for_tasks, gomp_team_barrier_done): New inlines. (gomp_barrier_wait_end): Change second argument to gomp_barrier_state_t. (gomp_barrier_last_thread, gomp_barrier_wait_last): New static inlines. * config/posix/bar.c (gomp_barrier_init): Clear generation field. (gomp_barrier_wait_end): Change second argument to gomp_barrier_state_t. (gomp_team_barrier_wait, gomp_team_barrier_wait_end, gomp_team_barrier_wake): New functions. * config/linux/mutex.c: Include wait.h instead of libgomp.h and futex.h. (gomp_futex_wake, gomp_futex_wait): New variables. (gomp_mutex_lock_slow): Call do_wait instead of futex_wait. * config/linux/lock.c: Rewrite to make locks task owned, for backwards compatibility provide the old entrypoints if symbol versioning. Include wait.h instead of libgomp.h and futex.h. (gomp_set_nest_lock_25): Call do_wait instead of futex_wait. * config/posix95/lock.c: Rewrite to make locks task owned, for backwards compatibility provide the old entrypoints if symbol versioning. * config/posix/lock.c: Rewrite to make locks task owned, for backwards compatibility provide the old entrypoints if symbol versioning. * config/linux/proc.c (gomp_init_num_threads): Use gomp_global_icv. (get_num_procs, gomp_dynamic_max_threads): Use gomp_icv. * config/posix/proc.c, config/mingw32/proc.c: Similarly. * config/linux/powerpc/futex.h (FUTEX_WAIT, FUTEX_WAKE): Remove. (sys_futex0): Return error code. (futex_wake, futex_wait): If ENOSYS was returned, clear FUTEX_PRIVATE_FLAG in gomp_futex_wa{ke,it} and retry. (cpu_relax, atomic_write_barrier): New static inlines. * config/linux/alpha/futex.h (FUTEX_WAIT, FUTEX_WAKE): Remove. (futex_wake, futex_wait): If ENOSYS was returned, clear FUTEX_PRIVATE_FLAG in gomp_futex_wa{ke,it} and retry. (cpu_relax, atomic_write_barrier): New static inlines. * config/linux/x86/futex.h (FUTEX_WAIT, FUTEX_WAKE): Remove. (sys_futex0): Return error code. (futex_wake, futex_wait): If ENOSYS was returned, clear FUTEX_PRIVATE_FLAG in gomp_futex_wa{ke,it} and retry. (cpu_relax, atomic_write_barrier): New static inlines. * config/linux/s390/futex.h (FUTEX_WAIT, FUTEX_WAKE): Remove. (sys_futex0): Return error code. (futex_wake, futex_wait): If ENOSYS was returned, clear FUTEX_PRIVATE_FLAG in gomp_futex_wa{ke,it} and retry. (cpu_relax, atomic_write_barrier): New static inlines. * config/linux/ia64/futex.h (FUTEX_WAIT, FUTEX_WAKE): Remove. (sys_futex0): Return error code. (futex_wake, futex_wait): If ENOSYS was returned, clear FUTEX_PRIVATE_FLAG in gomp_futex_wa{ke,it} and retry. (cpu_relax, atomic_write_barrier): New static inlines. * config/linux/sparc/futex.h (FUTEX_WAIT, FUTEX_WAKE): Remove. (sys_futex0): Return error code. (futex_wake, futex_wait): If ENOSYS was returned, clear FUTEX_PRIVATE_FLAG in gomp_futex_wa{ke,it} and retry. (cpu_relax, atomic_write_barrier): New static inlines. * config/linux/sem.c: Include wait.h instead of libgomp.h and futex.h. (gomp_sem_wait_slow): Call do_wait instead of futex_wait. * config/linux/affinity.c: Assume HAVE_SYNC_BUILTINS. * config/linux/omp-lock.h (omp_lock_25_t, omp_nest_lock_25_t): New types. (omp_nest_lock_t): Change owner into void *, add lock field. * config/posix95/omp-lock.h: Include semaphore.h. (omp_lock_25_t, omp_nest_lock_25_t): New types. (omp_lock_t): Use sem_t instead of mutex if semaphores aren't broken. (omp_nest_lock_t): Likewise. Change owner to void *. * config/posix/omp-lock.h: Include semaphore.h. (omp_lock_25_t, omp_nest_lock_25_t): New types. (omp_lock_t): Use sem_t instead of mutex if semaphores aren't broken. (omp_nest_lock_t): Likewise. Add owner field. * testsuite/libgomp.c/collapse-1.c: New test. * testsuite/libgomp.c/collapse-2.c: New test. * testsuite/libgomp.c/collapse-3.c: New test. * testsuite/libgomp.c/icv-1.c: New test. * testsuite/libgomp.c/icv-2.c: New test. * testsuite/libgomp.c/lib-2.c: New test. * testsuite/libgomp.c/lock-1.c: New test. * testsuite/libgomp.c/lock-2.c: New test. * testsuite/libgomp.c/lock-3.c: New test. * testsuite/libgomp.c/loop-4.c: New test. * testsuite/libgomp.c/loop-5.c: New test. * testsuite/libgomp.c/loop-6.c: New test. * testsuite/libgomp.c/loop-7.c: New test. * testsuite/libgomp.c/loop-8.c: New test. * testsuite/libgomp.c/loop-9.c: New test. * testsuite/libgomp.c/nested-3.c: New test. * testsuite/libgomp.c/nestedfn-6.c: New test. * testsuite/libgomp.c/sort-1.c: New test. * testsuite/libgomp.c/task-1.c: New test. * testsuite/libgomp.c/task-2.c: New test. * testsuite/libgomp.c/task-3.c: New test. * testsuite/libgomp.c/task-4.c: New test. * testsuite/libgomp.c++/c++.exp: Add libstdc++-v3 build includes to C++ testsuite default compiler options. * testsuite/libgomp.c++/collapse-1.C: New test. * testsuite/libgomp.c++/collapse-2.C: New test. * testsuite/libgomp.c++/ctor-10.C: New test. * testsuite/libgomp.c++/for-1.C: New test. * testsuite/libgomp.c++/for-2.C: New test. * testsuite/libgomp.c++/for-3.C: New test. * testsuite/libgomp.c++/for-4.C: New test. * testsuite/libgomp.c++/for-5.C: New test. * testsuite/libgomp.c++/loop-8.C: New test. * testsuite/libgomp.c++/loop-9.C: New test. * testsuite/libgomp.c++/loop-10.C: New test. * testsuite/libgomp.c++/task-1.C: New test. * testsuite/libgomp.c++/task-2.C: New test. * testsuite/libgomp.c++/task-3.C: New test. * testsuite/libgomp.c++/task-4.C: New test. * testsuite/libgomp.c++/task-5.C: New test. * testsuite/libgomp.c++/task-6.C: New test. * testsuite/libgomp.fortran/allocatable1.f90: New test. * testsuite/libgomp.fortran/allocatable2.f90: New test. * testsuite/libgomp.fortran/allocatable3.f90: New test. * testsuite/libgomp.fortran/allocatable4.f90: New test. * testsuite/libgomp.fortran/collapse1.f90: New test. * testsuite/libgomp.fortran/collapse2.f90: New test. * testsuite/libgomp.fortran/collapse3.f90: New test. * testsuite/libgomp.fortran/collapse4.f90: New test. * testsuite/libgomp.fortran/lastprivate1.f90: New test. * testsuite/libgomp.fortran/lastprivate2.f90: New test. * testsuite/libgomp.fortran/lib4.f90: New test. * testsuite/libgomp.fortran/lock-1.f90: New test. * testsuite/libgomp.fortran/lock-2.f90: New test. * testsuite/libgomp.fortran/nested1.f90: New test. * testsuite/libgomp.fortran/nestedfn4.f90: New test. * testsuite/libgomp.fortran/strassen.f90: New test. * testsuite/libgomp.fortran/tabs1.f90: New test. * testsuite/libgomp.fortran/tabs2.f: New test. * testsuite/libgomp.fortran/task1.f90: New test. * testsuite/libgomp.fortran/task2.f90: New test. * testsuite/libgomp.fortran/vla4.f90: Add dg-warning. * testsuite/libgomp.fortran/vla5.f90: Likewise. * testsuite/libgomp.c/pr26943-2.c: Likewise. * testsuite/libgomp.c/pr26943-3.c: Likewise. * testsuite/libgomp.c/pr26943-4.c: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@136433 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgomp/config')
-rw-r--r--libgomp/config/linux/affinity.c14
-rw-r--r--libgomp/config/linux/alpha/futex.h46
-rw-r--r--libgomp/config/linux/bar.c91
-rw-r--r--libgomp/config/linux/bar.h76
-rw-r--r--libgomp/config/linux/ia64/futex.h44
-rw-r--r--libgomp/config/linux/lock.c115
-rw-r--r--libgomp/config/linux/mutex.c9
-rw-r--r--libgomp/config/linux/omp-lock.h8
-rw-r--r--libgomp/config/linux/powerpc/futex.h39
-rw-r--r--libgomp/config/linux/proc.c18
-rw-r--r--libgomp/config/linux/ptrlock.c70
-rw-r--r--libgomp/config/linux/ptrlock.h65
-rw-r--r--libgomp/config/linux/s390/futex.h35
-rw-r--r--libgomp/config/linux/sem.c7
-rw-r--r--libgomp/config/linux/sparc/futex.h47
-rw-r--r--libgomp/config/linux/wait.h68
-rw-r--r--libgomp/config/linux/x86/futex.h70
-rw-r--r--libgomp/config/mingw32/proc.c9
-rw-r--r--libgomp/config/posix/bar.c76
-rw-r--r--libgomp/config/posix/bar.h63
-rw-r--r--libgomp/config/posix/lock.c207
-rw-r--r--libgomp/config/posix/omp-lock.h18
-rw-r--r--libgomp/config/posix/proc.c13
-rw-r--r--libgomp/config/posix/ptrlock.c1
-rw-r--r--libgomp/config/posix/ptrlock.h69
-rw-r--r--libgomp/config/posix95/lock.c210
-rw-r--r--libgomp/config/posix95/omp-lock.h18
27 files changed, 1328 insertions, 178 deletions
diff --git a/libgomp/config/linux/affinity.c b/libgomp/config/linux/affinity.c
index 8fcce5f3a5b..7b6d6c008d7 100644
--- a/libgomp/config/linux/affinity.c
+++ b/libgomp/config/linux/affinity.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
Contributed by Jakub Jelinek <jakub@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -38,9 +38,6 @@
#ifdef HAVE_PTHREAD_AFFINITY_NP
static unsigned int affinity_counter;
-#ifndef HAVE_SYNC_BUILTINS
-static gomp_mutex_t affinity_lock;
-#endif
void
gomp_init_affinity (void)
@@ -76,9 +73,6 @@ gomp_init_affinity (void)
CPU_SET (gomp_cpu_affinity[0], &cpuset);
pthread_setaffinity_np (pthread_self (), sizeof (cpuset), &cpuset);
affinity_counter = 1;
-#ifndef HAVE_SYNC_BUILTINS
- gomp_mutex_init (&affinity_lock);
-#endif
}
void
@@ -87,13 +81,7 @@ gomp_init_thread_affinity (pthread_attr_t *attr)
unsigned int cpu;
cpu_set_t cpuset;
-#ifdef HAVE_SYNC_BUILTINS
cpu = __sync_fetch_and_add (&affinity_counter, 1);
-#else
- gomp_mutex_lock (&affinity_lock);
- cpu = affinity_counter++;
- gomp_mutex_unlock (&affinity_lock);
-#endif
cpu %= gomp_cpu_affinity_len;
CPU_ZERO (&cpuset);
CPU_SET (gomp_cpu_affinity[cpu], &cpuset);
diff --git a/libgomp/config/linux/alpha/futex.h b/libgomp/config/linux/alpha/futex.h
index 98681a8526e..4f0bda2424c 100644
--- a/libgomp/config/linux/alpha/futex.h
+++ b/libgomp/config/linux/alpha/futex.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -30,8 +30,6 @@
#ifndef SYS_futex
#define SYS_futex 394
#endif
-#define FUTEX_WAIT 0
-#define FUTEX_WAKE 1
static inline void
@@ -45,7 +43,7 @@ futex_wait (int *addr, int val)
sc_0 = SYS_futex;
sc_16 = (long) addr;
- sc_17 = FUTEX_WAIT;
+ sc_17 = gomp_futex_wait;
sc_18 = val;
sc_19 = 0;
__asm volatile ("callsys"
@@ -53,6 +51,20 @@ futex_wait (int *addr, int val)
: "0"(sc_0), "r" (sc_16), "r"(sc_17), "r"(sc_18), "1"(sc_19)
: "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
"$22", "$23", "$24", "$25", "$27", "$28", "memory");
+ if (__builtin_expect (sc_19, 0) && sc_0 == ENOSYS)
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ sc_0 = SYS_futex;
+ sc_17 &= ~FUTEX_PRIVATE_FLAG;
+ sc_19 = 0;
+ __asm volatile ("callsys"
+ : "=r" (sc_0), "=r"(sc_19)
+ : "0"(sc_0), "r" (sc_16), "r"(sc_17), "r"(sc_18),
+ "1"(sc_19)
+ : "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
+ "$22", "$23", "$24", "$25", "$27", "$28", "memory");
+ }
}
static inline void
@@ -66,11 +78,35 @@ futex_wake (int *addr, int count)
sc_0 = SYS_futex;
sc_16 = (long) addr;
- sc_17 = FUTEX_WAKE;
+ sc_17 = gomp_futex_wake;
sc_18 = count;
__asm volatile ("callsys"
: "=r" (sc_0), "=r"(sc_19)
: "0"(sc_0), "r" (sc_16), "r"(sc_17), "r"(sc_18)
: "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
"$22", "$23", "$24", "$25", "$27", "$28", "memory");
+ if (__builtin_expect (sc_19, 0) && sc_0 == ENOSYS)
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ sc_0 = SYS_futex;
+ sc_17 &= ~FUTEX_PRIVATE_FLAG;
+ __asm volatile ("callsys"
+ : "=r" (sc_0), "=r"(sc_19)
+ : "0"(sc_0), "r" (sc_16), "r"(sc_17), "r"(sc_18)
+ : "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
+ "$22", "$23", "$24", "$25", "$27", "$28", "memory");
+ }
+}
+
+static inline void
+cpu_relax (void)
+{
+ __asm volatile ("" : : : "memory");
+}
+
+static inline void
+atomic_write_barrier (void)
+{
+ __asm volatile ("wmb" : : : "memory");
}
diff --git a/libgomp/config/linux/bar.c b/libgomp/config/linux/bar.c
index 5c4f32e6f8b..7af36d2c421 100644
--- a/libgomp/config/linux/bar.c
+++ b/libgomp/config/linux/bar.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -29,36 +29,97 @@
mechanism for libgomp. This type is private to the library. This
implementation uses atomic instructions and the futex syscall. */
-#include "libgomp.h"
-#include "futex.h"
#include <limits.h>
+#include "wait.h"
void
-gomp_barrier_wait_end (gomp_barrier_t *bar, bool last)
+gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
{
- if (last)
+ if (__builtin_expect ((state & 1) != 0, 0))
{
- bar->generation++;
- futex_wake (&bar->generation, INT_MAX);
+ /* Next time we'll be awaiting TOTAL threads again. */
+ bar->awaited = bar->total;
+ atomic_write_barrier ();
+ bar->generation += 4;
+ futex_wake ((int *) &bar->generation, INT_MAX);
}
else
{
- unsigned int generation = bar->generation;
-
- gomp_mutex_unlock (&bar->mutex);
+ unsigned int generation = state;
do
- futex_wait (&bar->generation, generation);
+ do_wait ((int *) &bar->generation, generation);
while (bar->generation == generation);
}
+}
+
+void
+gomp_barrier_wait (gomp_barrier_t *bar)
+{
+ gomp_barrier_wait_end (bar, gomp_barrier_wait_start (bar));
+}
- if (__sync_add_and_fetch (&bar->arrived, -1) == 0)
- gomp_mutex_unlock (&bar->mutex);
+/* Like gomp_barrier_wait, except that if the encountering thread
+ is not the last one to hit the barrier, it returns immediately.
+ The intended usage is that a thread which intends to gomp_barrier_destroy
+ this barrier calls gomp_barrier_wait, while all other threads
+ call gomp_barrier_wait_last. When gomp_barrier_wait returns,
+ the barrier can be safely destroyed. */
+
+void
+gomp_barrier_wait_last (gomp_barrier_t *bar)
+{
+ gomp_barrier_state_t state = gomp_barrier_wait_start (bar);
+ if (state & 1)
+ gomp_barrier_wait_end (bar, state);
+}
+
+void
+gomp_team_barrier_wake (gomp_barrier_t *bar, int count)
+{
+ futex_wake ((int *) &bar->generation, count == 0 ? INT_MAX : count);
+}
+
+void
+gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
+{
+ unsigned int generation;
+
+ if (__builtin_expect ((state & 1) != 0, 0))
+ {
+ /* Next time we'll be awaiting TOTAL threads again. */
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+ bar->awaited = bar->total;
+ atomic_write_barrier ();
+ if (__builtin_expect (team->task_count, 0))
+ {
+ gomp_barrier_handle_tasks (state);
+ state &= ~1;
+ }
+ else
+ {
+ bar->generation = state + 3;
+ futex_wake ((int *) &bar->generation, INT_MAX);
+ return;
+ }
+ }
+
+ generation = state;
+ do
+ {
+ do_wait ((int *) &bar->generation, generation);
+ if (__builtin_expect (bar->generation & 1, 0))
+ gomp_barrier_handle_tasks (state);
+ if ((bar->generation & 2))
+ generation |= 2;
+ }
+ while (bar->generation != state + 4);
}
void
-gomp_barrier_wait (gomp_barrier_t *barrier)
+gomp_team_barrier_wait (gomp_barrier_t *bar)
{
- gomp_barrier_wait_end (barrier, gomp_barrier_wait_start (barrier));
+ gomp_team_barrier_wait_end (bar, gomp_barrier_wait_start (bar));
}
diff --git a/libgomp/config/linux/bar.h b/libgomp/config/linux/bar.h
index 57268585d8b..85150caf189 100644
--- a/libgomp/config/linux/bar.h
+++ b/libgomp/config/linux/bar.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -36,40 +36,86 @@
typedef struct
{
- gomp_mutex_t mutex;
- unsigned total;
- unsigned arrived;
- int generation;
+ /* Make sure total/generation is in a mostly read cacheline, while
+ awaited in a separate cacheline. */
+ unsigned total __attribute__((aligned (64)));
+ unsigned generation;
+ unsigned awaited __attribute__((aligned (64)));
} gomp_barrier_t;
+typedef unsigned int gomp_barrier_state_t;
static inline void gomp_barrier_init (gomp_barrier_t *bar, unsigned count)
{
- gomp_mutex_init (&bar->mutex);
bar->total = count;
- bar->arrived = 0;
+ bar->awaited = count;
bar->generation = 0;
}
static inline void gomp_barrier_reinit (gomp_barrier_t *bar, unsigned count)
{
- gomp_mutex_lock (&bar->mutex);
+ __sync_fetch_and_add (&bar->awaited, count - bar->total);
bar->total = count;
- gomp_mutex_unlock (&bar->mutex);
}
static inline void gomp_barrier_destroy (gomp_barrier_t *bar)
{
- /* Before destroying, make sure all threads have left the barrier. */
- gomp_mutex_lock (&bar->mutex);
}
extern void gomp_barrier_wait (gomp_barrier_t *);
-extern void gomp_barrier_wait_end (gomp_barrier_t *, bool);
+extern void gomp_barrier_wait_last (gomp_barrier_t *);
+extern void gomp_barrier_wait_end (gomp_barrier_t *, gomp_barrier_state_t);
+extern void gomp_team_barrier_wait (gomp_barrier_t *);
+extern void gomp_team_barrier_wait_end (gomp_barrier_t *,
+ gomp_barrier_state_t);
+extern void gomp_team_barrier_wake (gomp_barrier_t *, int);
-static inline bool gomp_barrier_wait_start (gomp_barrier_t *bar)
+static inline gomp_barrier_state_t
+gomp_barrier_wait_start (gomp_barrier_t *bar)
{
- gomp_mutex_lock (&bar->mutex);
- return ++bar->arrived == bar->total;
+ unsigned int ret = bar->generation & ~3;
+ /* Do we need any barrier here or is __sync_add_and_fetch acting
+ as the needed LoadLoad barrier already? */
+ ret += __sync_add_and_fetch (&bar->awaited, -1) == 0;
+ return ret;
+}
+
+static inline bool
+gomp_barrier_last_thread (gomp_barrier_state_t state)
+{
+ return state & 1;
+}
+
+/* All the inlines below must be called with team->task_lock
+ held. */
+
+static inline void
+gomp_team_barrier_set_task_pending (gomp_barrier_t *bar)
+{
+ bar->generation |= 1;
+}
+
+static inline void
+gomp_team_barrier_clear_task_pending (gomp_barrier_t *bar)
+{
+ bar->generation &= ~1;
+}
+
+static inline void
+gomp_team_barrier_set_waiting_for_tasks (gomp_barrier_t *bar)
+{
+ bar->generation |= 2;
+}
+
+static inline bool
+gomp_team_barrier_waiting_for_tasks (gomp_barrier_t *bar)
+{
+ return (bar->generation & 2) != 0;
+}
+
+static inline void
+gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state)
+{
+ bar->generation = (state & ~3) + 4;
}
#endif /* GOMP_BARRIER_H */
diff --git a/libgomp/config/linux/ia64/futex.h b/libgomp/config/linux/ia64/futex.h
index 5e54982d6f7..35aa4f1fea0 100644
--- a/libgomp/config/linux/ia64/futex.h
+++ b/libgomp/config/linux/ia64/futex.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -29,23 +29,24 @@
#include <sys/syscall.h>
-#define FUTEX_WAIT 0
-#define FUTEX_WAKE 1
-static inline void
-sys_futex0(int *addr, int op, int val)
+static inline long
+sys_futex0(int *addr, long op, int val)
{
register long out0 asm ("out0") = (long) addr;
register long out1 asm ("out1") = op;
register long out2 asm ("out2") = val;
register long out3 asm ("out3") = 0;
+ register long r8 asm ("r8");
+ register long r10 asm ("r10");
register long r15 asm ("r15") = SYS_futex;
__asm __volatile ("break 0x100000"
- : "=r"(r15), "=r"(out0), "=r"(out1), "=r"(out2), "=r"(out3)
+ : "=r"(r15), "=r"(out0), "=r"(out1), "=r"(out2), "=r"(out3),
+ "=r"(r8), "=r"(r10)
: "r"(r15), "r"(out0), "r"(out1), "r"(out2), "r"(out3)
- : "memory", "r8", "r10", "out4", "out5", "out6", "out7",
+ : "memory", "out4", "out5", "out6", "out7",
/* Non-stacked integer registers, minus r8, r10, r15. */
"r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18",
"r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",
@@ -56,16 +57,41 @@ sys_futex0(int *addr, int op, int val)
"f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
/* Branch registers. */
"b6");
+ return r8 & r10;
}
static inline void
futex_wait (int *addr, int val)
{
- sys_futex0 (addr, FUTEX_WAIT, val);
+ long err = sys_futex0 (addr, gomp_futex_wait, val);
+ if (__builtin_expect (err == ENOSYS, 0))
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ sys_futex0 (addr, gomp_futex_wait, val);
+ }
}
static inline void
futex_wake (int *addr, int count)
{
- sys_futex0 (addr, FUTEX_WAKE, count);
+ long err = sys_futex0 (addr, gomp_futex_wake, count);
+ if (__builtin_expect (err == ENOSYS, 0))
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ sys_futex0 (addr, gomp_futex_wake, count);
+ }
+}
+
+static inline void
+cpu_relax (void)
+{
+ __asm volatile ("hint @pause" : : : "memory");
+}
+
+static inline void
+atomic_write_barrier (void)
+{
+ __sync_synchronize ();
}
diff --git a/libgomp/config/linux/lock.c b/libgomp/config/linux/lock.c
index 211f6007b43..a2e07d320fd 100644
--- a/libgomp/config/linux/lock.c
+++ b/libgomp/config/linux/lock.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -29,47 +29,109 @@
primitives. This implementation uses atomic instructions and the futex
syscall. */
-#include "libgomp.h"
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
-#include "futex.h"
+#include "wait.h"
/* The internal gomp_mutex_t and the external non-recursive omp_lock_t
have the same form. Re-use it. */
void
-omp_init_lock (omp_lock_t *lock)
+gomp_init_lock_30 (omp_lock_t *lock)
{
gomp_mutex_init (lock);
}
void
-omp_destroy_lock (omp_lock_t *lock)
+gomp_destroy_lock_30 (omp_lock_t *lock)
{
gomp_mutex_destroy (lock);
}
void
-omp_set_lock (omp_lock_t *lock)
+gomp_set_lock_30 (omp_lock_t *lock)
{
gomp_mutex_lock (lock);
}
void
-omp_unset_lock (omp_lock_t *lock)
+gomp_unset_lock_30 (omp_lock_t *lock)
{
gomp_mutex_unlock (lock);
}
int
-omp_test_lock (omp_lock_t *lock)
+gomp_test_lock_30 (omp_lock_t *lock)
{
return __sync_bool_compare_and_swap (lock, 0, 1);
}
-/* The external recursive omp_nest_lock_t form requires additional work. */
+void
+gomp_init_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ memset (lock, '\0', sizeof (*lock));
+}
+
+void
+gomp_destroy_nest_lock_30 (omp_nest_lock_t *lock)
+{
+}
+
+void
+gomp_set_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ void *me = gomp_icv (true);
+
+ if (lock->owner != me)
+ {
+ gomp_mutex_lock (&lock->lock);
+ lock->owner = me;
+ }
+
+ lock->count++;
+}
+
+void
+gomp_unset_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ if (--lock->count == 0)
+ {
+ lock->owner = NULL;
+ gomp_mutex_unlock (&lock->lock);
+ }
+}
+
+int
+gomp_test_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ void *me = gomp_icv (true);
+
+ if (lock->owner == me)
+ return ++lock->count;
+
+ if (__sync_bool_compare_and_swap (&lock->lock, 0, 1))
+ {
+ lock->owner = me;
+ lock->count = 1;
+ return 1;
+ }
+
+ return 0;
+}
+
+#ifdef LIBGOMP_GNU_SYMBOL_VERSIONING
+/* gomp_mutex_* can be safely locked in one thread and
+ unlocked in another thread, so the OpenMP 2.5 and OpenMP 3.0
+ non-nested locks can be the same. */
+strong_alias (gomp_init_lock_30, gomp_init_lock_25)
+strong_alias (gomp_destroy_lock_30, gomp_destroy_lock_25)
+strong_alias (gomp_set_lock_30, gomp_set_lock_25)
+strong_alias (gomp_unset_lock_30, gomp_unset_lock_25)
+strong_alias (gomp_test_lock_30, gomp_test_lock_25)
+
+/* The external recursive omp_nest_lock_25_t form requires additional work. */
/* We need an integer to uniquely identify this thread. Most generally
this is the thread's TID, which ideally we'd get this straight from
@@ -85,17 +147,17 @@ omp_test_lock (omp_lock_t *lock)
always available directly. Make do with the gomp_thread pointer
since it's handy. */
-#if !defined (HAVE_TLS)
+# if !defined (HAVE_TLS)
static inline int gomp_tid (void)
{
return syscall (SYS_gettid);
}
-#elif !defined(__LP64__)
+# elif !defined(__LP64__)
static inline int gomp_tid (void)
{
return (int) gomp_thread ();
}
-#else
+# else
static __thread int tid_cache;
static inline int gomp_tid (void)
{
@@ -104,22 +166,22 @@ static inline int gomp_tid (void)
tid_cache = tid = syscall (SYS_gettid);
return tid;
}
-#endif
+# endif
void
-omp_init_nest_lock (omp_nest_lock_t *lock)
+gomp_init_nest_lock_25 (omp_nest_lock_25_t *lock)
{
memset (lock, 0, sizeof (lock));
}
void
-omp_destroy_nest_lock (omp_nest_lock_t *lock)
+gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *lock)
{
}
void
-omp_set_nest_lock (omp_nest_lock_t *lock)
+gomp_set_nest_lock_25 (omp_nest_lock_25_t *lock)
{
int otid, tid = gomp_tid ();
@@ -137,12 +199,12 @@ omp_set_nest_lock (omp_nest_lock_t *lock)
return;
}
- futex_wait (&lock->owner, otid);
+ do_wait (&lock->owner, otid);
}
}
void
-omp_unset_nest_lock (omp_nest_lock_t *lock)
+gomp_unset_nest_lock_25 (omp_nest_lock_25_t *lock)
{
/* ??? Validate that we own the lock here. */
@@ -154,7 +216,7 @@ omp_unset_nest_lock (omp_nest_lock_t *lock)
}
int
-omp_test_nest_lock (omp_nest_lock_t *lock)
+gomp_test_nest_lock_25 (omp_nest_lock_25_t *lock)
{
int otid, tid = gomp_tid ();
@@ -170,6 +232,19 @@ omp_test_nest_lock (omp_nest_lock_t *lock)
return 0;
}
+omp_lock_symver (omp_init_lock)
+omp_lock_symver (omp_destroy_lock)
+omp_lock_symver (omp_set_lock)
+omp_lock_symver (omp_unset_lock)
+omp_lock_symver (omp_test_lock)
+omp_lock_symver (omp_init_nest_lock)
+omp_lock_symver (omp_destroy_nest_lock)
+omp_lock_symver (omp_set_nest_lock)
+omp_lock_symver (omp_unset_nest_lock)
+omp_lock_symver (omp_test_nest_lock)
+
+#else
+
ialias (omp_init_lock)
ialias (omp_init_nest_lock)
ialias (omp_destroy_lock)
@@ -180,3 +255,5 @@ ialias (omp_unset_lock)
ialias (omp_unset_nest_lock)
ialias (omp_test_lock)
ialias (omp_test_nest_lock)
+
+#endif
diff --git a/libgomp/config/linux/mutex.c b/libgomp/config/linux/mutex.c
index fa3dfd1cb03..36c362eb274 100644
--- a/libgomp/config/linux/mutex.c
+++ b/libgomp/config/linux/mutex.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -29,9 +29,10 @@
mechanism for libgomp. This type is private to the library. This
implementation uses atomic instructions and the futex syscall. */
-#include "libgomp.h"
-#include "futex.h"
+#include "wait.h"
+long int gomp_futex_wake = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
+long int gomp_futex_wait = FUTEX_WAIT | FUTEX_PRIVATE_FLAG;
void
gomp_mutex_lock_slow (gomp_mutex_t *mutex)
@@ -40,7 +41,7 @@ gomp_mutex_lock_slow (gomp_mutex_t *mutex)
{
int oldval = __sync_val_compare_and_swap (mutex, 1, 2);
if (oldval != 0)
- futex_wait (mutex, 2);
+ do_wait (mutex, 2);
}
while (!__sync_bool_compare_and_swap (mutex, 0, 2));
}
diff --git a/libgomp/config/linux/omp-lock.h b/libgomp/config/linux/omp-lock.h
index 350cba16056..e65aff7fce7 100644
--- a/libgomp/config/linux/omp-lock.h
+++ b/libgomp/config/linux/omp-lock.h
@@ -3,8 +3,10 @@
structures without polluting the namespace.
When using the Linux futex primitive, non-recursive locks require
- only one int. Recursive locks require we identify the owning thread
- and so require two ints. */
+ only one int. Recursive locks require we identify the owning task
+ and so require one int and a pointer. */
typedef int omp_lock_t;
-typedef struct { int owner, count; } omp_nest_lock_t;
+typedef struct { int lock, count; void *owner; } omp_nest_lock_t;
+typedef int omp_lock_25_t;
+typedef struct { int owner, count; } omp_nest_lock_25_t;
diff --git a/libgomp/config/linux/powerpc/futex.h b/libgomp/config/linux/powerpc/futex.h
index 20e03573783..c1e0d0f5651 100644
--- a/libgomp/config/linux/powerpc/futex.h
+++ b/libgomp/config/linux/powerpc/futex.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -28,10 +28,8 @@
/* Provide target-specific access to the futex system call. */
#include <sys/syscall.h>
-#define FUTEX_WAIT 0
-#define FUTEX_WAKE 1
-static inline void
+static inline long
sys_futex0 (int *addr, int op, int val)
{
register long int r0 __asm__ ("r0");
@@ -50,21 +48,48 @@ sys_futex0 (int *addr, int op, int val)
doesn't. It doesn't much matter for us. In the interest of unity,
go ahead and clobber it always. */
- __asm volatile ("sc"
+ __asm volatile ("sc; mfcr %0"
: "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6)
: "r"(r0), "r"(r3), "r"(r4), "r"(r5), "r"(r6)
: "r7", "r8", "r9", "r10", "r11", "r12",
"cr0", "ctr", "memory");
+ if (__builtin_expect (r0 & (1 << 28), 0))
+ return r3;
+ return 0;
}
static inline void
futex_wait (int *addr, int val)
{
- sys_futex0 (addr, FUTEX_WAIT, val);
+ long err = sys_futex0 (addr, gomp_futex_wait, val);
+ if (__builtin_expect (err == ENOSYS, 0))
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ sys_futex0 (addr, gomp_futex_wait, val);
+ }
}
static inline void
futex_wake (int *addr, int count)
{
- sys_futex0 (addr, FUTEX_WAKE, count);
+ long err = sys_futex0 (addr, gomp_futex_wake, count);
+ if (__builtin_expect (err == ENOSYS, 0))
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ sys_futex0 (addr, gomp_futex_wake, count);
+ }
+}
+
+static inline void
+cpu_relax (void)
+{
+ __asm volatile ("" : : : "memory");
+}
+
+static inline void
+atomic_write_barrier (void)
+{
+ __asm volatile ("eieio" : : : "memory");
}
diff --git a/libgomp/config/linux/proc.c b/libgomp/config/linux/proc.c
index 2267cfbd2d1..6a006f24aa3 100644
--- a/libgomp/config/linux/proc.c
+++ b/libgomp/config/linux/proc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Contributed by Jakub Jelinek <jakub@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -78,14 +78,14 @@ gomp_init_num_threads (void)
if (pthread_getaffinity_np (pthread_self (), sizeof (cpuset), &cpuset) == 0)
{
/* Count only the CPUs this process can use. */
- gomp_nthreads_var = cpuset_popcount (&cpuset);
- if (gomp_nthreads_var == 0)
- gomp_nthreads_var = 1;
+ gomp_global_icv.nthreads_var = cpuset_popcount (&cpuset);
+ if (gomp_global_icv.nthreads_var == 0)
+ gomp_global_icv.nthreads_var = 1;
return;
}
#endif
#ifdef _SC_NPROCESSORS_ONLN
- gomp_nthreads_var = sysconf (_SC_NPROCESSORS_ONLN);
+ gomp_global_icv.nthreads_var = sysconf (_SC_NPROCESSORS_ONLN);
#endif
}
@@ -132,7 +132,7 @@ get_num_procs (void)
#ifdef _SC_NPROCESSORS_ONLN
return sysconf (_SC_NPROCESSORS_ONLN);
#else
- return gomp_nthreads_var;
+ return gomp_icv (false)->nthreads_var;
#endif
}
@@ -146,11 +146,11 @@ get_num_procs (void)
unsigned
gomp_dynamic_max_threads (void)
{
- unsigned n_onln, loadavg;
+ unsigned n_onln, loadavg, nthreads_var = gomp_icv (false)->nthreads_var;
n_onln = get_num_procs ();
- if (n_onln > gomp_nthreads_var)
- n_onln = gomp_nthreads_var;
+ if (n_onln > nthreads_var)
+ n_onln = nthreads_var;
loadavg = 0;
#ifdef HAVE_GETLOADAVG
diff --git a/libgomp/config/linux/ptrlock.c b/libgomp/config/linux/ptrlock.c
new file mode 100644
index 00000000000..8faa1b2287d
--- /dev/null
+++ b/libgomp/config/linux/ptrlock.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Jakub Jelinek <jakub@redhat.com>.
+
+ This file is part of the GNU OpenMP Library (libgomp).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+/* This is a Linux specific implementation of a mutex synchronization
+ mechanism for libgomp. This type is private to the library. This
+ implementation uses atomic instructions and the futex syscall. */
+
+#include <endian.h>
+#include <limits.h>
+#include "wait.h"
+
+void *
+gomp_ptrlock_get_slow (gomp_ptrlock_t *ptrlock)
+{
+ int *intptr;
+ __sync_bool_compare_and_swap (ptrlock, 1, 2);
+
+ /* futex works on ints, not pointers.
+ But a valid work share pointer will be at least
+ 8 byte aligned, so it is safe to assume the low
+ 32-bits of the pointer won't contain values 1 or 2. */
+ __asm volatile ("" : "=r" (intptr) : "0" (ptrlock));
+#if __BYTE_ORDER == __BIG_ENDIAN
+ if (sizeof (*ptrlock) > sizeof (int))
+ intptr += (sizeof (*ptrlock) / sizeof (int)) - 1;
+#endif
+ do
+ do_wait (intptr, 2);
+ while (*intptr == 2);
+ __asm volatile ("" : : : "memory");
+ return *ptrlock;
+}
+
+void
+gomp_ptrlock_set_slow (gomp_ptrlock_t *ptrlock, void *ptr)
+{
+ int *intptr;
+
+ *ptrlock = ptr;
+ __asm volatile ("" : "=r" (intptr) : "0" (ptrlock));
+#if __BYTE_ORDER == __BIG_ENDIAN
+ if (sizeof (*ptrlock) > sizeof (int))
+ intptr += (sizeof (*ptrlock) / sizeof (int)) - 1;
+#endif
+ futex_wake (intptr, INT_MAX);
+}
diff --git a/libgomp/config/linux/ptrlock.h b/libgomp/config/linux/ptrlock.h
new file mode 100644
index 00000000000..bb5441676a4
--- /dev/null
+++ b/libgomp/config/linux/ptrlock.h
@@ -0,0 +1,65 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Jakub Jelinek <jakub@redhat.com>.
+
+ This file is part of the GNU OpenMP Library (libgomp).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+/* This is a Linux specific implementation of a mutex synchronization
+ mechanism for libgomp. This type is private to the library. This
+ implementation uses atomic instructions and the futex syscall. */
+
+#ifndef GOMP_PTRLOCK_H
+#define GOMP_PTRLOCK_H 1
+
+typedef void *gomp_ptrlock_t;
+
+static inline void gomp_ptrlock_init (gomp_ptrlock_t *ptrlock, void *ptr)
+{
+ *ptrlock = ptr;
+}
+
+extern void *gomp_ptrlock_get_slow (gomp_ptrlock_t *ptrlock);
+static inline void *gomp_ptrlock_get (gomp_ptrlock_t *ptrlock)
+{
+ if ((uintptr_t) *ptrlock > 2)
+ return *ptrlock;
+
+ if (__sync_bool_compare_and_swap (ptrlock, NULL, (uintptr_t) 1))
+ return NULL;
+
+ return gomp_ptrlock_get_slow (ptrlock);
+}
+
+extern void gomp_ptrlock_set_slow (gomp_ptrlock_t *ptrlock, void *ptr);
+static inline void gomp_ptrlock_set (gomp_ptrlock_t *ptrlock, void *ptr)
+{
+ if (!__sync_bool_compare_and_swap (ptrlock, (uintptr_t) 1, ptr))
+ gomp_ptrlock_set_slow (ptrlock, ptr);
+}
+
+static inline void gomp_ptrlock_destroy (gomp_ptrlock_t *ptrlock)
+{
+}
+
+#endif /* GOMP_PTRLOCK_H */
diff --git a/libgomp/config/linux/s390/futex.h b/libgomp/config/linux/s390/futex.h
index 9b3820c0d97..3c4e1fc5d25 100644
--- a/libgomp/config/linux/s390/futex.h
+++ b/libgomp/config/linux/s390/futex.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Jakub Jelinek <jakub@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -28,10 +28,8 @@
/* Provide target-specific access to the futex system call. */
#include <sys/syscall.h>
-#define FUTEX_WAIT 0
-#define FUTEX_WAKE 1
-static inline void
+static inline long
sys_futex0 (int *addr, int op, int val)
{
register long int gpr2 __asm__ ("2");
@@ -49,16 +47,41 @@ sys_futex0 (int *addr, int op, int val)
: "i" (SYS_futex),
"0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5)
: "memory");
+ return gpr2;
}
static inline void
futex_wait (int *addr, int val)
{
- sys_futex0 (addr, FUTEX_WAIT, val);
+ long err = sys_futex0 (addr, gomp_futex_wait, val);
+ if (__builtin_expect (err == -ENOSYS, 0))
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ sys_futex0 (addr, gomp_futex_wait, val);
+ }
}
static inline void
futex_wake (int *addr, int count)
{
- sys_futex0 (addr, FUTEX_WAKE, count);
+ long err = sys_futex0 (addr, gomp_futex_wake, count);
+ if (__builtin_expect (err == -ENOSYS, 0))
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ sys_futex0 (addr, gomp_futex_wake, count);
+ }
+}
+
+static inline void
+cpu_relax (void)
+{
+ __asm volatile ("" : : : "memory");
+}
+
+static inline void
+atomic_write_barrier (void)
+{
+ __sync_synchronize ();
}
diff --git a/libgomp/config/linux/sem.c b/libgomp/config/linux/sem.c
index 798e3f1f2c0..5615bc580ee 100644
--- a/libgomp/config/linux/sem.c
+++ b/libgomp/config/linux/sem.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -29,8 +29,7 @@
mechanism for libgomp. This type is private to the library. This
implementation uses atomic instructions and the futex syscall. */
-#include "libgomp.h"
-#include "futex.h"
+#include "wait.h"
void
@@ -44,7 +43,7 @@ gomp_sem_wait_slow (gomp_sem_t *sem)
if (__sync_bool_compare_and_swap (sem, val, val - 1))
return;
}
- futex_wait (sem, -1);
+ do_wait (sem, -1);
}
}
diff --git a/libgomp/config/linux/sparc/futex.h b/libgomp/config/linux/sparc/futex.h
index 7b1cc837956..b9bc387355f 100644
--- a/libgomp/config/linux/sparc/futex.h
+++ b/libgomp/config/linux/sparc/futex.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Jakub Jelinek <jakub@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -28,10 +28,8 @@
/* Provide target-specific access to the futex system call. */
#include <sys/syscall.h>
-#define FUTEX_WAIT 0
-#define FUTEX_WAKE 1
-static inline void
+static inline long
sys_futex0 (int *addr, int op, int val)
{
register long int g1 __asm__ ("g1");
@@ -47,9 +45,9 @@ sys_futex0 (int *addr, int op, int val)
o3 = 0;
#ifdef __arch64__
-# define SYSCALL_STRING "ta\t0x6d"
+# define SYSCALL_STRING "ta\t0x6d; bcs,a,pt %%xcc, 1f; sub %%g0, %%o0, %%o0; 1:"
#else
-# define SYSCALL_STRING "ta\t0x10"
+# define SYSCALL_STRING "ta\t0x10; bcs,a 1f; sub %%g0, %%o0, %%o0; 1:"
#endif
__asm volatile (SYSCALL_STRING
@@ -65,16 +63,49 @@ sys_futex0 (int *addr, int op, int val)
"f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
#endif
"cc", "memory");
+ return o0;
}
static inline void
futex_wait (int *addr, int val)
{
- sys_futex0 (addr, FUTEX_WAIT, val);
+ long err = sys_futex0 (addr, gomp_futex_wait, val);
+ if (__builtin_expect (err == ENOSYS, 0))
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ sys_futex0 (addr, gomp_futex_wait, val);
+ }
}
static inline void
futex_wake (int *addr, int count)
{
- sys_futex0 (addr, FUTEX_WAKE, count);
+ long err = sys_futex0 (addr, gomp_futex_wake, count);
+ if (__builtin_expect (err == ENOSYS, 0))
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ sys_futex0 (addr, gomp_futex_wake, count);
+ }
+}
+
+static inline void
+cpu_relax (void)
+{
+#if defined __arch64__ || defined __sparc_v9__
+ __asm volatile ("membar #LoadLoad" : : : "memory");
+#else
+ __asm volatile ("" : : : "memory");
+#endif
+}
+
+static inline void
+atomic_write_barrier (void)
+{
+#if defined __arch64__ || defined __sparc_v9__
+ __asm volatile ("membar #StoreStore" : : : "memory");
+#else
+ __sync_synchronize ();
+#endif
}
diff --git a/libgomp/config/linux/wait.h b/libgomp/config/linux/wait.h
new file mode 100644
index 00000000000..21f0ab8756c
--- /dev/null
+++ b/libgomp/config/linux/wait.h
@@ -0,0 +1,68 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Jakub Jelinek <jakub@redhat.com>.
+
+ This file is part of the GNU OpenMP Library (libgomp).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+/* This is a Linux specific implementation of a mutex synchronization
+ mechanism for libgomp. This type is private to the library. This
+ implementation uses atomic instructions and the futex syscall. */
+
+#ifndef GOMP_WAIT_H
+#define GOMP_WAIT_H 1
+
+#include "libgomp.h"
+#include <errno.h>
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+#define FUTEX_PRIVATE_FLAG 128L
+
+#ifdef HAVE_ATTRIBUTE_VISIBILITY
+# pragma GCC visibility push(hidden)
+#endif
+
+extern long int gomp_futex_wait, gomp_futex_wake;
+
+#include "futex.h"
+
+static inline void do_wait (int *addr, int val)
+{
+ unsigned long long i, count = gomp_spin_count_var;
+
+ if (__builtin_expect (gomp_managed_threads > gomp_available_cpus, 0))
+ count = gomp_throttled_spin_count_var;
+ for (i = 0; i < count; i++)
+ if (__builtin_expect (*addr != val, 0))
+ return;
+ else
+ cpu_relax ();
+ futex_wait (addr, val);
+}
+
+#ifdef HAVE_ATTRIBUTE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
+#endif /* GOMP_WAIT_H */
diff --git a/libgomp/config/linux/x86/futex.h b/libgomp/config/linux/x86/futex.h
index 4f9aac2ddbb..36af6aad93b 100644
--- a/libgomp/config/linux/x86/futex.h
+++ b/libgomp/config/linux/x86/futex.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -27,9 +27,6 @@
/* Provide target-specific access to the futex system call. */
-#define FUTEX_WAIT 0
-#define FUTEX_WAKE 1
-
#ifdef __LP64__
# ifndef SYS_futex
# define SYS_futex 202
@@ -38,14 +35,26 @@
static inline void
futex_wait (int *addr, int val)
{
- register long r10 __asm__("%r10") = 0;
+ register long r10 __asm__("%r10");
long res;
+ r10 = 0;
__asm volatile ("syscall"
: "=a" (res)
- : "0"(SYS_futex), "D" (addr), "S"(FUTEX_WAIT),
- "d"(val), "r"(r10)
+ : "0" (SYS_futex), "D" (addr), "S" (gomp_futex_wait),
+ "d" (val), "r" (r10)
: "r11", "rcx", "memory");
+ if (__builtin_expect (res == -ENOSYS, 0))
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ r10 = 0;
+ __asm volatile ("syscall"
+ : "=a" (res)
+ : "0" (SYS_futex), "D" (addr), "S" (gomp_futex_wait),
+ "d" (val), "r" (r10)
+ : "r11", "rcx", "memory");
+ }
}
static inline void
@@ -55,8 +64,19 @@ futex_wake (int *addr, int count)
__asm volatile ("syscall"
: "=a" (res)
- : "0"(SYS_futex), "D" (addr), "S"(FUTEX_WAKE), "d"(count)
+ : "0" (SYS_futex), "D" (addr), "S" (gomp_futex_wake),
+ "d" (count)
: "r11", "rcx", "memory");
+ if (__builtin_expect (res == -ENOSYS, 0))
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ __asm volatile ("syscall"
+ : "=a" (res)
+ : "0" (SYS_futex), "D" (addr), "S" (gomp_futex_wake),
+ "d" (count)
+ : "r11", "rcx", "memory");
+ }
}
#else
# ifndef SYS_futex
@@ -65,7 +85,7 @@ futex_wake (int *addr, int count)
# ifdef __PIC__
-static inline void
+static inline long
sys_futex0 (int *addr, int op, int val)
{
long res;
@@ -77,11 +97,12 @@ sys_futex0 (int *addr, int op, int val)
: "0"(SYS_futex), "r" (addr), "c"(op),
"d"(val), "S"(0)
: "memory");
+ return res;
}
# else
-static inline void
+static inline long
sys_futex0 (int *addr, int op, int val)
{
long res;
@@ -91,6 +112,7 @@ sys_futex0 (int *addr, int op, int val)
: "0"(SYS_futex), "b" (addr), "c"(op),
"d"(val), "S"(0)
: "memory");
+ return res;
}
# endif /* __PIC__ */
@@ -98,13 +120,37 @@ sys_futex0 (int *addr, int op, int val)
static inline void
futex_wait (int *addr, int val)
{
- sys_futex0 (addr, FUTEX_WAIT, val);
+ long res = sys_futex0 (addr, gomp_futex_wait, val);
+ if (__builtin_expect (res == -ENOSYS, 0))
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ sys_futex0 (addr, gomp_futex_wait, val);
+ }
}
static inline void
futex_wake (int *addr, int count)
{
- sys_futex0 (addr, FUTEX_WAKE, count);
+ long res = sys_futex0 (addr, gomp_futex_wake, count);
+ if (__builtin_expect (res == -ENOSYS, 0))
+ {
+ gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
+ gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
+ sys_futex0 (addr, gomp_futex_wake, count);
+ }
}
#endif /* __LP64__ */
+
+static inline void
+cpu_relax (void)
+{
+ __asm volatile ("rep; nop" : : : "memory");
+}
+
+static inline void
+atomic_write_barrier (void)
+{
+ __sync_synchronize ();
+}
diff --git a/libgomp/config/mingw32/proc.c b/libgomp/config/mingw32/proc.c
index def7bb5e8f4..4532f45f572 100644
--- a/libgomp/config/mingw32/proc.c
+++ b/libgomp/config/mingw32/proc.c
@@ -35,7 +35,7 @@
#include <windows.h>
/* Count the CPU's currently available to this process. */
-static int
+static unsigned int
count_avail_process_cpus ()
{
DWORD_PTR process_cpus;
@@ -59,7 +59,7 @@ count_avail_process_cpus ()
void
gomp_init_num_threads (void)
{
- gomp_nthreads_var = count_avail_process_cpus ();
+ gomp_global_icv.nthreads_var = count_avail_process_cpus ();
}
/* When OMP_DYNAMIC is set, at thread launch determine the number of
@@ -69,8 +69,9 @@ gomp_init_num_threads (void)
unsigned
gomp_dynamic_max_threads (void)
{
- int n_onln = count_avail_process_cpus ();
- return n_onln > gomp_nthreads_var ? gomp_nthreads_var : n_onln;
+ unsigned int n_onln = count_avail_process_cpus ();
+ unsigned int nthreads_var = gomp_icv (false)->nthreads_var;
+ return n_onln > nthreads_var ? nthreads_var : n_onln;
}
int
diff --git a/libgomp/config/posix/bar.c b/libgomp/config/posix/bar.c
index 79721610ca7..ff19e9353a3 100644
--- a/libgomp/config/posix/bar.c
+++ b/libgomp/config/posix/bar.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -44,6 +44,7 @@ gomp_barrier_init (gomp_barrier_t *bar, unsigned count)
gomp_sem_init (&bar->sem2, 0);
bar->total = count;
bar->arrived = 0;
+ bar->generation = 0;
}
void
@@ -70,11 +71,11 @@ gomp_barrier_reinit (gomp_barrier_t *bar, unsigned count)
}
void
-gomp_barrier_wait_end (gomp_barrier_t *bar, bool last)
+gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
{
unsigned int n;
- if (last)
+ if (state & 1)
{
n = --bar->arrived;
if (n > 0)
@@ -109,3 +110,72 @@ gomp_barrier_wait (gomp_barrier_t *barrier)
{
gomp_barrier_wait_end (barrier, gomp_barrier_wait_start (barrier));
}
+
+void
+gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
+{
+ unsigned int n;
+
+ if (state & 1)
+ {
+ n = --bar->arrived;
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+
+ if (team->task_count)
+ {
+ gomp_barrier_handle_tasks (state);
+ if (n > 0)
+ gomp_sem_wait (&bar->sem2);
+ gomp_mutex_unlock (&bar->mutex1);
+ return;
+ }
+
+ bar->generation = state + 3;
+ if (n > 0)
+ {
+ do
+ gomp_sem_post (&bar->sem1);
+ while (--n != 0);
+ gomp_sem_wait (&bar->sem2);
+ }
+ gomp_mutex_unlock (&bar->mutex1);
+ }
+ else
+ {
+ gomp_mutex_unlock (&bar->mutex1);
+ do
+ {
+ gomp_sem_wait (&bar->sem1);
+ if (bar->generation & 1)
+ gomp_barrier_handle_tasks (state);
+ }
+ while (bar->generation != state + 4);
+
+#ifdef HAVE_SYNC_BUILTINS
+ n = __sync_add_and_fetch (&bar->arrived, -1);
+#else
+ gomp_mutex_lock (&bar->mutex2);
+ n = --bar->arrived;
+ gomp_mutex_unlock (&bar->mutex2);
+#endif
+
+ if (n == 0)
+ gomp_sem_post (&bar->sem2);
+ }
+}
+
+void
+gomp_team_barrier_wait (gomp_barrier_t *barrier)
+{
+ gomp_team_barrier_wait_end (barrier, gomp_barrier_wait_start (barrier));
+}
+
+void
+gomp_team_barrier_wake (gomp_barrier_t *bar, int count)
+{
+ if (count == 0)
+ count = bar->total - 1;
+ while (count-- > 0)
+ gomp_sem_post (&bar->sem1);
+}
diff --git a/libgomp/config/posix/bar.h b/libgomp/config/posix/bar.h
index 5275efa96a7..e4d2e680af2 100644
--- a/libgomp/config/posix/bar.h
+++ b/libgomp/config/posix/bar.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -45,19 +45,74 @@ typedef struct
gomp_sem_t sem2;
unsigned total;
unsigned arrived;
+ unsigned generation;
} gomp_barrier_t;
+typedef unsigned int gomp_barrier_state_t;
extern void gomp_barrier_init (gomp_barrier_t *, unsigned);
extern void gomp_barrier_reinit (gomp_barrier_t *, unsigned);
extern void gomp_barrier_destroy (gomp_barrier_t *);
extern void gomp_barrier_wait (gomp_barrier_t *);
-extern void gomp_barrier_wait_end (gomp_barrier_t *, bool);
+extern void gomp_barrier_wait_end (gomp_barrier_t *, gomp_barrier_state_t);
+extern void gomp_team_barrier_wait (gomp_barrier_t *);
+extern void gomp_team_barrier_wait_end (gomp_barrier_t *,
+ gomp_barrier_state_t);
+extern void gomp_team_barrier_wake (gomp_barrier_t *, int);
-static inline bool gomp_barrier_wait_start (gomp_barrier_t *bar)
+static inline gomp_barrier_state_t
+gomp_barrier_wait_start (gomp_barrier_t *bar)
{
+ unsigned int ret;
gomp_mutex_lock (&bar->mutex1);
- return ++bar->arrived == bar->total;
+ ret = bar->generation & ~3;
+ ret += ++bar->arrived == bar->total;
+ return ret;
+}
+
+static inline bool
+gomp_barrier_last_thread (gomp_barrier_state_t state)
+{
+ return state & 1;
+}
+
+static inline void
+gomp_barrier_wait_last (gomp_barrier_t *bar)
+{
+ gomp_barrier_wait (bar);
+}
+
+/* All the inlines below must be called with team->task_lock
+ held. */
+
+static inline void
+gomp_team_barrier_set_task_pending (gomp_barrier_t *bar)
+{
+ bar->generation |= 1;
+}
+
+static inline void
+gomp_team_barrier_clear_task_pending (gomp_barrier_t *bar)
+{
+ bar->generation &= ~1;
+}
+
+static inline void
+gomp_team_barrier_set_waiting_for_tasks (gomp_barrier_t *bar)
+{
+ bar->generation |= 2;
+}
+
+static inline bool
+gomp_team_barrier_waiting_for_tasks (gomp_barrier_t *bar)
+{
+ return (bar->generation & 2) != 0;
+}
+
+static inline void
+gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state)
+{
+ bar->generation = (state & ~3) + 4;
}
#endif /* GOMP_BARRIER_H */
diff --git a/libgomp/config/posix/lock.c b/libgomp/config/posix/lock.c
index 59459bb86ce..c2868398c66 100644
--- a/libgomp/config/posix/lock.c
+++ b/libgomp/config/posix/lock.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -42,39 +42,209 @@
#include "libgomp.h"
+#ifdef HAVE_BROKEN_POSIX_SEMAPHORES
+void
+gomp_init_lock_30 (omp_lock_t *lock)
+{
+ pthread_mutex_init (lock, NULL);
+}
+
+void
+gomp_destroy_lock_30 (omp_lock_t *lock)
+{
+ pthread_mutex_destroy (lock);
+}
+
+void
+gomp_set_lock_30 (omp_lock_t *lock)
+{
+ pthread_mutex_lock (lock);
+}
+
+void
+gomp_unset_lock_30 (omp_lock_t *lock)
+{
+ pthread_mutex_unlock (lock);
+}
+
+int
+gomp_test_lock_30 (omp_lock_t *lock)
+{
+ return pthread_mutex_trylock (lock) == 0;
+}
+
+void
+gomp_init_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ pthread_mutex_init (&lock->lock, NULL);
+ lock->count = 0;
+ lock->owner = NULL;
+}
+
+void
+gomp_destroy_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ pthread_mutex_destroy (&lock->lock);
+}
+
+void
+gomp_set_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ void *me = gomp_icv (true);
+
+ if (lock->owner != me)
+ {
+ pthread_mutex_lock (&lock->lock);
+ lock->owner = me;
+ }
+ lock->count++;
+}
+
+void
+gomp_unset_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ if (--lock->count == 0)
+ {
+ lock->owner = NULL;
+ pthread_mutex_unlock (&lock->lock);
+ }
+}
+
+int
+gomp_test_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ void *me = gomp_icv (true);
+
+ if (lock->owner != me)
+ {
+ if (pthread_mutex_trylock (&lock->lock) != 0)
+ return 0;
+ lock->owner = me;
+ }
+
+ return ++lock->count;
+}
+
+#else
void
-omp_init_lock (omp_lock_t *lock)
+gomp_init_lock_30 (omp_lock_t *lock)
+{
+ sem_init (lock, 0, 1);
+}
+
+void
+gomp_destroy_lock_30 (omp_lock_t *lock)
+{
+ sem_destroy (lock);
+}
+
+void
+gomp_set_lock_30 (omp_lock_t *lock)
+{
+ while (sem_wait (lock) != 0)
+ ;
+}
+
+void
+gomp_unset_lock_30 (omp_lock_t *lock)
+{
+ sem_post (lock);
+}
+
+int
+gomp_test_lock_30 (omp_lock_t *lock)
+{
+ return sem_trywait (lock) == 0;
+}
+
+void
+gomp_init_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ sem_init (&lock->lock, 0, 1);
+ lock->count = 0;
+ lock->owner = NULL;
+}
+
+void
+gomp_destroy_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ sem_destroy (&lock->lock);
+}
+
+void
+gomp_set_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ void *me = gomp_icv (true);
+
+ if (lock->owner != me)
+ {
+ while (sem_wait (&lock->lock) != 0)
+ ;
+ lock->owner = me;
+ }
+ lock->count++;
+}
+
+void
+gomp_unset_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ if (--lock->count == 0)
+ {
+ lock->owner = NULL;
+ sem_post (&lock->lock);
+ }
+}
+
+int
+gomp_test_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ void *me = gomp_icv (true);
+
+ if (lock->owner != me)
+ {
+ if (sem_trywait (&lock->lock) != 0)
+ return 0;
+ lock->owner = me;
+ }
+
+ return ++lock->count;
+}
+#endif
+
+#ifdef LIBGOMP_GNU_SYMBOL_VERSIONING
+void
+gomp_init_lock_25 (omp_lock_25_t *lock)
{
pthread_mutex_init (lock, NULL);
}
void
-omp_destroy_lock (omp_lock_t *lock)
+gomp_destroy_lock_25 (omp_lock_25_t *lock)
{
pthread_mutex_destroy (lock);
}
void
-omp_set_lock (omp_lock_t *lock)
+gomp_set_lock_25 (omp_lock_25_t *lock)
{
pthread_mutex_lock (lock);
}
void
-omp_unset_lock (omp_lock_t *lock)
+gomp_unset_lock_25 (omp_lock_25_t *lock)
{
pthread_mutex_unlock (lock);
}
int
-omp_test_lock (omp_lock_t *lock)
+gomp_test_lock_25 (omp_lock_25_t *lock)
{
return pthread_mutex_trylock (lock) == 0;
}
void
-omp_init_nest_lock (omp_nest_lock_t *lock)
+gomp_init_nest_lock_25 (omp_nest_lock_25_t *lock)
{
pthread_mutexattr_t attr;
@@ -86,33 +256,46 @@ omp_init_nest_lock (omp_nest_lock_t *lock)
}
void
-omp_destroy_nest_lock (omp_nest_lock_t *lock)
+gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *lock)
{
pthread_mutex_destroy (&lock->lock);
}
void
-omp_set_nest_lock (omp_nest_lock_t *lock)
+gomp_set_nest_lock_25 (omp_nest_lock_25_t *lock)
{
pthread_mutex_lock (&lock->lock);
lock->count++;
}
void
-omp_unset_nest_lock (omp_nest_lock_t *lock)
+gomp_unset_nest_lock_25 (omp_nest_lock_25_t *lock)
{
lock->count--;
pthread_mutex_unlock (&lock->lock);
}
int
-omp_test_nest_lock (omp_nest_lock_t *lock)
+gomp_test_nest_lock_25 (omp_nest_lock_25_t *lock)
{
if (pthread_mutex_trylock (&lock->lock) == 0)
return ++lock->count;
return 0;
}
+omp_lock_symver (omp_init_lock)
+omp_lock_symver (omp_destroy_lock)
+omp_lock_symver (omp_set_lock)
+omp_lock_symver (omp_unset_lock)
+omp_lock_symver (omp_test_lock)
+omp_lock_symver (omp_init_nest_lock)
+omp_lock_symver (omp_destroy_nest_lock)
+omp_lock_symver (omp_set_nest_lock)
+omp_lock_symver (omp_unset_nest_lock)
+omp_lock_symver (omp_test_nest_lock)
+
+#else
+
ialias (omp_init_lock)
ialias (omp_init_nest_lock)
ialias (omp_destroy_lock)
@@ -123,3 +306,5 @@ ialias (omp_unset_lock)
ialias (omp_unset_nest_lock)
ialias (omp_test_lock)
ialias (omp_test_nest_lock)
+
+#endif
diff --git a/libgomp/config/posix/omp-lock.h b/libgomp/config/posix/omp-lock.h
index ed70618d87d..e51dc271f8a 100644
--- a/libgomp/config/posix/omp-lock.h
+++ b/libgomp/config/posix/omp-lock.h
@@ -2,10 +2,22 @@
alignment of the public OpenMP locks, so that we can export data
structures without polluting the namespace.
- In this default POSIX implementation, we map the two locks to the
- same PTHREADS primitive. */
+ In this default POSIX implementation, we used to map the two locks to the
+ same PTHREADS primitive, but for OpenMP 3.0 sem_t needs to be used
+ instead, as pthread_mutex_unlock should not be called by different
+ thread than the one that called pthread_mutex_lock. */
#include <pthread.h>
+#include <semaphore.h>
+typedef pthread_mutex_t omp_lock_25_t;
+typedef struct { pthread_mutex_t lock; int count; } omp_nest_lock_25_t;
+#ifdef HAVE_BROKEN_POSIX_SEMAPHORES
+/* If we don't have working semaphores, we'll make all explicit tasks
+ tied to the creating thread. */
typedef pthread_mutex_t omp_lock_t;
-typedef struct { pthread_mutex_t lock; int count; } omp_nest_lock_t;
+typedef struct { pthread_mutex_t lock; int count; void *owner; } omp_nest_lock_t;
+#else
+typedef sem_t omp_lock_t;
+typedef struct { sem_t lock; int count; void *owner; } omp_nest_lock_t;
+#endif
diff --git a/libgomp/config/posix/proc.c b/libgomp/config/posix/proc.c
index 3ee84f5c9d6..0c1096fb6b1 100644
--- a/libgomp/config/posix/proc.c
+++ b/libgomp/config/posix/proc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2006, 2008 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU OpenMP Library (libgomp).
@@ -48,7 +48,7 @@ void
gomp_init_num_threads (void)
{
#ifdef _SC_NPROCESSORS_ONLN
- gomp_nthreads_var = sysconf (_SC_NPROCESSORS_ONLN);
+ gomp_global_icv.nthreads_var = sysconf (_SC_NPROCESSORS_ONLN);
#endif
}
@@ -63,13 +63,14 @@ unsigned
gomp_dynamic_max_threads (void)
{
unsigned n_onln, loadavg;
+ unsigned nthreads_var = gomp_icv (false)->nthreads_var;
#ifdef _SC_NPROCESSORS_ONLN
n_onln = sysconf (_SC_NPROCESSORS_ONLN);
- if (n_onln > gomp_nthreads_var)
- n_onln = gomp_nthreads_var;
+ if (n_onln > nthreads_var)
+ n_onln = nthreads_var;
#else
- n_onln = gomp_nthreads_var;
+ n_onln = nthreads_var;
#endif
loadavg = 0;
@@ -96,7 +97,7 @@ omp_get_num_procs (void)
#ifdef _SC_NPROCESSORS_ONLN
return sysconf (_SC_NPROCESSORS_ONLN);
#else
- return gomp_nthreads_var;
+ return gomp_icv (false)->nthreads_var;
#endif
}
diff --git a/libgomp/config/posix/ptrlock.c b/libgomp/config/posix/ptrlock.c
new file mode 100644
index 00000000000..39bb64da0f9
--- /dev/null
+++ b/libgomp/config/posix/ptrlock.c
@@ -0,0 +1 @@
+/* Everything is in the header. */
diff --git a/libgomp/config/posix/ptrlock.h b/libgomp/config/posix/ptrlock.h
new file mode 100644
index 00000000000..1271ebb227b
--- /dev/null
+++ b/libgomp/config/posix/ptrlock.h
@@ -0,0 +1,69 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Jakub Jelinek <jakub@redhat.com>.
+
+ This file is part of the GNU OpenMP Library (libgomp).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+/* This is a Linux specific implementation of a mutex synchronization
+ mechanism for libgomp. This type is private to the library. This
+ implementation uses atomic instructions and the futex syscall. */
+
+#ifndef GOMP_PTRLOCK_H
+#define GOMP_PTRLOCK_H 1
+
+typedef struct { void *ptr; gomp_mutex_t lock; } gomp_ptrlock_t;
+
+static inline void gomp_ptrlock_init (gomp_ptrlock_t *ptrlock, void *ptr)
+{
+ ptrlock->ptr = ptr;
+ gomp_mutex_init (&ptrlock->lock);
+}
+
+static inline void *gomp_ptrlock_get (gomp_ptrlock_t *ptrlock)
+{
+ if (ptrlock->ptr != NULL)
+ return ptrlock->ptr;
+
+ gomp_mutex_lock (&ptrlock->lock);
+ if (ptrlock->ptr != NULL)
+ {
+ gomp_mutex_unlock (&ptrlock->lock);
+ return ptrlock->ptr;
+ }
+
+ return NULL;
+}
+
+static inline void gomp_ptrlock_set (gomp_ptrlock_t *ptrlock, void *ptr)
+{
+ ptrlock->ptr = ptr;
+ gomp_mutex_unlock (&ptrlock->lock);
+}
+
+static inline void gomp_ptrlock_destroy (gomp_ptrlock_t *ptrlock)
+{
+ gomp_mutex_destroy (&ptrlock->lock);
+}
+
+#endif /* GOMP_PTRLOCK_H */
diff --git a/libgomp/config/posix95/lock.c b/libgomp/config/posix95/lock.c
index 2416f1131c7..e27437ead16 100644
--- a/libgomp/config/posix95/lock.c
+++ b/libgomp/config/posix95/lock.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2006, 2008 Free Software Foundation, Inc.
This file is part of the GNU OpenMP Library (libgomp).
@@ -33,39 +33,212 @@
#include "libgomp.h"
+#ifdef HAVE_BROKEN_POSIX_SEMAPHORES
+void
+gomp_init_lock_30 (omp_lock_t *lock)
+{
+ pthread_mutex_init (lock, NULL);
+}
+
+void
+gomp_destroy_lock_30 (omp_lock_t *lock)
+{
+ pthread_mutex_destroy (lock);
+}
+
+void
+gomp_set_lock_30 (omp_lock_t *lock)
+{
+ pthread_mutex_lock (lock);
+}
+
+void
+gomp_unset_lock_30 (omp_lock_t *lock)
+{
+ pthread_mutex_unlock (lock);
+}
+
+int
+gomp_test_lock_30 (omp_lock_t *lock)
+{
+ return pthread_mutex_trylock (lock) == 0;
+}
+
+void
+gomp_init_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ pthread_mutex_init (&lock->lock, NULL);
+ lock->owner = NULL;
+ lock->count = 0;
+}
+
+void
+gomp_destroy_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ pthread_mutex_destroy (&lock->lock);
+}
void
-omp_init_lock (omp_lock_t *lock)
+gomp_set_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ void *me = gomp_icv (true);
+
+ if (lock->owner != me)
+ {
+ pthread_mutex_lock (&lock->lock);
+ lock->owner = me;
+ }
+
+ lock->count++;
+}
+
+void
+gomp_unset_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ lock->count--;
+
+ if (lock->count == 0)
+ {
+ lock->owner = NULL;
+ pthread_mutex_unlock (&lock->lock);
+ }
+}
+
+int
+gomp_test_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ void *me = gomp_icv (true);
+
+ if (lock->owner != me)
+ {
+ if (pthread_mutex_trylock (&lock->lock) != 0)
+ return 0;
+ lock->owner = me;
+ }
+
+ return ++lock->count;
+}
+
+#else
+
+void
+gomp_init_lock_30 (omp_lock_t *lock)
+{
+ sem_init (lock, 0, 1);
+}
+
+void
+gomp_destroy_lock_30 (omp_lock_t *lock)
+{
+ sem_destroy (lock);
+}
+
+void
+gomp_set_lock_30 (omp_lock_t *lock)
+{
+ while (sem_wait (lock) != 0)
+ ;
+}
+
+void
+gomp_unset_lock_30 (omp_lock_t *lock)
+{
+ sem_post (lock);
+}
+
+int
+gomp_test_lock_30 (omp_lock_t *lock)
+{
+ return sem_trywait (lock) == 0;
+}
+
+void
+gomp_init_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ sem_init (&lock->lock, 0, 1);
+ lock->count = 0;
+ lock->owner = NULL;
+}
+
+void
+gomp_destroy_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ sem_destroy (&lock->lock);
+}
+
+void
+gomp_set_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ void *me = gomp_icv (true);
+
+ if (lock->owner != me)
+ {
+ while (sem_wait (&lock->lock) != 0)
+ ;
+ lock->owner = me;
+ }
+ lock->count++;
+}
+
+void
+gomp_unset_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ if (--lock->count == 0)
+ {
+ lock->owner = NULL;
+ sem_post (&lock->lock);
+ }
+}
+
+int
+gomp_test_nest_lock_30 (omp_nest_lock_t *lock)
+{
+ void *me = gomp_icv (true);
+
+ if (lock->owner != me)
+ {
+ if (sem_trywait (&lock->lock) != 0)
+ return 0;
+ lock->owner = me;
+ }
+
+ return ++lock->count;
+}
+#endif
+
+#ifdef LIBGOMP_GNU_SYMBOL_VERSIONING
+void
+gomp_init_lock_25 (omp_lock_25_t *lock)
{
pthread_mutex_init (lock, NULL);
}
void
-omp_destroy_lock (omp_lock_t *lock)
+gomp_destroy_lock_25 (omp_lock_25_t *lock)
{
pthread_mutex_destroy (lock);
}
void
-omp_set_lock (omp_lock_t *lock)
+gomp_set_lock_25 (omp_lock_25_t *lock)
{
pthread_mutex_lock (lock);
}
void
-omp_unset_lock (omp_lock_t *lock)
+gomp_unset_lock_25 (omp_lock_25_t *lock)
{
pthread_mutex_unlock (lock);
}
int
-omp_test_lock (omp_lock_t *lock)
+gomp_test_lock_25 (omp_lock_25_t *lock)
{
return pthread_mutex_trylock (lock) == 0;
}
void
-omp_init_nest_lock (omp_nest_lock_t *lock)
+gomp_init_nest_lock_25 (omp_nest_lock_25_t *lock)
{
pthread_mutex_init (&lock->lock, NULL);
lock->owner = (pthread_t) 0;
@@ -73,13 +246,13 @@ omp_init_nest_lock (omp_nest_lock_t *lock)
}
void
-omp_destroy_nest_lock (omp_nest_lock_t *lock)
+gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *lock)
{
pthread_mutex_destroy (&lock->lock);
}
void
-omp_set_nest_lock (omp_nest_lock_t *lock)
+gomp_set_nest_lock_25 (omp_nest_lock_25_t *lock)
{
pthread_t me = pthread_self ();
@@ -93,7 +266,7 @@ omp_set_nest_lock (omp_nest_lock_t *lock)
}
void
-omp_unset_nest_lock (omp_nest_lock_t *lock)
+gomp_unset_nest_lock_25 (omp_nest_lock_25_t *lock)
{
lock->count--;
@@ -105,7 +278,7 @@ omp_unset_nest_lock (omp_nest_lock_t *lock)
}
int
-omp_test_nest_lock (omp_nest_lock_t *lock)
+gomp_test_nest_lock_25 (omp_nest_lock_25_t *lock)
{
pthread_t me = pthread_self ();
@@ -119,6 +292,19 @@ omp_test_nest_lock (omp_nest_lock_t *lock)
return ++lock->count;
}
+omp_lock_symver (omp_init_lock)
+omp_lock_symver (omp_destroy_lock)
+omp_lock_symver (omp_set_lock)
+omp_lock_symver (omp_unset_lock)
+omp_lock_symver (omp_test_lock)
+omp_lock_symver (omp_init_nest_lock)
+omp_lock_symver (omp_destroy_nest_lock)
+omp_lock_symver (omp_set_nest_lock)
+omp_lock_symver (omp_unset_nest_lock)
+omp_lock_symver (omp_test_nest_lock)
+
+#else
+
ialias (omp_init_lock)
ialias (omp_init_nest_lock)
ialias (omp_destroy_lock)
@@ -129,3 +315,5 @@ ialias (omp_unset_lock)
ialias (omp_unset_nest_lock)
ialias (omp_test_lock)
ialias (omp_test_nest_lock)
+
+#endif
diff --git a/libgomp/config/posix95/omp-lock.h b/libgomp/config/posix95/omp-lock.h
index c446aec01e5..b542ba13192 100644
--- a/libgomp/config/posix95/omp-lock.h
+++ b/libgomp/config/posix95/omp-lock.h
@@ -6,12 +6,16 @@
same PTHREADS primitive. */
#include <pthread.h>
+#include <semaphore.h>
+typedef pthread_mutex_t omp_lock_25_t;
+typedef struct { pthread_mutex_t lock; pthread_t owner; int count; } omp_nest_lock_25_t;
+#ifdef HAVE_BROKEN_POSIX_SEMAPHORES
+/* If we don't have working semaphores, we'll make all explicit tasks
+ tied to the creating thread. */
typedef pthread_mutex_t omp_lock_t;
-
-typedef struct
-{
- pthread_mutex_t lock;
- pthread_t owner;
- int count;
-} omp_nest_lock_t;
+typedef struct { pthread_mutex_t lock; int count; void *owner; } omp_nest_lock_t;
+#else
+typedef sem_t omp_lock_t;
+typedef struct { sem_t lock; int count; void *owner; } omp_nest_lock_t;
+#endif