diff options
author | Khem Raj <raj.khem@gmail.com> | 2009-08-06 19:46:45 -0700 |
---|---|---|
committer | Khem Raj <raj.khem@gmail.com> | 2009-08-06 19:46:45 -0700 |
commit | 7ccdfeffc5202da60d7da5b7cb99ea655fe89238 (patch) | |
tree | bde0790112755934890dedd6e015f01dcfaa66f5 /recipes/gcc/gcc-4.4.1/fedora | |
parent | eaf9eb0fbc98ae1a044e3bdc6e6d2bd0a51b9d26 (diff) |
gcc: Remove gcc 4.1.0 recipes in favour of gcc 4.4.1
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Diffstat (limited to 'recipes/gcc/gcc-4.4.1/fedora')
16 files changed, 4438 insertions, 0 deletions
diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-c++-builtin-redecl.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-c++-builtin-redecl.patch new file mode 100644 index 0000000000..77655ad792 --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-c++-builtin-redecl.patch @@ -0,0 +1,102 @@ +2007-10-02 Jakub Jelinek <jakub@redhat.com> + + * decl.c (duplicate_decls): When redeclaring a builtin function, + keep the merged decl builtin whenever types match, even if new + decl defines a function. + + * gcc.dg/builtins-65.c: New test. + * g++.dg/ext/builtin10.C: New test. + +--- gcc/cp/decl.c.jj 2007-10-01 22:11:09.000000000 +0200 ++++ gcc/cp/decl.c 2007-10-02 11:39:46.000000000 +0200 +@@ -1988,23 +1988,21 @@ duplicate_decls (tree newdecl, tree oldd + DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl); + DECL_RESULT (olddecl) = DECL_RESULT (newdecl); + } ++ /* If redeclaring a builtin function, it stays built in. */ ++ if (types_match && DECL_BUILT_IN (olddecl)) ++ { ++ DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); ++ DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); ++ /* If we're keeping the built-in definition, keep the rtl, ++ regardless of declaration matches. */ ++ COPY_DECL_RTL (olddecl, newdecl); ++ } + if (new_defines_function) + /* If defining a function declared with other language + linkage, use the previously declared language linkage. */ + SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl)); + else if (types_match) + { +- /* If redeclaring a builtin function, and not a definition, +- it stays built in. */ +- if (DECL_BUILT_IN (olddecl)) +- { +- DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); +- DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); +- /* If we're keeping the built-in definition, keep the rtl, +- regardless of declaration matches. */ +- COPY_DECL_RTL (olddecl, newdecl); +- } +- + DECL_RESULT (newdecl) = DECL_RESULT (olddecl); + /* Don't clear out the arguments if we're redefining a function. */ + if (DECL_ARGUMENTS (olddecl)) +--- gcc/testsuite/gcc.dg/builtins-65.c.jj 2007-10-02 11:23:51.000000000 +0200 ++++ gcc/testsuite/gcc.dg/builtins-65.c 2007-10-02 11:24:12.000000000 +0200 +@@ -0,0 +1,25 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2" } */ ++ ++typedef __SIZE_TYPE__ size_t; ++extern void __chk_fail (void); ++extern int snprintf (char *, size_t, const char *, ...); ++extern inline __attribute__((gnu_inline, always_inline)) int snprintf (char *a, size_t b, const char *fmt, ...) ++{ ++ if (__builtin_object_size (a, 0) != -1UL && __builtin_object_size (a, 0) < b) ++ __chk_fail (); ++ return __builtin_snprintf (a, b, fmt, __builtin_va_arg_pack ()); ++} ++extern int snprintf (char *, size_t, const char *, ...) __asm ("mysnprintf"); ++ ++char buf[10]; ++ ++int ++main (void) ++{ ++ snprintf (buf, 10, "%d%d\n", 10, 10); ++ return 0; ++} ++ ++/* { dg-final { scan-assembler "mysnprintf" } } */ ++/* { dg-final { scan-assembler-not "__chk_fail" } } */ +--- gcc/testsuite/g++.dg/ext/builtin10.C.jj 2007-10-02 11:19:45.000000000 +0200 ++++ gcc/testsuite/g++.dg/ext/builtin10.C 2007-10-02 11:23:26.000000000 +0200 +@@ -0,0 +1,27 @@ ++// { dg-do compile } ++// { dg-options "-O2" } ++ ++typedef __SIZE_TYPE__ size_t; ++extern "C" { ++extern void __chk_fail (void); ++extern int snprintf (char *, size_t, const char *, ...); ++extern inline __attribute__((gnu_inline, always_inline)) int snprintf (char *a, size_t b, const char *fmt, ...) ++{ ++ if (__builtin_object_size (a, 0) != -1UL && __builtin_object_size (a, 0) < b) ++ __chk_fail (); ++ return __builtin_snprintf (a, b, fmt, __builtin_va_arg_pack ()); ++} ++extern int snprintf (char *, size_t, const char *, ...) __asm ("mysnprintf"); ++} ++ ++char buf[10]; ++ ++int ++main (void) ++{ ++ snprintf (buf, 10, "%d%d\n", 10, 10); ++ return 0; ++} ++ ++// { dg-final { scan-assembler "mysnprintf" } } ++// { dg-final { scan-assembler-not "__chk_fail" } } diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-cpp-pragma.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-cpp-pragma.patch new file mode 100644 index 0000000000..00d37bd7ce --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-cpp-pragma.patch @@ -0,0 +1,284 @@ +2008-02-26 Jakub Jelinek <jakub@redhat.com> + + * c-ppoutput.c (scan_translation_unit): Handle CPP_PRAGMA + and CPP_PRAGMA_EOL. + * c-pragma.c (pragma_ns_name): New typedef. + (registered_pp_pragmas): New variable. + (c_pp_lookup_pragma): New function. + (c_register_pragma_1): If flag_preprocess_only, do nothing + for non-expanded pragmas, for expanded ones push pragma's + namespace and name into registered_pp_pragmas vector. + (c_invoke_pragma_handler): Register OpenMP pragmas even when + flag_preprocess_only, don't register GCC pch_preprocess + pragma if flag_preprocess_only. + * c-opts.c (c_common_init): Call init_pragma even if + flag_preprocess_only. + * c-pragma.c (c_pp_lookup_pragma): New prototype. + * config/darwin.h (DARWIN_REGISTER_TARGET_PRAGMAS): Don't call + cpp_register_pragma if flag_preprocess_only. + + * gcc.dg/gomp/preprocess-1.c: New test. + +--- gcc/c-ppoutput.c.jj 2008-01-26 18:01:16.000000000 +0100 ++++ gcc/c-ppoutput.c 2008-02-26 22:54:57.000000000 +0100 +@@ -1,6 +1,6 @@ + /* Preprocess only, using cpplib. +- Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007 +- Free Software Foundation, Inc. ++ Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, ++ 2008 Free Software Foundation, Inc. + Written by Per Bothner, 1994-95. + + This program is free software; you can redistribute it and/or modify it +@@ -177,7 +177,24 @@ scan_translation_unit (cpp_reader *pfile + avoid_paste = false; + print.source = NULL; + print.prev = token; +- cpp_output_token (token, print.outf); ++ if (token->type == CPP_PRAGMA) ++ { ++ const char *space; ++ const char *name; ++ ++ maybe_print_line (token->src_loc); ++ fputs ("#pragma ", print.outf); ++ c_pp_lookup_pragma (token->val.pragma, &space, &name); ++ if (space) ++ fprintf (print.outf, "%s %s", space, name); ++ else ++ fprintf (print.outf, "%s", name); ++ print.printed = 1; ++ } ++ else if (token->type == CPP_PRAGMA_EOL) ++ maybe_print_line (token->src_loc); ++ else ++ cpp_output_token (token, print.outf); + + if (token->type == CPP_COMMENT) + account_for_newlines (token->val.str.text, token->val.str.len); +--- gcc/c-pragma.c.jj 2008-02-15 18:43:03.000000000 +0100 ++++ gcc/c-pragma.c 2008-02-26 22:59:44.000000000 +0100 +@@ -1,6 +1,6 @@ + /* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack. + Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, +- 2006, 2007 Free Software Foundation, Inc. ++ 2006, 2007, 2008 Free Software Foundation, Inc. + + This file is part of GCC. + +@@ -872,6 +872,61 @@ DEF_VEC_ALLOC_O (pragma_handler, heap); + + static VEC(pragma_handler, heap) *registered_pragmas; + ++typedef struct ++{ ++ const char *space; ++ const char *name; ++} pragma_ns_name; ++ ++DEF_VEC_O (pragma_ns_name); ++DEF_VEC_ALLOC_O (pragma_ns_name, heap); ++ ++static VEC(pragma_ns_name, heap) *registered_pp_pragmas; ++ ++struct omp_pragma_def { const char *name; unsigned int id; }; ++static const struct omp_pragma_def omp_pragmas[] = { ++ { "atomic", PRAGMA_OMP_ATOMIC }, ++ { "barrier", PRAGMA_OMP_BARRIER }, ++ { "critical", PRAGMA_OMP_CRITICAL }, ++ { "flush", PRAGMA_OMP_FLUSH }, ++ { "for", PRAGMA_OMP_FOR }, ++ { "master", PRAGMA_OMP_MASTER }, ++ { "ordered", PRAGMA_OMP_ORDERED }, ++ { "parallel", PRAGMA_OMP_PARALLEL }, ++ { "section", PRAGMA_OMP_SECTION }, ++ { "sections", PRAGMA_OMP_SECTIONS }, ++ { "single", PRAGMA_OMP_SINGLE }, ++ { "threadprivate", PRAGMA_OMP_THREADPRIVATE } ++}; ++ ++void ++c_pp_lookup_pragma (unsigned int id, const char **space, const char **name) ++{ ++ const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas); ++ int i; ++ ++ for (i = 0; i < n_omp_pragmas; ++i) ++ if (omp_pragmas[i].id == id) ++ { ++ *space = "omp"; ++ *name = omp_pragmas[i].name; ++ return; ++ } ++ ++ if (id >= PRAGMA_FIRST_EXTERNAL ++ && (id < PRAGMA_FIRST_EXTERNAL ++ + VEC_length (pragma_ns_name, registered_pp_pragmas))) ++ { ++ *space = VEC_index (pragma_ns_name, registered_pp_pragmas, ++ id - PRAGMA_FIRST_EXTERNAL)->space; ++ *name = VEC_index (pragma_ns_name, registered_pp_pragmas, ++ id - PRAGMA_FIRST_EXTERNAL)->name; ++ return; ++ } ++ ++ gcc_unreachable (); ++} ++ + /* Front-end wrappers for pragma registration to avoid dragging + cpplib.h in almost everywhere. */ + +@@ -881,13 +936,29 @@ c_register_pragma_1 (const char *space, + { + unsigned id; + +- VEC_safe_push (pragma_handler, heap, registered_pragmas, &handler); +- id = VEC_length (pragma_handler, registered_pragmas); +- id += PRAGMA_FIRST_EXTERNAL - 1; +- +- /* The C++ front end allocates 6 bits in cp_token; the C front end +- allocates 7 bits in c_token. At present this is sufficient. */ +- gcc_assert (id < 64); ++ if (flag_preprocess_only) ++ { ++ pragma_ns_name ns_name; ++ ++ if (!allow_expansion) ++ return; ++ ++ ns_name.space = space; ++ ns_name.name = name; ++ VEC_safe_push (pragma_ns_name, heap, registered_pp_pragmas, &ns_name); ++ id = VEC_length (pragma_ns_name, registered_pp_pragmas); ++ id += PRAGMA_FIRST_EXTERNAL - 1; ++ } ++ else ++ { ++ VEC_safe_push (pragma_handler, heap, registered_pragmas, &handler); ++ id = VEC_length (pragma_handler, registered_pragmas); ++ id += PRAGMA_FIRST_EXTERNAL - 1; ++ ++ /* The C++ front end allocates 6 bits in cp_token; the C front end ++ allocates 7 bits in c_token. At present this is sufficient. */ ++ gcc_assert (id < 64); ++ } + + cpp_register_deferred_pragma (parse_in, space, name, id, + allow_expansion, false); +@@ -921,24 +992,8 @@ c_invoke_pragma_handler (unsigned int id + void + init_pragma (void) + { +- if (flag_openmp && !flag_preprocess_only) ++ if (flag_openmp) + { +- struct omp_pragma_def { const char *name; unsigned int id; }; +- static const struct omp_pragma_def omp_pragmas[] = { +- { "atomic", PRAGMA_OMP_ATOMIC }, +- { "barrier", PRAGMA_OMP_BARRIER }, +- { "critical", PRAGMA_OMP_CRITICAL }, +- { "flush", PRAGMA_OMP_FLUSH }, +- { "for", PRAGMA_OMP_FOR }, +- { "master", PRAGMA_OMP_MASTER }, +- { "ordered", PRAGMA_OMP_ORDERED }, +- { "parallel", PRAGMA_OMP_PARALLEL }, +- { "section", PRAGMA_OMP_SECTION }, +- { "sections", PRAGMA_OMP_SECTIONS }, +- { "single", PRAGMA_OMP_SINGLE }, +- { "threadprivate", PRAGMA_OMP_THREADPRIVATE } +- }; +- + const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas); + int i; + +@@ -947,8 +1002,9 @@ init_pragma (void) + omp_pragmas[i].id, true, true); + } + +- cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess", +- PRAGMA_GCC_PCH_PREPROCESS, false, false); ++ if (!flag_preprocess_only) ++ cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess", ++ PRAGMA_GCC_PCH_PREPROCESS, false, false); + + #ifdef HANDLE_PRAGMA_PACK + #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION +--- gcc/c-opts.c.jj 2008-02-26 22:53:23.000000000 +0100 ++++ gcc/c-opts.c 2008-02-26 22:54:57.000000000 +0100 +@@ -1,5 +1,5 @@ + /* C/ObjC/C++ command line option handling. +- Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 ++ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + Free Software Foundation, Inc. + Contributed by Neil Booth. + +@@ -1239,6 +1239,9 @@ c_common_init (void) + if (version_flag) + c_common_print_pch_checksum (stderr); + ++ /* Has to wait until now so that cpplib has its hash table. */ ++ init_pragma (); ++ + if (flag_preprocess_only) + { + finish_options (); +@@ -1246,9 +1249,6 @@ c_common_init (void) + return false; + } + +- /* Has to wait until now so that cpplib has its hash table. */ +- init_pragma (); +- + return true; + } + +--- gcc/c-pragma.h.jj 2008-01-26 18:01:16.000000000 +0100 ++++ gcc/c-pragma.h 2008-02-26 22:54:57.000000000 +0100 +@@ -1,6 +1,6 @@ + /* Pragma related interfaces. + Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, +- 2007 Free Software Foundation, Inc. ++ 2007, 2008 Free Software Foundation, Inc. + + This file is part of GCC. + +@@ -124,4 +124,6 @@ extern enum cpp_ttype pragma_lex (tree * + extern enum cpp_ttype c_lex_with_flags (tree *, location_t *, unsigned char *, + int); + ++extern void c_pp_lookup_pragma (unsigned int, const char **, const char **); ++ + #endif /* GCC_C_PRAGMA_H */ +--- gcc/config/darwin.h.jj 2008-02-11 14:48:12.000000000 +0100 ++++ gcc/config/darwin.h 2008-02-26 22:54:57.000000000 +0100 +@@ -892,8 +892,9 @@ enum machopic_addr_class { + + #define DARWIN_REGISTER_TARGET_PRAGMAS() \ + do { \ +- cpp_register_pragma (parse_in, NULL, "mark", \ +- darwin_pragma_ignore, false); \ ++ if (!flag_preprocess_only) \ ++ cpp_register_pragma (parse_in, NULL, "mark", \ ++ darwin_pragma_ignore, false); \ + c_register_pragma (0, "options", darwin_pragma_options); \ + c_register_pragma (0, "segment", darwin_pragma_ignore); \ + c_register_pragma (0, "unused", darwin_pragma_unused); \ +--- gcc/testsuite/gcc.dg/gomp/preprocess-1.c.jj 2008-02-26 22:54:57.000000000 +0100 ++++ gcc/testsuite/gcc.dg/gomp/preprocess-1.c 2008-02-26 22:54:57.000000000 +0100 +@@ -0,0 +1,16 @@ ++/* { dg-do preprocess } */ ++ ++void foo (void) ++{ ++ int i1, j1, k1; ++#define p parallel ++#define P(x) private (x##1) ++#define S(x) shared (x##1) ++#define F(x) firstprivate (x##1) ++#pragma omp p P(i) \ ++ S(j) \ ++ F(k) ++ ; ++} ++ ++/* { dg-final { scan-file preprocess-1.i "(^|\n)#pragma omp parallel private \\(i1\\) shared \\(j1\\) firstprivate \\(k1\\)($|\n)" } } */ diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-i386-libgomp.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-i386-libgomp.patch new file mode 100644 index 0000000000..2ad3b24d89 --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-i386-libgomp.patch @@ -0,0 +1,61 @@ +Build i386.rpm libgomp and libsupc++.a(guard.o) as i486+, pre-i486 +hardware isn't supported because NPTL doesn't support it anyway. + +--- libgomp/configure.tgt.jj 2008-01-10 20:53:48.000000000 +0100 ++++ libgomp/configure.tgt 2008-03-27 12:44:51.000000000 +0100 +@@ -44,14 +44,14 @@ if test $enable_linux_futex = yes; then + ;; + + # Note that bare i386 is not included here. We need cmpxchg. +- i[456]86-*-linux*) ++ i[3456]86-*-linux*) + config_path="linux/x86 linux posix" + case " ${CC} ${CFLAGS} " in + *" -m64 "*) + ;; + *) + if test -z "$with_arch"; then +- XCFLAGS="${XCFLAGS} -march=i486 -mtune=${target_cpu}" ++ XCFLAGS="${XCFLAGS} -march=i486 -mtune=generic" + fi + esac + ;; +@@ -63,7 +63,7 @@ if test $enable_linux_futex = yes; then + config_path="linux/x86 linux posix" + case " ${CC} ${CFLAGS} " in + *" -m32 "*) +- XCFLAGS="${XCFLAGS} -march=i486 -mtune=i686" ++ XCFLAGS="${XCFLAGS} -march=i486 -mtune=generic" + ;; + esac + ;; +--- libstdc++-v3/libsupc++/guard.cc.jj 2008-03-01 00:58:24.000000000 +0100 ++++ libstdc++-v3/libsupc++/guard.cc 2008-03-27 14:08:44.000000000 +0100 +@@ -35,6 +35,27 @@ + #include <new> + #include <ext/atomicity.h> + #include <ext/concurrence.h> ++#if defined __i386__ && !defined _GLIBCXX_ATOMIC_BUILTINS ++# define _GLIBCXX_ATOMIC_BUILTINS 1 ++# define __sync_val_compare_and_swap(a, b, c) \ ++ ({ \ ++ typedef char sltast[sizeof (*a) == sizeof (int) ? 1 : -1]; \ ++ int sltas; \ ++ __asm __volatile ("lock; cmpxchgl %3, (%1)" \ ++ : "=a" (sltas) \ ++ : "r" (a), "0" (b), "r" (c) : "memory"); \ ++ sltas; \ ++ }) ++# define __sync_lock_test_and_set(a, b) \ ++ ({ \ ++ typedef char sltast[sizeof (*a) == sizeof (int) ? 1 : -1]; \ ++ int sltas; \ ++ __asm __volatile ("xchgl (%1), %0" \ ++ : "=r" (sltas) \ ++ : "r" (a), "0" (b) : "memory"); \ ++ sltas; \ ++ }) ++#endif + #if defined(__GTHREADS) && defined(__GTHREAD_HAS_COND) \ + && defined(_GLIBCXX_ATOMIC_BUILTINS) && defined(_GLIBCXX_HAVE_LINUX_FUTEX) + # include <climits> diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-ia64-libunwind.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-ia64-libunwind.patch new file mode 100644 index 0000000000..8e10979ce8 --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-ia64-libunwind.patch @@ -0,0 +1,538 @@ +2004-11-27 Jakub Jelinek <jakub@redhat.com> + + * config.gcc (ia64*-*-linux*): If native and libelf is installed, + use ia64/t-glibc-no-libunwind instead of the other t-*unwind* + fragments. + * config/ia64/t-glibc-no-libunwind: New file. + * config/ia64/change-symver.c: New file. + * config/ia64/unwind-ia64.c: If USE_SYMVER_GLOBAL and SHARED, + define _Unwind_* to __symverglobal_Unwind_*. + (alias): Undefine. + (symverglobal): Define. Use it on _Unwind_*. + * config/ia64/mkmap-symver-multi.awk: New file. + * config/ia64/libgcc-ia64-no-libunwind.ver: New file. + +--- gcc/config.gcc.jj 2004-10-04 08:55:44.000000000 -0400 ++++ gcc/config.gcc 2004-11-13 05:23:50.000000000 -0500 +@@ -1185,9 +1185,16 @@ ia64*-*-freebsd*) + ;; + ia64*-*-linux*) + tm_file="${tm_file} dbxelf.h elfos.h svr4.h linux.h ia64/sysv4.h ia64/linux.h" +- tmake_file="${tmake_file} ia64/t-ia64 t-libunwind ia64/t-glibc" +- if test x$with_system_libunwind != xyes ; then +- tmake_file="${tmake_file} t-libunwind-elf ia64/t-glibc-libunwind" ++ tmake_file="${tmake_file} ia64/t-ia64" ++ if test x${target} = x${host} && test x${target} = x${build} \ ++ && grep gelf_getverdef /usr/include/gelf.h > /dev/null 2>&1 \ ++ && test -f /usr/lib/libelf.so; then ++ tmake_file="${tmake_file} ia64/t-glibc-no-libunwind" ++ else ++ tmake_file="${tmake_file} t-libunwind ia64/t-glibc" ++ if test x$with_system_libunwind != xyes ; then ++ tmake_file="${tmake_file} t-libunwind-elf ia64/t-glibc-libunwind" ++ fi + fi + target_cpu_default="MASK_GNU_AS|MASK_GNU_LD" + extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o" +--- gcc/config/ia64/t-glibc-no-libunwind.jj 2004-02-18 10:27:36.000000000 -0500 ++++ gcc/config/ia64/t-glibc-no-libunwind 2004-11-15 09:56:33.000000000 -0500 +@@ -0,0 +1,30 @@ ++# Don't use system libunwind library on IA-64 GLIBC based system, ++# but make _Unwind_* symbols unversioned, so that created programs ++# are usable even when libgcc_s uses libunwind. ++LIB2ADDEH += $(srcdir)/config/ia64/fde-glibc.c ++SHLIB_MAPFILES += $(srcdir)/config/ia64/libgcc-ia64-no-libunwind.ver ++SHLIB_MKMAP = $(srcdir)/config/ia64/mkmap-symver-multi.awk ++ ++SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \ ++ -Wl,--soname=$(SHLIB_SONAME) \ ++ -Wl,--version-script=$(SHLIB_MAP) \ ++ -o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ $(SHLIB_OBJS) -lc && \ ++ rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \ ++ if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \ ++ mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \ ++ $(SHLIB_DIR)/$(SHLIB_SONAME).backup; \ ++ else true; fi && \ ++ gcc -O2 -o $(SHLIB_DIR)/$(SHLIB_SONAME).tweak \ ++ $$(gcc_srcdir)/config/ia64/change-symver.c -lelf && \ ++ $(SHLIB_DIR)/$(SHLIB_SONAME).tweak $(SHLIB_DIR)/$(SHLIB_SONAME).tmp \ ++ GCC_3.4.2 _GLOBAL_ \ ++ _Unwind_GetGR _Unwind_RaiseException _Unwind_GetRegionStart _Unwind_SetIP \ ++ _Unwind_GetIP _Unwind_GetLanguageSpecificData _Unwind_Resume \ ++ _Unwind_DeleteException _Unwind_SetGR _Unwind_ForcedUnwind \ ++ _Unwind_Backtrace _Unwind_FindEnclosingFunction _Unwind_GetCFA \ ++ _Unwind_Resume_or_Rethrow _Unwind_GetBSP && \ ++ rm -f $(SHLIB_DIR)/$(SHLIB_SONAME).tweak && \ ++ mv $(SHLIB_DIR)/$(SHLIB_SONAME).tmp $(SHLIB_DIR)/$(SHLIB_SONAME) && \ ++ $(LN_S) $(SHLIB_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK) ++ ++TARGET_LIBGCC2_CFLAGS += -DUSE_SYMVER_GLOBAL +--- gcc/config/ia64/change-symver.c.jj 2004-02-18 10:27:36.000000000 -0500 ++++ gcc/config/ia64/change-symver.c 2004-11-13 05:23:50.000000000 -0500 +@@ -0,0 +1,211 @@ ++#define _GNU_SOURCE 1 ++#define _FILE_OFFSET_BITS 64 ++#include <endian.h> ++#include <errno.h> ++#include <error.h> ++#include <fcntl.h> ++#include <fnmatch.h> ++#include <gelf.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++ ++int ++compute_veridx (const char *name, Elf *elf, Elf_Data *verd, GElf_Shdr *verd_shdr) ++{ ++ if (strcmp (name, "_GLOBAL_") == 0) ++ return 1; ++ ++ int cnt; ++ size_t offset = 0; ++ for (cnt = verd_shdr->sh_info; --cnt >= 0; ) ++ { ++ GElf_Verdef defmem; ++ GElf_Verdef *def; ++ GElf_Verdaux auxmem; ++ GElf_Verdaux *aux; ++ unsigned int auxoffset; ++ ++ /* Get the data at the next offset. */ ++ def = gelf_getverdef (verd, offset, &defmem); ++ if (def == NULL) ++ break; ++ ++ auxoffset = offset + def->vd_aux; ++ aux = gelf_getverdaux (verd, auxoffset, &auxmem); ++ if (aux == NULL) ++ break; ++ ++ if (strcmp (name, elf_strptr (elf, verd_shdr->sh_link, ++ aux->vda_name)) == 0) ++ return def->vd_ndx; ++ ++ /* Find the next offset. */ ++ offset += def->vd_next; ++ } ++ ++ return -1; ++} ++ ++int ++main (int argc, char **argv) ++{ ++ if (argc < 4) ++ error (1, 0, "Usage: change_symver library from_symver to_symver symbol...\nExample: change_symver libfoo.so FOO_1.0 *global* bar baz"); ++ ++ const char *fname = argv[1]; ++ ++ /* Open the file. */ ++ int fd; ++ fd = open (fname, O_RDWR); ++ if (fd == -1) ++ error (1, errno, fname); ++ ++ elf_version (EV_CURRENT); ++ ++ /* Now get the ELF descriptor. */ ++ Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); ++ if (elf == NULL || elf_kind (elf) != ELF_K_ELF) ++ error (1, 0, "Couldn't open %s: %s", fname, elf_errmsg (-1)); ++ ++ size_t shstrndx; ++ /* Get the section header string table index. */ ++ if (elf_getshstrndx (elf, &shstrndx) < 0) ++ error (1, 0, "cannot get shstrndx from %s", fname); ++ ++ GElf_Ehdr ehdr_mem; ++ GElf_Ehdr *ehdr; ++ ++ /* We need the ELF header in a few places. */ ++ ehdr = gelf_getehdr (elf, &ehdr_mem); ++ if (ehdr == NULL) ++ error (1, 0, "couldn't get ELF headers %s: %s", fname, elf_errmsg (-1)); ++ ++ Elf_Scn *scn = NULL; ++ GElf_Shdr shdr_mem, verd_shdr, ver_shdr, dynsym_shdr; ++ Elf_Data *ver = NULL, *verd = NULL, *dynsym = NULL; ++ ++ while ((scn = elf_nextscn (elf, scn)) != NULL) ++ { ++ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); ++ ++ if (shdr == NULL) ++ error (1, 0, "couldn't get shdr from %s", fname); ++ ++ if ((shdr->sh_flags & SHF_ALLOC) != 0) ++ { ++ const char *name = elf_strptr (elf, shstrndx, shdr->sh_name); ++ Elf_Data **p; ++ ++ if (strcmp (name, ".gnu.version") == 0) ++ { ++ p = &ver; ++ ver_shdr = *shdr; ++ } ++ else if (strcmp (name, ".gnu.version_d") == 0) ++ { ++ p = &verd; ++ verd_shdr = *shdr; ++ } ++ else if (strcmp (name, ".dynsym") == 0) ++ { ++ p = &dynsym; ++ dynsym_shdr = *shdr; ++ } ++ else ++ continue; ++ ++ if (*p != NULL) ++ error (1, 0, "Two %s sections in %s", name, fname); ++ *p = elf_getdata (scn, NULL); ++ if (*p == NULL || elf_getdata (scn, *p) != NULL) ++ error (1, 0, "No data or non-contiguous data in %s section in %s", ++ name, fname); ++ } ++ } ++ ++ if (ver == NULL || verd == NULL || dynsym == NULL) ++ error (1, 0, "Couldn't find one of the needed sections in %s", fname); ++ ++ int from_idx = compute_veridx (argv[2], elf, verd, &verd_shdr); ++ if (from_idx == -1) ++ error (1, 0, "Could not find symbol version %s in %s", argv[2], fname); ++ ++ int to_idx = compute_veridx (argv[3], elf, verd, &verd_shdr); ++ if (to_idx == -1) ++ error (1, 0, "Could not find symbol version %s in %s", argv[3], fname); ++ ++ if (dynsym_shdr.sh_entsize != gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version) ++ || dynsym_shdr.sh_size % dynsym_shdr.sh_entsize ++ || ver_shdr.sh_entsize != 2 ++ || (ver_shdr.sh_size & 1) ++ || dynsym_shdr.sh_size / dynsym_shdr.sh_entsize != ver_shdr.sh_size / 2) ++ error (1, 0, "Unexpected sh_size or sh_entsize in %s", fname); ++ ++ size_t nentries = ver_shdr.sh_size / 2; ++ size_t cnt; ++ GElf_Versym array[nentries]; ++ for (cnt = 0; cnt < nentries; ++cnt) ++ { ++ GElf_Versym vsymmem; ++ GElf_Versym *vsym; ++ ++ vsym = gelf_getversym (ver, cnt, &vsymmem); ++ if (vsym == NULL) ++ error (1, 0, "gelt_getversym failed in %s: %s", fname, elf_errmsg (-1)); ++ ++ array[cnt] = *vsym; ++ if (*vsym != from_idx) ++ continue; ++ ++ GElf_Sym sym_mem; ++ GElf_Sym *sym; ++ sym = gelf_getsym (dynsym, cnt, &sym_mem); ++ if (sym == NULL) ++ error (1, 0, "gelt_getsym failed in %s: %s", fname, elf_errmsg (-1)); ++ ++ const char *name = elf_strptr (elf, dynsym_shdr.sh_link, sym->st_name); ++ ++ int argn; ++ for (argn = 4; argn < argc; ++argn) ++ if (fnmatch (argv[argn], name, 0) == 0) ++ { ++ array[cnt] = to_idx; ++ break; ++ } ++ } ++ ++ if (sizeof (array[0]) != 2) ++ abort (); ++ ++#if __BYTE_ORDER == __LITTLE_ENDIAN ++ if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) ++ ; ++ else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) ++#elif __BYTE_ORDER == __BIG_ENDIAN ++ if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) ++ ; ++ else if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) ++#else ++# error Unsupported endianity ++#endif ++ { ++ for (cnt = 0; cnt < nentries; ++cnt) ++ array[cnt] = ((array[cnt] & 0xff) << 8) | ((array[cnt] & 0xff00) >> 8); ++ } ++ else ++ error (1, 0, "Unknown EI_DATA %d in %s", ehdr->e_ident[EI_DATA], fname); ++ ++ if (elf_end (elf) != 0) ++ error (1, 0, "couldn't close %s: %s", fname, elf_errmsg (-1)); ++ ++ if (lseek (fd, ver_shdr.sh_offset, SEEK_SET) != (off_t) ver_shdr.sh_offset) ++ error (1, 0, "failed to seek to %zd in %s", (size_t) ver_shdr.sh_offset, ++ fname); ++ ++ if (write (fd, array, 2 * nentries) != (ssize_t) (2 * nentries)) ++ error (1, 0, "failed to write .gnu.version section into %s", fname); ++ ++ close (fd); ++ return 0; ++} +--- gcc/config/ia64/unwind-ia64.c.jj 2004-10-04 08:55:57.000000000 -0400 ++++ gcc/config/ia64/unwind-ia64.c 2004-11-15 09:07:45.000000000 -0500 +@@ -51,6 +51,51 @@ + #define UNW_FLAG_UHANDLER(x) ((x) & 0x0000000200000000L) + #define UNW_LENGTH(x) ((x) & 0x00000000ffffffffL) + ++#if defined (USE_SYMVER_GLOBAL) && defined (SHARED) ++extern _Unwind_Reason_Code __symverglobal_Unwind_Backtrace ++ (_Unwind_Trace_Fn, void *); ++extern void __symverglobal_Unwind_DeleteException ++ (struct _Unwind_Exception *); ++extern void * __symverglobal_Unwind_FindEnclosingFunction (void *); ++extern _Unwind_Reason_Code __symverglobal_Unwind_ForcedUnwind ++ (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); ++extern _Unwind_Word __symverglobal_Unwind_GetCFA ++ (struct _Unwind_Context *); ++extern _Unwind_Word __symverglobal_Unwind_GetBSP ++ (struct _Unwind_Context *); ++extern _Unwind_Word __symverglobal_Unwind_GetGR ++ (struct _Unwind_Context *, int ); ++extern _Unwind_Ptr __symverglobal_Unwind_GetIP (struct _Unwind_Context *); ++extern void *__symverglobal_Unwind_GetLanguageSpecificData ++ (struct _Unwind_Context *); ++extern _Unwind_Ptr __symverglobal_Unwind_GetRegionStart ++ (struct _Unwind_Context *); ++extern _Unwind_Reason_Code __symverglobal_Unwind_RaiseException ++ (struct _Unwind_Exception *); ++extern void __symverglobal_Unwind_Resume (struct _Unwind_Exception *); ++extern _Unwind_Reason_Code __symverglobal_Unwind_Resume_or_Rethrow ++ (struct _Unwind_Exception *); ++extern void __symverglobal_Unwind_SetGR ++ (struct _Unwind_Context *, int, _Unwind_Word); ++extern void __symverglobal_Unwind_SetIP ++ (struct _Unwind_Context *, _Unwind_Ptr); ++#define _Unwind_Backtrace __symverglobal_Unwind_Backtrace ++#define _Unwind_DeleteException __symverglobal_Unwind_DeleteException ++#define _Unwind_FindEnclosingFunction __symverglobal_Unwind_FindEnclosingFunction ++#define _Unwind_ForcedUnwind __symverglobal_Unwind_ForcedUnwind ++#define _Unwind_GetBSP __symverglobal_Unwind_GetBSP ++#define _Unwind_GetCFA __symverglobal_Unwind_GetCFA ++#define _Unwind_GetGR __symverglobal_Unwind_GetGR ++#define _Unwind_GetIP __symverglobal_Unwind_GetIP ++#define _Unwind_GetLanguageSpecificData __symverglobal_Unwind_GetLanguageSpecificData ++#define _Unwind_GetRegionStart __symverglobal_Unwind_GetRegionStart ++#define _Unwind_RaiseException __symverglobal_Unwind_RaiseException ++#define _Unwind_Resume __symverglobal_Unwind_Resume ++#define _Unwind_Resume_or_Rethrow __symverglobal_Unwind_Resume_or_Rethrow ++#define _Unwind_SetGR __symverglobal_Unwind_SetGR ++#define _Unwind_SetIP __symverglobal_Unwind_SetIP ++#endif ++ + enum unw_application_register + { + UNW_AR_BSP, +@@ -2402,4 +2447,44 @@ alias (_Unwind_SetGR); + alias (_Unwind_SetIP); + #endif + ++#if defined (USE_SYMVER_GLOBAL) && defined (SHARED) ++#undef alias ++#define symverglobal(name, version) \ ++__typeof (__symverglobal##name) __symverlocal##name \ ++ __attribute__ ((alias ("__symverglobal" #name))); \ ++__asm__ (".symver __symverglobal" #name"," #name "@@GCC_3.4.2");\ ++__asm__ (".symver __symverlocal" #name"," #name "@" #version) ++ ++#undef _Unwind_Backtrace ++#undef _Unwind_DeleteException ++#undef _Unwind_FindEnclosingFunction ++#undef _Unwind_ForcedUnwind ++#undef _Unwind_GetBSP ++#undef _Unwind_GetCFA ++#undef _Unwind_GetGR ++#undef _Unwind_GetIP ++#undef _Unwind_GetLanguageSpecificData ++#undef _Unwind_GetRegionStart ++#undef _Unwind_RaiseException ++#undef _Unwind_Resume ++#undef _Unwind_Resume_or_Rethrow ++#undef _Unwind_SetGR ++#undef _Unwind_SetIP ++symverglobal (_Unwind_Backtrace, GCC_3.3); ++symverglobal (_Unwind_DeleteException, GCC_3.0); ++symverglobal (_Unwind_FindEnclosingFunction, GCC_3.3); ++symverglobal (_Unwind_ForcedUnwind, GCC_3.0); ++symverglobal (_Unwind_GetBSP, GCC_3.3.2); ++symverglobal (_Unwind_GetCFA, GCC_3.3); ++symverglobal (_Unwind_GetGR, GCC_3.0); ++symverglobal (_Unwind_GetIP, GCC_3.0); ++symverglobal (_Unwind_GetLanguageSpecificData, GCC_3.0); ++symverglobal (_Unwind_GetRegionStart, GCC_3.0); ++symverglobal (_Unwind_RaiseException, GCC_3.0); ++symverglobal (_Unwind_Resume, GCC_3.0); ++symverglobal (_Unwind_Resume_or_Rethrow, GCC_3.3); ++symverglobal (_Unwind_SetGR, GCC_3.0); ++symverglobal (_Unwind_SetIP, GCC_3.0); ++#endif ++ + #endif +--- gcc/config/ia64/mkmap-symver-multi.awk.jj 2004-02-18 10:27:36.000000000 -0500 ++++ gcc/config/ia64/mkmap-symver-multi.awk 2004-11-15 09:46:50.000000000 -0500 +@@ -0,0 +1,133 @@ ++# Generate an ELF symbol version map a-la Solaris and GNU ld. ++# Contributed by Richard Henderson <rth@cygnus.com> ++# ++# This file is part of GCC. ++# ++# GCC is free software; you can redistribute it and/or modify it under ++# the terms of the GNU General Public License as published by the Free ++# Software Foundation; either version 2, or (at your option) any later ++# version. ++# ++# GCC 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 General Public ++# License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with GCC; see the file COPYING. If not, write to the Free ++# Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA ++# 02110-1301, USA. ++ ++BEGIN { ++ state = "nm"; ++ sawsymbol = 0; ++} ++ ++# Remove comment and blank lines. ++/^ *#/ || /^ *$/ { ++ next; ++} ++ ++# We begin with nm input. Collect the set of symbols that are present ++# so that we can not emit them into the final version script -- Solaris ++# complains at us if we do. ++ ++state == "nm" && /^%%/ { ++ state = "ver"; ++ next; ++} ++ ++state == "nm" && ($1 == "U" || $2 == "U") { ++ next; ++} ++ ++state == "nm" && NF == 3 { ++ if ($3 ~ /^[^@]*@GCC_[0-9.]*$/) { ++ def[$3] = 1 ++ tl=$3 ++ sub(/^.*@/,"",tl) ++ ver[$3] = tl ++ } else { ++ sub(/@@?GCC_[0-9.]*$/,"",$3) ++ def[$3] = 1; ++ } ++ sawsymbol = 1; ++ next; ++} ++ ++state == "nm" { ++ next; ++} ++ ++# Now we process a simplified variant of the Solaris symbol version ++# script. We have one symbol per line, no semicolons, simple markers ++# for beginning and ending each section, and %inherit markers for ++# describing version inheritence. A symbol may appear in more than ++# one symbol version, and the last seen takes effect. ++ ++NF == 3 && $1 == "%inherit" { ++ inherit[$2] = $3; ++ next; ++} ++ ++NF == 2 && $2 == "{" { ++ libs[$1] = 1; ++ thislib = $1; ++ next; ++} ++ ++$1 == "}" { ++ thislib = ""; ++ next; ++} ++ ++{ ++ ver[$1] = thislib; ++ next; ++} ++ ++END { ++ if (!sawsymbol) ++ { ++ print "No symbols seen -- broken or mis-installed nm?" | "cat 1>&2"; ++ exit 1; ++ } ++ for (l in libs) ++ output(l); ++} ++ ++function output(lib) { ++ if (done[lib]) ++ return; ++ done[lib] = 1; ++ if (inherit[lib]) ++ output(inherit[lib]); ++ ++ empty=1 ++ for (sym in ver) ++ if ((ver[sym] == lib) && (sym in def)) ++ { ++ if (empty) ++ { ++ printf("%s {\n", lib); ++ printf(" global:\n"); ++ empty = 0; ++ } ++ symp = sym; ++ sub(/@GCC_[0-9.]*$/,"",symp); ++ printf("\t%s;\n", symp); ++ if (dotsyms) ++ printf("\t.%s;\n", symp); ++ } ++ ++ if (empty) ++ { ++ for (l in libs) ++ if (inherit[l] == lib) ++ inherit[l] = inherit[lib]; ++ } ++ else if (inherit[lib]) ++ printf("} %s;\n", inherit[lib]); ++ else ++ printf ("\n local:\n\t*;\n};\n"); ++} +--- gcc/config/ia64/libgcc-ia64-no-libunwind.ver.jj 2004-02-18 10:27:36.000000000 -0500 ++++ gcc/config/ia64/libgcc-ia64-no-libunwind.ver 2004-11-15 09:19:56.000000000 -0500 +@@ -0,0 +1,17 @@ ++GCC_3.4.2 { ++ _Unwind_GetGR ++ _Unwind_RaiseException ++ _Unwind_GetRegionStart ++ _Unwind_SetIP ++ _Unwind_GetIP ++ _Unwind_GetLanguageSpecificData ++ _Unwind_Resume ++ _Unwind_DeleteException ++ _Unwind_SetGR ++ _Unwind_ForcedUnwind ++ _Unwind_Backtrace ++ _Unwind_FindEnclosingFunction ++ _Unwind_GetCFA ++ _Unwind_Resume_or_Rethrow ++ _Unwind_GetBSP ++} diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-java-debug-iface-type.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-java-debug-iface-type.patch new file mode 100644 index 0000000000..63a1b50a76 --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-java-debug-iface-type.patch @@ -0,0 +1,17 @@ +2008-01-25 Jakub Jelinek <jakub@redhat.com> + + * lang.c (java_classify_record): Revert 2007-12-20 change. + +--- gcc/java/lang.c 2007-12-27 09:09:49.000000000 +0100 ++++ gcc/java/lang.c 2008-01-25 17:43:57.000000000 +0100 +@@ -965,9 +965,7 @@ java_classify_record (tree type) + if (! CLASS_P (type)) + return RECORD_IS_STRUCT; + +- /* ??? GDB does not support DW_TAG_interface_type as of December, +- 2007. Re-enable this at a later time. */ +- if (0 && CLASS_INTERFACE (TYPE_NAME (type))) ++ if (CLASS_INTERFACE (TYPE_NAME (type))) + return RECORD_IS_INTERFACE; + + return RECORD_IS_CLASS; diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-java-nomulti.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-java-nomulti.patch new file mode 100644 index 0000000000..f07ead8f2b --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-java-nomulti.patch @@ -0,0 +1,44 @@ +--- libjava/configure.ac.jj 2007-12-07 17:55:50.000000000 +0100 ++++ libjava/configure.ac 2007-12-07 18:36:56.000000000 +0100 +@@ -82,6 +82,13 @@ AC_ARG_ENABLE(java-maintainer-mode, + [allow rebuilding of .class and .h files])) + AM_CONDITIONAL(JAVA_MAINTAINER_MODE, test "$enable_java_maintainer_mode" = yes) + ++AC_ARG_ENABLE(libjava-multilib, ++ AS_HELP_STRING([--enable-libjava-multilib], [build libjava as multilib])) ++if test "$enable_libjava_multilib" = no; then ++ multilib=no ++ ac_configure_args="$ac_configure_args --disable-multilib" ++fi ++ + # It may not be safe to run linking tests in AC_PROG_CC/AC_PROG_CXX. + GCC_NO_EXECUTABLES + +--- libjava/configure.jj 2007-12-07 17:55:50.000000000 +0100 ++++ libjava/configure 2007-12-07 18:39:58.000000000 +0100 +@@ -1018,6 +1018,8 @@ Optional Features: + --enable-gconf-peer compile GConf native peers for util.preferences + --enable-java-maintainer-mode + allow rebuilding of .class and .h files ++ --enable-libjava-multilib ++ build libjava as multilib + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-maintainer-mode enable make rules and dependencies not useful +@@ -1848,6 +1850,16 @@ else + fi + + ++# Check whether --enable-libjava-multilib was given. ++if test "${enable_libjava_multilib+set}" = set; then ++ enableval=$enable_libjava_multilib; ++fi ++ ++if test "$enable_libjava_multilib" = no; then ++ multilib=no ++ ac_configure_args="$ac_configure_args --disable-multilib" ++fi ++ + # It may not be safe to run linking tests in AC_PROG_CC/AC_PROG_CXX. + + diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-libgomp-speedup.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-libgomp-speedup.patch new file mode 100644 index 0000000000..da85e556ec --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-libgomp-speedup.patch @@ -0,0 +1,2797 @@ +2008-03-28 Jakub Jelinek <jakub@redhat.com> + + * config/linux/sparc/futex.h (atomic_write_barrier): Fix membar + argument. + +2008-03-27 Jakub Jelinek <jakub@redhat.com> + + * libgomp.h (struct gomp_team_state): Remove single_count field + ifndef HAVE_SYNC_BUILTINS. + (struct gomp_team): Likewise. Add work_share_list_free_lock + ifndef HAVE_SYNC_BUILTINS. + * team.c (gomp_new_team): If HAVE_SYNC_BUILTINS is not defined, + don't initialize single_count, but instead initialize + work_share_list_free_lock. + (free_team): Destroy work_share_list_free_lock ifndef + HAVE_SYNC_BUILTINS. + (gomp_team_start): Don't initialize ts.single_count ifndef + HAVE_SYNC_BUILTINS. + * work.c (alloc_work_share, free_work_share): Use + work_share_list_free_lock instead of atomic chaining ifndef + HAVE_SYNC_BUILTINS. + +2008-03-26 Jakub Jelinek <jakub@redhat.com> + + * loop.c (gomp_loop_init): Fix GFS_DYNAMIC ws->mode setting. + * testsuite/libgomp.c/loop-4.c: New test. + + * libgomp.h (struct gomp_team_state): Add single_count field. + (struct gomp_team): Likewise. + * team.c (gomp_new_team): Clear single_count. + (gomp_team_start): Likewise. + * single.c (GOMP_single_start): Rewritten if HAVE_SYNC_BUILTINS. + +2008-03-25 Jakub Jelinek <jakub@redhat.com> + + * team.c (gomp_thread_start): Don't clear ts.static_trip here. + * loop.c (gomp_loop_static_start, gomp_loop_dynamic_start): Clear + ts.static_trip here. + * work.c (gomp_work_share_start): Don't clear ts.static_trip here. + +2008-03-21 Jakub Jelinek <jakub@redhat.com> + + * libgomp.h: Include ptrlock.h. + (struct gomp_work_share): 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. + (struct gomp_team_state): Add last_work_share field, remove + work_share_generation. + (struct gomp_team): 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. + (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. + * team.c (gomp_thread_start): Clear ts.last_work_share, don't clear + ts.work_share_generation. + (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_start): 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. + (gomp_team_end): Call gomp_fini_work_share. + * work.c (gomp_new_work_share): Removed. + (alloc_work_share, gomp_init_work_share, gomp_fini_work_share): New + functions. + (free_work_share): 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. + (gomp_work_share_start, gomp_work_share_end, + gomp_work_share_end_nowait): Rewritten. + * 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. + * loop.c (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. + * single.c (GOMP_single_start, GOMP_single_copy_start): Call + gomp_work_share_init_done if gomp_work_share_start returned true. + Don't unlock ws->lock. + * parallel.c (GOMP_parallel_start): Call gomp_new_team and pass that + as last argument to gomp_team_start. + * config/linux/ptrlock.c: New file. + * config/linux/ptrlock.h: New file. + * config/posix/ptrlock.c: New file. + * config/posix/ptrlock.h: New file. + * Makefile.am (libgomp_la_SOURCES): Add ptrlock.c. + * Makefile.in: Regenerated. + * testsuite/Makefile.in: Regenerated. + +2008-03-19 Jakub Jelinek <jakub@redhat.com> + + * libgomp.h (gomp_active_wait_policy): Remove decl. + (gomp_throttled_spin_count_var, gomp_available_cpus, + gomp_managed_threads): New extern decls. + * team.c (gomp_team_start, gomp_team_end): If number of threads + changed, adjust atomically gomp_managed_threads. + * env.c (gomp_active_wait_policy, gomp_block_time_var): Remove. + (gomp_throttled_spin_count_var, gomp_available_cpus, + gomp_managed_threads): New variables. + (parse_millis): Removed. + (parse_spincount): New function. + (parse_wait_policy): Return -1/0/1 instead of setting + gomp_active_wait_policy. + (initialize_env): Call gomp_init_num_threads unconditionally. + Initialize gomp_available_cpus. Call parse_spincount instead + of parse_millis, initialize gomp_{,throttled_}spin_count_var + depending on presence and value of OMP_WAIT_POLICY and + GOMP_SPINCOUNT env vars. + * config/linux/wait.h (do_wait): Use gomp_throttled_spin_count_var + instead of gomp_spin_count_var if gomp_managed_threads > + gomp_available_cpus. + + * config/linux/wait.h: Include errno.h. + (FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Define. + (gomp_futex_wake, gomp_futex_wait): New extern decls. + * config/linux/mutex.c (gomp_futex_wake, gomp_futex_wait): New + variables. + * 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. + * 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. + * 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. + * 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. + * 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. + * 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. + +2008-03-18 Jakub Jelinek <jakub@redhat.com> + + * libgomp.h (struct gomp_work_share): Add mode field. Put lock and + next into a different cache line from most of the write-once fields. + * loop.c: Include limits.h. + (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. + * 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. + * work.c: Include stddef.h. + (gomp_new_work_share): Use offsetof rather than sizeof. + +2008-03-17 Jakub Jelinek <jakub@redhat.com> + + * libgomp.h (struct gomp_team): Change ordered_release field + into gomp_sem_t ** from flexible array member. Add implicit_task + and initial_work_shares fields. + (gomp_new_task): Removed. + (gomp_init_task): New prototype. + * team.c (new_team): Allocate implicit_task for each thread + and initial work_shares together with gomp_team allocation. + (free_team): Only free work_shares if it is not init_work_shares. + (gomp_team_start): Use gomp_init_task instead of gomp_new_task, + set thr->task to the corresponding implicit_task array entry. + * task.c (gomp_new_task): Removed. + (gomp_init_task): New function. + (gomp_end_task): Don't free the task. + (GOMP_task): Allocate struct gomp_task on the stack, call + gomp_init_task rather than gomp_new_task. + * work.c (gomp_work_share_start): If work_shares == + init_work_shares, gomp_malloc + memcpy rather than gomp_realloc. + +2008-03-15 Jakub Jelinek <jakub@redhat.com> + Ulrich Drepper <drepper@redhat.com> + + * config/linux/bar.h (gomp_barrier_state_t): Rewritten. + (gomp_barrier_state_t): Change to unsigned int. + (gomp_barrier_init, gomp_barrier_reinit, gomp_barrier_destroy, + gomp_barrier_wait_start, gomp_barrier_last_thread): Rewritten. + (gomp_barrier_wait_last): Prototype rather than inline. + * config/linux/bar.c (gomp_barrier_wait_end): Rewritten. + (gomp_barrier_wait_last): New function. + +2008-03-15 Jakub Jelinek <jakub@redhat.com> + + * team.c (gomp_thread_start): Use gomp_barrier_wait_last instead + of gomp_barrier_wait. + * env.c (gomp_block_time_var, gomp_spin_count_var): New variables. + (parse_millis): New function. + (initialize_env): Handle GOMP_BLOCKTIME env var. + * libgomp.h (struct gomp_team): Move close to the end of the struct. + (gomp_spin_count_var): New extern var decl. + * work.c (gomp_work_share_end): Use gomp_barrier_state_t bstate + var instead of bool last, call gomp_barrier_last_thread to check + for last thread, pass bstate to gomp_barrier_wait_end. + * config/linux/wait.h: New file. + * config/linux/mutex.c: Include wait.h instead of libgomp.h and + futex.h. + (gomp_mutex_lock_slow): Call do_wait instead of futex_wait. + * config/linux/bar.c: Include wait.h instead of libgomp.h and + futex.h. + (gomp_barrier_wait_end): Change second argument to + gomp_barrier_state_t. Call do_wait instead of futex_wait. + * 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/lock.c: Include wait.h instead of libgomp.h and + futex.h. + (gomp_set_nest_lock_25): Call do_wait instead of futex_wait. + * config/linux/affinity.c: Assume HAVE_SYNC_BUILTINS. + * config/linux/bar.h (gomp_barrier_state_t): New typedef. + (gomp_barrier_wait_end): Change second argument to + gomp_barrier_state_t. + (gomp_barrier_wait_start): Return gomp_barrier_state_t. + (gomp_barrier_last_thread, gomp_barrier_wait_last): New static + inlines. + * config/linux/powerpc/futex.h (cpu_relax, atomic_write_barrier): New + static inlines. + * config/linux/alpha/futex.h (cpu_relax, atomic_write_barrier): + Likewise. + * config/linux/x86/futex.h (cpu_relax, atomic_write_barrier): + Likewise. + * config/linux/s390/futex.h (cpu_relax, atomic_write_barrier): + Likewise. + * config/linux/ia64/futex.h (cpu_relax, atomic_write_barrier): + Likewise. + * config/linux/sparc/futex.h (cpu_relax, atomic_write_barrier): + Likewise. + * config/posix/bar.c (gomp_barrier_wait_end): Change second argument + to gomp_barrier_state_t. + * config/posix/bar.h (gomp_barrier_state_t): New typedef. + (gomp_barrier_wait_end): Change second argument to + gomp_barrier_state_t. + (gomp_barrier_wait_start): Return gomp_barrier_state_t. + (gomp_barrier_last_thread, gomp_barrier_wait_last): New static + inlines. + +--- libgomp/parallel.c.jj 2007-12-07 14:41:01.000000000 +0100 ++++ libgomp/parallel.c 2008-03-26 15:32:06.000000000 +0100 +@@ -68,7 +68,7 @@ void + GOMP_parallel_start (void (*fn) (void *), void *data, unsigned num_threads) + { + num_threads = gomp_resolve_num_threads (num_threads); +- gomp_team_start (fn, data, num_threads, NULL); ++ gomp_team_start (fn, data, num_threads, gomp_new_team (num_threads)); + } + + void +--- libgomp/sections.c.jj 2007-12-07 14:41:01.000000000 +0100 ++++ libgomp/sections.c 2008-03-26 15:33:06.000000000 +0100 +@@ -59,14 +59,24 @@ GOMP_sections_start (unsigned count) + long s, e, ret; + + if (gomp_work_share_start (false)) +- gomp_sections_init (thr->ts.work_share, count); ++ { ++ gomp_sections_init (thr->ts.work_share, count); ++ gomp_work_share_init_done (); ++ } + ++#ifdef HAVE_SYNC_BUILTINS ++ if (gomp_iter_dynamic_next (&s, &e)) ++ ret = s; ++ else ++ ret = 0; ++#else ++ gomp_mutex_lock (&thr->ts.work_share->lock); + if (gomp_iter_dynamic_next_locked (&s, &e)) + ret = s; + else + ret = 0; +- + gomp_mutex_unlock (&thr->ts.work_share->lock); ++#endif + + return ret; + } +@@ -83,15 +93,23 @@ GOMP_sections_start (unsigned count) + unsigned + GOMP_sections_next (void) + { +- struct gomp_thread *thr = gomp_thread (); + long s, e, ret; + ++#ifdef HAVE_SYNC_BUILTINS ++ if (gomp_iter_dynamic_next (&s, &e)) ++ ret = s; ++ else ++ ret = 0; ++#else ++ struct gomp_thread *thr = gomp_thread (); ++ + gomp_mutex_lock (&thr->ts.work_share->lock); + if (gomp_iter_dynamic_next_locked (&s, &e)) + ret = s; + else + ret = 0; + gomp_mutex_unlock (&thr->ts.work_share->lock); ++#endif + + return ret; + } +@@ -103,15 +121,15 @@ void + GOMP_parallel_sections_start (void (*fn) (void *), void *data, + unsigned num_threads, unsigned count) + { +- struct gomp_work_share *ws; ++ struct gomp_team *team; + + num_threads = gomp_resolve_num_threads (num_threads); + if (gomp_dyn_var && num_threads > count) + num_threads = count; + +- ws = gomp_new_work_share (false, num_threads); +- gomp_sections_init (ws, count); +- gomp_team_start (fn, data, num_threads, ws); ++ team = gomp_new_team (num_threads); ++ gomp_sections_init (&team->work_shares[0], count); ++ gomp_team_start (fn, data, num_threads, team); + } + + /* The GOMP_section_end* routines are called after the thread is told +--- libgomp/env.c.jj 2007-12-07 14:41:01.000000000 +0100 ++++ libgomp/env.c 2008-03-26 16:40:26.000000000 +0100 +@@ -44,6 +44,11 @@ enum gomp_schedule_type gomp_run_sched_v + unsigned long gomp_run_sched_chunk = 1; + unsigned short *gomp_cpu_affinity; + size_t gomp_cpu_affinity_len; ++#ifndef HAVE_SYNC_BUILTINS ++gomp_mutex_t gomp_remaining_threads_lock; ++#endif ++unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1; ++unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var; + + /* Parse the OMP_SCHEDULE environment variable. */ + +@@ -147,6 +152,79 @@ parse_unsigned_long (const char *name, u + return false; + } + ++/* Parse the GOMP_SPINCOUNT environment varible. Return true if one was ++ present and it was successfully parsed. */ ++ ++static bool ++parse_spincount (const char *name, unsigned long long *pvalue) ++{ ++ char *env, *end; ++ unsigned long long value, mult = 1; ++ ++ env = getenv (name); ++ if (env == NULL) ++ return false; ++ ++ while (isspace ((unsigned char) *env)) ++ ++env; ++ if (*env == '\0') ++ goto invalid; ++ ++ if (strncasecmp (env, "infinite", 8) == 0 ++ || strncasecmp (env, "infinity", 8) == 0) ++ { ++ value = ~0ULL; ++ end = env + 8; ++ goto check_tail; ++ } ++ ++ errno = 0; ++ value = strtoull (env, &end, 10); ++ if (errno) ++ goto invalid; ++ ++ while (isspace ((unsigned char) *end)) ++ ++end; ++ if (*end != '\0') ++ { ++ switch (tolower (*end)) ++ { ++ case 'k': ++ mult = 1000LL; ++ break; ++ case 'm': ++ mult = 1000LL * 1000LL; ++ break; ++ case 'g': ++ mult = 1000LL * 1000LL * 1000LL; ++ break; ++ case 't': ++ mult = 1000LL * 1000LL * 1000LL * 1000LL; ++ break; ++ default: ++ goto invalid; ++ } ++ ++end; ++ check_tail: ++ while (isspace ((unsigned char) *end)) ++ ++end; ++ if (*end != '\0') ++ goto invalid; ++ } ++ ++ if (value > ~0ULL / mult) ++ value = ~0ULL; ++ else ++ value *= mult; ++ ++ *pvalue = value; ++ return true; ++ ++ invalid: ++ gomp_error ("Invalid value for environment variable %s", name); ++ return false; ++} ++ + /* Parse a boolean value for environment variable NAME and store the + result in VALUE. */ + +@@ -281,10 +359,25 @@ initialize_env (void) + parse_schedule (); + parse_boolean ("OMP_DYNAMIC", &gomp_dyn_var); + parse_boolean ("OMP_NESTED", &gomp_nest_var); ++ gomp_init_num_threads (); ++ gomp_available_cpus = gomp_nthreads_var; + if (!parse_unsigned_long ("OMP_NUM_THREADS", &gomp_nthreads_var)) +- gomp_init_num_threads (); ++ gomp_nthreads_var = gomp_available_cpus; + if (parse_affinity ()) + gomp_init_affinity (); ++ if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var)) ++ { ++ /* Using a rough estimation of 100000 spins per msec, ++ use 200 msec blocking. ++ Depending on the CPU speed, this can be e.g. 5 times longer ++ or 5 times shorter. */ ++ gomp_spin_count_var = 20000000LL; ++ } ++ /* gomp_throttled_spin_count_var is used when there are more libgomp ++ managed threads than available CPUs. Use very short spinning. */ ++ gomp_throttled_spin_count_var = 100LL; ++ if (gomp_throttled_spin_count_var > gomp_spin_count_var) ++ gomp_throttled_spin_count_var = gomp_spin_count_var; + + /* Not strictly environment related, but ordering constructors is tricky. */ + pthread_attr_init (&gomp_thread_attr); +--- libgomp/libgomp.h.jj 2007-12-07 14:41:01.000000000 +0100 ++++ libgomp/libgomp.h 2008-03-27 12:21:51.000000000 +0100 +@@ -50,6 +50,7 @@ + #include "sem.h" + #include "mutex.h" + #include "bar.h" ++#include "ptrlock.h" + + + /* This structure contains the data to control one work-sharing construct, +@@ -70,6 +71,8 @@ struct gomp_work_share + If this is a SECTIONS construct, this value will always be DYNAMIC. */ + enum gomp_schedule_type sched; + ++ int mode; ++ + /* This is the chunk_size argument to the SCHEDULE clause. */ + long chunk_size; + +@@ -81,17 +84,38 @@ struct gomp_work_share + is always 1. */ + long incr; + +- /* This lock protects the update of the following members. */ +- gomp_mutex_t lock; ++ /* This is a circular queue that details which threads will be allowed ++ into the ordered region and in which order. When a thread allocates ++ iterations on which it is going to work, it also registers itself at ++ the end of the array. When a thread reaches the ordered region, it ++ checks to see if it is the one at the head of the queue. If not, it ++ blocks on its RELEASE semaphore. */ ++ unsigned *ordered_team_ids; + +- union { +- /* This is the next iteration value to be allocated. In the case of +- GFS_STATIC loops, this the iteration start point and never changes. */ +- long next; ++ /* This is the number of threads that have registered themselves in ++ the circular queue ordered_team_ids. */ ++ unsigned ordered_num_used; + +- /* This is the returned data structure for SINGLE COPYPRIVATE. */ +- void *copyprivate; +- }; ++ /* This is the team_id of the currently acknowledged owner of the ordered ++ section, or -1u if the ordered section has not been acknowledged by ++ any thread. This is distinguished from the thread that is *allowed* ++ to take the section next. */ ++ unsigned ordered_owner; ++ ++ /* This is the index into the circular queue ordered_team_ids of the ++ current thread that's allowed into the ordered reason. */ ++ unsigned ordered_cur; ++ ++ /* This is a chain of allocated gomp_work_share blocks, valid only ++ in the first gomp_work_share struct in the block. */ ++ struct gomp_work_share *next_alloc; ++ ++ /* The above fields are written once during workshare initialization, ++ or related to ordered worksharing. Make sure the following fields ++ are in a different cache line. */ ++ ++ /* This lock protects the update of the following members. */ ++ gomp_mutex_t lock __attribute__((aligned (64))); + + /* This is the count of the number of threads that have exited the work + share construct. If the construct was marked nowait, they have moved on +@@ -99,27 +123,28 @@ struct gomp_work_share + of the team to exit the work share construct must deallocate it. */ + unsigned threads_completed; + +- /* This is the index into the circular queue ordered_team_ids of the +- current thread that's allowed into the ordered reason. */ +- unsigned ordered_cur; ++ union { ++ /* This is the next iteration value to be allocated. In the case of ++ GFS_STATIC loops, this the iteration start point and never changes. */ ++ long next; + +- /* This is the number of threads that have registered themselves in +- the circular queue ordered_team_ids. */ +- unsigned ordered_num_used; ++ /* This is the returned data structure for SINGLE COPYPRIVATE. */ ++ void *copyprivate; ++ }; + +- /* This is the team_id of the currently acknoledged owner of the ordered +- section, or -1u if the ordered section has not been acknowledged by +- any thread. This is distinguished from the thread that is *allowed* +- to take the section next. */ +- unsigned ordered_owner; ++ union { ++ /* Link to gomp_work_share struct for next work sharing construct ++ encountered after this one. */ ++ gomp_ptrlock_t next_ws; ++ ++ /* gomp_work_share structs are chained in the free work share cache ++ through this. */ ++ struct gomp_work_share *next_free; ++ }; + +- /* This is a circular queue that details which threads will be allowed +- into the ordered region and in which order. When a thread allocates +- iterations on which it is going to work, it also registers itself at +- the end of the array. When a thread reaches the ordered region, it +- checks to see if it is the one at the head of the queue. If not, it +- blocks on its RELEASE semaphore. */ +- unsigned ordered_team_ids[]; ++ /* If only few threads are in the team, ordered_team_ids can point ++ to this array which fills the padding at the end of this struct. */ ++ unsigned inline_ordered_team_ids[0]; + }; + + /* This structure contains all of the thread-local data associated with +@@ -133,21 +158,24 @@ struct gomp_team_state + + /* This is the work share construct which this thread is currently + processing. Recall that with NOWAIT, not all threads may be +- processing the same construct. This value is NULL when there +- is no construct being processed. */ ++ processing the same construct. */ + struct gomp_work_share *work_share; + ++ /* This is the previous work share construct or NULL if there wasn't any. ++ When all threads are done with the current work sharing construct, ++ the previous one can be freed. The current one can't, as its ++ next_ws field is used. */ ++ struct gomp_work_share *last_work_share; ++ + /* This is the ID of this thread within the team. This value is + guaranteed to be between 0 and N-1, where N is the number of + threads in the team. */ + unsigned team_id; + +- /* The work share "generation" is a number that increases by one for +- each work share construct encountered in the dynamic flow of the +- program. It is used to find the control data for the work share +- when encountering it for the first time. This particular number +- reflects the generation of the work_share member of this struct. */ +- unsigned work_share_generation; ++#ifdef HAVE_SYNC_BUILTINS ++ /* Number of single stmts encountered. */ ++ unsigned long single_count; ++#endif + + /* For GFS_RUNTIME loops that resolved to GFS_STATIC, this is the + trip number through the loop. So first time a particular loop +@@ -163,41 +191,53 @@ struct gomp_team_state + + struct gomp_team + { +- /* This lock protects access to the following work shares data structures. */ +- gomp_mutex_t work_share_lock; +- +- /* This is a dynamically sized array containing pointers to the control +- structs for all "live" work share constructs. Here "live" means that +- the construct has been encountered by at least one thread, and not +- completed by all threads. */ +- struct gomp_work_share **work_shares; +- +- /* The work_shares array is indexed by "generation & generation_mask". +- The mask will be 2**N - 1, where 2**N is the size of the array. */ +- unsigned generation_mask; +- +- /* These two values define the bounds of the elements of the work_shares +- array that are currently in use. */ +- unsigned oldest_live_gen; +- unsigned num_live_gen; +- + /* This is the number of threads in the current team. */ + unsigned nthreads; + ++ /* This is number of gomp_work_share structs that have been allocated ++ as a block last time. */ ++ unsigned work_share_chunk; ++ + /* This is the saved team state that applied to a master thread before + the current thread was created. */ + struct gomp_team_state prev_ts; + +- /* This barrier is used for most synchronization of the team. */ +- gomp_barrier_t barrier; +- + /* This semaphore should be used by the master thread instead of its + "native" semaphore in the thread structure. Required for nested + parallels, as the master is a member of two teams. */ + gomp_sem_t master_release; + +- /* This array contains pointers to the release semaphore of the threads +- in the team. */ ++ /* List of gomp_work_share structs chained through next_free fields. ++ This is populated and taken off only by the first thread in the ++ team encountering a new work sharing construct, in a critical ++ section. */ ++ struct gomp_work_share *work_share_list_alloc; ++ ++ /* List of gomp_work_share structs freed by free_work_share. New ++ entries are atomically added to the start of the list, and ++ alloc_work_share can safely only move all but the first entry ++ to work_share_list alloc, as free_work_share can happen concurrently ++ with alloc_work_share. */ ++ struct gomp_work_share *work_share_list_free; ++ ++#ifdef HAVE_SYNC_BUILTINS ++ /* Number of simple single regions encountered by threads in this ++ team. */ ++ unsigned long single_count; ++#else ++ /* Mutex protecting addition of workshares to work_share_list_free. */ ++ gomp_mutex_t work_share_list_free_lock; ++#endif ++ ++ /* This barrier is used for most synchronization of the team. */ ++ gomp_barrier_t barrier; ++ ++ /* Initial work shares, to avoid allocating any gomp_work_share ++ structs in the common case. */ ++ struct gomp_work_share work_shares[8]; ++ ++ /* This is an array with pointers to the release semaphore ++ of the threads in the team. */ + gomp_sem_t *ordered_release[]; + }; + +@@ -242,6 +282,11 @@ extern bool gomp_dyn_var; + extern bool gomp_nest_var; + extern enum gomp_schedule_type gomp_run_sched_var; + extern unsigned long gomp_run_sched_chunk; ++#ifndef HAVE_SYNC_BUILTINS ++extern gomp_mutex_t gomp_remaining_threads_lock; ++#endif ++extern unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var; ++extern unsigned long gomp_available_cpus, gomp_managed_threads; + + /* The attributes to be used during thread creation. */ + extern pthread_attr_t gomp_thread_attr; +@@ -306,17 +351,27 @@ extern unsigned gomp_dynamic_max_threads + + /* team.c */ + ++extern struct gomp_team *gomp_new_team (unsigned); + extern void gomp_team_start (void (*) (void *), void *, unsigned, +- struct gomp_work_share *); ++ struct gomp_team *); + extern void gomp_team_end (void); + + /* work.c */ + +-extern struct gomp_work_share * gomp_new_work_share (bool, unsigned); ++extern void gomp_init_work_share (struct gomp_work_share *, bool, unsigned); ++extern void gomp_fini_work_share (struct gomp_work_share *); + extern bool gomp_work_share_start (bool); + extern void gomp_work_share_end (void); + extern void gomp_work_share_end_nowait (void); + ++static inline void ++gomp_work_share_init_done (void) ++{ ++ struct gomp_thread *thr = gomp_thread (); ++ if (__builtin_expect (thr->ts.last_work_share != NULL, 1)) ++ gomp_ptrlock_set (&thr->ts.last_work_share->next_ws, thr->ts.work_share); ++} ++ + #ifdef HAVE_ATTRIBUTE_VISIBILITY + # pragma GCC visibility pop + #endif +--- libgomp/iter.c.jj 2008-03-26 14:48:34.000000000 +0100 ++++ libgomp/iter.c 2008-03-26 15:11:23.000000000 +0100 +@@ -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). +@@ -154,7 +154,7 @@ gomp_iter_dynamic_next_locked (long *pst + if (start == ws->end) + return false; + +- chunk = ws->chunk_size * ws->incr; ++ chunk = ws->chunk_size; + left = ws->end - start; + if (ws->incr < 0) + { +@@ -186,11 +186,38 @@ gomp_iter_dynamic_next (long *pstart, lo + struct gomp_work_share *ws = thr->ts.work_share; + long start, end, nend, chunk, incr; + +- start = ws->next; + end = ws->end; + incr = ws->incr; +- chunk = ws->chunk_size * incr; ++ chunk = ws->chunk_size; ++ ++ if (__builtin_expect (ws->mode, 1)) ++ { ++ long tmp = __sync_fetch_and_add (&ws->next, chunk); ++ if (incr > 0) ++ { ++ if (tmp >= end) ++ return false; ++ nend = tmp + chunk; ++ if (nend > end) ++ nend = end; ++ *pstart = tmp; ++ *pend = nend; ++ return true; ++ } ++ else ++ { ++ if (tmp <= end) ++ return false; ++ nend = tmp + chunk; ++ if (nend < end) ++ nend = end; ++ *pstart = tmp; ++ *pend = nend; ++ return true; ++ } ++ } + ++ start = ws->next; + while (1) + { + long left = end - start; +--- libgomp/work.c.jj 2007-12-07 14:41:01.000000000 +0100 ++++ libgomp/work.c 2008-03-27 12:21:51.000000000 +0100 +@@ -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,39 +29,138 @@ + of threads. */ + + #include "libgomp.h" ++#include <stddef.h> + #include <stdlib.h> + #include <string.h> + + +-/* Create a new work share structure. */ ++/* Allocate a new work share structure, preferably from current team's ++ free gomp_work_share cache. */ + +-struct gomp_work_share * +-gomp_new_work_share (bool ordered, unsigned nthreads) ++static struct gomp_work_share * ++alloc_work_share (struct gomp_team *team) + { + struct gomp_work_share *ws; +- size_t size; ++ unsigned int i; + +- size = sizeof (*ws); +- if (ordered) +- size += nthreads * sizeof (ws->ordered_team_ids[0]); ++ /* This is called in a critical section. */ ++ if (team->work_share_list_alloc != NULL) ++ { ++ ws = team->work_share_list_alloc; ++ team->work_share_list_alloc = ws->next_free; ++ return ws; ++ } + +- ws = gomp_malloc_cleared (size); +- gomp_mutex_init (&ws->lock); +- ws->ordered_owner = -1; ++#ifdef HAVE_SYNC_BUILTINS ++ ws = team->work_share_list_free; ++ /* We need atomic read from work_share_list_free, ++ as free_work_share can be called concurrently. */ ++ __asm ("" : "+r" (ws)); ++ ++ if (ws && ws->next_free) ++ { ++ struct gomp_work_share *next = ws->next_free; ++ ws->next_free = NULL; ++ team->work_share_list_alloc = next->next_free; ++ return next; ++ } ++#else ++ gomp_mutex_lock (&team->work_share_list_free_lock); ++ ws = team->work_share_list_free; ++ if (ws) ++ { ++ team->work_share_list_alloc = ws->next_free; ++ team->work_share_list_free = NULL; ++ gomp_mutex_unlock (&team->work_share_list_free_lock); ++ return ws; ++ } ++ gomp_mutex_unlock (&team->work_share_list_free_lock); ++#endif + ++ team->work_share_chunk *= 2; ++ ws = gomp_malloc (team->work_share_chunk * sizeof (struct gomp_work_share)); ++ ws->next_alloc = team->work_shares[0].next_alloc; ++ team->work_shares[0].next_alloc = ws; ++ team->work_share_list_alloc = &ws[1]; ++ for (i = 1; i < team->work_share_chunk - 1; i++) ++ ws[i].next_free = &ws[i + 1]; ++ ws[i].next_free = NULL; + return ws; + } + ++/* Initialize an already allocated struct gomp_work_share. ++ This shouldn't touch the next_alloc field. */ ++ ++void ++gomp_init_work_share (struct gomp_work_share *ws, bool ordered, ++ unsigned nthreads) ++{ ++ gomp_mutex_init (&ws->lock); ++ if (__builtin_expect (ordered, 0)) ++ { ++#define INLINE_ORDERED_TEAM_IDS_CNT \ ++ ((sizeof (struct gomp_work_share) \ ++ - offsetof (struct gomp_work_share, inline_ordered_team_ids)) \ ++ / sizeof (((struct gomp_work_share *) 0)->inline_ordered_team_ids[0])) ++ ++ if (nthreads > INLINE_ORDERED_TEAM_IDS_CNT) ++ ws->ordered_team_ids ++ = gomp_malloc (nthreads * sizeof (*ws->ordered_team_ids)); ++ else ++ ws->ordered_team_ids = ws->inline_ordered_team_ids; ++ memset (ws->ordered_team_ids, '\0', ++ nthreads * sizeof (*ws->ordered_team_ids)); ++ ws->ordered_num_used = 0; ++ ws->ordered_owner = -1; ++ ws->ordered_cur = 0; ++ } ++ else ++ ws->ordered_team_ids = NULL; ++ gomp_ptrlock_init (&ws->next_ws, NULL); ++ ws->threads_completed = 0; ++} + +-/* Free a work share structure. */ ++/* Do any needed destruction of gomp_work_share fields before it ++ is put back into free gomp_work_share cache or freed. */ + +-static void +-free_work_share (struct gomp_work_share *ws) ++void ++gomp_fini_work_share (struct gomp_work_share *ws) + { + gomp_mutex_destroy (&ws->lock); +- free (ws); ++ if (ws->ordered_team_ids != ws->inline_ordered_team_ids) ++ free (ws->ordered_team_ids); ++ gomp_ptrlock_destroy (&ws->next_ws); + } + ++/* Free a work share struct, if not orphaned, put it into current ++ team's free gomp_work_share cache. */ ++ ++static inline void ++free_work_share (struct gomp_team *team, struct gomp_work_share *ws) ++{ ++ gomp_fini_work_share (ws); ++ if (__builtin_expect (team == NULL, 0)) ++ free (ws); ++ else ++ { ++ struct gomp_work_share *next_ws; ++#ifdef HAVE_SYNC_BUILTINS ++ do ++ { ++ next_ws = team->work_share_list_free; ++ ws->next_free = next_ws; ++ } ++ while (!__sync_bool_compare_and_swap (&team->work_share_list_free, ++ next_ws, ws)); ++#else ++ gomp_mutex_lock (&team->work_share_list_free_lock); ++ next_ws = team->work_share_list_free; ++ ws->next_free = next_ws; ++ team->work_share_list_free = ws; ++ gomp_mutex_unlock (&team->work_share_list_free_lock); ++#endif ++ } ++} + + /* The current thread is ready to begin the next work sharing construct. + In all cases, thr->ts.work_share is updated to point to the new +@@ -74,71 +173,34 @@ gomp_work_share_start (bool ordered) + struct gomp_thread *thr = gomp_thread (); + struct gomp_team *team = thr->ts.team; + struct gomp_work_share *ws; +- unsigned ws_index, ws_gen; + + /* Work sharing constructs can be orphaned. */ + if (team == NULL) + { +- ws = gomp_new_work_share (ordered, 1); ++ ws = gomp_malloc (sizeof (*ws)); ++ gomp_init_work_share (ws, ordered, 1); + thr->ts.work_share = ws; +- thr->ts.static_trip = 0; +- gomp_mutex_lock (&ws->lock); +- return true; ++ return ws; + } + +- gomp_mutex_lock (&team->work_share_lock); +- +- /* This thread is beginning its next generation. */ +- ws_gen = ++thr->ts.work_share_generation; +- +- /* If this next generation is not newer than any other generation in +- the team, then simply reference the existing construct. */ +- if (ws_gen - team->oldest_live_gen < team->num_live_gen) ++ ws = thr->ts.work_share; ++ thr->ts.last_work_share = ws; ++ ws = gomp_ptrlock_get (&ws->next_ws); ++ if (ws == NULL) + { +- ws_index = ws_gen & team->generation_mask; +- ws = team->work_shares[ws_index]; ++ /* This thread encountered a new ws first. */ ++ struct gomp_work_share *ws = alloc_work_share (team); ++ gomp_init_work_share (ws, ordered, team->nthreads); + thr->ts.work_share = ws; +- thr->ts.static_trip = 0; +- +- gomp_mutex_lock (&ws->lock); +- gomp_mutex_unlock (&team->work_share_lock); +- +- return false; ++ return true; + } +- +- /* Resize the work shares queue if we've run out of space. */ +- if (team->num_live_gen++ == team->generation_mask) ++ else + { +- team->work_shares = gomp_realloc (team->work_shares, +- 2 * team->num_live_gen +- * sizeof (*team->work_shares)); +- +- /* Unless oldest_live_gen is zero, the sequence of live elements +- wraps around the end of the array. If we do nothing, we break +- lookup of the existing elements. Fix that by unwrapping the +- data from the front to the end. */ +- if (team->oldest_live_gen > 0) +- memcpy (team->work_shares + team->num_live_gen, +- team->work_shares, +- (team->oldest_live_gen & team->generation_mask) +- * sizeof (*team->work_shares)); +- +- team->generation_mask = team->generation_mask * 2 + 1; +- } +- +- ws_index = ws_gen & team->generation_mask; +- ws = gomp_new_work_share (ordered, team->nthreads); +- thr->ts.work_share = ws; +- thr->ts.static_trip = 0; +- team->work_shares[ws_index] = ws; +- +- gomp_mutex_lock (&ws->lock); +- gomp_mutex_unlock (&team->work_share_lock); +- +- return true; ++ thr->ts.work_share = ws; ++ return false; ++ } + } + +- + /* The current thread is done with its current work sharing construct. + This version does imply a barrier at the end of the work-share. */ + +@@ -147,36 +209,28 @@ gomp_work_share_end (void) + { + struct gomp_thread *thr = gomp_thread (); + struct gomp_team *team = thr->ts.team; +- struct gomp_work_share *ws = thr->ts.work_share; +- bool last; +- +- thr->ts.work_share = NULL; ++ gomp_barrier_state_t bstate; + + /* Work sharing constructs can be orphaned. */ + if (team == NULL) + { +- free_work_share (ws); ++ free_work_share (NULL, thr->ts.work_share); ++ thr->ts.work_share = NULL; + return; + } + +- last = gomp_barrier_wait_start (&team->barrier); ++ bstate = gomp_barrier_wait_start (&team->barrier); + +- if (last) ++ if (gomp_barrier_last_thread (bstate)) + { +- unsigned ws_index; +- +- ws_index = thr->ts.work_share_generation & team->generation_mask; +- team->work_shares[ws_index] = NULL; +- team->oldest_live_gen++; +- team->num_live_gen = 0; +- +- free_work_share (ws); ++ if (__builtin_expect (thr->ts.last_work_share != NULL, 1)) ++ free_work_share (team, thr->ts.last_work_share); + } + +- gomp_barrier_wait_end (&team->barrier, last); ++ gomp_barrier_wait_end (&team->barrier, bstate); ++ thr->ts.last_work_share = NULL; + } + +- + /* The current thread is done with its current work sharing construct. + This version does NOT imply a barrier at the end of the work-share. */ + +@@ -188,15 +242,17 @@ gomp_work_share_end_nowait (void) + struct gomp_work_share *ws = thr->ts.work_share; + unsigned completed; + +- thr->ts.work_share = NULL; +- + /* Work sharing constructs can be orphaned. */ + if (team == NULL) + { +- free_work_share (ws); ++ free_work_share (NULL, ws); ++ thr->ts.work_share = NULL; + return; + } + ++ if (__builtin_expect (thr->ts.last_work_share == NULL, 0)) ++ return; ++ + #ifdef HAVE_SYNC_BUILTINS + completed = __sync_add_and_fetch (&ws->threads_completed, 1); + #else +@@ -206,18 +262,6 @@ gomp_work_share_end_nowait (void) + #endif + + if (completed == team->nthreads) +- { +- unsigned ws_index; +- +- gomp_mutex_lock (&team->work_share_lock); +- +- ws_index = thr->ts.work_share_generation & team->generation_mask; +- team->work_shares[ws_index] = NULL; +- team->oldest_live_gen++; +- team->num_live_gen--; +- +- gomp_mutex_unlock (&team->work_share_lock); +- +- free_work_share (ws); +- } ++ free_work_share (team, thr->ts.last_work_share); ++ thr->ts.last_work_share = NULL; + } +--- libgomp/single.c.jj 2007-12-07 14:41:01.000000000 +0100 ++++ libgomp/single.c 2008-03-26 15:11:32.000000000 +0100 +@@ -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). +@@ -37,10 +37,24 @@ + bool + GOMP_single_start (void) + { ++#ifdef HAVE_SYNC_BUILTINS ++ struct gomp_thread *thr = gomp_thread (); ++ struct gomp_team *team = thr->ts.team; ++ unsigned long single_count; ++ ++ if (__builtin_expect (team == NULL, 0)) ++ return true; ++ ++ single_count = thr->ts.single_count++; ++ return __sync_bool_compare_and_swap (&team->single_count, single_count, ++ single_count + 1L); ++#else + bool ret = gomp_work_share_start (false); +- gomp_mutex_unlock (&gomp_thread ()->ts.work_share->lock); ++ if (ret) ++ gomp_work_share_init_done (); + gomp_work_share_end_nowait (); + return ret; ++#endif + } + + /* This routine is called when first encountering a SINGLE construct that +@@ -57,10 +71,12 @@ GOMP_single_copy_start (void) + void *ret; + + first = gomp_work_share_start (false); +- gomp_mutex_unlock (&thr->ts.work_share->lock); + + if (first) +- ret = NULL; ++ { ++ gomp_work_share_init_done (); ++ ret = NULL; ++ } + else + { + gomp_barrier_wait (&thr->ts.team->barrier); +--- libgomp/loop.c.jj 2007-12-07 14:41:01.000000000 +0100 ++++ libgomp/loop.c 2008-03-26 18:47:04.000000000 +0100 +@@ -27,8 +27,9 @@ + + /* This file handles the LOOP (FOR/DO) construct. */ + +-#include "libgomp.h" ++#include <limits.h> + #include <stdlib.h> ++#include "libgomp.h" + + + /* Initialize the given work share construct from the given arguments. */ +@@ -44,6 +45,39 @@ gomp_loop_init (struct gomp_work_share * + ? start : end; + ws->incr = incr; + ws->next = start; ++ if (sched == GFS_DYNAMIC) ++ { ++ ws->chunk_size *= incr; ++ ++#ifdef HAVE_SYNC_BUILTINS ++ { ++ /* For dynamic scheduling prepare things to make each iteration ++ faster. */ ++ struct gomp_thread *thr = gomp_thread (); ++ struct gomp_team *team = thr->ts.team; ++ long nthreads = team ? team->nthreads : 1; ++ ++ if (__builtin_expect (incr > 0, 1)) ++ { ++ /* Cheap overflow protection. */ ++ if (__builtin_expect ((nthreads | ws->chunk_size) ++ >= 1UL << (sizeof (long) ++ * __CHAR_BIT__ / 2 - 1), 0)) ++ ws->mode = 0; ++ else ++ ws->mode = ws->end < (LONG_MAX ++ - (nthreads + 1) * ws->chunk_size); ++ } ++ /* Cheap overflow protection. */ ++ else if (__builtin_expect ((nthreads | -ws->chunk_size) ++ >= 1UL << (sizeof (long) ++ * __CHAR_BIT__ / 2 - 1), 0)) ++ ws->mode = 0; ++ else ++ ws->mode = ws->end > (nthreads + 1) * -ws->chunk_size - LONG_MAX; ++ } ++#endif ++ } + } + + /* The *_start routines are called when first encountering a loop construct +@@ -68,10 +102,13 @@ gomp_loop_static_start (long start, long + { + struct gomp_thread *thr = gomp_thread (); + ++ thr->ts.static_trip = 0; + if (gomp_work_share_start (false)) +- gomp_loop_init (thr->ts.work_share, start, end, incr, +- GFS_STATIC, chunk_size); +- gomp_mutex_unlock (&thr->ts.work_share->lock); ++ { ++ gomp_loop_init (thr->ts.work_share, start, end, incr, ++ GFS_STATIC, chunk_size); ++ gomp_work_share_init_done (); ++ } + + return !gomp_iter_static_next (istart, iend); + } +@@ -84,13 +121,16 @@ gomp_loop_dynamic_start (long start, lon + bool ret; + + if (gomp_work_share_start (false)) +- gomp_loop_init (thr->ts.work_share, start, end, incr, +- GFS_DYNAMIC, chunk_size); ++ { ++ gomp_loop_init (thr->ts.work_share, start, end, incr, ++ GFS_DYNAMIC, chunk_size); ++ gomp_work_share_init_done (); ++ } + + #ifdef HAVE_SYNC_BUILTINS +- gomp_mutex_unlock (&thr->ts.work_share->lock); + ret = gomp_iter_dynamic_next (istart, iend); + #else ++ gomp_mutex_lock (&thr->ts.work_share->lock); + ret = gomp_iter_dynamic_next_locked (istart, iend); + gomp_mutex_unlock (&thr->ts.work_share->lock); + #endif +@@ -106,13 +146,16 @@ gomp_loop_guided_start (long start, long + bool ret; + + if (gomp_work_share_start (false)) +- gomp_loop_init (thr->ts.work_share, start, end, incr, +- GFS_GUIDED, chunk_size); ++ { ++ gomp_loop_init (thr->ts.work_share, start, end, incr, ++ GFS_GUIDED, chunk_size); ++ gomp_work_share_init_done (); ++ } + + #ifdef HAVE_SYNC_BUILTINS +- gomp_mutex_unlock (&thr->ts.work_share->lock); + ret = gomp_iter_guided_next (istart, iend); + #else ++ gomp_mutex_lock (&thr->ts.work_share->lock); + ret = gomp_iter_guided_next_locked (istart, iend); + gomp_mutex_unlock (&thr->ts.work_share->lock); + #endif +@@ -149,13 +192,14 @@ gomp_loop_ordered_static_start (long sta + { + struct gomp_thread *thr = gomp_thread (); + ++ thr->ts.static_trip = 0; + if (gomp_work_share_start (true)) + { + gomp_loop_init (thr->ts.work_share, start, end, incr, + GFS_STATIC, chunk_size); + gomp_ordered_static_init (); ++ gomp_work_share_init_done (); + } +- gomp_mutex_unlock (&thr->ts.work_share->lock); + + return !gomp_iter_static_next (istart, iend); + } +@@ -168,8 +212,14 @@ gomp_loop_ordered_dynamic_start (long st + bool ret; + + if (gomp_work_share_start (true)) +- gomp_loop_init (thr->ts.work_share, start, end, incr, +- GFS_DYNAMIC, chunk_size); ++ { ++ gomp_loop_init (thr->ts.work_share, start, end, incr, ++ GFS_DYNAMIC, chunk_size); ++ gomp_mutex_lock (&thr->ts.work_share->lock); ++ gomp_work_share_init_done (); ++ } ++ else ++ gomp_mutex_lock (&thr->ts.work_share->lock); + + ret = gomp_iter_dynamic_next_locked (istart, iend); + if (ret) +@@ -187,8 +237,14 @@ gomp_loop_ordered_guided_start (long sta + bool ret; + + if (gomp_work_share_start (true)) +- gomp_loop_init (thr->ts.work_share, start, end, incr, +- GFS_GUIDED, chunk_size); ++ { ++ gomp_loop_init (thr->ts.work_share, start, end, incr, ++ GFS_GUIDED, chunk_size); ++ gomp_mutex_lock (&thr->ts.work_share->lock); ++ gomp_work_share_init_done (); ++ } ++ else ++ gomp_mutex_lock (&thr->ts.work_share->lock); + + ret = gomp_iter_guided_next_locked (istart, iend); + if (ret) +@@ -375,12 +431,12 @@ gomp_parallel_loop_start (void (*fn) (vo + long incr, enum gomp_schedule_type sched, + long chunk_size) + { +- struct gomp_work_share *ws; ++ struct gomp_team *team; + + num_threads = gomp_resolve_num_threads (num_threads); +- ws = gomp_new_work_share (false, num_threads); +- gomp_loop_init (ws, start, end, incr, sched, chunk_size); +- gomp_team_start (fn, data, num_threads, ws); ++ team = gomp_new_team (num_threads); ++ gomp_loop_init (&team->work_shares[0], start, end, incr, sched, chunk_size); ++ gomp_team_start (fn, data, num_threads, team); + } + + void +--- libgomp/Makefile.in.jj 2008-01-10 20:53:47.000000000 +0100 ++++ libgomp/Makefile.in 2008-03-26 18:51:01.000000000 +0100 +@@ -83,7 +83,7 @@ libgomp_la_LIBADD = + am_libgomp_la_OBJECTS = alloc.lo barrier.lo critical.lo env.lo \ + error.lo iter.lo loop.lo ordered.lo parallel.lo sections.lo \ + single.lo team.lo work.lo lock.lo mutex.lo proc.lo sem.lo \ +- bar.lo time.lo fortran.lo affinity.lo ++ bar.lo ptrlock.lo time.lo fortran.lo affinity.lo + libgomp_la_OBJECTS = $(am_libgomp_la_OBJECTS) + DEFAULT_INCLUDES = -I. -I$(srcdir) -I. + depcomp = $(SHELL) $(top_srcdir)/../depcomp +@@ -292,7 +292,7 @@ libgomp_version_info = -version-info $(l + libgomp_la_LDFLAGS = $(libgomp_version_info) $(libgomp_version_script) + libgomp_la_SOURCES = alloc.c barrier.c critical.c env.c error.c iter.c \ + loop.c ordered.c parallel.c sections.c single.c team.c work.c \ +- lock.c mutex.c proc.c sem.c bar.c time.c fortran.c affinity.c ++ lock.c mutex.c proc.c sem.c bar.c ptrlock.c time.c fortran.c affinity.c + + nodist_noinst_HEADERS = libgomp_f.h + nodist_libsubinclude_HEADERS = omp.h +@@ -434,6 +434,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ordered.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parallel.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptrlock.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sections.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sem.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/single.Plo@am__quote@ +--- libgomp/testsuite/libgomp.c/loop-4.c.jj 2008-03-26 18:47:04.000000000 +0100 ++++ libgomp/testsuite/libgomp.c/loop-4.c 2008-03-26 18:47:04.000000000 +0100 +@@ -0,0 +1,28 @@ ++/* { dg-do run } */ ++ ++extern void abort (void); ++ ++int ++main (void) ++{ ++ int e = 0; ++#pragma omp parallel num_threads (4) reduction(+:e) ++ { ++ long i; ++ #pragma omp for schedule(dynamic,1) ++ for (i = __LONG_MAX__ - 30001; i <= __LONG_MAX__ - 10001; i += 10000) ++ if (i != __LONG_MAX__ - 30001 ++ && i != __LONG_MAX__ - 20001 ++ && i != __LONG_MAX__ - 10001) ++ e = 1; ++ #pragma omp for schedule(dynamic,1) ++ for (i = -__LONG_MAX__ + 30000; i >= -__LONG_MAX__ + 10000; i -= 10000) ++ if (i != -__LONG_MAX__ + 30000 ++ && i != -__LONG_MAX__ + 20000 ++ && i != -__LONG_MAX__ + 10000) ++ e = 1; ++ } ++ if (e) ++ abort (); ++ return 0; ++} +--- libgomp/Makefile.am.jj 2007-12-07 14:41:01.000000000 +0100 ++++ libgomp/Makefile.am 2008-03-26 15:15:19.000000000 +0100 +@@ -31,7 +31,7 @@ libgomp_la_LDFLAGS = $(libgomp_version_i + + libgomp_la_SOURCES = alloc.c barrier.c critical.c env.c error.c iter.c \ + loop.c ordered.c parallel.c sections.c single.c team.c work.c \ +- lock.c mutex.c proc.c sem.c bar.c time.c fortran.c affinity.c ++ lock.c mutex.c proc.c sem.c bar.c ptrlock.c time.c fortran.c affinity.c + + nodist_noinst_HEADERS = libgomp_f.h + nodist_libsubinclude_HEADERS = omp.h +--- libgomp/team.c.jj 2007-12-07 14:41:01.000000000 +0100 ++++ libgomp/team.c 2008-03-27 12:22:26.000000000 +0100 +@@ -94,7 +94,7 @@ gomp_thread_start (void *xdata) + { + gomp_barrier_wait (&thr->ts.team->barrier); + local_fn (local_data); +- gomp_barrier_wait (&thr->ts.team->barrier); ++ gomp_barrier_wait_last (&thr->ts.team->barrier); + } + else + { +@@ -114,11 +114,10 @@ gomp_thread_start (void *xdata) + thr->data = NULL; + thr->ts.team = NULL; + thr->ts.work_share = NULL; ++ thr->ts.last_work_share = NULL; + thr->ts.team_id = 0; +- thr->ts.work_share_generation = 0; +- thr->ts.static_trip = 0; + +- gomp_barrier_wait (&team->barrier); ++ gomp_barrier_wait_last (&team->barrier); + gomp_barrier_wait (&gomp_threads_dock); + + local_fn = thr->fn; +@@ -133,21 +132,29 @@ gomp_thread_start (void *xdata) + + /* Create a new team data structure. */ + +-static struct gomp_team * +-new_team (unsigned nthreads, struct gomp_work_share *work_share) ++struct gomp_team * ++gomp_new_team (unsigned nthreads) + { + struct gomp_team *team; + size_t size; ++ int i; + + size = sizeof (*team) + nthreads * sizeof (team->ordered_release[0]); + team = gomp_malloc (size); +- gomp_mutex_init (&team->work_share_lock); + +- team->work_shares = gomp_malloc (4 * sizeof (struct gomp_work_share *)); +- team->generation_mask = 3; +- team->oldest_live_gen = work_share == NULL; +- team->num_live_gen = work_share != NULL; +- team->work_shares[0] = work_share; ++ team->work_share_chunk = 8; ++#ifdef HAVE_SYNC_BUILTINS ++ team->single_count = 0; ++#else ++ gomp_mutex_init (&team->work_share_list_free_lock); ++#endif ++ gomp_init_work_share (&team->work_shares[0], false, nthreads); ++ team->work_shares[0].next_alloc = NULL; ++ team->work_share_list_free = NULL; ++ team->work_share_list_alloc = &team->work_shares[1]; ++ for (i = 1; i < 7; i++) ++ team->work_shares[i].next_free = &team->work_shares[i + 1]; ++ team->work_shares[i].next_free = NULL; + + team->nthreads = nthreads; + gomp_barrier_init (&team->barrier, nthreads); +@@ -164,10 +171,22 @@ new_team (unsigned nthreads, struct gomp + static void + free_team (struct gomp_team *team) + { +- free (team->work_shares); +- gomp_mutex_destroy (&team->work_share_lock); ++ if (__builtin_expect (team->work_shares[0].next_alloc != NULL, 0)) ++ { ++ struct gomp_work_share *ws = team->work_shares[0].next_alloc; ++ do ++ { ++ struct gomp_work_share *next_ws = ws->next_alloc; ++ free (ws); ++ ws = next_ws; ++ } ++ while (ws != NULL); ++ } + gomp_barrier_destroy (&team->barrier); + gomp_sem_destroy (&team->master_release); ++#ifndef HAVE_SYNC_BUILTINS ++ gomp_mutex_destroy (&team->work_share_list_free_lock); ++#endif + free (team); + } + +@@ -176,11 +195,10 @@ free_team (struct gomp_team *team) + + void + gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads, +- struct gomp_work_share *work_share) ++ struct gomp_team *team) + { + struct gomp_thread_start_data *start_data; + struct gomp_thread *thr, *nthr; +- struct gomp_team *team; + bool nested; + unsigned i, n, old_threads_used = 0; + pthread_attr_t thread_attr, *attr; +@@ -188,17 +206,18 @@ gomp_team_start (void (*fn) (void *), vo + thr = gomp_thread (); + nested = thr->ts.team != NULL; + +- team = new_team (nthreads, work_share); +- + /* Always save the previous state, even if this isn't a nested team. + In particular, we should save any work share state from an outer + orphaned work share construct. */ + team->prev_ts = thr->ts; + + thr->ts.team = team; +- thr->ts.work_share = work_share; + thr->ts.team_id = 0; +- thr->ts.work_share_generation = 0; ++ thr->ts.work_share = &team->work_shares[0]; ++ thr->ts.last_work_share = NULL; ++#ifdef HAVE_SYNC_BUILTINS ++ thr->ts.single_count = 0; ++#endif + thr->ts.static_trip = 0; + + if (nthreads == 1) +@@ -241,9 +260,12 @@ gomp_team_start (void (*fn) (void *), vo + { + nthr = gomp_threads[i]; + nthr->ts.team = team; +- nthr->ts.work_share = work_share; ++ nthr->ts.work_share = &team->work_shares[0]; ++ nthr->ts.last_work_share = NULL; + nthr->ts.team_id = i; +- nthr->ts.work_share_generation = 0; ++#ifdef HAVE_SYNC_BUILTINS ++ nthr->ts.single_count = 0; ++#endif + nthr->ts.static_trip = 0; + nthr->fn = fn; + nthr->data = data; +@@ -266,8 +288,24 @@ gomp_team_start (void (*fn) (void *), vo + } + } + ++ if (__builtin_expect (nthreads > old_threads_used, 0)) ++ { ++ long diff = (long) nthreads - (long) old_threads_used; ++ ++ if (old_threads_used == 0) ++ --diff; ++ ++#ifdef HAVE_SYNC_BUILTINS ++ __sync_fetch_and_add (&gomp_managed_threads, diff); ++#else ++ gomp_mutex_lock (&gomp_remaining_threads_lock); ++ gomp_managed_threads += diff; ++ gomp_mutex_unlock (&gomp_remaining_threads_lock); ++#endif ++ } ++ + attr = &gomp_thread_attr; +- if (gomp_cpu_affinity != NULL) ++ if (__builtin_expect (gomp_cpu_affinity != NULL, 0)) + { + size_t stacksize; + pthread_attr_init (&thread_attr); +@@ -287,9 +325,12 @@ gomp_team_start (void (*fn) (void *), vo + int err; + + start_data->ts.team = team; +- start_data->ts.work_share = work_share; ++ start_data->ts.work_share = &team->work_shares[0]; ++ start_data->ts.last_work_share = NULL; + start_data->ts.team_id = i; +- start_data->ts.work_share_generation = 0; ++#ifdef HAVE_SYNC_BUILTINS ++ start_data->ts.single_count = 0; ++#endif + start_data->ts.static_trip = 0; + start_data->fn = fn; + start_data->fn_data = data; +@@ -303,7 +344,7 @@ gomp_team_start (void (*fn) (void *), vo + gomp_fatal ("Thread creation failed: %s", strerror (err)); + } + +- if (gomp_cpu_affinity != NULL) ++ if (__builtin_expect (gomp_cpu_affinity != NULL, 0)) + pthread_attr_destroy (&thread_attr); + + do_release: +@@ -313,8 +354,20 @@ gomp_team_start (void (*fn) (void *), vo + that should arrive back at the end of this team. The extra + threads should be exiting. Note that we arrange for this test + to never be true for nested teams. */ +- if (nthreads < old_threads_used) +- gomp_barrier_reinit (&gomp_threads_dock, nthreads); ++ if (__builtin_expect (nthreads < old_threads_used, 0)) ++ { ++ long diff = (long) nthreads - (long) old_threads_used; ++ ++ gomp_barrier_reinit (&gomp_threads_dock, nthreads); ++ ++#ifdef HAVE_SYNC_BUILTINS ++ __sync_fetch_and_add (&gomp_managed_threads, diff); ++#else ++ gomp_mutex_lock (&gomp_remaining_threads_lock); ++ gomp_managed_threads += diff; ++ gomp_mutex_unlock (&gomp_remaining_threads_lock); ++#endif ++ } + } + + +@@ -329,8 +382,21 @@ gomp_team_end (void) + + gomp_barrier_wait (&team->barrier); + ++ gomp_fini_work_share (thr->ts.work_share); ++ + thr->ts = team->prev_ts; + ++ if (__builtin_expect (thr->ts.team != NULL, 0)) ++ { ++#ifdef HAVE_SYNC_BUILTINS ++ __sync_fetch_and_add (&gomp_managed_threads, 1L - team->nthreads); ++#else ++ gomp_mutex_lock (&gomp_remaining_threads_lock); ++ gomp_managed_threads -= team->nthreads - 1L; ++ gomp_mutex_unlock (&gomp_remaining_threads_lock); ++#endif ++ } ++ + free_team (team); + } + +--- libgomp/config/posix/bar.h.jj 2007-12-07 14:41:01.000000000 +0100 ++++ libgomp/config/posix/bar.h 2008-03-26 15:11:32.000000000 +0100 +@@ -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). +@@ -46,18 +46,32 @@ typedef struct + unsigned total; + unsigned arrived; + } gomp_barrier_t; ++typedef bool 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); + +-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->mutex1); + return ++bar->arrived == bar->total; + } + ++static inline bool ++gomp_barrier_last_thread (gomp_barrier_state_t state) ++{ ++ return state; ++} ++ ++static inline void ++gomp_barrier_wait_last (gomp_barrier_t *bar) ++{ ++ gomp_barrier_wait (bar); ++} ++ + #endif /* GOMP_BARRIER_H */ +--- libgomp/config/posix/ptrlock.h.jj 2008-03-26 15:11:32.000000000 +0100 ++++ libgomp/config/posix/ptrlock.h 2008-03-26 15:11:32.000000000 +0100 +@@ -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 */ +--- libgomp/config/posix/ptrlock.c.jj 2008-03-26 15:11:32.000000000 +0100 ++++ libgomp/config/posix/ptrlock.c 2008-03-26 15:11:32.000000000 +0100 +@@ -0,0 +1 @@ ++/* Everything is in the header. */ +--- libgomp/config/posix/bar.c.jj 2007-12-07 14:41:01.000000000 +0100 ++++ libgomp/config/posix/bar.c 2008-03-26 15:11:32.000000000 +0100 +@@ -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). +@@ -70,7 +70,7 @@ gomp_barrier_reinit (gomp_barrier_t *bar + } + + void +-gomp_barrier_wait_end (gomp_barrier_t *bar, bool last) ++gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t last) + { + unsigned int n; + +--- libgomp/config/linux/alpha/futex.h.jj 2007-12-07 14:41:00.000000000 +0100 ++++ libgomp/config/linux/alpha/futex.h 2008-03-26 15:11:32.000000000 +0100 +@@ -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"); + } +--- libgomp/config/linux/affinity.c.jj 2007-12-07 14:41:00.000000000 +0100 ++++ libgomp/config/linux/affinity.c 2008-03-26 15:11:32.000000000 +0100 +@@ -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_ + 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); +--- libgomp/config/linux/bar.h.jj 2007-12-07 14:41:00.000000000 +0100 ++++ libgomp/config/linux/bar.h 2008-03-26 15:11:32.000000000 +0100 +@@ -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,49 @@ + + 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); + +-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; ++ /* 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; + } + + #endif /* GOMP_BARRIER_H */ +--- libgomp/config/linux/ptrlock.h.jj 2008-03-26 15:11:32.000000000 +0100 ++++ libgomp/config/linux/ptrlock.h 2008-03-26 15:11:32.000000000 +0100 +@@ -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 */ +--- libgomp/config/linux/lock.c.jj 2007-12-07 14:41:00.000000000 +0100 ++++ libgomp/config/linux/lock.c 2008-03-26 15:11:32.000000000 +0100 +@@ -29,11 +29,10 @@ + 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 +@@ -137,7 +136,7 @@ omp_set_nest_lock (omp_nest_lock_t *lock + return; + } + +- futex_wait (&lock->owner, otid); ++ do_wait (&lock->owner, otid); + } + } + +--- libgomp/config/linux/ptrlock.c.jj 2008-03-26 15:11:32.000000000 +0100 ++++ libgomp/config/linux/ptrlock.c 2008-03-26 15:11:32.000000000 +0100 +@@ -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); ++} +--- libgomp/config/linux/x86/futex.h.jj 2007-12-07 14:41:00.000000000 +0100 ++++ libgomp/config/linux/x86/futex.h 2008-03-26 15:11:32.000000000 +0100 +@@ -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 (); ++} +--- libgomp/config/linux/wait.h.jj 2008-03-26 15:11:32.000000000 +0100 ++++ libgomp/config/linux/wait.h 2008-03-26 15:11:32.000000000 +0100 +@@ -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 */ +--- libgomp/config/linux/sparc/futex.h.jj 2007-12-07 14:41:00.000000000 +0100 ++++ libgomp/config/linux/sparc/futex.h 2008-03-26 15:11:32.000000000 +0100 +@@ -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 + } +--- libgomp/config/linux/ia64/futex.h.jj 2007-12-07 14:41:00.000000000 +0100 ++++ libgomp/config/linux/ia64/futex.h 2008-03-26 15:11:32.000000000 +0100 +@@ -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 (); + } +--- libgomp/config/linux/s390/futex.h.jj 2007-12-07 14:41:00.000000000 +0100 ++++ libgomp/config/linux/s390/futex.h 2008-03-26 15:11:32.000000000 +0100 +@@ -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 (); + } +--- libgomp/config/linux/mutex.c.jj 2007-12-07 14:41:00.000000000 +0100 ++++ libgomp/config/linux/mutex.c 2008-03-26 15:11:32.000000000 +0100 +@@ -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 *mute + { + 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)); + } +--- libgomp/config/linux/sem.c.jj 2007-12-07 14:41:00.000000000 +0100 ++++ libgomp/config/linux/sem.c 2008-03-26 15:11:32.000000000 +0100 +@@ -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); + } + } + +--- libgomp/config/linux/powerpc/futex.h.jj 2007-12-07 14:41:00.000000000 +0100 ++++ libgomp/config/linux/powerpc/futex.h 2008-03-26 15:11:32.000000000 +0100 +@@ -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"); + } +--- libgomp/config/linux/bar.c.jj 2007-12-07 14:41:00.000000000 +0100 ++++ libgomp/config/linux/bar.c 2008-03-26 15:11:32.000000000 +0100 +@@ -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,32 +29,29 @@ + 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 += 2; ++ 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); + } +- +- if (__sync_add_and_fetch (&bar->arrived, -1) == 0) +- gomp_mutex_unlock (&bar->mutex); + } + + void +@@ -62,3 +59,18 @@ gomp_barrier_wait (gomp_barrier_t *barri + { + gomp_barrier_wait_end (barrier, gomp_barrier_wait_start (barrier)); + } ++ ++/* 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 *barrier) ++{ ++ gomp_barrier_state_t state = gomp_barrier_wait_start (barrier); ++ if (state & 1) ++ gomp_barrier_wait_end (barrier, state); ++} diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-ppc32-retaddr.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-ppc32-retaddr.patch new file mode 100644 index 0000000000..e9ae1bc303 --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-ppc32-retaddr.patch @@ -0,0 +1,86 @@ +2005-11-28 Jakub Jelinek <jakub@redhat.com> + + * config/rs6000/rs6000.c (rs6000_return_addr): If COUNT == 0, + read word RETURN_ADDRESS_OFFSET bytes above arg_pointer_rtx + instead of doing an extran indirection from frame_pointer_rtx. + + * gcc.dg/20051128-1.c: New test. + +--- gcc/config/rs6000/rs6000.c.jj 2005-11-26 14:38:01.000000000 +0100 ++++ gcc/config/rs6000/rs6000.c 2005-11-28 20:32:18.000000000 +0100 +@@ -13166,17 +13166,22 @@ rs6000_return_addr (int count, rtx frame + don't try to be too clever here. */ + if (count != 0 || (DEFAULT_ABI != ABI_AIX && flag_pic)) + { ++ rtx x; + cfun->machine->ra_needs_full_frame = 1; + +- return +- gen_rtx_MEM +- (Pmode, +- memory_address +- (Pmode, +- plus_constant (copy_to_reg +- (gen_rtx_MEM (Pmode, +- memory_address (Pmode, frame))), +- RETURN_ADDRESS_OFFSET))); ++ if (count == 0) ++ { ++ gcc_assert (frame == frame_pointer_rtx); ++ x = arg_pointer_rtx; ++ } ++ else ++ { ++ x = memory_address (Pmode, frame); ++ x = copy_to_reg (gen_rtx_MEM (Pmode, x)); ++ } ++ ++ x = plus_constant (x, RETURN_ADDRESS_OFFSET); ++ return gen_rtx_MEM (Pmode, memory_address (Pmode, x)); + } + + cfun->machine->ra_need_lr = 1; +--- gcc/testsuite/gcc.dg/20051128-1.c.jj 2005-10-10 11:21:41.096999000 +0200 ++++ gcc/testsuite/gcc.dg/20051128-1.c 2005-11-28 12:30:57.000000000 +0100 +@@ -0,0 +1,41 @@ ++/* { dg-do run } */ ++/* { dg-options "-O2 -fpic" } */ ++ ++extern void exit (int); ++extern void abort (void); ++ ++int b; ++ ++struct A ++{ ++ void *pad[147]; ++ void *ra, *h; ++ long o; ++}; ++ ++void ++__attribute__((noinline)) ++foo (struct A *a, void *x) ++{ ++ __builtin_memset (a, 0, sizeof (a)); ++ if (!b) ++ exit (0); ++} ++ ++void ++__attribute__((noinline)) ++bar (void) ++{ ++ struct A a; ++ ++ __builtin_unwind_init (); ++ foo (&a, __builtin_return_address (0)); ++} ++ ++int ++main (void) ++{ ++ bar (); ++ abort (); ++ return 0; ++} diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr27898.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr27898.patch new file mode 100644 index 0000000000..172bb81171 --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr27898.patch @@ -0,0 +1,16 @@ +2006-08-18 Jakub Jelinek <jakub@redhat.com> + + PR c/27898 + * gcc.dg/pr27898.c: New test. + +--- gcc/testsuite/gcc.dg/pr27898.c.jj 2006-08-18 09:19:33.000000000 +0200 ++++ gcc/testsuite/gcc.dg/pr27898.c 2006-08-18 09:19:27.000000000 +0200 +@@ -0,0 +1,8 @@ ++/* PR c/27898 */ ++/* { dg-do compile } */ ++/* { dg-options "--combine" } */ ++/* { dg-additional-sources "pr27898.c" } */ ++ ++union u { struct { int i; }; }; ++ ++extern int foo (union u *); diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr32139.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr32139.patch new file mode 100644 index 0000000000..f35696703d --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr32139.patch @@ -0,0 +1,19 @@ +2007-06-01 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/32139 + * gcc.c-torture/compile/20070531-1.c: New test. + +--- gcc/testsuite/gcc.c-torture/compile/20070531-1.c.jj 2007-05-31 13:47:22.000000000 +0200 ++++ gcc/testsuite/gcc.c-torture/compile/20070531-1.c 2007-06-01 10:57:15.000000000 +0200 +@@ -0,0 +1,11 @@ ++/* PR tree-optimization/32139 */ ++int foo (void); ++int bar (void) __attribute__ ((const)); ++ ++int ++test (int x) ++{ ++ int a = (x == 10000 ? foo : bar) (); ++ int b = (x == 10000 ? foo : bar) (); ++ return a + b; ++} diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr33763.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr33763.patch new file mode 100644 index 0000000000..9e9c90d271 --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr33763.patch @@ -0,0 +1,153 @@ +2007-11-06 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/33763 + * gcc.dg/pr33763.c: New test. + * g++.dg/opt/inline13.C: New test. + +2007-11-06 Jan Hubicka <jh@suse.cz> + + PR tree-optimization/33763 + * tree-inline.c (expand_call_inline): Silently ignore always_inline + attribute for redefined extern inline functions. + +--- gcc/tree-inline.c.jj 2007-11-06 09:29:04.000000000 +0100 ++++ gcc/tree-inline.c 2007-11-06 16:19:12.000000000 +0100 +@@ -2582,6 +2582,12 @@ expand_call_inline (basic_block bb, tree + if (!cgraph_inline_p (cg_edge, &reason)) + { + if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) ++ /* For extern inline functions that get redefined we always ++ silently ignored alway_inline flag. Better behaviour would ++ be to be able to keep both bodies and use extern inline body ++ for inlining, but we can't do that because frontends overwrite ++ the body. */ ++ && !cg_edge->callee->local.redefined_extern_inline + /* Avoid warnings during early inline pass. */ + && (!flag_unit_at_a_time || cgraph_global_info_ready)) + { +--- gcc/testsuite/gcc.dg/pr33763.c.jj 2007-11-06 16:19:12.000000000 +0100 ++++ gcc/testsuite/gcc.dg/pr33763.c 2007-11-06 16:19:12.000000000 +0100 +@@ -0,0 +1,60 @@ ++/* PR tree-optimization/33763 */ ++/* { dg-do compile } */ ++/* { dg-options "-O2" } */ ++ ++typedef struct ++{ ++ void *a; ++ void *b; ++} T; ++extern void *foo (const char *, const char *); ++extern void *bar (void *, const char *, T); ++extern int baz (const char *, int); ++ ++extern inline __attribute__ ((always_inline, gnu_inline)) int ++baz (const char *x, int y) ++{ ++ return 2; ++} ++ ++int ++baz (const char *x, int y) ++{ ++ return 1; ++} ++ ++int xa, xb; ++ ++static void * ++inl (const char *x, const char *y) ++{ ++ T t = { &xa, &xb }; ++ int *f = (int *) __builtin_malloc (sizeof (int)); ++ const char *z; ++ int o = 0; ++ void *r = 0; ++ ++ for (z = y; *z; z++) ++ { ++ if (*z == 'r') ++ o |= 1; ++ if (*z == 'w') ++ o |= 2; ++ } ++ if (o == 1) ++ *f = baz (x, 0); ++ if (o == 2) ++ *f = baz (x, 1); ++ if (o == 3) ++ *f = baz (x, 2); ++ ++ if (o && *f > 0) ++ r = bar (f, "w", t); ++ return r; ++} ++ ++void * ++foo (const char *x, const char *y) ++{ ++ return inl (x, y); ++} +--- gcc/testsuite/g++.dg/opt/inline13.C.jj 2007-11-06 16:20:20.000000000 +0100 ++++ gcc/testsuite/g++.dg/opt/inline13.C 2007-11-06 16:21:30.000000000 +0100 +@@ -0,0 +1,60 @@ ++// PR tree-optimization/33763 ++// { dg-do compile } ++// { dg-options "-O2" } ++ ++typedef struct ++{ ++ void *a; ++ void *b; ++} T; ++extern void *foo (const char *, const char *); ++extern void *bar (void *, const char *, T); ++extern int baz (const char *, int); ++ ++extern inline __attribute__ ((always_inline, gnu_inline)) int ++baz (const char *x, int y) ++{ ++ return 2; ++} ++ ++int ++baz (const char *x, int y) ++{ ++ return 1; ++} ++ ++int xa, xb; ++ ++static void * ++inl (const char *x, const char *y) ++{ ++ T t = { &xa, &xb }; ++ int *f = (int *) __builtin_malloc (sizeof (int)); ++ const char *z; ++ int o = 0; ++ void *r = 0; ++ ++ for (z = y; *z; z++) ++ { ++ if (*z == 'r') ++ o |= 1; ++ if (*z == 'w') ++ o |= 2; ++ } ++ if (o == 1) ++ *f = baz (x, 0); ++ if (o == 2) ++ *f = baz (x, 1); ++ if (o == 3) ++ *f = baz (x, 2); ++ ++ if (o && *f > 0) ++ r = bar (f, "w", t); ++ return r; ++} ++ ++void * ++foo (const char *x, const char *y) ++{ ++ return inl (x, y); ++} diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr35440.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr35440.patch new file mode 100644 index 0000000000..6bf3f0d9d8 --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr35440.patch @@ -0,0 +1,56 @@ +2008-03-19 Jakub Jelinek <jakub@redhat.com> + + PR c/35440 + * c-pretty-print.c (pp_c_initializer_list): Handle CONSTRUCTOR + for all types. + + * gcc.dg/pr35440.c: New test. + +--- gcc/c-pretty-print.c.jj 2008-02-11 14:48:12.000000000 +0100 ++++ gcc/c-pretty-print.c 2008-03-19 14:50:09.000000000 +0100 +@@ -1173,6 +1173,12 @@ pp_c_initializer_list (c_pretty_printer + tree type = TREE_TYPE (e); + const enum tree_code code = TREE_CODE (type); + ++ if (TREE_CODE (e) == CONSTRUCTOR) ++ { ++ pp_c_constructor_elts (pp, CONSTRUCTOR_ELTS (e)); ++ return; ++ } ++ + switch (code) + { + case RECORD_TYPE: +@@ -1207,16 +1213,12 @@ pp_c_initializer_list (c_pretty_printer + case VECTOR_TYPE: + if (TREE_CODE (e) == VECTOR_CST) + pp_c_expression_list (pp, TREE_VECTOR_CST_ELTS (e)); +- else if (TREE_CODE (e) == CONSTRUCTOR) +- pp_c_constructor_elts (pp, CONSTRUCTOR_ELTS (e)); + else + break; + return; + + case COMPLEX_TYPE: +- if (TREE_CODE (e) == CONSTRUCTOR) +- pp_c_constructor_elts (pp, CONSTRUCTOR_ELTS (e)); +- else if (TREE_CODE (e) == COMPLEX_CST || TREE_CODE (e) == COMPLEX_EXPR) ++ if (TREE_CODE (e) == COMPLEX_CST || TREE_CODE (e) == COMPLEX_EXPR) + { + const bool cst = TREE_CODE (e) == COMPLEX_CST; + pp_expression (pp, cst ? TREE_REALPART (e) : TREE_OPERAND (e, 0)); +--- gcc/testsuite/gcc.dg/pr35440.c.jj 2008-03-19 15:57:13.000000000 +0100 ++++ gcc/testsuite/gcc.dg/pr35440.c 2008-03-19 15:47:35.000000000 +0100 +@@ -0,0 +1,12 @@ ++/* PR c/35440 */ ++/* { dg-do compile } */ ++/* { dg-options "-std=gnu99" } */ ++ ++struct A {}; ++struct B { int i; char j[2]; }; ++ ++void foo (void) ++{ ++ (struct A){}(); /* { dg-error "called object" } */ ++ (struct B){ .i = 2, .j[1] = 1 }(); /* { dg-error "called object" } */ ++} diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr35751.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr35751.patch new file mode 100644 index 0000000000..37b84275e2 --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-pr35751.patch @@ -0,0 +1,114 @@ +2008-04-03 Jakub Jelinek <jakub@redhat.com> + + PR c/35751 + * c-decl.c (finish_decl): If extern or static var has variable + size, set TREE_TYPE (decl) to error_mark_node. + + * decl.c (layout_var_decl): If extern or static var has variable + size, set TREE_TYPE (decl) to error_mark_node. + + * gcc.dg/gomp/pr35751.c: New test. + * g++.dg/gomp/pr35751.C: New test. + +--- gcc/c-decl.c.jj 2008-04-03 09:41:42.000000000 +0200 ++++ gcc/c-decl.c 2008-04-03 18:20:52.000000000 +0200 +@@ -3481,7 +3481,10 @@ finish_decl (tree decl, tree init, tree + if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST) + constant_expression_warning (DECL_SIZE (decl)); + else +- error ("storage size of %q+D isn%'t constant", decl); ++ { ++ error ("storage size of %q+D isn%'t constant", decl); ++ TREE_TYPE (decl) = error_mark_node; ++ } + } + + if (TREE_USED (type)) +--- gcc/cp/decl.c.jj 2008-03-31 23:54:40.000000000 +0200 ++++ gcc/cp/decl.c 2008-04-03 18:30:19.000000000 +0200 +@@ -4442,7 +4442,10 @@ layout_var_decl (tree decl) + if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST) + constant_expression_warning (DECL_SIZE (decl)); + else +- error ("storage size of %qD isn't constant", decl); ++ { ++ error ("storage size of %qD isn't constant", decl); ++ TREE_TYPE (decl) = error_mark_node; ++ } + } + } + +--- gcc/testsuite/gcc.dg/gomp/pr35751.c.jj 2008-04-03 18:26:12.000000000 +0200 ++++ gcc/testsuite/gcc.dg/gomp/pr35751.c 2008-04-03 18:25:51.000000000 +0200 +@@ -0,0 +1,34 @@ ++/* PR c/35751 */ ++/* { dg-do compile } */ ++/* { dg-options "-fopenmp" } */ ++ ++void ++foo (int i) ++{ ++ extern int a[i]; /* { dg-error "must have no linkage|storage size of" } */ ++ static int b[i]; /* { dg-error "storage size of" } */ ++ ++#pragma omp parallel ++ { ++ a[0] = 0; ++ b[0] = 0; ++ } ++ ++#pragma omp parallel shared (a, b) ++ { ++ a[0] = 0; ++ b[0] = 0; ++ } ++ ++#pragma omp parallel private (a, b) ++ { ++ a[0] = 0; ++ b[0] = 0; ++ } ++ ++#pragma omp parallel firstprivate (a, b) ++ { ++ a[0] = 0; ++ b[0] = 0; ++ } ++} +--- gcc/testsuite/g++.dg/gomp/pr35751.C.jj 2008-04-03 18:32:13.000000000 +0200 ++++ gcc/testsuite/g++.dg/gomp/pr35751.C 2008-04-03 18:32:32.000000000 +0200 +@@ -0,0 +1,34 @@ ++// PR c/35751 ++// { dg-do compile } ++// { dg-options "-fopenmp" } ++ ++void ++foo (int i) ++{ ++ extern int a[i]; // { dg-error "storage size of" } ++ static int b[i]; // { dg-error "storage size of" } ++ ++#pragma omp parallel ++ { ++ a[0] = 0; ++ b[0] = 0; ++ } ++ ++#pragma omp parallel shared (a, b) ++ { ++ a[0] = 0; ++ b[0] = 0; ++ } ++ ++#pragma omp parallel private (a, b) ++ { ++ a[0] = 0; ++ b[0] = 0; ++ } ++ ++#pragma omp parallel firstprivate (a, b) ++ { ++ a[0] = 0; ++ b[0] = 0; ++ } ++} diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-rh251682.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-rh251682.patch new file mode 100644 index 0000000000..e96ae6f134 --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-rh251682.patch @@ -0,0 +1,89 @@ +2008-04-01 Jakub Jelinek <jakub@redhat.com> + + PR pch/13675 + * files.c (struct _cpp_file): Remove pch field. + (pch_open_file): Don't set file->pch, just file->pchname. + (should_stack_file): After pfile->cb.read_pch call + free pchname and clear pchname, don't close file->fd. + Test file->pchname instead of file->pch. Don't close fd after cb. + (_cpp_stack_include): Test file->pchname instead of file->pch. + + * c-pch.c (c_common_read_pch): On error close (fd) resp. fclose (f). + +--- libcpp/files.c.jj 2008-02-18 23:50:17.000000000 +0100 ++++ libcpp/files.c 2008-03-31 15:59:01.000000000 +0200 +@@ -106,9 +106,6 @@ struct _cpp_file + + /* If BUFFER above contains the true contents of the file. */ + bool buffer_valid; +- +- /* File is a PCH (on return from find_include_file). */ +- bool pch; + }; + + /* A singly-linked list for all searches for a given file name, with +@@ -322,9 +319,7 @@ pch_open_file (cpp_reader *pfile, _cpp_f + } + closedir (pchdir); + } +- if (valid) +- file->pch = true; +- else ++ if (!valid) + *invalid_pch = true; + } + +@@ -703,11 +698,12 @@ should_stack_file (cpp_reader *pfile, _c + return false; + + /* Handle PCH files immediately; don't stack them. */ +- if (file->pch) ++ if (file->pchname) + { + pfile->cb.read_pch (pfile, file->pchname, file->fd, file->path); +- close (file->fd); + file->fd = -1; ++ free ((void *) file->pchname); ++ file->pchname = NULL; + return false; + } + +@@ -916,7 +912,7 @@ _cpp_stack_include (cpp_reader *pfile, c + complicates LAST_SOURCE_LINE_LOCATION. This does not apply if we + found a PCH file (in which case linemap_add is not called) or we + were included from the command-line. */ +- if (! file->pch && file->err_no == 0 && type != IT_CMDLINE) ++ if (file->pchname == NULL && file->err_no == 0 && type != IT_CMDLINE) + pfile->line_table->highest_location--; + + return _cpp_stack_file (pfile, file, type == IT_IMPORT); +--- gcc/c-pch.c.jj 2008-02-18 23:46:08.000000000 +0100 ++++ gcc/c-pch.c 2008-03-31 15:56:00.000000000 +0200 +@@ -372,6 +372,7 @@ c_common_read_pch (cpp_reader *pfile, co + if (f == NULL) + { + cpp_errno (pfile, CPP_DL_ERROR, "calling fdopen"); ++ close (fd); + return; + } + +@@ -380,6 +381,7 @@ c_common_read_pch (cpp_reader *pfile, co + if (fread (&h, sizeof (h), 1, f) != 1) + { + cpp_errno (pfile, CPP_DL_ERROR, "reading"); ++ fclose (f); + return; + } + +@@ -425,7 +427,10 @@ c_common_read_pch (cpp_reader *pfile, co + gt_pch_restore (f); + + if (cpp_read_state (pfile, name, f, smd) != 0) +- return; ++ { ++ fclose (f); ++ return; ++ } + + fclose (f); + diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-rh330771.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-rh330771.patch new file mode 100644 index 0000000000..c894f83b43 --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-rh330771.patch @@ -0,0 +1,34 @@ +2007-10-16 Jakub Jelinek <jakub@redhat.com> + + * Makefile.am (libgcj_tools_la_LIBADD): Add. + * Makefile.in: Regenerated. + +--- libjava/Makefile.am.jj 2007-03-17 09:20:30.000000000 +0100 ++++ libjava/Makefile.am 2007-10-16 15:45:14.000000000 +0200 +@@ -262,6 +262,8 @@ EXTRA_libgcj_la_SOURCES = java/lang/Obje + + libgcj_tools_la_SOURCES = classpath/tools/tools.zip + libgcj_tools_la_GCJFLAGS = $(AM_GCJFLAGS) -findirect-dispatch -fno-indirect-classes -fsource-filename=$(here)/classpath/tools/all-classes.lst ++## See jv_convert_LDADD. ++libgcj_tools_la_LIBADD = -L$(here)/.libs libgcj.la + libgcj_tools_la_LDFLAGS = -rpath $(toolexeclibdir) \ + -version-info `grep -v '^\#' $(srcdir)/libtool-version` + libgcj_tools_la_DEPENDENCIES = libgcj.la libgcj.spec +--- libjava/Makefile.in.jj 2007-07-04 21:11:11.000000000 +0200 ++++ libjava/Makefile.in 2007-10-16 15:56:07.000000000 +0200 +@@ -146,7 +146,6 @@ am__objects_1 = gnu/gcj/xlib/lib_gnu_awt + am_lib_gnu_awt_xlib_la_OBJECTS = $(am__objects_1) + lib_gnu_awt_xlib_la_OBJECTS = $(am_lib_gnu_awt_xlib_la_OBJECTS) + @XLIB_AWT_TRUE@am_lib_gnu_awt_xlib_la_rpath = -rpath $(toolexeclibdir) +-libgcj_tools_la_LIBADD = + am_libgcj_tools_la_OBJECTS = classpath/tools/libgcj_tools_la-tools.lo + libgcj_tools_la_OBJECTS = $(am_libgcj_tools_la_OBJECTS) + am__DEPENDENCIES_1 = gnu/awt.lo gnu/awt/j2d.lo gnu/classpath.lo \ +@@ -894,6 +893,7 @@ libgcj_la_LINK = $(LIBLINK) + EXTRA_libgcj_la_SOURCES = java/lang/Object.java + libgcj_tools_la_SOURCES = classpath/tools/tools.zip + libgcj_tools_la_GCJFLAGS = $(AM_GCJFLAGS) -findirect-dispatch -fno-indirect-classes -fsource-filename=$(here)/classpath/tools/all-classes.lst ++libgcj_tools_la_LIBADD = -L$(here)/.libs libgcj.la + libgcj_tools_la_LDFLAGS = -rpath $(toolexeclibdir) \ + -version-info `grep -v '^\#' $(srcdir)/libtool-version` + diff --git a/recipes/gcc/gcc-4.4.1/fedora/gcc43-rh341221.patch b/recipes/gcc/gcc-4.4.1/fedora/gcc43-rh341221.patch new file mode 100644 index 0000000000..28e73b07c3 --- /dev/null +++ b/recipes/gcc/gcc-4.4.1/fedora/gcc43-rh341221.patch @@ -0,0 +1,28 @@ +2007-10-21 Jakub Jelinek <jakub@redhat.com> + + * doc/Makefile.am (POD2MAN): Set date from cp-tools.texinfo + timestamp rather than from current date. + * doc/Makefile.in: Regenerated. + +--- libjava/classpath/doc/Makefile.am.jj 2007-12-07 17:55:00.000000000 +0100 ++++ libjava/classpath/doc/Makefile.am 2007-12-07 18:55:28.000000000 +0100 +@@ -30,7 +30,7 @@ TOOLS_MANFILES = \ + gserialver.1 \ + gtnameserv.1 + +-POD2MAN = pod2man --center="GNU" --release="$(VERSION)" ++POD2MAN = pod2man --center="GNU" --release="$(VERSION)" --date="$(shell ls --time-style=+%F -l $(srcdir)/cp-tools.texinfo | awk '{print $$6}')" + TEXI2POD = perl $(srcdir)/texi2pod.pl + STAMP = echo timestamp > + +--- libjava/classpath/doc/Makefile.in.jj 2007-12-07 17:55:00.000000000 +0100 ++++ libjava/classpath/doc/Makefile.in 2007-12-07 18:55:43.000000000 +0100 +@@ -357,7 +357,7 @@ TOOLS_MANFILES = \ + gserialver.1 \ + gtnameserv.1 + +-POD2MAN = pod2man --center="GNU" --release="$(VERSION)" ++POD2MAN = pod2man --center="GNU" --release="$(VERSION)" --date="$(shell ls --time-style=+%F -l $(srcdir)/cp-tools.texinfo | awk '{print $$6}')" + TEXI2POD = perl $(srcdir)/texi2pod.pl + STAMP = echo timestamp > + @GENINSRC_FALSE@STAMP_GENINSRC = |