From 8dc56a2244cfe35cbdb53e0f586c16f90a2677e4 Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Fri, 1 Nov 2019 20:35:12 +0000 Subject: RISC-V: Build soft-float divide routines for -mno-fdiv. Using -mno-fdiv gives linker errors unless we build the missing divide routines in libgcc always. There is at least one university project designing RISC-V parts without FP divide that wants to use the option. libgcc/ * config/riscv/t-softfp32 (softfp_extra): Add FP divide routines From-SVN: r277723 --- libgcc/ChangeLog | 4 ++++ libgcc/config/riscv/t-softfp32 | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 9919994..4a855cb 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,7 @@ +2019-11-01 Jim Wilson + + * config/riscv/t-softfp32 (softfp_extra): Add FP divide routines + 2019-10-23 Jozef Lawrynowicz * config/msp430/lib2hw_mul.S: Fix wrong syntax in branch instruction. diff --git a/libgcc/config/riscv/t-softfp32 b/libgcc/config/riscv/t-softfp32 index 1bd51e8..59be1df 100644 --- a/libgcc/config/riscv/t-softfp32 +++ b/libgcc/config/riscv/t-softfp32 @@ -12,7 +12,11 @@ softfp_float_modes := tf softfp_extensions := sftf dftf softfp_truncations := tfsf tfdf +# Enable divide routines to make -mno-fdiv work. +softfp_extras := divsf3 divdf3 + else +# !ABI_DOUBLE softfp_float_modes := df tf softfp_extensions := sfdf sftf dftf @@ -20,7 +24,20 @@ softfp_truncations := dfsf tfsf tfdf ifndef ABI_SINGLE softfp_float_modes += sf +else +# ABI_SINGLE + +# Enable divide routines to make -mno-fdiv work. +softfp_extras := divsf3 + endif endif + +else +# ABI_QUAD + +# Enable divide routines to make -mno-fdiv work. +softfp_extras := divsf3 divdf3 divtf3 + endif -- cgit v1.1 From da5c1bbe973db144cc1d297ad49b519a870ab0ba Mon Sep 17 00:00:00 2001 From: Oleg Endo Date: Sun, 3 Nov 2019 12:09:26 +0000 Subject: re PR libgcc/78804 ([RX] -m64bit-doubles does not work) libgcc/ PR libgcc/78804 * fp-bit.h: Remove FLOAT_BIT_ORDER_MISMATCH. * fp-bit.c (pack_d, unpack_d): Remove special cases for FLOAT_BIT_ORDER_MISMATCH. * config/arc/t-arc: Remove FLOAT_BIT_ORDER_MISMATCH. From-SVN: r277752 --- libgcc/ChangeLog | 8 ++++++++ libgcc/config/arc/t-arc | 2 -- libgcc/fp-bit.c | 20 ++++---------------- libgcc/fp-bit.h | 14 -------------- 4 files changed, 12 insertions(+), 32 deletions(-) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 4a855cb..806d048 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,11 @@ +2019-11-03 Oleg Endo + + PR libgcc/78804 + * fp-bit.h: Remove FLOAT_BIT_ORDER_MISMATCH. + * fp-bit.c (pack_d, unpack_d): Remove special cases for + FLOAT_BIT_ORDER_MISMATCH. + * config/arc/t-arc: Remove FLOAT_BIT_ORDER_MISMATCH. + 2019-11-01 Jim Wilson * config/riscv/t-softfp32 (softfp_extra): Add FP divide routines diff --git a/libgcc/config/arc/t-arc b/libgcc/config/arc/t-arc index 7b0956c..9e1b130 100644 --- a/libgcc/config/arc/t-arc +++ b/libgcc/config/arc/t-arc @@ -46,7 +46,6 @@ LIB2ADD = fp-bit.c dp-bit.c dp-bit.c: $(srcdir)/fp-bit.c echo '#ifndef __big_endian__' > dp-bit.c - echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c echo '#endif' >> dp-bit.c echo '#include "fp-bit.h"' >> dp-bit.c echo '#include "config/arc/dp-hack.h"' >> dp-bit.c @@ -55,7 +54,6 @@ dp-bit.c: $(srcdir)/fp-bit.c fp-bit.c: $(srcdir)/fp-bit.c echo '#define FLOAT' > fp-bit.c echo '#ifndef __big_endian__' >> fp-bit.c - echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c echo '#endif' >> fp-bit.c echo '#include "config/arc/fp-hack.h"' >> fp-bit.c cat $(srcdir)/fp-bit.c >> fp-bit.c diff --git a/libgcc/fp-bit.c b/libgcc/fp-bit.c index a9cc3c0..658f42c 100644 --- a/libgcc/fp-bit.c +++ b/libgcc/fp-bit.c @@ -316,12 +316,7 @@ pack_d (const fp_number_type *src) /* We previously used bitfields to store the number, but this doesn't handle little/big endian systems conveniently, so use shifts and masks */ -#ifdef FLOAT_BIT_ORDER_MISMATCH - dst.bits.fraction = fraction; - dst.bits.exp = exp; - dst.bits.sign = sign; -#else -# if defined TFLOAT && defined HALFFRACBITS +#if defined TFLOAT && defined HALFFRACBITS { halffractype high, low, unity; int lowsign, lowexp; @@ -394,11 +389,10 @@ pack_d (const fp_number_type *src) } dst.value_raw = ((fractype) high << HALFSHIFT) | low; } -# else +#else dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1); dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS; dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS); -# endif #endif #if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT) @@ -450,12 +444,7 @@ unpack_d (FLO_union_type * src, fp_number_type * dst) src = &swapped; #endif -#ifdef FLOAT_BIT_ORDER_MISMATCH - fraction = src->bits.fraction; - exp = src->bits.exp; - sign = src->bits.sign; -#else -# if defined TFLOAT && defined HALFFRACBITS +#if defined TFLOAT && defined HALFFRACBITS { halffractype high, low; @@ -498,11 +487,10 @@ unpack_d (FLO_union_type * src, fp_number_type * dst) } } } -# else +#else fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1); exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1); sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1; -# endif #endif dst->sign = sign; diff --git a/libgcc/fp-bit.h b/libgcc/fp-bit.h index 5c2b3df..de679bd 100644 --- a/libgcc/fp-bit.h +++ b/libgcc/fp-bit.h @@ -128,10 +128,6 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); #define NO_DI_MODE #endif -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define FLOAT_BIT_ORDER_MISMATCH -#endif - #if __BYTE_ORDER__ != __FLOAT_WORD_ORDER__ #define FLOAT_WORD_ORDER_MISMATCH #endif @@ -354,16 +350,6 @@ typedef union # endif #endif -#ifdef FLOAT_BIT_ORDER_MISMATCH - struct - { - fractype fraction:FRACBITS __attribute__ ((packed)); - unsigned int exp:EXPBITS __attribute__ ((packed)); - unsigned int sign:1 __attribute__ ((packed)); - } - bits; -#endif - #ifdef _DEBUG_BITFLOAT struct { -- cgit v1.1 From 62ec242ea1e75cf3200c59a97ea941046e5d6408 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Mon, 4 Nov 2019 12:41:56 +0000 Subject: libgcc: Fix incorrect use of USE_TM_CLONE_REGISTRY 2019-11-04 Jozef Lawrynowicz * crtstuff.c: Define USE_TM_CLONE_REGISTRY to 0 if it's undefined and the target output object format is not ELF. s/defined(USE_TM_CLONE_REGISTRY)/USE_TM_CLONE_REGISTRY. From-SVN: r277775 --- libgcc/ChangeLog | 6 ++++++ libgcc/crtstuff.c | 11 +++++------ 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 806d048..c528cec 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,9 @@ +2019-11-04 Jozef Lawrynowicz + + * crtstuff.c: Define USE_TM_CLONE_REGISTRY to 0 if it's undefined and + the target output object format is not ELF. + s/defined(USE_TM_CLONE_REGISTRY)/USE_TM_CLONE_REGISTRY. + 2019-11-03 Oleg Endo PR libgcc/78804 diff --git a/libgcc/crtstuff.c b/libgcc/crtstuff.c index c93e1cb..ae6328d 100644 --- a/libgcc/crtstuff.c +++ b/libgcc/crtstuff.c @@ -153,6 +153,8 @@ call_ ## FUNC (void) \ #if !defined(USE_TM_CLONE_REGISTRY) && defined(OBJECT_FORMAT_ELF) # define USE_TM_CLONE_REGISTRY 1 +#elif !defined(USE_TM_CLONE_REGISTRY) +# define USE_TM_CLONE_REGISTRY 0 #endif /* We do not want to add the weak attribute to the declarations of these @@ -450,8 +452,7 @@ CRT_CALL_STATIC_FUNCTION (__LIBGCC_INIT_SECTION_ASM_OP__, __do_global_dtors_aux_1) #endif -#if defined(USE_EH_FRAME_REGISTRY) \ - || defined(USE_TM_CLONE_REGISTRY) +#if defined(USE_EH_FRAME_REGISTRY) || USE_TM_CLONE_REGISTRY /* Stick a call to __register_frame_info into the .init section. For some reason calls with no arguments work more reliably in .init, so stick the call in another function. */ @@ -560,8 +561,7 @@ __do_global_dtors (void) #endif } -#if defined(USE_EH_FRAME_REGISTRY) \ - || defined(USE_TM_CLONE_REGISTRY) +#if defined(USE_EH_FRAME_REGISTRY) || USE_TM_CLONE_REGISTRY /* A helper function for __do_global_ctors, which is in crtend.o. Here in crtbegin.o, we can reference a couple of symbols not visible there. Plus, since we're before libgcc.a, we have no problems referencing @@ -733,8 +733,7 @@ void __do_global_ctors (void) { func_ptr *p; -#if defined(USE_EH_FRAME_REGISTRY) \ - || defined(USE_TM_CLONE_REGISTRY) +#if defined(USE_EH_FRAME_REGISTRY) || USE_TM_CLONE_REGISTRY __do_global_ctors_1(); #endif for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--) -- cgit v1.1 From 29f3def30844dd13e79972fa03a50af68120f7ac Mon Sep 17 00:00:00 2001 From: Georg-Johann Lay Date: Thu, 7 Nov 2019 09:19:31 +0000 Subject: Support 64-bit double and 64-bit long double configurations. gcc/ Support 64-bit double and 64-bit long double configurations. PR target/92055 * config.gcc (tm_defines) [avr]: Set from --with-double=, --with-long-double=. * config/avr/t-multilib: Remove. * config/avr/t-avr: Output of genmultilib.awk is now fully dynamically generated and no more part of the repo. (HAVE_DOUBLE_MULTILIB, HAVE_LONG_DOUBLE_MULTILIB): New variables. Pass them down to... * config/avr/genmultilib.awk: ...here and handle them. * gcc/config/avr/avr.opt (-mdouble=, avr_double). New option and var. (-mlong-double=, avr_long_double). New option and var. * common/config/avr/avr-common.c (opts.h, diagnostic.h): Include. (TARGET_OPTION_OPTIMIZATION_TABLE) <-mdouble=, -mlong-double=>: Set default as requested by --with-double= (TARGET_HANDLE_OPTION): Define to this... (avr_handle_option): ...new hook worker. * config/avr/avr.h (DOUBLE_TYPE_SIZE): Define to avr_double. (LONG_DOUBLE_TYPE_SIZE): Define to avr_long_double. (avr_double_lib): New proto for spec function. (EXTRA_SPEC_FUNCTIONS) : Add. (DRIVER_SELF_SPECS): Call %:double-lib. * config/avr/avr.c (avr_option_override): Assert sizeof(long double) >= sizeof(double) for the target. * config/avr/avr-c.c (avr_cpu_cpp_builtins) [__HAVE_DOUBLE_MULTILIB__, __HAVE_LONG_DOUBLE_MULTILIB__] [__HAVE_DOUBLE64__, __HAVE_DOUBLE32__, __DEFAULT_DOUBLE__=] [__HAVE_LONG_DOUBLE64__, __HAVE_LONG_DOUBLE32__] [__HAVE_LONG_DOUBLE_IS_DOUBLE__, __DEFAULT_LONG_DOUBLE__=]: New built-in define depending on --with-double=, --with-long-double=. * config/avr/driver-avr.c (avr_double_lib): New spec function. * doc/invoke.tex (AVR Options) <-mdouble=,-mlong-double=>: Doc. * doc/install.texi (Cross-Compiler-Specific Options) <--with-double=, --with-long-double=>: Doc. libgcc/ Support 64-bit double and 64-bit long double configurations. PR target/92055 * config/avr/t-avr (HOST_LIBGCC2_CFLAGS): Only add -DF=SF if long double is a 32-bit type. * config/avr/t-avrlibc: Copy double64 and long-double64 multilib(s) from the vanilla one. * config/avr/t-copy-libgcc: New Makefile snip. From-SVN: r277908 --- libgcc/ChangeLog | 11 +++++++++++ libgcc/config.host | 3 +++ libgcc/config/avr/t-avr | 8 ++++++-- libgcc/config/avr/t-avrlibc | 31 +++++++++++++++++++++++++++++++ libgcc/config/avr/t-copy-libgcc | 13 +++++++++++++ 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 libgcc/config/avr/t-copy-libgcc (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index c528cec..ff26a0c 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,14 @@ +2019-11-07 Georg-Johann Lay + + Support 64-bit double and 64-bit long double configurations. + + PR target/92055 + * config/avr/t-avr (HOST_LIBGCC2_CFLAGS): Only add -DF=SF if + long double is a 32-bit type. + * config/avr/t-avrlibc: Copy double64 and long-double64 + multilib(s) from the vanilla one. + * config/avr/t-copy-libgcc: New Makefile snip. + 2019-11-04 Jozef Lawrynowicz * crtstuff.c: Define USE_TM_CLONE_REGISTRY to 0 if it's undefined and diff --git a/libgcc/config.host b/libgcc/config.host index 122113f..0b8eb4e 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -505,6 +505,9 @@ avr-*-*) tmake_file="$tmake_file ${cpu_type}/t-avrlibc" fi tm_file="$tm_file avr/avr-lib.h" + if test x${with_fixed_point} = xno; then + fixed_point=no + fi ;; bfin*-elf*) tmake_file="bfin/t-bfin bfin/t-crtlibid bfin/t-crtstuff t-libgcc-pic t-fdpbit" diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr index c420c5d..e4f867b 100644 --- a/libgcc/config/avr/t-avr +++ b/libgcc/config/avr/t-avr @@ -112,10 +112,14 @@ LIB2FUNCS_EXCLUDE = \ _clrsbdi2 \ -# We do not have the DF type. +ifeq ($(long_double_type_size),32) +# We do not have the DFtype. +HOST_LIBGCC2_CFLAGS += -DDF=SF +endif + # Most of the C functions in libgcc2 use almost all registers, # so use -mcall-prologues for smaller code size. -HOST_LIBGCC2_CFLAGS += -DDF=SF -Dinhibit_libc -mcall-prologues -Os +HOST_LIBGCC2_CFLAGS += -Dinhibit_libc -mcall-prologues -Os # Extra 16-bit integer functions. intfuncs16 = _absvXX2 _addvXX3 _subvXX3 _mulvXX3 _negvXX2 _clrsbXX2 diff --git a/libgcc/config/avr/t-avrlibc b/libgcc/config/avr/t-avrlibc index d2c8b87..2424d66 100644 --- a/libgcc/config/avr/t-avrlibc +++ b/libgcc/config/avr/t-avrlibc @@ -64,3 +64,34 @@ LIB2FUNCS_EXCLUDE += \ _fixunssfsi _fixsfdi \ _fixunssfdi \ _floatdisf _floatundisf + +ifneq (,$(findstring avr,$(MULTISUBDIR))) + +# We are not in the avr2 (default) subdir, hence copying will work. +# In default dir, copying won'twork because the default multilib is +# built after all the others. + +ifneq (,$(findstring double64,$(MULTISUBDIR))) + +# We are in double64/libgcc or long-double64/libgcc: +# Just copy from the [long ]double=float multilib; we would remove any DFmode +# bits from this multilib variant, anyway, because the current assumption +# is that avr-libc hosts *all* the IEEE-double stuff. + +LIB2FUNCS_EXCLUDE := % +LIB1ASMFUNCS := +libgcc-objects := +libgcov-objects := +objects := + +t-copy-libgcc.dep: $(srcdir)/config/avr/t-copy-libgcc + -rm -f libgcc.a + -rm -f libgcov.a + cp $< $@ + +libgcc.a libgcov.a libgcc_tm.h: t-copy-libgcc.dep + +Makefile: t-copy-libgcc.dep + +endif +endif diff --git a/libgcc/config/avr/t-copy-libgcc b/libgcc/config/avr/t-copy-libgcc new file mode 100644 index 0000000..d34cbde --- /dev/null +++ b/libgcc/config/avr/t-copy-libgcc @@ -0,0 +1,13 @@ +# Only used with --with-avrlibc & (-mlong-double=64 | -mdouble=64) +# +# Inserted at the end of Makefile by magic[tm]. +# We need this *after* Makefile's rules so we can override them. + +libgcc.a: ../../libgcc/libgcc.a + cp $< $@ + +libgcov.a: ../../libgcc/libgcov.a + @: +ifeq ($(enable_gcov),yes) + cp $< $@ +endif -- cgit v1.1 From 78e49fb1bc69592389a09ce5544b40fef634e893 Mon Sep 17 00:00:00 2001 From: Jerome Lambourg Date: Thu, 14 Nov 2019 15:53:23 +0000 Subject: Introduce vxworks specific crtstuff support 2019-11-06 Jerome Lambourg Olivier Hainque libgcc/ * config/vxcrtstuff.c: New file. * config/t-vxcrtstuff: New Makefile fragment. * config.host: Append t-vxcrtstuff to the tmake_file list on all VxWorks ports using dwarf for table based EH. gcc/ * config/vx-common.h (USE_TM_CLONE_REGISTRY): Remove definition, pointless with a VxWorks specific version of crtstuff. (DWARF2_UNWIND_INFO): Conditionalize on !ARM_UNWIND_INFO. * config/vxworks.h (VX_CRTBEGIN_SPEC, VX_CRTEND_SPEC): New local macros, controlling the addition of vxworks specific crtstuff objects depending on the EH mechanism and kind of module being linked. (VXWORKS_STARTFILE_SPEC, VXWORKS_ENDFILE_SPEC): Use them. Co-Authored-By: Olivier Hainque From-SVN: r278248 --- libgcc/ChangeLog | 8 +++ libgcc/config.host | 10 ++++ libgcc/config/t-vxcrtstuff | 12 +++++ libgcc/config/vxcrtstuff.c | 132 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 libgcc/config/t-vxcrtstuff create mode 100644 libgcc/config/vxcrtstuff.c (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index ff26a0c..845dbd0 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,11 @@ +2019-11-06 Jerome Lambourg + Olivier Hainque + + * config/vxcrtstuff.c: New file. + * config/t-vxcrtstuff: New Makefile fragment. + * config.host: Append t-vxcrtstuff to the tmake_file list + on all VxWorks ports using dwarf for table based EH. + 2019-11-07 Georg-Johann Lay Support 64-bit double and 64-bit long double configurations. diff --git a/libgcc/config.host b/libgcc/config.host index 0b8eb4e..b2004af 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -329,6 +329,16 @@ case ${host} in ;; esac +# Except on ARM where we do not use DWARF, table based EH on VxWorks +# relies on specially crafted crtstuff files +case ${host} in +arm-*-vxworks*) + ;; +*-*-vxworks*) + tmake_file="${tmake_file} t-vxcrtstuff" + ;; +esac + case ${host} in *-*-darwin* | *-*-dragonfly* | *-*-freebsd* | *-*-netbsd* | *-*-openbsd* | \ *-*-solaris2*) diff --git a/libgcc/config/t-vxcrtstuff b/libgcc/config/t-vxcrtstuff new file mode 100644 index 0000000..96b7285 --- /dev/null +++ b/libgcc/config/t-vxcrtstuff @@ -0,0 +1,12 @@ +# crtbegin/crtend for VxWorks (DKM or RTP) + +vx_crtbegin-kernel.o: $(srcdir)/config/vxcrtstuff.c + $(crt_compile) $(CRTSTUFF_T_CFLAGS) -DCRT_BEGIN -c $< + +vx_crtbegin-rtp.o: $(srcdir)/config/vxcrtstuff.c + $(crt_compile) $(CRTSTUFF_T_CFLAGS) -DCRT_BEGIN -c $< -mrtp + +vx_crtend.o: $(srcdir)/config/vxcrtstuff.c + $(crt_compile) $(CRTSTUFF_T_CFLAGS) -DCRT_END -c $< + +EXTRA_PARTS += vx_crtbegin-kernel.o vx_crtbegin-rtp.o vx_crtend.o diff --git a/libgcc/config/vxcrtstuff.c b/libgcc/config/vxcrtstuff.c new file mode 100644 index 0000000..616ad07 --- /dev/null +++ b/libgcc/config/vxcrtstuff.c @@ -0,0 +1,132 @@ +/* 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 3, 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* The essential point of the crtbegin/crtend files on VxWorks is to handle + the eh frames registration thanks to dedicated constructors and + destructors. What needs to be done depends on the VxWorks version and the + kind of module (rtp, dkm, ...) one is building. */ + +#define IN_LIBGCC2 + +#include "auto-host.h" +#include "tconfig.h" +#include "tsystem.h" +#include "coretypes.h" +#include "tm.h" +#include "libgcc_tm.h" +#include "unwind-dw2-fde.h" + +/* If we are entitled/requested to use init/fini arrays, we'll rely on that. + Otherwise, we may rely on ctors/dtors sections for RTPs or expect munch to + be involved for kernel modules. */ + +#if !defined(USE_INIT_FINI_ARRAY) && defined(__RTP__) +#define USE_CDTORS_SECTIONS +#endif + +/* ------------------------------ crtbegin ------------------------------- */ + +#ifdef CRT_BEGIN + +/* Stick a label at the beginning of the frame unwind info so we can register + and deregister it with the exception handling library code. */ +static const char __EH_FRAME_BEGIN__[] +__attribute__((section(__LIBGCC_EH_FRAME_SECTION_NAME__), aligned(4))) + = { }; + +/* Determine what names to use for the constructor/destructor functions. */ + +#if defined(USE_CDTORS_SECTIONS) || defined(USE_INITFINI_ARRAY) + +#define EH_CTOR_NAME _crtbe_register_frame +#define EH_DTOR_NAME _ctrbe_deregister_frame + +#else + +/* No specific sections for constructors or destructors: we thus use a + symbol naming convention so that the constructors are then recognized + by munch or whatever tool is used for the final link phase. */ +#define EH_CTOR_NAME _GLOBAL__I_00101_0__crtbe_register_frame +#define EH_DTOR_NAME _GLOBAL__D_00101_1__crtbe_deregister_frame + +#endif + +#ifdef USE_INITFINI_ARRAY +/* .init_array and .fini_array is supported starting VxWorks 7.2 in all + cases. The compiler is then configured to always support priorities in + constructors, so we can rely on the constructor and destructor attributes + to generate the proper sections. */ +#define EH_CTOR_ATTRIBUTE __attribute__((constructor (101))) +#define EH_DTOR_ATTRIBUTE __attribute__((destructor (101))) + +#else /* USE_INITFINI_ARRAY */ + +/* Note: Even in case of .ctors/.dtors sections, we can't use the attribute + (constructor (15)) here as gcc may have been configured with constructors + priority disabled. We will instead craft an explicit section name for this + purpose. */ +#define EH_CTOR_ATTRIBUTE +#define EH_DTOR_ATTRIBUTE + +#endif /* USE_INITFINI_ARRAY */ + +void EH_CTOR_NAME (void); +void EH_DTOR_NAME (void); + +EH_CTOR_ATTRIBUTE void EH_CTOR_NAME (void) +{ + static struct object object; + __register_frame_info (__EH_FRAME_BEGIN__, &object); +} + +EH_DTOR_ATTRIBUTE void EH_DTOR_NAME (void) +{ + __deregister_frame_info (__EH_FRAME_BEGIN__); +} + +#ifdef USE_CDTORS_SECTIONS +/* As explained above, we need to manually build the sections here as the + compiler may not have support for constructors priority enabled. */ +static void (* volatile eh_registration_ctors[])() + __attribute__((section (".ctors.101"))) += { &EH_CTOR_NAME }; +static void (* volatile eh_registration_dtors[])() + __attribute__((section (".dtors.65434"))) += { &EH_DTOR_NAME }; +#endif + +/* ------------------------------ crtend --------------------------------- */ + +#elif defined (CRT_END) /* ! CRT_BEGIN */ + +/* Terminate the frame unwind info section with a 4byte 0 as a sentinel; + this would be the 'length' field in a real FDE. */ + +static const char __FRAME_END__[] + __attribute__ ((used, section(__LIBGCC_EH_FRAME_SECTION_NAME__), + aligned(4))) + = { 0, 0, 0, 0 }; + +#else /* ! CRT_BEGIN & ! CRT_END */ + +#error "One of CRT_BEGIN or CRT_END must be defined." + +#endif -- cgit v1.1 From 806dd0472f56fd8fc410f106660b1ad2c7505bd7 Mon Sep 17 00:00:00 2001 From: Corentin Gay Date: Thu, 14 Nov 2019 15:58:31 +0000 Subject: Improve the thread support for VxWorks 2019-11-12 Corentin Gay Jerome Lambourg Olivier Hainque libgcc/ * config/t-gthr-vxworks: New file, add all the gthr-vxworks sources to LIB2ADDEH. * config/t-vxworks: Remove adjustments to LIB2ADDEH. * config/t-vxworks7: Likewise. * config.host: Append a block at the end of the file to add the t-gthr files to the tmake_file list for VxWorks after everything else. * config/vxlib.c: Rename as gthr-vxworks.c. * config/vxlib-tls.c: Rename as gthr-vxworks-tls.c. * config/gthr-vxworks.h: Simplify a few comments. Expose a TAS API and a basic error checking API, both internal. Simplify the __gthread_once_t type definition and initializers. Add sections for condition variables support and for the C++0x thread support, conditioned against Vx653 for the latter. * config/gthr-vxworks.c (__gthread_once): Simplify comments and implementation, leveraging the TAS internal API. * config/gthr-vxworks-tls.c: Introduce an internal TLS data access API, leveraging the general availability of TLS services in VxWorks7 post SR6xxx. (__gthread_setspecific, __gthread_setspecific): Use it. (tls_delete_hook): Likewise, and simplify the enter/leave dtor logic. * config/gthr-vxworks-cond.c: New file. GTHREAD_COND variable support based on VxWorks primitives. * config/gthr-vxworks-thread.c: New file. GTHREAD_CXX0X support based on VxWorks primitives. Co-Authored-By: Jerome Lambourg Co-Authored-By: Olivier Hainque From-SVN: r278249 --- libgcc/ChangeLog | 34 ++++ libgcc/config.host | 12 ++ libgcc/config/gthr-vxworks-cond.c | 83 ++++++++ libgcc/config/gthr-vxworks-thread.c | 349 ++++++++++++++++++++++++++++++++++ libgcc/config/gthr-vxworks-tls.c | 362 +++++++++++++++++++++++++++++++++++ libgcc/config/gthr-vxworks.c | 87 +++++++++ libgcc/config/gthr-vxworks.h | 272 ++++++++++++++++++++------ libgcc/config/t-gthr-vxworks | 5 + libgcc/config/t-vxworks | 3 - libgcc/config/t-vxworks7 | 4 - libgcc/config/vxlib-tls.c | 370 ------------------------------------ libgcc/config/vxlib.c | 95 --------- 12 files changed, 1146 insertions(+), 530 deletions(-) create mode 100644 libgcc/config/gthr-vxworks-cond.c create mode 100644 libgcc/config/gthr-vxworks-thread.c create mode 100644 libgcc/config/gthr-vxworks-tls.c create mode 100644 libgcc/config/gthr-vxworks.c create mode 100644 libgcc/config/t-gthr-vxworks delete mode 100644 libgcc/config/vxlib-tls.c delete mode 100644 libgcc/config/vxlib.c (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 845dbd0..21efeb5 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,37 @@ +2019-11-12 Corentin Gay + Jerome Lambourg + Olivier Hainque + + * config/t-gthr-vxworks: New file, add all the gthr-vxworks + sources to LIB2ADDEH. + * config/t-vxworks: Remove adjustments to LIB2ADDEH. + * config/t-vxworks7: Likewise. + + * config.host: Append a block at the end of the file to add the + t-gthr files to the tmake_file list for VxWorks after everything + else. + + * config/vxlib.c: Rename as gthr-vxworks.c. + * config/vxlib-tls.c: Rename as gthr-vxworks-tls.c. + + * config/gthr-vxworks.h: Simplify a few comments. Expose a TAS + API and a basic error checking API, both internal. Simplify the + __gthread_once_t type definition and initializers. Add sections + for condition variables support and for the C++0x thread support, + conditioned against Vx653 for the latter. + + * config/gthr-vxworks.c (__gthread_once): Simplify comments and + implementation, leveraging the TAS internal API. + * config/gthr-vxworks-tls.c: Introduce an internal TLS data access + API, leveraging the general availability of TLS services in VxWorks7 + post SR6xxx. + (__gthread_setspecific, __gthread_setspecific): Use it. + (tls_delete_hook): Likewise, and simplify the enter/leave dtor logic. + * config/gthr-vxworks-cond.c: New file. GTHREAD_COND variable + support based on VxWorks primitives. + * config/gthr-vxworks-thread.c: New file. GTHREAD_CXX0X support + based on VxWorks primitives. + 2019-11-06 Jerome Lambourg Olivier Hainque diff --git a/libgcc/config.host b/libgcc/config.host index b2004af..8a090bd 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -1513,3 +1513,15 @@ aarch64*-*-*) tm_file="${tm_file} aarch64/value-unwind.h" ;; esac + +# The vxworks threads implementation relies on a few extra sources, +# which we arrange to add after everything else: + +case ${target_thread_file} in +vxworks) + case ${host} in + *-*-vxworks*) + tmake_file="${tmake_file} t-gthr-vxworks" + ;; + esac +esac diff --git a/libgcc/config/gthr-vxworks-cond.c b/libgcc/config/gthr-vxworks-cond.c new file mode 100644 index 0000000..0747a3d --- /dev/null +++ b/libgcc/config/gthr-vxworks-cond.c @@ -0,0 +1,83 @@ +/* Copyright (C) 2002-2019 Free Software Foundation, Inc. + +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 3, 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* Threads compatibility routines for libgcc2 for VxWorks. + + This file implements the GTHREAD_HAS_COND part of the interface + exposed by gthr-vxworks.h. */ + +#include "gthr.h" +#include + +/* --------------------------- Condition Variables ------------------------ */ + +void +__gthread_cond_init (__gthread_cond_t *cond) +{ + if (!cond) + return; + *cond = semBCreate (SEM_Q_FIFO, SEM_EMPTY); +} + +int +__gthread_cond_destroy (__gthread_cond_t *cond) +{ + if (!cond) + return ERROR; + return __CHECK_RESULT (semDelete (*cond)); +} + +int +__gthread_cond_broadcast (__gthread_cond_t *cond) +{ + if (!cond) + return ERROR; + + return __CHECK_RESULT (semFlush (*cond)); +} + +int +__gthread_cond_wait (__gthread_cond_t *cond, + __gthread_mutex_t *mutex) +{ + if (!cond) + return ERROR; + + if (!mutex) + return ERROR; + + __RETURN_ERRNO_IF_NOT_OK (semGive (*mutex)); + + __RETURN_ERRNO_IF_NOT_OK (semTake (*cond, WAIT_FOREVER)); + + __RETURN_ERRNO_IF_NOT_OK (semTake (*mutex, WAIT_FOREVER)); + + return OK; +} + +int +__gthread_cond_wait_recursive (__gthread_cond_t *cond, + __gthread_recursive_mutex_t *mutex) +{ + return __gthread_cond_wait (cond, mutex); +} diff --git a/libgcc/config/gthr-vxworks-thread.c b/libgcc/config/gthr-vxworks-thread.c new file mode 100644 index 0000000..3c880ba --- /dev/null +++ b/libgcc/config/gthr-vxworks-thread.c @@ -0,0 +1,349 @@ +/* Copyright (C) 2002-2019 Free Software Foundation, Inc. + +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 3, 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* Threads compatibility routines for libgcc2 for VxWorks. + + This file implements the GTHREAD_CXX0X part of the interface + exposed by gthr-vxworks.h, using APIs exposed by regular (!AE/653) + VxWorks kernels. */ + +#include "gthr.h" +#include + +#define __TIMESPEC_TO_NSEC(timespec) \ + ((long long)timespec.tv_sec * 1000000000 + (long long)timespec.tv_nsec) + +#define __TIMESPEC_TO_TICKS(timespec) \ + ((long long)(sysClkRateGet() * __TIMESPEC_TO_NSEC(timespec) + 999999999) \ + / 1000000000) + +#ifdef __RTP__ + void tls_delete_hook (); + #define __CALL_DELETE_HOOK(tcb) tls_delete_hook() +#else + /* In kernel mode, we need to pass the TCB to task_delete_hook. The TCB is + the pointer to the WIND_TCB structure and is the ID of the task. */ + void tls_delete_hook (void *TCB); + #define __CALL_DELETE_HOOK(tcb) tls_delete_hook((WIND_TCB *) ((tcb)->task_id)) +#endif + +/* -------------------- Timed Condition Variables --------------------- */ + +int +__gthread_cond_signal (__gthread_cond_t *cond) +{ + if (!cond) + return ERROR; + + return __CHECK_RESULT (semGive (*cond)); +} + +int +__gthread_cond_timedwait (__gthread_cond_t *cond, + __gthread_mutex_t *mutex, + const __gthread_time_t *abs_timeout) +{ + if (!cond) + return ERROR; + + if (!mutex) + return ERROR; + + if (!abs_timeout) + return ERROR; + + struct timespec current; + if (clock_gettime (CLOCK_REALTIME, ¤t) == ERROR) + /* CLOCK_REALTIME is not supported. */ + return ERROR; + + const long long abs_timeout_ticks = __TIMESPEC_TO_TICKS ((*abs_timeout)); + const long long current_ticks = __TIMESPEC_TO_TICKS (current); + + long long waiting_ticks; + + if (current_ticks < abs_timeout_ticks) + waiting_ticks = abs_timeout_ticks - current_ticks; + else + /* The point until we would need to wait is in the past, + no need to wait at all. */ + waiting_ticks = 0; + + /* We check that waiting_ticks can be safely casted as an int. */ + if (waiting_ticks > INT_MAX) + waiting_ticks = INT_MAX; + + __RETURN_ERRNO_IF_NOT_OK (semGive (*mutex)); + + __RETURN_ERRNO_IF_NOT_OK (semTake (*cond, waiting_ticks)); + + __RETURN_ERRNO_IF_NOT_OK (semTake (*mutex, WAIT_FOREVER)); + + return OK; +} + +/* --------------------------- Timed Mutexes ------------------------------ */ + +int +__gthread_mutex_timedlock (__gthread_mutex_t *m, + const __gthread_time_t *abs_time) +{ + if (!m) + return ERROR; + + if (!abs_time) + return ERROR; + + struct timespec current; + if (clock_gettime (CLOCK_REALTIME, ¤t) == ERROR) + /* CLOCK_REALTIME is not supported. */ + return ERROR; + + const long long abs_timeout_ticks = __TIMESPEC_TO_TICKS ((*abs_time)); + const long long current_ticks = __TIMESPEC_TO_TICKS (current); + long long waiting_ticks; + + if (current_ticks < abs_timeout_ticks) + waiting_ticks = abs_timeout_ticks - current_ticks; + else + /* The point until we would need to wait is in the past, + no need to wait at all. */ + waiting_ticks = 0; + + /* Make sure that waiting_ticks can be safely casted as an int. */ + if (waiting_ticks > INT_MAX) + waiting_ticks = INT_MAX; + + return __CHECK_RESULT (semTake (*m, waiting_ticks)); +} + +int +__gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *mutex, + const __gthread_time_t *abs_timeout) +{ + return __gthread_mutex_timedlock ((__gthread_mutex_t *)mutex, abs_timeout); +} + +/* ------------------------------ Threads --------------------------------- */ + +/* Task control block initialization and destruction functions. */ + +int +__init_gthread_tcb (__gthread_t __tcb) +{ + if (!__tcb) + return ERROR; + + __gthread_mutex_init (&(__tcb->return_value_available)); + if (__tcb->return_value_available == SEM_ID_NULL) + return ERROR; + + __gthread_mutex_init (&(__tcb->delete_ok)); + if (__tcb->delete_ok == SEM_ID_NULL) + goto return_sem_delete; + + /* We lock the two mutexes used for signaling. */ + if (__gthread_mutex_lock (&(__tcb->delete_ok)) != OK) + goto delete_sem_delete; + + if (__gthread_mutex_lock (&(__tcb->return_value_available)) != OK) + goto delete_sem_delete; + + __tcb->task_id = TASK_ID_NULL; + return OK; + +delete_sem_delete: + semDelete (__tcb->delete_ok); +return_sem_delete: + semDelete (__tcb->return_value_available); + return ERROR; +} + +/* Here, we pass a pointer to a tcb to allow calls from + cleanup attributes. */ +void +__delete_gthread_tcb (__gthread_t* __tcb) +{ + semDelete ((*__tcb)->return_value_available); + semDelete ((*__tcb)->delete_ok); + free (*__tcb); +} + +/* This __gthread_t stores the address of the TCB malloc'ed in + __gthread_create. It is then accessible via __gthread_self(). */ +__thread __gthread_t __local_tcb = NULL; + +__gthread_t +__gthread_self (void) +{ + if (!__local_tcb) + { + /* We are in the initial thread, we need to initialize the TCB. */ + __local_tcb = malloc (sizeof (*__local_tcb)); + if (!__local_tcb) + return NULL; + + if (__init_gthread_tcb (__local_tcb) != OK) + { + __delete_gthread_tcb (&__local_tcb); + return NULL; + } + /* We do not set the mutexes in the structure as a thread is not supposed + to join or detach himself. */ + __local_tcb->task_id = taskIdSelf (); + } + return __local_tcb; +} + +int +__task_wrapper (__gthread_t tcb, FUNCPTR __func, _Vx_usr_arg_t __args) +{ + if (!tcb) + return ERROR; + + __local_tcb = tcb; + + /* We use this variable to avoid memory leaks in the case where + the underlying function throws an exception. */ + __attribute__ ((cleanup (__delete_gthread_tcb))) __gthread_t __tmp = tcb; + + void *return_value = (void *) __func (__args); + tcb->return_value = return_value; + + /* Call the destructors. */ + __CALL_DELETE_HOOK (tcb); + + /* Future calls of join() will be able to retrieve the return value. */ + __gthread_mutex_unlock (&tcb->return_value_available); + + /* We wait for the thread to be joined or detached. */ + __gthread_mutex_lock (&(tcb->delete_ok)); + __gthread_mutex_unlock (&(tcb->delete_ok)); + + /* Memory deallocation is done by the cleanup attribute of the tmp variable. */ + + return OK; +} + +/* Proper gthreads API. */ + +int +__gthread_create (__gthread_t * __threadid, void *(*__func) (void *), + void *__args) +{ + if (!__threadid) + return ERROR; + + int priority; + __RETURN_ERRNO_IF_NOT_OK (taskPriorityGet (taskIdSelf (), &priority)); + + int options; + __RETURN_ERRNO_IF_NOT_OK (taskOptionsGet (taskIdSelf (), &options)); + +#if defined (__SPE__) + options |= VX_SPE_TASK; +#else + options |= VX_FP_TASK; +#endif + options &= VX_USR_TASK_OPTIONS; + + int stacksize = 20 * 1024; + + __gthread_t tcb = malloc (sizeof (*tcb)); + if (!tcb) + return ERROR; + + if (__init_gthread_tcb (tcb) != OK) + { + free (tcb); + return ERROR; + } + + TASK_ID task_id = taskCreate (NULL, + priority, options, stacksize, + (FUNCPTR) & __task_wrapper, + (_Vx_usr_arg_t) tcb, + (_Vx_usr_arg_t) __func, + (_Vx_usr_arg_t) __args, + 0, 0, 0, 0, 0, 0, 0); + + /* If taskCreate succeeds, task_id will be a valid TASK_ID and not zero. */ + __RETURN_ERRNO_IF_NOT_OK (!task_id); + + tcb->task_id = task_id; + *__threadid = tcb; + + return __CHECK_RESULT (taskActivate (task_id)); +} + +int +__gthread_equal (__gthread_t __t1, __gthread_t __t2) +{ + return (__t1 == __t2) ? OK : ERROR; +} + +int +__gthread_yield (void) +{ + return taskDelay (0); +} + +int +__gthread_join (__gthread_t __threadid, void **__value_ptr) +{ + if (!__threadid) + return ERROR; + + /* A thread cannot join itself. */ + if (__threadid->task_id == taskIdSelf ()) + return ERROR; + + /* Waiting for the task to set the return value. */ + __gthread_mutex_lock (&__threadid->return_value_available); + __gthread_mutex_unlock (&__threadid->return_value_available); + + if (__value_ptr) + *__value_ptr = __threadid->return_value; + + /* The task will be safely be deleted. */ + __gthread_mutex_unlock (&(__threadid->delete_ok)); + + __RETURN_ERRNO_IF_NOT_OK (taskWait (__threadid->task_id, WAIT_FOREVER)); + + return OK; +} + +int +__gthread_detach (__gthread_t __threadid) +{ + if (!__threadid) + return ERROR; + + if (taskIdVerify (__threadid->task_id) != OK) + return ERROR; + + /* The task will be safely be deleted. */ + __gthread_mutex_unlock (&(__threadid->delete_ok)); + + return OK; +} diff --git a/libgcc/config/gthr-vxworks-tls.c b/libgcc/config/gthr-vxworks-tls.c new file mode 100644 index 0000000..cd5f7ac --- /dev/null +++ b/libgcc/config/gthr-vxworks-tls.c @@ -0,0 +1,362 @@ +/* Copyright (C) 2002-2018 Free Software Foundation, Inc. + Contributed by Zack Weinberg + +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 3, 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* Threads compatibility routines for libgcc2 for VxWorks. + These are out-of-line routines called from gthr-vxworks.h. + + This file provides the TLS related support routines, calling specific + VxWorks kernel entry points for this purpose. */ + +#include "tconfig.h" +#include "tsystem.h" +#include "gthr.h" + +#if defined(__GTHREADS) + +#include +#ifndef __RTP__ +#include +#endif +#include +#ifndef __RTP__ +#include +#else +#include +#endif + +/* Thread-local storage. + + A gthread TLS key is simply an offset in an array, the address of which + we store in a single pointer field associated with the current task. + + On VxWorks 7, we have direct support for __thread variables and use + such a variable as the pointer "field". On other versions, we resort + to __gthread_get_tls_data and __gthread_set_tls_data functions provided + by the kernel. + + There is also a global array which records which keys are valid and + which have destructors. + + A task delete hook is installed to execute key destructors. The routines + __gthread_enter_tls_dtor_context and __gthread_leave_tls_dtor_context, + which are also provided by the kernel, ensure that it is safe to call + free() on memory allocated by the task being deleted. This is a no-op on + VxWorks 5, but a major undertaking on AE. + + The task delete hook is only installed when at least one thread + has TLS data. This is a necessary precaution, to allow this module + to be unloaded - a module with a hook can not be removed. + + Since this interface is used to allocate only a small number of + keys, the table size is small and static, which simplifies the + code quite a bit. Revisit this if and when it becomes necessary. */ + +#define MAX_KEYS 4 + +/* This is the structure pointed to by the pointer returned + by __gthread_get_tls_data. */ +struct tls_data +{ + int *owner; + void *values[MAX_KEYS]; + unsigned int generation[MAX_KEYS]; +}; + +/* To make sure we only delete TLS data associated with this object, + include a pointer to a local variable in the TLS data object. */ +static int self_owner; + +/* Flag to check whether the delete hook is installed. Once installed + it is only removed when unloading this module. */ +static volatile int delete_hook_installed; + +/* TLS data access internal API. A straight __thread variable on VxWorks 7, + a pointer returned by kernel provided routines otherwise. */ + +#ifdef __VXWORKS7__ + +static __thread struct tls_data *__gthread_tls_data; + +#define VX_GET_TLS_DATA() __gthread_tls_data +#define VX_SET_TLS_DATA(x) __gthread_tls_data = (x) + +#define VX_ENTER_TLS_DTOR() +#define VX_LEAVE_TLS_DTOR() + +#else + +extern void *__gthread_get_tls_data (void); +extern void __gthread_set_tls_data (void *data); + +extern void __gthread_enter_tls_dtor_context (void); +extern void __gthread_leave_tls_dtor_context (void); + +#define VX_GET_TLS_DATA() __gthread_get_tls_data() +#define VX_SET_TLS_DATA(x) __gthread_set_tls_data(x) + +#define VX_ENTER_TLS_DTOR() __gthread_enter_tls_dtor_context () +#define VX_LEAVE_TLS_DTOR() __gthread_leave_tls_dtor_context () + +#endif /* __VXWORKS7__ */ + +/* This is a global structure which records all of the active keys. + + A key is potentially valid (i.e. has been handed out by + __gthread_key_create) iff its generation count in this structure is + even. In that case, the matching entry in the dtors array is a + routine to be called when a thread terminates with a valid, + non-NULL specific value for that key. + + A key is actually valid in a thread T iff the generation count + stored in this structure is equal to the generation count stored in + T's specific-value structure. */ + +typedef void (*tls_dtor) (void *); + +struct tls_keys +{ + tls_dtor dtor[MAX_KEYS]; + unsigned int generation[MAX_KEYS]; +}; + +#define KEY_VALID_P(key) !(tls_keys.generation[key] & 1) + +/* Note: if MAX_KEYS is increased, this initializer must be updated + to match. All the generation counts begin at 1, which means no + key is valid. */ +static struct tls_keys tls_keys = +{ + { NULL, NULL, NULL, NULL }, + { 1, 1, 1, 1 } +}; + +/* This lock protects the tls_keys structure. */ +static __gthread_mutex_t tls_lock; + +static __gthread_once_t tls_init_guard = __GTHREAD_ONCE_INIT; + +/* Internal routines. */ + +/* The task TCB has just been deleted. Call the destructor + function for each TLS key that has both a destructor and + a non-NULL specific value in this thread. + + This routine does not need to take tls_lock; the generation + count protects us from calling a stale destructor. It does + need to read tls_keys.dtor[key] atomically. */ + +void +tls_delete_hook (void *tcb ATTRIBUTE_UNUSED) +{ + struct tls_data *data; + __gthread_key_t key; + + data = VX_GET_TLS_DATA(); + + if (data && data->owner == &self_owner) + { + VX_ENTER_TLS_DTOR(); + for (key = 0; key < MAX_KEYS; key++) + { + if (data->generation[key] == tls_keys.generation[key]) + { + tls_dtor dtor = tls_keys.dtor[key]; + + if (dtor) + dtor (data->values[key]); + } + } + free (data); + + VX_LEAVE_TLS_DTOR(); + VX_SET_TLS_DATA(NULL); + } +} + +/* Initialize global data used by the TLS system. */ +static void +tls_init (void) +{ + __GTHREAD_MUTEX_INIT_FUNCTION (&tls_lock); +} + +static void tls_destructor (void) __attribute__ ((destructor)); +static void +tls_destructor (void) +{ +#ifdef __RTP__ + /* All threads but this one should have exited by now. */ + tls_delete_hook (NULL); +#endif + /* Unregister the hook. */ + if (delete_hook_installed) + taskDeleteHookDelete ((FUNCPTR)tls_delete_hook); + + if (tls_init_guard.done && __gthread_mutex_lock (&tls_lock) != ERROR) + semDelete (tls_lock); +} + +/* External interface */ + +/* Store in KEYP a value which can be passed to __gthread_setspecific/ + __gthread_getspecific to store and retrieve a value which is + specific to each calling thread. If DTOR is not NULL, it will be + called when a thread terminates with a non-NULL specific value for + this key, with the value as its sole argument. */ + +int +__gthread_key_create (__gthread_key_t *keyp, tls_dtor dtor) +{ + __gthread_key_t key; + + __gthread_once (&tls_init_guard, tls_init); + + if (__gthread_mutex_lock (&tls_lock) == ERROR) + return errno; + + for (key = 0; key < MAX_KEYS; key++) + if (!KEY_VALID_P (key)) + goto found_slot; + + /* no room */ + __gthread_mutex_unlock (&tls_lock); + return EAGAIN; + + found_slot: + tls_keys.generation[key]++; /* making it even */ + tls_keys.dtor[key] = dtor; + *keyp = key; + __gthread_mutex_unlock (&tls_lock); + return 0; +} + +/* Invalidate KEY; it can no longer be used as an argument to + setspecific/getspecific. Note that this does NOT call destructor + functions for any live values for this key. */ +int +__gthread_key_delete (__gthread_key_t key) +{ + if (key >= MAX_KEYS) + return EINVAL; + + __gthread_once (&tls_init_guard, tls_init); + + if (__gthread_mutex_lock (&tls_lock) == ERROR) + return errno; + + if (!KEY_VALID_P (key)) + { + __gthread_mutex_unlock (&tls_lock); + return EINVAL; + } + + tls_keys.generation[key]++; /* making it odd */ + tls_keys.dtor[key] = 0; + + __gthread_mutex_unlock (&tls_lock); + return 0; +} + +/* Retrieve the thread-specific value for KEY. If it has never been + set in this thread, or KEY is invalid, returns NULL. + + It does not matter if this function races with key_create or + key_delete; the worst that can happen is you get a value other than + the one that a serialized implementation would have provided. */ + +void * +__gthread_getspecific (__gthread_key_t key) +{ + struct tls_data *data; + + if (key >= MAX_KEYS) + return 0; + + data = GET_VX_TLS_DATA(); + + if (!data) + return 0; + + if (data->generation[key] != tls_keys.generation[key]) + return 0; + + return data->values[key]; +} + +/* Set the thread-specific value for KEY. If KEY is invalid, or + memory allocation fails, returns -1, otherwise 0. + + The generation count protects this function against races with + key_create/key_delete; the worst thing that can happen is that a + value is successfully stored into a dead generation (and then + immediately becomes invalid). However, we do have to make sure + to read tls_keys.generation[key] atomically. */ + +int +__gthread_setspecific (__gthread_key_t key, void *value) +{ + struct tls_data *data; + unsigned int generation; + + if (key >= MAX_KEYS) + return EINVAL; + + data = VX_GET_TLS_DATA(); + + if (!data) + { + if (!delete_hook_installed) + { + /* Install the delete hook. */ + if (__gthread_mutex_lock (&tls_lock) == ERROR) + return ENOMEM; + if (!delete_hook_installed) + { + taskDeleteHookAdd ((FUNCPTR)tls_delete_hook); + delete_hook_installed = 1; + } + __gthread_mutex_unlock (&tls_lock); + } + + data = malloc (sizeof (struct tls_data)); + if (!data) + return ENOMEM; + + memset (data, 0, sizeof (struct tls_data)); + data->owner = &self_owner; + + VX_SET_TLS_DATA(data); + } + + generation = tls_keys.generation[key]; + + if (generation & 1) + return EINVAL; + + data->generation[key] = generation; + data->values[key] = value; + + return 0; +} +#endif /* __GTHREADS */ diff --git a/libgcc/config/gthr-vxworks.c b/libgcc/config/gthr-vxworks.c new file mode 100644 index 0000000..ddc3593 --- /dev/null +++ b/libgcc/config/gthr-vxworks.c @@ -0,0 +1,87 @@ +/* Copyright (C) 2002-2019 Free Software Foundation, Inc. + Contributed by Zack Weinberg + +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 3, 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* Threads compatibility routines for libgcc2 for VxWorks. + + This file implements the init-once service exposed by gthr-vxworks.h. */ + +#include "tconfig.h" +#include "tsystem.h" +#include "gthr.h" + +#if defined(__GTHREADS) + +#include + +#ifndef __RTP__ +# include +# include +#else /* __RTP__ */ +# include +#endif /* __RTP__ */ + +/* ----------------------------- Init-once ------------------------------- */ + +static void +__release (__gthread_once_t ** __guard) +{ + (*__guard)->busy = 0; +} + +int +__gthread_once (__gthread_once_t * __guard, void (*__func) (void)) +{ + if (__guard->done) + return 0; + + /* Busy-wait until we have exclusive access to the state. Check if + another thread managed to perform the init call in the interim. */ + + while (!__TAS(&__guard->busy)) + { + if (__guard->done) + return 0; + taskDelay (1); + } + + if (!__guard->done) + { +#ifndef __USING_SJLJ_EXCEPTIONS__ + /* Setup a cleanup to release the guard when __func() throws an + exception. We cannot use this with SJLJ exceptions as + Unwind_Register calls __gthread_once, leading to an infinite + recursion. */ + __attribute__ ((cleanup (__release))) + __gthread_once_t *__temp = __guard; +#endif + + __func (); + __guard->done = 1; + } + + __release(&__guard); + return 0; +} + +#endif /* __GTHREADS */ diff --git a/libgcc/config/gthr-vxworks.h b/libgcc/config/gthr-vxworks.h index c9214a5..7e3779a 100644 --- a/libgcc/config/gthr-vxworks.h +++ b/libgcc/config/gthr-vxworks.h @@ -1,6 +1,6 @@ /* Threads compatibility routines for libgcc2 and libobjc for VxWorks. */ /* Compile this one with gcc. */ -/* Copyright (C) 1997-2019 Free Software Foundation, Inc. +/* Copyright (C) 1997-2018 Free Software Foundation, Inc. Contributed by Mike Stump . This file is part of GCC. @@ -33,139 +33,295 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "gthr-posix.h" #else -#ifdef __cplusplus -#define UNUSED(x) -#else -#define UNUSED(x) x __attribute__((__unused__)) + +#include +#include + +/* Conditional compilation directives are easier to read when they fit on a + single line, which is helped by macros with shorter names. */ +#define _VXW_MAJOR _WRS_VXWORKS_MAJOR +#define _VXW_MINOR _WRS_VXWORKS_MINOR +#define _VXW_PRE_69 (_VXW_MAJOR < 6 || (_VXW_MAJOR == 6 && _VXW_MINOR < 9)) + +/* Some VxWorks headers profusely use typedefs of a pointer to a function with + undefined number of arguments. */ +#pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-prototypes" + #include +#pragma GCC diagnostic pop + +#include + + +/* --------------------- Test & Set/Swap internal API --------------------- */ + +/* We use a bare atomic primitive with busy loops to handle mutual exclusion. + Inefficient, but reliable. The actual primitive used depends on the mode + (RTP vs Kernel) and the version of VxWorks. We define a macro and a type + here, for reuse without conditionals cluttering in the code afterwards. */ + +/* RTP, pre 6.9. */ + +#if defined(__RTP__) && _VXW_PRE_69 + +#define __TAS(x) vxCas ((x), 0, 1) +typedef volatile unsigned char __vx_tas_t; + +#endif + +/* RTP, 6.9 and beyond. */ + +#if defined(__RTP__) && !_VXW_PRE_69 + +#define __TAS(x) vxAtomicCas ((x), 0, 1) +typedef atomic_t __vx_tas_t; + +#include + +#endif + +/* Kernel */ + +#if !defined(__RTP__) + +#define __TAS(x) vxTas (x) +typedef volatile unsigned char __vx_tas_t; + #endif #ifdef __cplusplus extern "C" { #endif +/* ------------------------ Base __GTHREADS support ----------------------- */ + #define __GTHREADS 1 #define __gthread_active_p() 1 /* Mutexes are easy, except that they need to be initialized at runtime. */ -#include - -typedef SEM_ID __gthread_mutex_t; /* All VxWorks mutexes are recursive. */ +typedef SEM_ID __gthread_mutex_t; typedef SEM_ID __gthread_recursive_mutex_t; -#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function -#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function +#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init +#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init + +#define __CHECK_RESULT(result) (((result) == OK) ? OK : errnoGet()) + +/* If a call to the VxWorks API fails, we must propagate the errno value. */ +#define __RETURN_ERRNO_IF_NOT_OK(exp) if ((exp) != OK) return errnoGet() + +/* Non re-entrant mutex implementation. Libstdc++ expects the default + gthread mutex to be non reentrant. */ static inline void -__gthread_mutex_init_function (__gthread_mutex_t *mutex) +__gthread_mutex_init (__gthread_mutex_t * __mutex) { - *mutex = semMCreate (SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); + if (!__mutex) + return; + *__mutex = semBCreate (SEM_Q_PRIORITY, SEM_FULL); } static inline int -__gthread_mutex_destroy (__gthread_mutex_t *mutex) +__gthread_mutex_destroy (__gthread_mutex_t * __mutex) { - semDelete(*mutex); - return 0; + if (!__mutex) + return ERROR; + return __CHECK_RESULT (semDelete (*__mutex)); } static inline int -__gthread_mutex_lock (__gthread_mutex_t *mutex) +__gthread_mutex_lock (__gthread_mutex_t * __mutex) { - return semTake (*mutex, WAIT_FOREVER); + if (!__mutex) + return ERROR; + return __CHECK_RESULT (semTake(*__mutex, WAIT_FOREVER)); } static inline int -__gthread_mutex_trylock (__gthread_mutex_t *mutex) +__gthread_mutex_trylock (__gthread_mutex_t * __mutex) { - return semTake (*mutex, NO_WAIT); + if (!__mutex) + return ERROR; + return __CHECK_RESULT (semTake (*__mutex, NO_WAIT)); } static inline int -__gthread_mutex_unlock (__gthread_mutex_t *mutex) +__gthread_mutex_unlock (__gthread_mutex_t * __mutex) { - return semGive (*mutex); + if (!__mutex) + return ERROR; + return __CHECK_RESULT (semGive (*__mutex)); } +/* Recursive mutex implementation. The only change is that we use semMCreate() + instead of semBCreate(). */ + static inline void -__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex) +__gthread_recursive_mutex_init (__gthread_recursive_mutex_t * __mutex) { - __gthread_mutex_init_function (mutex); + if (!__mutex) + return; + *__mutex = + semMCreate (SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); } static inline int -__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) +__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t * __mutex) { - return __gthread_mutex_lock (mutex); + return __gthread_mutex_destroy (__mutex); } static inline int -__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) +__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t * __mutex) { - return __gthread_mutex_trylock (mutex); + return __gthread_mutex_lock (__mutex); } static inline int -__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) +__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t * __mutex) { - return __gthread_mutex_unlock (mutex); + return __gthread_mutex_trylock (__mutex); } static inline int -__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex) +__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t * __mutex) { - return __gthread_mutex_destroy (__mutex); + return __gthread_mutex_unlock (__mutex); } -/* pthread_once is complicated enough that it's implemented - out-of-line. See config/vxlib.c. */ - typedef struct { -#if !defined(__RTP__) + /* PPC's test-and-set kernel mode implementation requires a pointer aligned + object, of which it only sets the first byte. We use padding in addition + to an alignment request here to maxmise the factors leading to the + desired actual alignment choice by the compiler. */ #if defined(__PPC__) - __attribute ((aligned (__alignof (unsigned)))) -#endif - volatile unsigned char busy; + __attribute ((aligned (__alignof__ (void *)))) #endif + + __vx_tas_t busy; volatile unsigned char done; + #if !defined(__RTP__) && defined(__PPC__) - /* PPC's test-and-set implementation requires a 4 byte aligned - object, of which it only sets the first byte. We use padding - here, in order to maintain some amount of backwards - compatibility. Without this padding, gthread_once objects worked - by accident because they happen to be static objects and the ppc - port automatically increased their alignment to 4 bytes. */ unsigned char pad1; unsigned char pad2; #endif -} -__gthread_once_t; - -#if defined (__RTP__) -# define __GTHREAD_ONCE_INIT { 0 } -#elif defined (__PPC__) -# define __GTHREAD_ONCE_INIT { 0, 0, 0, 0 } -#else -# define __GTHREAD_ONCE_INIT { 0, 0 } +#if !defined(__RTP__) && defined(__PPC64__) + unsigned char pad3; + unsigned char pad4; + unsigned char pad5; + unsigned char pad6; #endif +} __gthread_once_t; + +#define __GTHREAD_ONCE_INIT { 0 } extern int __gthread_once (__gthread_once_t *__once, void (*__func)(void)); -/* Thread-specific data requires a great deal of effort, since VxWorks - is not really set up for it. See config/vxlib.c for the gory - details. All the TSD routines are sufficiently complex that they +/* All the TSD routines are sufficiently complex that they need to be implemented out of line. */ typedef unsigned int __gthread_key_t; -extern int __gthread_key_create (__gthread_key_t *__keyp, void (*__dtor)(void *)); +extern int __gthread_key_create (__gthread_key_t *__keyp, + void (*__dtor)(void *)); extern int __gthread_key_delete (__gthread_key_t __key); extern void *__gthread_getspecific (__gthread_key_t __key); extern int __gthread_setspecific (__gthread_key_t __key, void *__ptr); -#undef UNUSED +/* ------------------ Base condition variables support ------------------- */ + +#define __GTHREAD_HAS_COND 1 + +typedef SEM_ID __gthread_cond_t; + +#define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init + +/* Condition variable declarations. */ + +extern void __gthread_cond_init (__gthread_cond_t *cond); + +extern int __gthread_cond_destroy (__gthread_cond_t *cond); + +extern int __gthread_cond_broadcast (__gthread_cond_t *cond); + +extern int __gthread_cond_wait (__gthread_cond_t *cond, + __gthread_mutex_t *mutex); + +extern int __gthread_cond_wait_recursive (__gthread_cond_t *cond, + __gthread_recursive_mutex_t *mutex); + +/* ----------------------- C++0x thread support ------------------------- */ + +/* We do not support C++0x threads on that VxWorks 653, which we can + recognize by VTHREADS being defined. */ + +#ifndef VTHREADS + +#define __GTHREADS_CXX0X 1 + +#include +#include +#include +#include +#include + +typedef struct +{ + TASK_ID task_id; + void *return_value; + + /* This mutex is used to block in join() while the return value is + unavailable. */ + __gthread_mutex_t return_value_available; + + /* Before freeing the structure in the task wrapper, we need to wait until + join() or detach() are called on that thread. */ + __gthread_mutex_t delete_ok; +} __gthread_tcb; + +typedef __gthread_tcb *__gthread_t; + +/* Typedefs specific to different vxworks versions. */ +#if _VXW_PRE_69 + typedef int _Vx_usr_arg_t; + #define TASK_ID_NULL ((TASK_ID)NULL) + #define SEM_ID_NULL ((SEM_ID)NULL) +#endif + +typedef struct timespec __gthread_time_t; + +/* Timed mutex lock declarations. */ + +extern int __gthread_mutex_timedlock (__gthread_mutex_t *m, + const __gthread_time_t *abs_time); + +extern int __gthread_recursive_mutex_timedlock + (__gthread_recursive_mutex_t *mutex, + const __gthread_time_t *abs_timeout); + +/* Timed condition variable declarations. */ + +extern int __gthread_cond_signal (__gthread_cond_t *cond); +extern int __gthread_cond_timedwait (__gthread_cond_t *cond, + __gthread_mutex_t *mutex, + const __gthread_time_t *abs_timeout); + +/* gthreads declarations. */ + +extern int __gthread_equal (__gthread_t t1, __gthread_t t2); +extern int __gthread_yield (void); +extern int __gthread_create (__gthread_t *__threadid, + void *(*__func) (void*), + void *__args); +extern int __gthread_join (__gthread_t thread, void **value_ptr); +extern int __gthread_detach (__gthread_t thread); + +extern __gthread_t __gthread_self (void); + +#endif #ifdef __cplusplus } diff --git a/libgcc/config/t-gthr-vxworks b/libgcc/config/t-gthr-vxworks new file mode 100644 index 0000000..455d0b3 --- /dev/null +++ b/libgcc/config/t-gthr-vxworks @@ -0,0 +1,5 @@ +# Extra libgcc2 modules used by gthr-vxworks.h functions +LIB2ADDEH += $(srcdir)/config/gthr-vxworks.c\ + $(srcdir)/config/gthr-vxworks-cond.c\ + $(srcdir)/config/gthr-vxworks-thread.c\ + $(srcdir)/config/gthr-vxworks-tls.c \ No newline at end of file diff --git a/libgcc/config/t-vxworks b/libgcc/config/t-vxworks index 2db8e05..757cead 100644 --- a/libgcc/config/t-vxworks +++ b/libgcc/config/t-vxworks @@ -6,9 +6,6 @@ LIBGCC2_DEBUG_CFLAGS = LIB2FUNCS_EXCLUDE += _clear_cache LIB2ADD += $(srcdir)/config/vxcache.c -# Extra libgcc2 modules used by gthr-vxworks.h functions -LIB2ADDEH += $(srcdir)/config/vxlib.c $(srcdir)/config/vxlib-tls.c - # This ensures that the correct target headers are used; some VxWorks # system headers have names that collide with GCC's internal (host) # headers, e.g. regs.h. Make sure the local libgcc headers still diff --git a/libgcc/config/t-vxworks7 b/libgcc/config/t-vxworks7 index 054ab7c..f2cc904 100644 --- a/libgcc/config/t-vxworks7 +++ b/libgcc/config/t-vxworks7 @@ -6,9 +6,6 @@ LIBGCC2_DEBUG_CFLAGS = LIB2FUNCS_EXCLUDE += _clear_cache LIB2ADD += $(srcdir)/config/vxcache.c -# Extra libgcc2 modules used by gthr-vxworks.h functions -LIB2ADDEH += $(srcdir)/config/vxlib.c $(srcdir)/config/vxlib-tls.c - # This ensures that the correct target headers are used; some VxWorks # system headers have names that collide with GCC's internal (host) # headers, e.g. regs.h. Make sure the local libgcc headers still @@ -21,4 +18,3 @@ LIBGCC2_INCLUDES = -nostdinc -I. \ */mrtp*) echo -I$(VSB_DIR)/usr/h/public -I$(VSB_DIR)/usr/h ;; \ *) echo -I$(VSB_DIR)/krnl/h/system -I$(VSB_DIR)/krnl/h/public ;; \ esac` - diff --git a/libgcc/config/vxlib-tls.c b/libgcc/config/vxlib-tls.c deleted file mode 100644 index b8d6907..0000000 --- a/libgcc/config/vxlib-tls.c +++ /dev/null @@ -1,370 +0,0 @@ -/* Copyright (C) 2002-2019 Free Software Foundation, Inc. - Contributed by Zack Weinberg - -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 3, 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. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -. */ - -/* Threads compatibility routines for libgcc2 for VxWorks. - These are out-of-line routines called from gthr-vxworks.h. - - This file provides the TLS related support routines, calling specific - VxWorks kernel entry points for this purpose. The base VxWorks 5.x kernels - don't feature these entry points, and we provide gthr_supp_vxw_5x.c as an - option to fill this gap. Asking users to rebuild a kernel is not to be - taken lightly, still, so we have isolated these routines from the rest of - vxlib to ensure that the kernel dependencies are only dragged when really - necessary. */ - -#include "tconfig.h" -#include "tsystem.h" -#include "gthr.h" - -#if defined(__GTHREADS) -#include -#ifndef __RTP__ -#include -#endif -#include -#ifndef __RTP__ -#include -#else -# include -#endif - -/* Thread-local storage. - - We reserve a field in the TCB to point to a dynamically allocated - array which is used to store TLS values. A TLS key is simply an - offset in this array. The exact location of the TCB field is not - known to this code nor to vxlib.c -- all access to it indirects - through the routines __gthread_get_tls_data and - __gthread_set_tls_data, which are provided by the VxWorks kernel. - - There is also a global array which records which keys are valid and - which have destructors. - - A task delete hook is installed to execute key destructors. The - routines __gthread_enter_tls_dtor_context and - __gthread_leave_tls_dtor_context, which are also provided by the - kernel, ensure that it is safe to call free() on memory allocated - by the task being deleted. (This is a no-op on VxWorks 5, but - a major undertaking on AE.) - - The task delete hook is only installed when at least one thread - has TLS data. This is a necessary precaution, to allow this module - to be unloaded - a module with a hook cannot be removed. - - Since this interface is used to allocate only a small number of - keys, the table size is small and static, which simplifies the - code quite a bit. Revisit this if and when it becomes necessary. */ - -#define MAX_KEYS 4 - -/* This is the structure pointed to by the pointer returned - by __gthread_get_tls_data. */ -struct tls_data -{ - int *owner; - void *values[MAX_KEYS]; - unsigned int generation[MAX_KEYS]; -}; - -/* To make sure we only delete TLS data associated with this object, - include a pointer to a local variable in the TLS data object. */ -static int self_owner; - -/* Flag to check whether the delete hook is installed. Once installed - it is only removed when unloading this module. */ -static volatile int delete_hook_installed; - -/* kernel provided routines */ -extern void *__gthread_get_tls_data (void); -extern void __gthread_set_tls_data (void *data); - -extern void __gthread_enter_tls_dtor_context (void); -extern void __gthread_leave_tls_dtor_context (void); - -#ifndef __RTP__ - -extern void *__gthread_get_tsd_data (WIND_TCB *tcb); -extern void __gthread_set_tsd_data (WIND_TCB *tcb, void *data); -extern void __gthread_enter_tsd_dtor_context (WIND_TCB *tcb); -extern void __gthread_leave_tsd_dtor_context (WIND_TCB *tcb); - -#endif /* __RTP__ */ - -/* This is a global structure which records all of the active keys. - - A key is potentially valid (i.e. has been handed out by - __gthread_key_create) iff its generation count in this structure is - even. In that case, the matching entry in the dtors array is a - routine to be called when a thread terminates with a valid, - non-NULL specific value for that key. - - A key is actually valid in a thread T iff the generation count - stored in this structure is equal to the generation count stored in - T's specific-value structure. */ - -typedef void (*tls_dtor) (void *); - -struct tls_keys -{ - tls_dtor dtor[MAX_KEYS]; - unsigned int generation[MAX_KEYS]; -}; - -#define KEY_VALID_P(key) !(tls_keys.generation[key] & 1) - -/* Note: if MAX_KEYS is increased, this initializer must be updated - to match. All the generation counts begin at 1, which means no - key is valid. */ -static struct tls_keys tls_keys = -{ - { 0, 0, 0, 0 }, - { 1, 1, 1, 1 } -}; - -/* This lock protects the tls_keys structure. */ -static __gthread_mutex_t tls_lock; - -static __gthread_once_t tls_init_guard = __GTHREAD_ONCE_INIT; - -/* Internal routines. */ - -/* The task TCB has just been deleted. Call the destructor - function for each TLS key that has both a destructor and - a non-NULL specific value in this thread. - - This routine does not need to take tls_lock; the generation - count protects us from calling a stale destructor. It does - need to read tls_keys.dtor[key] atomically. */ - -static void -tls_delete_hook (void *tcb ATTRIBUTE_UNUSED) -{ - struct tls_data *data; - __gthread_key_t key; - -#ifdef __RTP__ - data = __gthread_get_tls_data (); -#else - /* In kernel mode, we can be called in the context of the thread - doing the killing, so must use the TCB to determine the data of - the thread being killed. */ - data = __gthread_get_tsd_data (tcb); -#endif - - if (data && data->owner == &self_owner) - { -#ifdef __RTP__ - __gthread_enter_tls_dtor_context (); -#else - __gthread_enter_tsd_dtor_context (tcb); -#endif - for (key = 0; key < MAX_KEYS; key++) - { - if (data->generation[key] == tls_keys.generation[key]) - { - tls_dtor dtor = tls_keys.dtor[key]; - - if (dtor) - dtor (data->values[key]); - } - } - free (data); -#ifdef __RTP__ - __gthread_leave_tls_dtor_context (); -#else - __gthread_leave_tsd_dtor_context (tcb); -#endif - -#ifdef __RTP__ - __gthread_set_tls_data (0); -#else - __gthread_set_tsd_data (tcb, 0); -#endif - } -} - -/* Initialize global data used by the TLS system. */ -static void -tls_init (void) -{ - __GTHREAD_MUTEX_INIT_FUNCTION (&tls_lock); -} - -static void tls_destructor (void) __attribute__ ((destructor)); -static void -tls_destructor (void) -{ -#ifdef __RTP__ - /* All threads but this one should have exited by now. */ - tls_delete_hook (NULL); -#endif - /* Unregister the hook. */ - if (delete_hook_installed) - taskDeleteHookDelete ((FUNCPTR)tls_delete_hook); - - if (tls_init_guard.done && __gthread_mutex_lock (&tls_lock) != ERROR) - semDelete (tls_lock); -} - -/* External interface */ - -/* Store in KEYP a value which can be passed to __gthread_setspecific/ - __gthread_getspecific to store and retrieve a value which is - specific to each calling thread. If DTOR is not NULL, it will be - called when a thread terminates with a non-NULL specific value for - this key, with the value as its sole argument. */ - -int -__gthread_key_create (__gthread_key_t *keyp, tls_dtor dtor) -{ - __gthread_key_t key; - - __gthread_once (&tls_init_guard, tls_init); - - if (__gthread_mutex_lock (&tls_lock) == ERROR) - return errno; - - for (key = 0; key < MAX_KEYS; key++) - if (!KEY_VALID_P (key)) - goto found_slot; - - /* no room */ - __gthread_mutex_unlock (&tls_lock); - return EAGAIN; - - found_slot: - tls_keys.generation[key]++; /* making it even */ - tls_keys.dtor[key] = dtor; - *keyp = key; - __gthread_mutex_unlock (&tls_lock); - return 0; -} - -/* Invalidate KEY; it can no longer be used as an argument to - setspecific/getspecific. Note that this does NOT call destructor - functions for any live values for this key. */ -int -__gthread_key_delete (__gthread_key_t key) -{ - if (key >= MAX_KEYS) - return EINVAL; - - __gthread_once (&tls_init_guard, tls_init); - - if (__gthread_mutex_lock (&tls_lock) == ERROR) - return errno; - - if (!KEY_VALID_P (key)) - { - __gthread_mutex_unlock (&tls_lock); - return EINVAL; - } - - tls_keys.generation[key]++; /* making it odd */ - tls_keys.dtor[key] = 0; - - __gthread_mutex_unlock (&tls_lock); - return 0; -} - -/* Retrieve the thread-specific value for KEY. If it has never been - set in this thread, or KEY is invalid, returns NULL. - - It does not matter if this function races with key_create or - key_delete; the worst that can happen is you get a value other than - the one that a serialized implementation would have provided. */ - -void * -__gthread_getspecific (__gthread_key_t key) -{ - struct tls_data *data; - - if (key >= MAX_KEYS) - return 0; - - data = __gthread_get_tls_data (); - - if (!data) - return 0; - - if (data->generation[key] != tls_keys.generation[key]) - return 0; - - return data->values[key]; -} - -/* Set the thread-specific value for KEY. If KEY is invalid, or - memory allocation fails, returns -1, otherwise 0. - - The generation count protects this function against races with - key_create/key_delete; the worst thing that can happen is that a - value is successfully stored into a dead generation (and then - immediately becomes invalid). However, we do have to make sure - to read tls_keys.generation[key] atomically. */ - -int -__gthread_setspecific (__gthread_key_t key, void *value) -{ - struct tls_data *data; - unsigned int generation; - - if (key >= MAX_KEYS) - return EINVAL; - - data = __gthread_get_tls_data (); - if (!data) - { - if (!delete_hook_installed) - { - /* Install the delete hook. */ - if (__gthread_mutex_lock (&tls_lock) == ERROR) - return ENOMEM; - if (!delete_hook_installed) - { - taskDeleteHookAdd ((FUNCPTR)tls_delete_hook); - delete_hook_installed = 1; - } - __gthread_mutex_unlock (&tls_lock); - } - - data = malloc (sizeof (struct tls_data)); - if (!data) - return ENOMEM; - - memset (data, 0, sizeof (struct tls_data)); - data->owner = &self_owner; - __gthread_set_tls_data (data); - } - - generation = tls_keys.generation[key]; - - if (generation & 1) - return EINVAL; - - data->generation[key] = generation; - data->values[key] = value; - - return 0; -} -#endif /* __GTHREADS */ diff --git a/libgcc/config/vxlib.c b/libgcc/config/vxlib.c deleted file mode 100644 index 78b6776..0000000 --- a/libgcc/config/vxlib.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2002-2019 Free Software Foundation, Inc. - Contributed by Zack Weinberg - -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 3, 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. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -. */ - -/* Threads compatibility routines for libgcc2 for VxWorks. - These are out-of-line routines called from gthr-vxworks.h. */ - -#include "tconfig.h" -#include "tsystem.h" -#include "gthr.h" - -#if defined(__GTHREADS) -#include -#ifndef __RTP__ -#include -#endif -#include -#ifndef __RTP__ -#include -#else -# include -#endif - -/* Init-once operation. - - This would be a clone of the implementation from gthr-solaris.h, - except that we have a bootstrap problem - the whole point of this - exercise is to prevent double initialization, but if two threads - are racing with each other, once->mutex is liable to be initialized - by both. Then each thread will lock its own mutex, and proceed to - call the initialization routine. - - So instead we use a bare atomic primitive (vxTas()) to handle - mutual exclusion. Threads losing the race then busy-wait, calling - taskDelay() to yield the processor, until the initialization is - completed. Inefficient, but reliable. */ - -int -__gthread_once (__gthread_once_t *guard, void (*func)(void)) -{ - if (guard->done) - return 0; - -#ifdef __RTP__ - __gthread_lock_library (); -#else - while (!vxTas ((void *)&guard->busy)) - { -#ifdef __PPC__ - /* This can happen on powerpc, which is using all 32 bits - of the gthread_once_t structure. */ - if (guard->done) - return 0; -#endif - taskDelay (1); - } -#endif - - /* Only one thread at a time gets here. Check ->done again, then - go ahead and call func() if no one has done it yet. */ - if (!guard->done) - { - func (); - guard->done = 1; - } - -#ifdef __RTP__ - __gthread_unlock_library (); -#else - guard->busy = 0; -#endif - return 0; -} - -#endif /* __GTHREADS */ -- cgit v1.1 From 36e5f4d4f34dc06bddd1b8047727a1aa9db61a21 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Thu, 14 Nov 2019 16:00:55 +0000 Subject: Update the libgcc support for VxWorks AE/653 2019-11-12 Olivier Hainque libgcc/ * config/t-gthr-vxworksae: New file, add all the gthr-vxworks sources except the cxx0x support to LIB2ADDEH. We don't support cxx0x on AE/653. * config/t-vxworksae: New file. * config.host: Handle *-*-vxworksae: Add the two aforementioned Makefile fragment files at their expected position in the tmake_file list, in accordance with what is done for other VxWorks variants. From-SVN: r278250 --- libgcc/ChangeLog | 10 ++++++++++ libgcc/config.host | 6 ++++++ libgcc/config/t-gthr-vxworksae | 7 +++++++ libgcc/config/t-vxworksae | 17 +++++++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 libgcc/config/t-gthr-vxworksae create mode 100644 libgcc/config/t-vxworksae (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 21efeb5..ccd72ea 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,13 @@ +2019-11-12 Olivier Hainque + + * config/t-gthr-vxworksae: New file, add all the gthr-vxworks + sources except the cxx0x support to LIB2ADDEH. We don't support + cxx0x on AE/653. + * config/t-vxworksae: New file. + * config.host: Handle *-*-vxworksae: Add the two aforementioned + Makefile fragment files at their expected position in the tmake_file + list, in accordance with what is done for other VxWorks variants. + 2019-11-12 Corentin Gay Jerome Lambourg Olivier Hainque diff --git a/libgcc/config.host b/libgcc/config.host index 8a090bd..4950303 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -321,6 +321,9 @@ case ${host} in *-*-vxworks7*) tmake_file=t-vxworks7 ;; +*-*-vxworksae*) + tmake_file=t-vxworksae + ;; *-*-vxworks*) tmake_file=t-vxworks ;; @@ -1520,6 +1523,9 @@ esac case ${target_thread_file} in vxworks) case ${host} in + *-*-vxworksae) + tmake_file="${tmake_file} t-gthr-vxworksae" + ;; *-*-vxworks*) tmake_file="${tmake_file} t-gthr-vxworks" ;; diff --git a/libgcc/config/t-gthr-vxworksae b/libgcc/config/t-gthr-vxworksae new file mode 100644 index 0000000..1471298 --- /dev/null +++ b/libgcc/config/t-gthr-vxworksae @@ -0,0 +1,7 @@ +# Extra libgcc2 modules used by gthr-vxworks.h functions. We don't +# support the C++ threads on vx653. + +LIB2ADDEH += $(srcdir)/config/gthr-vxworks.c\ + $(srcdir)/config/gthr-vxworks-cond.c\ + $(srcdir)/config/gthr-vxworks-tls.c + diff --git a/libgcc/config/t-vxworksae b/libgcc/config/t-vxworksae new file mode 100644 index 0000000..f5003ab --- /dev/null +++ b/libgcc/config/t-vxworksae @@ -0,0 +1,17 @@ +# Don't build libgcc.a with debug info +LIBGCC2_DEBUG_CFLAGS = + +# We do not have access to the cache library when building a vThreads +# application. + +# This ensures that the correct target headers are used; some VxWorks +# system headers have names that collide with GCC's internal (host) +# headers, e.g. regs.h. Make sure the local libgcc headers still +# prevail (e.g. unwind.h), and that gcc provided header files intended +# to be user visible eventually are visible as well. +LIBGCC2_INCLUDES = -nostdinc -I. \ + -I$(MULTIBUILDTOP)../../gcc/include \ + `case "/$(MULTIDIR)" in \ + */mvthreads*) echo -I$(WIND_BASE)/target/vThreads/h -I$(WIND_BASE)/target/val/h -I$(WIND_BASE)/target/h/wrn/coreip ;; \ + *) echo -I$(WIND_BASE)/target/h -I$(WIND_BASE)/target/h/wrn/coreip ;; \ + esac` -- cgit v1.1 From 3004f893b43d48ca72ef1fe676d0930bb49a4f36 Mon Sep 17 00:00:00 2001 From: Doug Rupp Date: Thu, 14 Nov 2019 16:05:08 +0000 Subject: Base support for vxworks 7 on aarch64 2019-11-14 Doug Rupp Olivier Hainque Jerome Lambourg gcc/ * config.gcc: Handle aarch64*-wrs-vxworks7*. * config/aarch64/aarch64-vxworks.h: New file. * config/aarch64/t-aarch64-vxworks: New file. libgcc/ * config.host: Handle aarch64*-wrs-vxworks7*. Co-Authored-By: Jerome Lambourg Co-Authored-By: Olivier Hainque From-SVN: r278251 --- libgcc/ChangeLog | 5 +++++ libgcc/config.host | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index ccd72ea..dfb30a6 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,8 @@ +2019-11-14 Doug Rupp + Olivier Hainque + + * config.host: Handle aarch64*-wrs-vxworks7*. + 2019-11-12 Olivier Hainque * config/t-gthr-vxworksae: New file, add all the gthr-vxworks diff --git a/libgcc/config.host b/libgcc/config.host index 4950303..1c8d63b 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -392,6 +392,12 @@ aarch64*-*-linux*) tmake_file="${tmake_file} ${cpu_type}/t-lse t-slibgcc-libgcc" tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm" ;; +aarch64*-*-vxworks7*) + extra_parts="$extra_parts crtfastmath.o" + md_unwind_header=aarch64/aarch64-unwind.h + tmake_file="${tmake_file} ${cpu_type}/t-aarch64" + tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm" + ;; alpha*-*-linux*) tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee t-crtfm alpha/t-linux" extra_parts="$extra_parts crtfastmath.o" -- cgit v1.1 From 27204060db51ed0637e394dff387c66c6b944726 Mon Sep 17 00:00:00 2001 From: Jerome Lambourg Date: Thu, 14 Nov 2019 16:11:30 +0000 Subject: Update the arm-*-vxworks* support 2019-11-13 Jerome Lambourg Doug Rupp Olivier Hainque gcc/ * config.gcc: Collapse the arm-vxworks entries into a single arm-wrs-vxworks7* one, bpabi based. Update the default cpu from arm8 to armv7-a * config/arm/vxworks.h (CC1_SPEC): Simplify, knowing that we always use ARM_UNWIND_INFO. (DWARF2_UNWIND_INFO): Remove redefinition. (ARM_TARGET2_DWARF_FORMAT): Likewise. (VXWORKS_PERSONALITY): Define, to "llvm". (VXWORKS_EXTRA_LIBS_RTP): Define, to "-lllvm". libgcc/ * config.host: Collapse the arm-vxworks entries into a single arm-wrs-vxworks7* one. * config/arm/unwind-arm-vxworks.c: Update comments. Provide __gnu_Unwind_Find_exidx and a weak dummy __cxa_type_match for kernel modules, to be overriden by libstdc++ when we link with it. Rely on externally provided __exidx_start/end. Co-Authored-By: Doug Rupp Co-Authored-By: Olivier Hainque From-SVN: r278253 --- libgcc/ChangeLog | 11 ++++++ libgcc/config.host | 16 +++------ libgcc/config/arm/unwind-arm-vxworks.c | 65 ++++++++++++++++++++++++++++------ 3 files changed, 71 insertions(+), 21 deletions(-) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index dfb30a6..dfc842d 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,14 @@ +2019-11-14 Jerome Lambourg + Doug Rupp + Olivier Hainque + + * config.host: Collapse the arm-vxworks entries into + a single arm-wrs-vxworks7* one. + * config/arm/unwind-arm-vxworks.c: Update comments. Provide + __gnu_Unwind_Find_exidx and a weak dummy __cxa_type_match for + kernel modules, to be overriden by libstdc++ when we link with + it. Rely on externally provided __exidx_start/end. + 2019-11-14 Doug Rupp Olivier Hainque diff --git a/libgcc/config.host b/libgcc/config.host index 1c8d63b..3035168 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -438,18 +438,12 @@ arc*-*-linux*) extra_parts="$extra_parts crttls.o" md_unwind_header=arc/linux-unwind.h ;; -arm-wrs-vxworks|arm-wrs-vxworks7) - tmake_file="$tmake_file arm/t-arm arm/t-elf t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp" +arm-wrs-vxworks7*) + tmake_file="$tmake_file arm/t-arm arm/t-elf arm/t-bpabi arm/t-vxworks7" + tmake_file="$tmake_file t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp" + tm_file="$tm_file arm/bpabi-lib.h" + unwind_header=config/arm/unwind-arm.h extra_parts="$extra_parts crti.o crtn.o" - case ${host} in - *-*-vxworks7) - # Note that arm/t-bpabi will reset the LIB2ADDEH macro. - # This is intentional. - tmake_file="$tmake_file arm/t-bpabi arm/t-vxworks7" - tm_file="$tm_file arm/bpabi-lib.h" - unwind_header=config/arm/unwind-arm.h - ;; - esac ;; arm*-*-freebsd*) # ARM FreeBSD EABI tmake_file="${tmake_file} arm/t-arm t-fixedpoint-gnu-prefix arm/t-elf" diff --git a/libgcc/config/arm/unwind-arm-vxworks.c b/libgcc/config/arm/unwind-arm-vxworks.c index 03d753d..6fccf10 100644 --- a/libgcc/config/arm/unwind-arm-vxworks.c +++ b/libgcc/config/arm/unwind-arm-vxworks.c @@ -1,4 +1,4 @@ -/* Support for ARM EABI unwinding in VxWorks Downloadable Kernel Modules. +/* Support for ARM EABI unwinding on VxWorks Downloadable Kernel Modules. Copyright (C) 2017-2019 Free Software Foundation, Inc. This file is free software; you can redistribute it and/or modify it @@ -20,14 +20,59 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ -#if defined(__vxworks) && !defined (__RTP__) -/* Vxworks for ARM uses __gnu_Unwind_Find_exidx to retrieve the exception - table for downloadable kernel modules. As those modules are only partially - linked, the linker won't generate __exidx_start|end, but the two symbols - are still used in alternate paths from unwind-arm-common.inc. +/* The common unwinding code refers to __gnu_Unwind_Find_exidx and + __cxa_type_match symbols, which are not in VxWorks kernels on ARM, + now llvm based. + + While the common code works just fine for RTPs thanks to weak references + and proper positioning of __exidx_start/end from linker scripts, we need + symbol definitions for kernel modules. */ + +#ifndef __RTP__ + +#include + +/* __gnu_Unwind_Find_exidx. See if we can use _func_moduleExidxGet to + refine whatever we have in __exidx_start and __exidx_end. */ + +typedef struct +{ + UINT32 fnoffset; + UINT32 content; +} __EIT_entry; + +extern __EIT_entry __exidx_start; +extern __EIT_entry __exidx_end; + +__EIT_entry * +__gnu_Unwind_Find_exidx (void *pc, int *nrec) +{ + __EIT_entry *pstart = 0; + __EIT_entry *pend = 0; + + if (_func_moduleExidxGet != NULL) + _func_moduleExidxGet (pc, + (void *) &__exidx_start, (void *) &__exidx_end, + (void **) &pstart, (void **) &pend); + + if (!pstart) + { + pstart = &__exidx_start; + pend = &__exidx_end; + } + + *nrec = pend - pstart; + + return pstart; +} + +/* __cxa_type_match. A dummy version to be overridden by the libstdc++ one + when we link with it. */ + +void * __attribute__((weak)) +__cxa_type_match () +{ + return (void *) 0; +} - As we don't rely on them, but still need the symbols, we define dummy - values here. */ -void *__exidx_start __attribute__((__visibility__ ("hidden"))); -void *__exidx_end __attribute__((__visibility__ ("hidden"))); #endif -- cgit v1.1 From 838fd641a6ffb7e4734321de14385bece3e4506b Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Fri, 15 Nov 2019 19:47:12 +0000 Subject: m68k: add musl support Add the dynamic linker name and fix a type name to use the public name instead of the glibc internal name. gcc/ChangeLog: 2019-11-15 Szabolcs Nagy * config/m68k/linux.h (MUSL_DYNAMIC_LINKER): Define. libgcc/ChangeLog: 2019-11-15 Szabolcs Nagy * config/m68k/linux-unwind.h (struct uw_ucontext): Use sigset_t instead of __sigset_t. From-SVN: r278312 --- libgcc/ChangeLog | 5 +++++ libgcc/config/m68k/linux-unwind.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index dfc842d..a93048c 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,8 @@ +2019-11-15 Szabolcs Nagy + + * config/m68k/linux-unwind.h (struct uw_ucontext): Use sigset_t instead + of __sigset_t. + 2019-11-14 Jerome Lambourg Doug Rupp Olivier Hainque diff --git a/libgcc/config/m68k/linux-unwind.h b/libgcc/config/m68k/linux-unwind.h index fbe0d47..57c354e 100644 --- a/libgcc/config/m68k/linux-unwind.h +++ b/libgcc/config/m68k/linux-unwind.h @@ -37,7 +37,7 @@ struct uw_ucontext { stack_t uc_stack; mcontext_t uc_mcontext; unsigned long uc_filler[80]; - __sigset_t uc_sigmask; + sigset_t uc_sigmask; }; #define MD_FALLBACK_FRAME_STATE_FOR m68k_fallback_frame_state -- cgit v1.1 From 632b5e3da795a326196eab31ff4c22ed854716ed Mon Sep 17 00:00:00 2001 From: John David Anglin Date: Sun, 17 Nov 2019 23:11:52 +0000 Subject: linux-atomic.c (__kernel_cmpxchg): Change argument 1 to volatile void *. * config/pa/linux-atomic.c (__kernel_cmpxchg): Change argument 1 to volatile void *. Remove trap check. (__kernel_cmpxchg2): Likewise. (FETCH_AND_OP_2): Adjust operand types. (OP_AND_FETCH_2): Likewise. (FETCH_AND_OP_WORD): Likewise. (OP_AND_FETCH_WORD): Likewise. (COMPARE_AND_SWAP_2): Likewise. (__sync_val_compare_and_swap_4): Likewise. (__sync_bool_compare_and_swap_4): Likewise. (SYNC_LOCK_TEST_AND_SET_2): Likewise. (__sync_lock_test_and_set_4): Likewise. (SYNC_LOCK_RELEASE_1): Likewise. Use __kernel_cmpxchg2 for release. (__sync_lock_release_4): Adjust operand types. Use __kernel_cmpxchg for release. (__sync_lock_release_8): Remove. From-SVN: r278377 --- libgcc/ChangeLog | 19 ++++ libgcc/config/pa/linux-atomic.c | 210 +++++++++++++++++++++------------------- 2 files changed, 129 insertions(+), 100 deletions(-) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index a93048c..16e5696 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,22 @@ +2019-11-17 John David Anglin + + * config/pa/linux-atomic.c (__kernel_cmpxchg): Change argument 1 to + volatile void *. Remove trap check. + (__kernel_cmpxchg2): Likewise. + (FETCH_AND_OP_2): Adjust operand types. + (OP_AND_FETCH_2): Likewise. + (FETCH_AND_OP_WORD): Likewise. + (OP_AND_FETCH_WORD): Likewise. + (COMPARE_AND_SWAP_2): Likewise. + (__sync_val_compare_and_swap_4): Likewise. + (__sync_bool_compare_and_swap_4): Likewise. + (SYNC_LOCK_TEST_AND_SET_2): Likewise. + (__sync_lock_test_and_set_4): Likewise. + (SYNC_LOCK_RELEASE_1): Likewise. Use __kernel_cmpxchg2 for release. + (__sync_lock_release_4): Adjust operand types. Use __kernel_cmpxchg + for release. + (__sync_lock_release_8): Remove. + 2019-11-15 Szabolcs Nagy * config/m68k/linux-unwind.h (struct uw_ucontext): Use sigset_t instead diff --git a/libgcc/config/pa/linux-atomic.c b/libgcc/config/pa/linux-atomic.c index 28b41a7..4cd69f7 100644 --- a/libgcc/config/pa/linux-atomic.c +++ b/libgcc/config/pa/linux-atomic.c @@ -41,7 +41,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see /* Kernel helper for compare-and-exchange a 32-bit value. */ static inline long -__kernel_cmpxchg (int *mem, int oldval, int newval) +__kernel_cmpxchg (volatile void *mem, int oldval, int newval) { register unsigned long lws_mem asm("r26") = (unsigned long) (mem); register int lws_old asm("r25") = oldval; @@ -54,20 +54,18 @@ __kernel_cmpxchg (int *mem, int oldval, int newval) : "i" (LWS_CAS), "r" (lws_mem), "r" (lws_old), "r" (lws_new) : "r1", "r20", "r22", "r23", "r29", "r31", "memory" ); - if (__builtin_expect (lws_errno == -EFAULT || lws_errno == -ENOSYS, 0)) - __builtin_trap (); /* If the kernel LWS call succeeded (lws_errno == 0), lws_ret contains the old value from memory. If this value is equal to OLDVAL, the new value was written to memory. If not, return -EBUSY. */ if (!lws_errno && lws_ret != oldval) - lws_errno = -EBUSY; + return -EBUSY; return lws_errno; } static inline long -__kernel_cmpxchg2 (void *mem, const void *oldval, const void *newval, +__kernel_cmpxchg2 (volatile void *mem, const void *oldval, const void *newval, int val_size) { register unsigned long lws_mem asm("r26") = (unsigned long) (mem); @@ -88,9 +86,6 @@ __kernel_cmpxchg2 (void *mem, const void *oldval, const void *newval, if (__builtin_expect (lws_ret == 0, 1)) return 0; - if (__builtin_expect (lws_errno == -EFAULT || lws_errno == -ENOSYS, 0)) - __builtin_trap (); - /* If the kernel LWS call fails with no error, return -EBUSY */ if (__builtin_expect (!lws_errno, 0)) return -EBUSY; @@ -108,13 +103,13 @@ __kernel_cmpxchg2 (void *mem, const void *oldval, const void *newval, #define FETCH_AND_OP_2(OP, PFX_OP, INF_OP, TYPE, WIDTH, INDEX) \ TYPE HIDDEN \ - __sync_fetch_and_##OP##_##WIDTH (TYPE *ptr, TYPE val) \ + __sync_fetch_and_##OP##_##WIDTH (volatile void *ptr, TYPE val) \ { \ TYPE tmp, newval; \ long failure; \ \ do { \ - tmp = __atomic_load_n (ptr, __ATOMIC_RELAXED); \ + tmp = __atomic_load_n ((volatile TYPE *)ptr, __ATOMIC_RELAXED); \ newval = PFX_OP (tmp INF_OP val); \ failure = __kernel_cmpxchg2 (ptr, &tmp, &newval, INDEX); \ } while (failure != 0); \ @@ -122,36 +117,36 @@ __kernel_cmpxchg2 (void *mem, const void *oldval, const void *newval, return tmp; \ } -FETCH_AND_OP_2 (add, , +, long long, 8, 3) -FETCH_AND_OP_2 (sub, , -, long long, 8, 3) -FETCH_AND_OP_2 (or, , |, long long, 8, 3) -FETCH_AND_OP_2 (and, , &, long long, 8, 3) -FETCH_AND_OP_2 (xor, , ^, long long, 8, 3) -FETCH_AND_OP_2 (nand, ~, &, long long, 8, 3) - -FETCH_AND_OP_2 (add, , +, short, 2, 1) -FETCH_AND_OP_2 (sub, , -, short, 2, 1) -FETCH_AND_OP_2 (or, , |, short, 2, 1) -FETCH_AND_OP_2 (and, , &, short, 2, 1) -FETCH_AND_OP_2 (xor, , ^, short, 2, 1) -FETCH_AND_OP_2 (nand, ~, &, short, 2, 1) - -FETCH_AND_OP_2 (add, , +, signed char, 1, 0) -FETCH_AND_OP_2 (sub, , -, signed char, 1, 0) -FETCH_AND_OP_2 (or, , |, signed char, 1, 0) -FETCH_AND_OP_2 (and, , &, signed char, 1, 0) -FETCH_AND_OP_2 (xor, , ^, signed char, 1, 0) -FETCH_AND_OP_2 (nand, ~, &, signed char, 1, 0) +FETCH_AND_OP_2 (add, , +, long long unsigned int, 8, 3) +FETCH_AND_OP_2 (sub, , -, long long unsigned int, 8, 3) +FETCH_AND_OP_2 (or, , |, long long unsigned int, 8, 3) +FETCH_AND_OP_2 (and, , &, long long unsigned int, 8, 3) +FETCH_AND_OP_2 (xor, , ^, long long unsigned int, 8, 3) +FETCH_AND_OP_2 (nand, ~, &, long long unsigned int, 8, 3) + +FETCH_AND_OP_2 (add, , +, short unsigned int, 2, 1) +FETCH_AND_OP_2 (sub, , -, short unsigned int, 2, 1) +FETCH_AND_OP_2 (or, , |, short unsigned int, 2, 1) +FETCH_AND_OP_2 (and, , &, short unsigned int, 2, 1) +FETCH_AND_OP_2 (xor, , ^, short unsigned int, 2, 1) +FETCH_AND_OP_2 (nand, ~, &, short unsigned int, 2, 1) + +FETCH_AND_OP_2 (add, , +, unsigned char, 1, 0) +FETCH_AND_OP_2 (sub, , -, unsigned char, 1, 0) +FETCH_AND_OP_2 (or, , |, unsigned char, 1, 0) +FETCH_AND_OP_2 (and, , &, unsigned char, 1, 0) +FETCH_AND_OP_2 (xor, , ^, unsigned char, 1, 0) +FETCH_AND_OP_2 (nand, ~, &, unsigned char, 1, 0) #define OP_AND_FETCH_2(OP, PFX_OP, INF_OP, TYPE, WIDTH, INDEX) \ TYPE HIDDEN \ - __sync_##OP##_and_fetch_##WIDTH (TYPE *ptr, TYPE val) \ + __sync_##OP##_and_fetch_##WIDTH (volatile void *ptr, TYPE val) \ { \ TYPE tmp, newval; \ long failure; \ \ do { \ - tmp = __atomic_load_n (ptr, __ATOMIC_RELAXED); \ + tmp = __atomic_load_n ((volatile TYPE *)ptr, __ATOMIC_RELAXED); \ newval = PFX_OP (tmp INF_OP val); \ failure = __kernel_cmpxchg2 (ptr, &tmp, &newval, INDEX); \ } while (failure != 0); \ @@ -159,36 +154,37 @@ FETCH_AND_OP_2 (nand, ~, &, signed char, 1, 0) return PFX_OP (tmp INF_OP val); \ } -OP_AND_FETCH_2 (add, , +, long long, 8, 3) -OP_AND_FETCH_2 (sub, , -, long long, 8, 3) -OP_AND_FETCH_2 (or, , |, long long, 8, 3) -OP_AND_FETCH_2 (and, , &, long long, 8, 3) -OP_AND_FETCH_2 (xor, , ^, long long, 8, 3) -OP_AND_FETCH_2 (nand, ~, &, long long, 8, 3) - -OP_AND_FETCH_2 (add, , +, short, 2, 1) -OP_AND_FETCH_2 (sub, , -, short, 2, 1) -OP_AND_FETCH_2 (or, , |, short, 2, 1) -OP_AND_FETCH_2 (and, , &, short, 2, 1) -OP_AND_FETCH_2 (xor, , ^, short, 2, 1) -OP_AND_FETCH_2 (nand, ~, &, short, 2, 1) - -OP_AND_FETCH_2 (add, , +, signed char, 1, 0) -OP_AND_FETCH_2 (sub, , -, signed char, 1, 0) -OP_AND_FETCH_2 (or, , |, signed char, 1, 0) -OP_AND_FETCH_2 (and, , &, signed char, 1, 0) -OP_AND_FETCH_2 (xor, , ^, signed char, 1, 0) -OP_AND_FETCH_2 (nand, ~, &, signed char, 1, 0) +OP_AND_FETCH_2 (add, , +, long long unsigned int, 8, 3) +OP_AND_FETCH_2 (sub, , -, long long unsigned int, 8, 3) +OP_AND_FETCH_2 (or, , |, long long unsigned int, 8, 3) +OP_AND_FETCH_2 (and, , &, long long unsigned int, 8, 3) +OP_AND_FETCH_2 (xor, , ^, long long unsigned int, 8, 3) +OP_AND_FETCH_2 (nand, ~, &, long long unsigned int, 8, 3) + +OP_AND_FETCH_2 (add, , +, short unsigned int, 2, 1) +OP_AND_FETCH_2 (sub, , -, short unsigned int, 2, 1) +OP_AND_FETCH_2 (or, , |, short unsigned int, 2, 1) +OP_AND_FETCH_2 (and, , &, short unsigned int, 2, 1) +OP_AND_FETCH_2 (xor, , ^, short unsigned int, 2, 1) +OP_AND_FETCH_2 (nand, ~, &, short unsigned int, 2, 1) + +OP_AND_FETCH_2 (add, , +, unsigned char, 1, 0) +OP_AND_FETCH_2 (sub, , -, unsigned char, 1, 0) +OP_AND_FETCH_2 (or, , |, unsigned char, 1, 0) +OP_AND_FETCH_2 (and, , &, unsigned char, 1, 0) +OP_AND_FETCH_2 (xor, , ^, unsigned char, 1, 0) +OP_AND_FETCH_2 (nand, ~, &, unsigned char, 1, 0) #define FETCH_AND_OP_WORD(OP, PFX_OP, INF_OP) \ - int HIDDEN \ - __sync_fetch_and_##OP##_4 (int *ptr, int val) \ + unsigned int HIDDEN \ + __sync_fetch_and_##OP##_4 (volatile void *ptr, unsigned int val) \ { \ - int tmp; \ + unsigned int tmp; \ long failure; \ \ do { \ - tmp = __atomic_load_n (ptr, __ATOMIC_RELAXED); \ + tmp = __atomic_load_n ((volatile unsigned int *)ptr, \ + __ATOMIC_RELAXED); \ failure = __kernel_cmpxchg (ptr, tmp, PFX_OP (tmp INF_OP val)); \ } while (failure != 0); \ \ @@ -203,14 +199,15 @@ FETCH_AND_OP_WORD (xor, , ^) FETCH_AND_OP_WORD (nand, ~, &) #define OP_AND_FETCH_WORD(OP, PFX_OP, INF_OP) \ - int HIDDEN \ - __sync_##OP##_and_fetch_4 (int *ptr, int val) \ + unsigned int HIDDEN \ + __sync_##OP##_and_fetch_4 (volatile void *ptr, unsigned int val) \ { \ - int tmp; \ + unsigned int tmp; \ long failure; \ \ do { \ - tmp = __atomic_load_n (ptr, __ATOMIC_RELAXED); \ + tmp = __atomic_load_n ((volatile unsigned int *)ptr, \ + __ATOMIC_RELAXED); \ failure = __kernel_cmpxchg (ptr, tmp, PFX_OP (tmp INF_OP val)); \ } while (failure != 0); \ \ @@ -228,7 +225,7 @@ typedef unsigned char bool; #define COMPARE_AND_SWAP_2(TYPE, WIDTH, INDEX) \ TYPE HIDDEN \ - __sync_val_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \ + __sync_val_compare_and_swap_##WIDTH (volatile void *ptr, TYPE oldval, \ TYPE newval) \ { \ TYPE actual_oldval; \ @@ -236,7 +233,8 @@ typedef unsigned char bool; \ while (1) \ { \ - actual_oldval = __atomic_load_n (ptr, __ATOMIC_RELAXED); \ + actual_oldval = __atomic_load_n ((volatile TYPE *)ptr, \ + __ATOMIC_RELAXED); \ \ if (__builtin_expect (oldval != actual_oldval, 0)) \ return actual_oldval; \ @@ -248,27 +246,29 @@ typedef unsigned char bool; } \ } \ \ - bool HIDDEN \ - __sync_bool_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \ - TYPE newval) \ + _Bool HIDDEN \ + __sync_bool_compare_and_swap_##WIDTH (volatile void *ptr, \ + TYPE oldval, TYPE newval) \ { \ long failure = __kernel_cmpxchg2 (ptr, &oldval, &newval, INDEX); \ return (failure == 0); \ } -COMPARE_AND_SWAP_2 (long long, 8, 3) -COMPARE_AND_SWAP_2 (short, 2, 1) -COMPARE_AND_SWAP_2 (char, 1, 0) +COMPARE_AND_SWAP_2 (long long unsigned int, 8, 3) +COMPARE_AND_SWAP_2 (short unsigned int, 2, 1) +COMPARE_AND_SWAP_2 (unsigned char, 1, 0) -int HIDDEN -__sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval) +unsigned int HIDDEN +__sync_val_compare_and_swap_4 (volatile void *ptr, unsigned int oldval, + unsigned int newval) { long fail; - int actual_oldval; + unsigned int actual_oldval; while (1) { - actual_oldval = __atomic_load_n (ptr, __ATOMIC_RELAXED); + actual_oldval = __atomic_load_n ((volatile unsigned int *)ptr, + __ATOMIC_RELAXED); if (__builtin_expect (oldval != actual_oldval, 0)) return actual_oldval; @@ -280,8 +280,9 @@ __sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval) } } -bool HIDDEN -__sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval) +_Bool HIDDEN +__sync_bool_compare_and_swap_4 (volatile void *ptr, unsigned int oldval, + unsigned int newval) { long failure = __kernel_cmpxchg (ptr, oldval, newval); return (failure == 0); @@ -289,55 +290,64 @@ __sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval) #define SYNC_LOCK_TEST_AND_SET_2(TYPE, WIDTH, INDEX) \ TYPE HIDDEN \ - __sync_lock_test_and_set_##WIDTH (TYPE *ptr, TYPE val) \ + __sync_lock_test_and_set_##WIDTH (volatile void *ptr, TYPE val) \ { \ TYPE oldval; \ long failure; \ \ do { \ - oldval = __atomic_load_n (ptr, __ATOMIC_RELAXED); \ + oldval = __atomic_load_n ((volatile TYPE *)ptr, \ + __ATOMIC_RELAXED); \ failure = __kernel_cmpxchg2 (ptr, &oldval, &val, INDEX); \ } while (failure != 0); \ \ return oldval; \ } -SYNC_LOCK_TEST_AND_SET_2 (long long, 8, 3) -SYNC_LOCK_TEST_AND_SET_2 (short, 2, 1) -SYNC_LOCK_TEST_AND_SET_2 (signed char, 1, 0) +SYNC_LOCK_TEST_AND_SET_2 (long long unsigned int, 8, 3) +SYNC_LOCK_TEST_AND_SET_2 (short unsigned int, 2, 1) +SYNC_LOCK_TEST_AND_SET_2 (unsigned char, 1, 0) -int HIDDEN -__sync_lock_test_and_set_4 (int *ptr, int val) +unsigned int HIDDEN +__sync_lock_test_and_set_4 (volatile void *ptr, unsigned int val) { long failure; - int oldval; + unsigned int oldval; do { - oldval = __atomic_load_n (ptr, __ATOMIC_RELAXED); + oldval = __atomic_load_n ((volatile unsigned int *)ptr, __ATOMIC_RELAXED); failure = __kernel_cmpxchg (ptr, oldval, val); } while (failure != 0); return oldval; } -void HIDDEN -__sync_lock_release_8 (long long *ptr) -{ - /* All accesses must be complete before we release the lock. */ - __sync_synchronize (); - *(double *)ptr = 0; -} - -#define SYNC_LOCK_RELEASE_1(TYPE, WIDTH) \ +#define SYNC_LOCK_RELEASE_1(TYPE, WIDTH, INDEX) \ void HIDDEN \ - __sync_lock_release_##WIDTH (TYPE *ptr) \ + __sync_lock_release_##WIDTH (volatile void *ptr) \ { \ - /* All accesses must be complete before we release \ - the lock. */ \ - __sync_synchronize (); \ - *ptr = 0; \ + TYPE oldval, val = 0; \ + long failure; \ + \ + do { \ + oldval = __atomic_load_n ((volatile TYPE *)ptr, \ + __ATOMIC_RELAXED); \ + failure = __kernel_cmpxchg2 (ptr, &oldval, &val, INDEX); \ + } while (failure != 0); \ } -SYNC_LOCK_RELEASE_1 (int, 4) -SYNC_LOCK_RELEASE_1 (short, 2) -SYNC_LOCK_RELEASE_1 (signed char, 1) +SYNC_LOCK_RELEASE_1 (long long unsigned int, 8, 3) +SYNC_LOCK_RELEASE_1 (short unsigned int, 2, 1) +SYNC_LOCK_RELEASE_1 (unsigned char, 1, 0) + +void HIDDEN +__sync_lock_release_4 (volatile void *ptr) +{ + long failure; + unsigned int oldval; + + do { + oldval = __atomic_load_n ((volatile unsigned int *)ptr, __ATOMIC_RELAXED); + failure = __kernel_cmpxchg (ptr, oldval, 0); + } while (failure != 0); +} -- cgit v1.1 From 3d3a96a26eff2367d6573b30683c3c2945f443eb Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Mon, 18 Nov 2019 12:08:18 +0000 Subject: musl: Don't use gthr weak refs in libgcc PR91737 The gthr weak reference based single thread detection is unsafe with static linking and in case of dynamic linking it's ineffective on musl since pthread symbols are defined in libc.so. (Ideally this should be fixed for all targets, since glibc plans to move libpthread.so into libc.so too and users want to static link to pthread without --whole-archive: PR87189.) For now we have to explicitly opt out from the broken behaviour in the config machinery of each target lib and libgcc was previously missed. libgcc/ChangeLog: 2019-11-18 Szabolcs Nagy * config.host: Add t-gthr-noweak on *-*-musl*. * config/t-gthr-noweak: New file. From-SVN: r278399 --- libgcc/ChangeLog | 5 +++++ libgcc/config.host | 7 +++++++ libgcc/config/t-gthr-noweak | 2 ++ 3 files changed, 14 insertions(+) create mode 100644 libgcc/config/t-gthr-noweak (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 16e5696..f7fc821 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,8 @@ +2019-11-18 Szabolcs Nagy + + * config.host: Add t-gthr-noweak on *-*-musl*. + * config/t-gthr-noweak: New file. + 2019-11-17 John David Anglin * config/pa/linux-atomic.c (__kernel_cmpxchg): Change argument 1 to diff --git a/libgcc/config.host b/libgcc/config.host index 3035168..bc3e497 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -1531,3 +1531,10 @@ vxworks) ;; esac esac + +case ${host} in +*-*-musl*) + # The gthr weak references are unsafe with static linking + tmake_file="$tmake_file t-gthr-noweak" + ;; +esac diff --git a/libgcc/config/t-gthr-noweak b/libgcc/config/t-gthr-noweak new file mode 100644 index 0000000..45a21e9 --- /dev/null +++ b/libgcc/config/t-gthr-noweak @@ -0,0 +1,2 @@ +# Don't use weak references for single-thread detection +HOST_LIBGCC2_CFLAGS += -DGTHREAD_USE_WEAK=0 -- cgit v1.1 From 34b4d99d0ce35b51c536b46bb7d49e8f56db4024 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Mon, 18 Nov 2019 12:46:56 +0000 Subject: fix ChangeLog to reference the PR From-SVN: r278403 --- libgcc/ChangeLog | 1 + 1 file changed, 1 insertion(+) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index f7fc821..bf5c131 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,5 +1,6 @@ 2019-11-18 Szabolcs Nagy + PR libgcc/91737 * config.host: Add t-gthr-noweak on *-*-musl*. * config/t-gthr-noweak: New file. -- cgit v1.1 From 08d7ff78b3dc364d12c448521a25bc55f93e8684 Mon Sep 17 00:00:00 2001 From: Georg-Johann Lay Date: Thu, 5 Dec 2019 09:47:35 +0000 Subject: re PR target/92055 ([avr] Support 64-bit double) PR target/92055 * config/avr/t-avrlibc (MULTISUBDIR): Search for double, not double64. From-SVN: r278992 --- libgcc/ChangeLog | 5 +++++ libgcc/config/avr/t-avrlibc | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index bf5c131..78aefe8 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,8 @@ +2019-12-05 Georg-Johann Lay + + PR target/92055 + * config/avr/t-avrlibc (MULTISUBDIR): Search for double, not double64. + 2019-11-18 Szabolcs Nagy PR libgcc/91737 diff --git a/libgcc/config/avr/t-avrlibc b/libgcc/config/avr/t-avrlibc index 2424d66..34eca4f 100644 --- a/libgcc/config/avr/t-avrlibc +++ b/libgcc/config/avr/t-avrlibc @@ -71,9 +71,9 @@ ifneq (,$(findstring avr,$(MULTISUBDIR))) # In default dir, copying won'twork because the default multilib is # built after all the others. -ifneq (,$(findstring double64,$(MULTISUBDIR))) +ifneq (,$(findstring double,$(MULTISUBDIR))) -# We are in double64/libgcc or long-double64/libgcc: +# We are in double{32|64}/libgcc or long-double{32|64}/libgcc: # Just copy from the [long ]double=float multilib; we would remove any DFmode # bits from this multilib variant, anyway, because the current assumption # is that avr-libc hosts *all* the IEEE-double stuff. -- cgit v1.1 From ad8b778345e01ff8ce252bf572965684a0826082 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Mon, 9 Dec 2019 11:41:07 +0000 Subject: libgcc: Dont define __do_global_dtors_aux if it will be empty 2019-12-09 Jozef Lawrynowicz * crtstuff.c (__do_global_dtors_aux): Wrap in #if so it's only defined if it will have contents. From-SVN: r279123 --- libgcc/ChangeLog | 5 +++++ libgcc/crtstuff.c | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 78aefe8..0359f3a 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,8 @@ +2019-12-09 Jozef Lawrynowicz + + * crtstuff.c (__do_global_dtors_aux): Wrap in #if so it's only defined + if it will have contents. + 2019-12-05 Georg-Johann Lay PR target/92055 diff --git a/libgcc/crtstuff.c b/libgcc/crtstuff.c index ae6328d..80cc78d 100644 --- a/libgcc/crtstuff.c +++ b/libgcc/crtstuff.c @@ -364,8 +364,12 @@ extern void __cxa_finalize (void *) TARGET_ATTRIBUTE_WEAK; On some systems, this routine is run more than once from the .fini, when exit is called recursively, so we arrange to remember where in the list we left off processing, and we resume at that point, - should we be re-invoked. */ + should we be re-invoked. + This routine does not need to be run if none of the following clauses are + true, as it will not do anything, so can be removed. */ +#if defined(CRTSTUFFS_O) || !defined(FINI_ARRAY_SECTION_ASM_OP) \ + || USE_TM_CLONE_REGISTRY || USE_EH_FRAME_REGISTRY static void __attribute__((used)) __do_global_dtors_aux (void) { @@ -451,6 +455,8 @@ __do_global_dtors_aux_1 (void) CRT_CALL_STATIC_FUNCTION (__LIBGCC_INIT_SECTION_ASM_OP__, __do_global_dtors_aux_1) #endif +#endif /* defined(CRTSTUFFS_O) || !defined(FINI_ARRAY_SECTION_ASM_OP) + || defined(USE_TM_CLONE_REGISTRY) || defined(USE_EH_FRAME_REGISTRY) */ #if defined(USE_EH_FRAME_REGISTRY) || USE_TM_CLONE_REGISTRY /* Stick a call to __register_frame_info into the .init section. For some -- cgit v1.1 From 21a098f4a173fd5da3a36e86e4e41e6a8c920b51 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Mon, 9 Dec 2019 12:35:55 +0000 Subject: libgcc: Fix misuse of USE_EH_FRAME_REGISTRY in crtstuff.c 2019-12-09 Jozef Lawrynowicz * crtstuff.c (__do_global_dtors_aux): Check if USE_EH_FRAME_REGISTRY is defined instead of its value. From-SVN: r279125 --- libgcc/ChangeLog | 5 +++++ libgcc/crtstuff.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 0359f3a..c8480cd 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,5 +1,10 @@ 2019-12-09 Jozef Lawrynowicz + * crtstuff.c (__do_global_dtors_aux): Check if USE_EH_FRAME_REGISTRY is + defined instead of its value. + +2019-12-09 Jozef Lawrynowicz + * crtstuff.c (__do_global_dtors_aux): Wrap in #if so it's only defined if it will have contents. diff --git a/libgcc/crtstuff.c b/libgcc/crtstuff.c index 80cc78d..9346cc5 100644 --- a/libgcc/crtstuff.c +++ b/libgcc/crtstuff.c @@ -369,7 +369,7 @@ extern void __cxa_finalize (void *) TARGET_ATTRIBUTE_WEAK; This routine does not need to be run if none of the following clauses are true, as it will not do anything, so can be removed. */ #if defined(CRTSTUFFS_O) || !defined(FINI_ARRAY_SECTION_ASM_OP) \ - || USE_TM_CLONE_REGISTRY || USE_EH_FRAME_REGISTRY + || USE_TM_CLONE_REGISTRY || defined(USE_EH_FRAME_REGISTRY) static void __attribute__((used)) __do_global_dtors_aux (void) { @@ -456,7 +456,7 @@ CRT_CALL_STATIC_FUNCTION (__LIBGCC_INIT_SECTION_ASM_OP__, __do_global_dtors_aux_1) #endif #endif /* defined(CRTSTUFFS_O) || !defined(FINI_ARRAY_SECTION_ASM_OP) - || defined(USE_TM_CLONE_REGISTRY) || defined(USE_EH_FRAME_REGISTRY) */ + || USE_TM_CLONE_REGISTRY || defined(USE_EH_FRAME_REGISTRY) */ #if defined(USE_EH_FRAME_REGISTRY) || USE_TM_CLONE_REGISTRY /* Stick a call to __register_frame_info into the .init section. For some -- cgit v1.1 From 34a53788fec49e0a85bd32b51b057cfaae0200c8 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Wed, 11 Dec 2019 18:59:38 +0000 Subject: libgcc: Declare __dso_handle only if DEFAULT_USE_CXA_ATEXIT is true 2019-12-11 Jozef Lawrynowicz * crtstuff.c: Declare __dso_handle only if DEFAULT_USE_CXA_ATEXIT is true. From-SVN: r279243 --- libgcc/ChangeLog | 5 +++++ libgcc/crtstuff.c | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index c8480cd..b415d78 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,8 @@ +2019-12-11 Jozef Lawrynowicz + + * crtstuff.c: Declare __dso_handle only if DEFAULT_USE_CXA_ATEXIT is + true. + 2019-12-09 Jozef Lawrynowicz * crtstuff.c (__do_global_dtors_aux): Check if USE_EH_FRAME_REGISTRY is diff --git a/libgcc/crtstuff.c b/libgcc/crtstuff.c index 9346cc5..e282cb1 100644 --- a/libgcc/crtstuff.c +++ b/libgcc/crtstuff.c @@ -325,11 +325,14 @@ register_tm_clones (void) #ifdef OBJECT_FORMAT_ELF +#if DEFAULT_USE_CXA_ATEXIT /* Declare the __dso_handle variable. It should have a unique value in every shared-object; in a main program its value is zero. The object should in any case be protected. This means the instance in one DSO or the main program is not used in another object. The - dynamic linker takes care of this. */ + dynamic linker takes care of this. + If __cxa_atexit is not being used, __dso_handle will not be used and + doesn't need to be defined. */ #ifdef TARGET_LIBGCC_SDATA_SECTION extern void *__dso_handle __attribute__ ((__section__ (TARGET_LIBGCC_SDATA_SECTION))); @@ -342,6 +345,7 @@ void *__dso_handle = &__dso_handle; #else void *__dso_handle = 0; #endif +#endif /* DEFAULT_USE_CXA_ATEXIT */ /* The __cxa_finalize function may not be available so we use only a weak declaration. */ -- cgit v1.1 From a9046e9853024206bec092dd63e21e152cb5cbca Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Wed, 11 Dec 2019 19:19:50 +0000 Subject: MSP430: Add -fno-exceptions multilib ChangeLog: 2019-12-11 Jozef Lawrynowicz * config-ml.in (msp430-*-*): Support --disable-no-exceptions configure flag. gcc/ChangeLog: 2019-12-11 Jozef Lawrynowicz * config/msp430/msp430.h (STARTFILE_SPEC) [!fexceptions]: Use crtbegin_no_eh.o if building for the C language. [fno-exceptions]: Use crtbegin_no_eh.o if building for any language except C. (ENDFILE_SPEC) [!fexceptions]: Use crtend_no_eh.o if building for the C language. [fno-exceptions]: Use crtend_no_eh.o if building for any language except C. * config/msp430/t-msp430: Add -fno-exceptions multilib. * doc/install.texi: Document --disable-no-exceptions multilib configure option. * doc/sourcebuild.texi: Document exceptions_enabled effective target. gcc/testsuite/ChangeLog: 2019-12-11 Jozef Lawrynowicz * lib/gcc-dg.exp: Add dg-prune messages for when exception handling is disabled. * lib/target-supports.exp (check_effective_target_exceptions_enabled): New. libgcc/ChangeLog: 2019-12-11 Jozef Lawrynowicz * config.host: Add crt{begin,end}_no_eh.o to "extra_parts". * config.host (msp430*-*-elf): Add crt{begin,end}_no_eh.o to "extra_parts". From-SVN: r279246 --- libgcc/ChangeLog | 6 ++++++ libgcc/config.host | 3 ++- libgcc/config/msp430/t-msp430 | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index b415d78..90ea2a4 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,5 +1,11 @@ 2019-12-11 Jozef Lawrynowicz + * config.host (msp430*-*-elf): Add crt{begin,end}_no_eh.o to + "extra_parts". + * config/msp430/t-msp430: Add rules to build crt{begin,end}_no_eh.o. + +2019-12-11 Jozef Lawrynowicz + * crtstuff.c: Declare __dso_handle only if DEFAULT_USE_CXA_ATEXIT is true. diff --git a/libgcc/config.host b/libgcc/config.host index bc3e497..5686871 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -1045,7 +1045,8 @@ moxie-*-elf | moxie-*-moxiebox* | moxie-*-uclinux* | moxie-*-rtems*) ;; msp430*-*-elf) tmake_file="$tm_file t-crtstuff t-fdpbit msp430/t-msp430" - extra_parts="$extra_parts libmul_none.a libmul_16.a libmul_32.a libmul_f5.a" + extra_parts="$extra_parts crtbegin_no_eh.o crtend_no_eh.o" + extra_parts="$extra_parts libmul_none.a libmul_16.a libmul_32.a libmul_f5.a" ;; nds32*-linux*) # Basic makefile fragment and extra_parts for crt stuff. diff --git a/libgcc/config/msp430/t-msp430 b/libgcc/config/msp430/t-msp430 index 17d85b6..72ae93a 100644 --- a/libgcc/config/msp430/t-msp430 +++ b/libgcc/config/msp430/t-msp430 @@ -42,6 +42,12 @@ LIB2ADD = \ HOST_LIBGCC2_CFLAGS += -Os -ffunction-sections -fdata-sections -mhwmult=none +crtbegin_no_eh.o: $(srcdir)/crtstuff.c + $(crt_compile) -U__LIBGCC_EH_FRAME_SECTION_NAME__ -c $< -DCRT_BEGIN + +crtend_no_eh.o: $(srcdir)/crtstuff.c + $(crt_compile) -U__LIBGCC_EH_FRAME_SECTION_NAME__ -c $< -DCRT_END + mpy.o: $(srcdir)/config/msp430/mpy.c $(gcc_compile) $< -c -- cgit v1.1