diff mbox series

libgcc, libstdc++: Make more entities no longer TU-local [PR115126]

Message ID 66f35cff.650a0220.2897d1.6678@mx.google.com
State New
Headers show
Series libgcc, libstdc++: Make more entities no longer TU-local [PR115126] | expand

Commit Message

Nathaniel Shead Sept. 25, 2024, 12:44 a.m. UTC
I found that my previous minimal change to libstdc++ was only sufficient
to pass regtest on x86_64-pc-linux-gnu; Linaro complained about ARM and
aarch64.  This patch removes the rest of the internal-linkage entities I
could find exposed via libstdc++.

The libgcc changes include some blocks specific to FreeBSD, Solaris <10,
and HP-UX; I haven't been able to test these changes at this time.
Happy to adjust or remove those hunks as needed.  Apologies if I haven't
CC'd in the correct people.

Bootstrapped and regtested on x86_64-pc-linux-gnu and
aarch64-unknown-linux-gnu, OK for trunk?

-- >8 --

In C++20, modules streaming check for exposures of TU-local entities.
In general exposing internal linkage functions in a header is liable to
cause ODR violations in C++, and this is now detected in a module
context.

This patch goes through and removes 'static' from many functions exposed
through libstdc++ to prevent code like the following from failing:

  export module M;
  extern "C++" {
    #include <bits/stdc++.h>
  }

Since gthreads is used from C as well, we need to choose whether to use
'inline' or 'static inline' depending on whether we're compiling for C
or C++ (since the semantics of 'inline' are different between the
languages).  Additionally we need to remove static global variables, so
we migrate these to function-local statics to avoid the ODR issues.

There doesn't seem to be a good workaround for weakrefs, so I've left
them as-is and will work around it in the modules streaming code to
consider them as not TU-local.

The same issue occurs in the objective-C specific parts of gthreads, but
I'm not familiar with the surrounding context and we don't currently
test modules with Objective C++ anyway so I've left it as-is.

	PR libstdc++/115126

libgcc/ChangeLog:

	* gthr-posix.h (__GTHREAD_INLINE): New macro.
	(__gthread_active): Convert from variable to function.
	(__gthread_trigger): Mark as __GTHREAD_INLINE instead of static.
	(__gthread_active_p): Likewise.
	(__gthread_create): Likewise.
	(__gthread_join): Likewise.
	(__gthread_detach): Likewise.
	(__gthread_equal): Likewise.
	(__gthread_self): Likewise.
	(__gthread_yield): Likewise.
	(__gthread_once): Likewise.
	(__gthread_key_create): Likewise.
	(__gthread_key_delete): Likewise.
	(__gthread_getspecific): Likewise.
	(__gthread_setspecific): Likewise.
	(__gthread_mutex_init_function): Likewise.
	(__gthread_mutex_destroy): Likewise.
	(__gthread_mutex_lock): Likewise.
	(__gthread_mutex_trylock): Likewise.
	(__gthread_mutex_timedlock): Likewise.
	(__gthread_mutex_unlock): Likewise.
	(__gthread_recursive_mutex_init_function): Likewise.
	(__gthread_recursive_mutex_lock): Likewise.
	(__gthread_recursive_mutex_trylock): Likewise.
	(__gthread_recursive_mutex_timedlock): Likewise.
	(__gthread_recursive_mutex_unlock): Likewise.
	(__gthread_recursive_mutex_destroy): Likewise.
	(__gthread_cond_init_function): Likewise.
	(__gthread_cond_broadcast): Likewise.
	(__gthread_cond_signal): Likewise.
	(__gthread_cond_wait): Likewise.
	(__gthread_cond_timedwait): Likewise.
	(__gthread_cond_wait_recursive): Likewise.
	(__gthread_cond_destroy): Likewise.
	(__gthread_rwlock_rdlock): Likewise.
	(__gthread_rwlock_tryrdlock): Likewise.
	(__gthread_rwlock_wrlock): Likewise.
	(__gthread_rwlock_trywrlock): Likewise.
	(__gthread_rwlock_unlock): Likewise.
	* gthr-single.h (__GTHREAD_INLINE): New macro.
	(__gthread_active_p): Mark as __GTHREAD_INLINE instead of static.
	(__gthread_once): Likewise.
	(__gthread_key_create): Likewise.
	(__gthread_key_delete): Likewise.
	(__gthread_getspecific): Likewise.
	(__gthread_setspecific): Likewise.
	(__gthread_mutex_destroy): Likewise.
	(__gthread_mutex_lock): Likewise.
	(__gthread_mutex_trylock): Likewise.
	(__gthread_mutex_unlock): Likewise.
	(__gthread_recursive_mutex_lock): Likewise.
	(__gthread_recursive_mutex_trylock): Likewise.
	(__gthread_recursive_mutex_unlock): Likewise.
	(__gthread_recursive_mutex_destroy): Likewise.

libstdc++-v3/ChangeLog:

	* include/bits/shared_ptr.h (std::__is_shared_ptr): Remove
	unnecessary 'static'.
	* include/bits/unique_ptr.h (std::__is_unique_ptr): Likewise.
	* include/std/future (std::__craete_task_state): Likewise.
	* include/std/shared_mutex (_GLIBCXX_GTRHW): Likewise.
	(__glibcxx_rwlock_init): Likewise.
	(__glibcxx_rwlock_timedrdlock): Likewise.
	(__glibcxx_rwlock_timedwrlock): Likewise.
	(__glibcxx_rwlock_rdlock): Likewise.
	(__glibcxx_rwlock_tryrdlock): Likewise.
	(__glibcxx_rwlock_wrlock): Likewise.
	(__glibcxx_rwlock_trywrlock): Likewise.
	(__glibcxx_rwlock_unlock): Likewise.
	(__glibcxx_rwlock_destroy): Likewise.
	(__glibcxx_rwlock_init): Likewise.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
---
 libgcc/gthr-posix.h                    | 116 ++++++++++++++-----------
 libgcc/gthr-single.h                   |  34 +++++---
 libstdc++-v3/include/bits/shared_ptr.h |   4 +-
 libstdc++-v3/include/bits/unique_ptr.h |   4 +-
 libstdc++-v3/include/std/future        |   2 +-
 libstdc++-v3/include/std/shared_mutex  |  26 +++---
 6 files changed, 104 insertions(+), 82 deletions(-)

Comments

Jonathan Wakely Sept. 25, 2024, 9:43 a.m. UTC | #1
On Wed, 25 Sept 2024 at 01:50, Nathaniel Shead
<nathanieloshead@gmail.com> wrote:
>
> I found that my previous minimal change to libstdc++ was only sufficient
> to pass regtest on x86_64-pc-linux-gnu; Linaro complained about ARM and
> aarch64.  This patch removes the rest of the internal-linkage entities I
> could find exposed via libstdc++.
>
> The libgcc changes include some blocks specific to FreeBSD, Solaris <10,
> and HP-UX; I haven't been able to test these changes at this time.
> Happy to adjust or remove those hunks as needed.  Apologies if I haven't
> CC'd in the correct people.
>
> Bootstrapped and regtested on x86_64-pc-linux-gnu and
> aarch64-unknown-linux-gnu, OK for trunk?
>
> -- >8 --
>
> In C++20, modules streaming check for exposures of TU-local entities.
> In general exposing internal linkage functions in a header is liable to
> cause ODR violations in C++, and this is now detected in a module
> context.
>
> This patch goes through and removes 'static' from many functions exposed
> through libstdc++ to prevent code like the following from failing:
>
>   export module M;
>   extern "C++" {
>     #include <bits/stdc++.h>
>   }
>
> Since gthreads is used from C as well, we need to choose whether to use
> 'inline' or 'static inline' depending on whether we're compiling for C
> or C++ (since the semantics of 'inline' are different between the
> languages).  Additionally we need to remove static global variables, so
> we migrate these to function-local statics to avoid the ODR issues.
>
> There doesn't seem to be a good workaround for weakrefs, so I've left
> them as-is and will work around it in the modules streaming code to
> consider them as not TU-local.
>
> The same issue occurs in the objective-C specific parts of gthreads, but
> I'm not familiar with the surrounding context and we don't currently
> test modules with Objective C++ anyway so I've left it as-is.
>
>         PR libstdc++/115126
>
> libgcc/ChangeLog:
>
>         * gthr-posix.h (__GTHREAD_INLINE): New macro.
>         (__gthread_active): Convert from variable to function.
>         (__gthread_trigger): Mark as __GTHREAD_INLINE instead of static.
>         (__gthread_active_p): Likewise.
>         (__gthread_create): Likewise.
>         (__gthread_join): Likewise.
>         (__gthread_detach): Likewise.
>         (__gthread_equal): Likewise.
>         (__gthread_self): Likewise.
>         (__gthread_yield): Likewise.
>         (__gthread_once): Likewise.
>         (__gthread_key_create): Likewise.
>         (__gthread_key_delete): Likewise.
>         (__gthread_getspecific): Likewise.
>         (__gthread_setspecific): Likewise.
>         (__gthread_mutex_init_function): Likewise.
>         (__gthread_mutex_destroy): Likewise.
>         (__gthread_mutex_lock): Likewise.
>         (__gthread_mutex_trylock): Likewise.
>         (__gthread_mutex_timedlock): Likewise.
>         (__gthread_mutex_unlock): Likewise.
>         (__gthread_recursive_mutex_init_function): Likewise.
>         (__gthread_recursive_mutex_lock): Likewise.
>         (__gthread_recursive_mutex_trylock): Likewise.
>         (__gthread_recursive_mutex_timedlock): Likewise.
>         (__gthread_recursive_mutex_unlock): Likewise.
>         (__gthread_recursive_mutex_destroy): Likewise.
>         (__gthread_cond_init_function): Likewise.
>         (__gthread_cond_broadcast): Likewise.
>         (__gthread_cond_signal): Likewise.
>         (__gthread_cond_wait): Likewise.
>         (__gthread_cond_timedwait): Likewise.
>         (__gthread_cond_wait_recursive): Likewise.
>         (__gthread_cond_destroy): Likewise.
>         (__gthread_rwlock_rdlock): Likewise.
>         (__gthread_rwlock_tryrdlock): Likewise.
>         (__gthread_rwlock_wrlock): Likewise.
>         (__gthread_rwlock_trywrlock): Likewise.
>         (__gthread_rwlock_unlock): Likewise.
>         * gthr-single.h (__GTHREAD_INLINE): New macro.
>         (__gthread_active_p): Mark as __GTHREAD_INLINE instead of static.
>         (__gthread_once): Likewise.
>         (__gthread_key_create): Likewise.
>         (__gthread_key_delete): Likewise.
>         (__gthread_getspecific): Likewise.
>         (__gthread_setspecific): Likewise.
>         (__gthread_mutex_destroy): Likewise.
>         (__gthread_mutex_lock): Likewise.
>         (__gthread_mutex_trylock): Likewise.
>         (__gthread_mutex_unlock): Likewise.
>         (__gthread_recursive_mutex_lock): Likewise.
>         (__gthread_recursive_mutex_trylock): Likewise.
>         (__gthread_recursive_mutex_unlock): Likewise.
>         (__gthread_recursive_mutex_destroy): Likewise.
>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/shared_ptr.h (std::__is_shared_ptr): Remove
>         unnecessary 'static'.
>         * include/bits/unique_ptr.h (std::__is_unique_ptr): Likewise.
>         * include/std/future (std::__craete_task_state): Likewise.

Typo in the function name here.

The libstdc++ parts are OK for trunk (and gcc-14 if that makes sense
too, maybe for Clang?). If the libgcc parts take longer to get
approved, please feel free to split the patch and push the libstdc++
parts separately.

I can't approve the libgcc parts myself, but they look OK to me. I
have one comment about them below.

>         * include/std/shared_mutex (_GLIBCXX_GTRHW): Likewise.
>         (__glibcxx_rwlock_init): Likewise.
>         (__glibcxx_rwlock_timedrdlock): Likewise.
>         (__glibcxx_rwlock_timedwrlock): Likewise.
>         (__glibcxx_rwlock_rdlock): Likewise.
>         (__glibcxx_rwlock_tryrdlock): Likewise.
>         (__glibcxx_rwlock_wrlock): Likewise.
>         (__glibcxx_rwlock_trywrlock): Likewise.
>         (__glibcxx_rwlock_unlock): Likewise.
>         (__glibcxx_rwlock_destroy): Likewise.
>         (__glibcxx_rwlock_init): Likewise.
>
> Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
> ---
>  libgcc/gthr-posix.h                    | 116 ++++++++++++++-----------
>  libgcc/gthr-single.h                   |  34 +++++---
>  libstdc++-v3/include/bits/shared_ptr.h |   4 +-
>  libstdc++-v3/include/bits/unique_ptr.h |   4 +-
>  libstdc++-v3/include/std/future        |   2 +-
>  libstdc++-v3/include/std/shared_mutex  |  26 +++---
>  6 files changed, 104 insertions(+), 82 deletions(-)
>
> diff --git a/libgcc/gthr-posix.h b/libgcc/gthr-posix.h
> index 82e8f9ffcf6..557bae7aaaa 100644
> --- a/libgcc/gthr-posix.h
> +++ b/libgcc/gthr-posix.h
> @@ -44,6 +44,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>  # endif
>  #endif
>
> +#ifdef __cplusplus
> +# define __GTHREAD_INLINE inline
> +#else
> +# define __GTHREAD_INLINE static inline
> +#endif
> +
>  typedef pthread_t __gthread_t;
>  typedef pthread_key_t __gthread_key_t;
>  typedef pthread_once_t __gthread_once_t;
> @@ -182,22 +188,27 @@ __gthrw(pthread_setschedparam)
>
>  #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
>
> -static volatile int __gthread_active = -1;
> +__GTHREAD_INLINE volatile int *
> +__gthread_active (void)
> +{
> +  static volatile int __gthread_active_var = -1;
> +  return &__gthread_active_var;
> +}
>
> -static void
> +__GTHREAD_INLINE void
>  __gthread_trigger (void)
>  {
> -  __gthread_active = 1;
> +  *__gthread_active () = 1;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_active_p (void)
>  {
>    static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
>    static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
>
>    /* Avoid reading __gthread_active twice on the main code path.  */
> -  int __gthread_active_latest_value = __gthread_active;
> +  int __gthread_active_latest_value = *__gthread_active ();
>
>    /* This test is not protected to avoid taking a lock on the main code
>       path so every update of __gthread_active in a threaded program must
> @@ -214,10 +225,10 @@ __gthread_active_p (void)
>         }
>
>        /* Make sure we'll never enter this block again.  */
> -      if (__gthread_active < 0)
> -       __gthread_active = 0;
> +      if (*__gthread_active () < 0)
> +       *__gthread_active () = 0;
>
> -      __gthread_active_latest_value = __gthread_active;
> +      __gthread_active_latest_value = *__gthread_active ();
>      }
>
>    return __gthread_active_latest_value != 0;
> @@ -257,7 +268,7 @@ __gthrw2(__gthrw_(__pthread_key_create),
>  # define GTHR_ACTIVE_PROXY     __gthrw_(pthread_cancel)
>  #endif
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_active_p (void)
>  {
>    static void *const __gthread_active_ptr
> @@ -288,20 +299,25 @@ __gthread_active_p (void)
>
>  #if defined(__hppa__) && defined(__hpux__)
>
> -static volatile int __gthread_active = -1;
> +__GTHREAD_INLINE volatile int *
> +__gthread_active (void)
> +{
> +  static volatile int __gthread_active_var = -1;
> +  return &__gthread_active_var;
> +}
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_active_p (void)
>  {
>    /* Avoid reading __gthread_active twice on the main code path.  */
> -  int __gthread_active_latest_value = __gthread_active;
> +  int __gthread_active_latest_value = *__gthread_active ();
>    size_t __s;
>
>    if (__builtin_expect (__gthread_active_latest_value < 0, 0))
>      {
>        pthread_default_stacksize_np (0, &__s);
> -      __gthread_active = __s ? 1 : 0;
> -      __gthread_active_latest_value = __gthread_active;
> +      *__gthread_active () = __s ? 1 : 0;
> +      __gthread_active_latest_value = *__gthread_active ();
>      }
>
>    return __gthread_active_latest_value != 0;
> @@ -309,7 +325,7 @@ __gthread_active_p (void)
>
>  #else /* not hppa-hpux */
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_active_p (void)
>  {
>    return 1;
> @@ -669,44 +685,44 @@ __gthread_objc_condition_signal (objc_condition_t condition)
>
>  #else /* _LIBOBJC */
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_create (__gthread_t *__threadid, void *(*__func) (void*),
>                   void *__args)
>  {
>    return __gthrw_(pthread_create) (__threadid, NULL, __func, __args);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_join (__gthread_t __threadid, void **__value_ptr)
>  {
>    return __gthrw_(pthread_join) (__threadid, __value_ptr);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_detach (__gthread_t __threadid)
>  {
>    return __gthrw_(pthread_detach) (__threadid);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_equal (__gthread_t __t1, __gthread_t __t2)
>  {
>    return __gthrw_(pthread_equal) (__t1, __t2);
>  }
>
> -static inline __gthread_t
> +__GTHREAD_INLINE __gthread_t
>  __gthread_self (void)
>  {
>    return __gthrw_(pthread_self) ();
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_yield (void)
>  {
>    return __gthrw_(sched_yield) ();
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_once (__gthread_once_t *__once, void (*__func) (void))
>  {
>    if (__gthread_active_p ())
> @@ -715,38 +731,38 @@ __gthread_once (__gthread_once_t *__once, void (*__func) (void))
>      return -1;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
>  {
>    return __gthrw_(pthread_key_create) (__key, __dtor);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_key_delete (__gthread_key_t __key)
>  {
>    return __gthrw_(pthread_key_delete) (__key);
>  }
>
> -static inline void *
> +__GTHREAD_INLINE void *
>  __gthread_getspecific (__gthread_key_t __key)
>  {
>    return __gthrw_(pthread_getspecific) (__key);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
>  {
>    return __gthrw_(pthread_setspecific) (__key, __ptr);
>  }
>
> -static inline void
> +__GTHREAD_INLINE void
>  __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
>  {
>    if (__gthread_active_p ())
>      __gthrw_(pthread_mutex_init) (__mutex, NULL);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
>  {
>    if (__gthread_active_p ())
> @@ -755,7 +771,7 @@ __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
>      return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_mutex_lock (__gthread_mutex_t *__mutex)
>  {
>    if (__gthread_active_p ())
> @@ -764,7 +780,7 @@ __gthread_mutex_lock (__gthread_mutex_t *__mutex)
>      return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
>  {
>    if (__gthread_active_p ())
> @@ -774,7 +790,7 @@ __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
>  }
>
>  #if _GTHREAD_USE_MUTEX_TIMEDLOCK
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
>                            const __gthread_time_t *__abs_timeout)
>  {
> @@ -785,7 +801,7 @@ __gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
>  }
>  #endif
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
>  {
>    if (__gthread_active_p ())
> @@ -796,7 +812,7 @@ __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
>
>  #if !defined( PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) \
>    || defined(_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC)
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
>  {
>    if (__gthread_active_p ())
> @@ -818,20 +834,20 @@ __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
>  }
>  #endif
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
>  {
>    return __gthread_mutex_lock (__mutex);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
>  {
>    return __gthread_mutex_trylock (__mutex);
>  }
>
>  #if _GTHREAD_USE_MUTEX_TIMEDLOCK
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
>                                      const __gthread_time_t *__abs_timeout)
>  {
> @@ -839,20 +855,20 @@ __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
>  }
>  #endif
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
>  {
>    return __gthread_mutex_unlock (__mutex);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
>  {
>    return __gthread_mutex_destroy (__mutex);
>  }
>
>  #ifdef _GTHREAD_USE_COND_INIT_FUNC
> -static inline void
> +__GTHREAD_INLINE void
>  __gthread_cond_init_function (__gthread_cond_t *__cond)
>  {
>    if (__gthread_active_p ())
> @@ -860,46 +876,46 @@ __gthread_cond_init_function (__gthread_cond_t *__cond)
>  }
>  #endif
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_cond_broadcast (__gthread_cond_t *__cond)
>  {
>    return __gthrw_(pthread_cond_broadcast) (__cond);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_cond_signal (__gthread_cond_t *__cond)
>  {
>    return __gthrw_(pthread_cond_signal) (__cond);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
>  {
>    return __gthrw_(pthread_cond_wait) (__cond, __mutex);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
>                           const __gthread_time_t *__abs_timeout)
>  {
>    return __gthrw_(pthread_cond_timedwait) (__cond, __mutex, __abs_timeout);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_cond_wait_recursive (__gthread_cond_t *__cond,
>                                __gthread_recursive_mutex_t *__mutex)
>  {
>    return __gthread_cond_wait (__cond, __mutex);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_cond_destroy (__gthread_cond_t* __cond)
>  {
>    return __gthrw_(pthread_cond_destroy) (__cond);
>  }
>
>  #ifndef __cplusplus
> -static inline int
> +__GTHREAD_INLINE int

This is a ! __cplusplus group, so these could stay as static inline.

However, I don't understand why r14-6425-gb806c88fab3f9c added those
for !__cplusplus instead of just adding them unconditionally and
removing the equivalent code in <shared_mutex>. We should fix that,
and then I suppose the functions in gthr-posix.h would want to use
__GTHREAD_INLINE here. So for consistency and futureproofing, I think
it makes sense to change them here.

>  __gthread_rwlock_rdlock (__gthread_rwlock_t *__rwlock)
>  {
>    if (__gthread_active_p ())
> @@ -908,7 +924,7 @@ __gthread_rwlock_rdlock (__gthread_rwlock_t *__rwlock)
>      return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_rwlock_tryrdlock (__gthread_rwlock_t *__rwlock)
>  {
>    if (__gthread_active_p ())
> @@ -917,7 +933,7 @@ __gthread_rwlock_tryrdlock (__gthread_rwlock_t *__rwlock)
>      return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_rwlock_wrlock (__gthread_rwlock_t *__rwlock)
>  {
>    if (__gthread_active_p ())
> @@ -926,7 +942,7 @@ __gthread_rwlock_wrlock (__gthread_rwlock_t *__rwlock)
>      return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_rwlock_trywrlock (__gthread_rwlock_t *__rwlock)
>  {
>    if (__gthread_active_p ())
> @@ -935,7 +951,7 @@ __gthread_rwlock_trywrlock (__gthread_rwlock_t *__rwlock)
>      return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_rwlock_unlock (__gthread_rwlock_t *__rwlock)
>  {
>    if (__gthread_active_p ())
> diff --git a/libgcc/gthr-single.h b/libgcc/gthr-single.h
> index 8ee6b170840..0473daaf89d 100644
> --- a/libgcc/gthr-single.h
> +++ b/libgcc/gthr-single.h
> @@ -38,6 +38,12 @@ typedef int __gthread_recursive_mutex_t;
>  #define __GTHREAD_MUTEX_INIT_FUNCTION(mx) do {} while (0)
>  #define __GTHREAD_RECURSIVE_MUTEX_INIT 0
>
> +#ifdef __cplusplus
> +# define __GTHREAD_INLINE inline
> +#else
> +# define __GTHREAD_INLINE static inline
> +#endif
> +
>  #define UNUSED __attribute__((__unused__))
>
>  #ifdef _LIBOBJC
> @@ -207,85 +213,85 @@ __gthread_objc_condition_signal (objc_condition_t condition UNUSED)
>
>  #else /* _LIBOBJC */
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_active_p (void)
>  {
>    return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_once (__gthread_once_t *__once UNUSED, void (*__func) (void) UNUSED)
>  {
>    return 0;
>  }
>
> -static inline int UNUSED
> +__GTHREAD_INLINE int UNUSED
>  __gthread_key_create (__gthread_key_t *__key UNUSED, void (*__func) (void *) UNUSED)
>  {
>    return 0;
>  }
>
> -static int UNUSED
> +__GTHREAD_INLINE int UNUSED
>  __gthread_key_delete (__gthread_key_t __key UNUSED)
>  {
>    return 0;
>  }
>
> -static inline void *
> +__GTHREAD_INLINE void *
>  __gthread_getspecific (__gthread_key_t __key UNUSED)
>  {
>    return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_setspecific (__gthread_key_t __key UNUSED, const void *__v UNUSED)
>  {
>    return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_mutex_destroy (__gthread_mutex_t *__mutex UNUSED)
>  {
>    return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_mutex_lock (__gthread_mutex_t *__mutex UNUSED)
>  {
>    return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_mutex_trylock (__gthread_mutex_t *__mutex UNUSED)
>  {
>    return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_mutex_unlock (__gthread_mutex_t *__mutex UNUSED)
>  {
>    return 0;
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
>  {
>    return __gthread_mutex_lock (__mutex);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
>  {
>    return __gthread_mutex_trylock (__mutex);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
>  {
>    return __gthread_mutex_unlock (__mutex);
>  }
>
> -static inline int
> +__GTHREAD_INLINE int
>  __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
>  {
>    return __gthread_mutex_destroy (__mutex);
> diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
> index 13273afa9d2..9b1c2b4eb3d 100644
> --- a/libstdc++-v3/include/bits/shared_ptr.h
> +++ b/libstdc++-v3/include/bits/shared_ptr.h
> @@ -1160,9 +1160,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
>  #if __cpp_variable_templates
>    template<typename _Tp>
> -    static constexpr bool __is_shared_ptr = false;
> +    constexpr bool __is_shared_ptr = false;
>    template<typename _Tp>
> -    static constexpr bool __is_shared_ptr<shared_ptr<_Tp>> = true;
> +    constexpr bool __is_shared_ptr<shared_ptr<_Tp>> = true;
>  #endif
>
>    /// @} relates shared_ptr
> diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h
> index edcff78bff9..182173aa857 100644
> --- a/libstdc++-v3/include/bits/unique_ptr.h
> +++ b/libstdc++-v3/include/bits/unique_ptr.h
> @@ -1157,9 +1157,9 @@ namespace __detail
>
>  #if __cpp_variable_templates
>    template<typename _Tp>
> -    static constexpr bool __is_unique_ptr = false;
> +    constexpr bool __is_unique_ptr = false;
>    template<typename _Tp, typename _Del>
> -    static constexpr bool __is_unique_ptr<unique_ptr<_Tp, _Del>> = true;
> +    constexpr bool __is_unique_ptr<unique_ptr<_Tp, _Del>> = true;
>  #endif
>
>    /// @} group pointer_abstractions
> diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
> index 6ce7d89ca3f..437453eaa44 100644
> --- a/libstdc++-v3/include/std/future
> +++ b/libstdc++-v3/include/std/future
> @@ -1526,7 +1526,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
>    template<typename _Signature, typename _Fn,
>            typename _Alloc = std::allocator<int>>
> -    static shared_ptr<__future_base::_Task_state_base<_Signature>>
> +    shared_ptr<__future_base::_Task_state_base<_Signature>>
>      __create_task_state(_Fn&& __fn, const _Alloc& __a = _Alloc())
>      {
>        typedef typename decay<_Fn>::type _Fn2;
> diff --git a/libstdc++-v3/include/std/shared_mutex b/libstdc++-v3/include/std/shared_mutex
> index 1b6478f30c3..7e7941dd7a1 100644
> --- a/libstdc++-v3/include/std/shared_mutex
> +++ b/libstdc++-v3/include/std/shared_mutex
> @@ -72,7 +72,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  #ifdef __gthrw
>  #define _GLIBCXX_GTHRW(name) \
>    __gthrw(pthread_ ## name); \
> -  static inline int \
> +  inline int \
>    __glibcxx_ ## name (pthread_rwlock_t *__rwlock) \
>    { \
>      if (__gthread_active_p ()) \
> @@ -88,7 +88,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  # ifndef PTHREAD_RWLOCK_INITIALIZER
>    _GLIBCXX_GTHRW(rwlock_destroy)
>    __gthrw(pthread_rwlock_init);
> -  static inline int
> +  inline int
>    __glibcxx_rwlock_init (pthread_rwlock_t *__rwlock)
>    {
>      if (__gthread_active_p ())
> @@ -99,7 +99,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  # endif
>  # if _GTHREAD_USE_MUTEX_TIMEDLOCK
>     __gthrw(pthread_rwlock_timedrdlock);
> -  static inline int
> +  inline int
>    __glibcxx_rwlock_timedrdlock (pthread_rwlock_t *__rwlock,
>                                 const timespec *__ts)
>    {
> @@ -109,7 +109,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        return 0;
>    }
>     __gthrw(pthread_rwlock_timedwrlock);
> -  static inline int
> +  inline int
>    __glibcxx_rwlock_timedwrlock (pthread_rwlock_t *__rwlock,
>                                 const timespec *__ts)
>    {
> @@ -120,33 +120,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    }
>  # endif
>  #else
> -  static inline int
> +  inline int
>    __glibcxx_rwlock_rdlock (pthread_rwlock_t *__rwlock)
>    { return pthread_rwlock_rdlock (__rwlock); }
> -  static inline int
> +  inline int
>    __glibcxx_rwlock_tryrdlock (pthread_rwlock_t *__rwlock)
>    { return pthread_rwlock_tryrdlock (__rwlock); }
> -  static inline int
> +  inline int
>    __glibcxx_rwlock_wrlock (pthread_rwlock_t *__rwlock)
>    { return pthread_rwlock_wrlock (__rwlock); }
> -  static inline int
> +  inline int
>    __glibcxx_rwlock_trywrlock (pthread_rwlock_t *__rwlock)
>    { return pthread_rwlock_trywrlock (__rwlock); }
> -  static inline int
> +  inline int
>    __glibcxx_rwlock_unlock (pthread_rwlock_t *__rwlock)
>    { return pthread_rwlock_unlock (__rwlock); }
> -  static inline int
> +  inline int
>    __glibcxx_rwlock_destroy(pthread_rwlock_t *__rwlock)
>    { return pthread_rwlock_destroy (__rwlock); }
> -  static inline int
> +  inline int
>    __glibcxx_rwlock_init(pthread_rwlock_t *__rwlock)
>    { return pthread_rwlock_init (__rwlock, NULL); }
>  # if _GTHREAD_USE_MUTEX_TIMEDLOCK
> -  static inline int
> +  inline int
>    __glibcxx_rwlock_timedrdlock (pthread_rwlock_t *__rwlock,
>                                 const timespec *__ts)
>    { return pthread_rwlock_timedrdlock (__rwlock, __ts); }
> -  static inline int
> +  inline int
>    __glibcxx_rwlock_timedwrlock (pthread_rwlock_t *__rwlock,
>                                 const timespec *__ts)
>    { return pthread_rwlock_timedwrlock (__rwlock, __ts); }
> --
> 2.46.0
>
Jakub Jelinek Sept. 25, 2024, 10:29 a.m. UTC | #2
On Wed, Sep 25, 2024 at 10:43:50AM +0100, Jonathan Wakely wrote:
> > libgcc/ChangeLog:
> >
> >         * gthr-posix.h (__GTHREAD_INLINE): New macro.
> >         (__gthread_active): Convert from variable to function.
> >         (__gthread_trigger): Mark as __GTHREAD_INLINE instead of static.
> >         (__gthread_active_p): Likewise.
> >         (__gthread_create): Likewise.
> >         (__gthread_join): Likewise.
> >         (__gthread_detach): Likewise.
> >         (__gthread_equal): Likewise.
> >         (__gthread_self): Likewise.
> >         (__gthread_yield): Likewise.
> >         (__gthread_once): Likewise.
> >         (__gthread_key_create): Likewise.
> >         (__gthread_key_delete): Likewise.
> >         (__gthread_getspecific): Likewise.
> >         (__gthread_setspecific): Likewise.
> >         (__gthread_mutex_init_function): Likewise.
> >         (__gthread_mutex_destroy): Likewise.
> >         (__gthread_mutex_lock): Likewise.
> >         (__gthread_mutex_trylock): Likewise.
> >         (__gthread_mutex_timedlock): Likewise.
> >         (__gthread_mutex_unlock): Likewise.
> >         (__gthread_recursive_mutex_init_function): Likewise.
> >         (__gthread_recursive_mutex_lock): Likewise.
> >         (__gthread_recursive_mutex_trylock): Likewise.
> >         (__gthread_recursive_mutex_timedlock): Likewise.
> >         (__gthread_recursive_mutex_unlock): Likewise.
> >         (__gthread_recursive_mutex_destroy): Likewise.
> >         (__gthread_cond_init_function): Likewise.
> >         (__gthread_cond_broadcast): Likewise.
> >         (__gthread_cond_signal): Likewise.
> >         (__gthread_cond_wait): Likewise.
> >         (__gthread_cond_timedwait): Likewise.
> >         (__gthread_cond_wait_recursive): Likewise.
> >         (__gthread_cond_destroy): Likewise.
> >         (__gthread_rwlock_rdlock): Likewise.
> >         (__gthread_rwlock_tryrdlock): Likewise.
> >         (__gthread_rwlock_wrlock): Likewise.
> >         (__gthread_rwlock_trywrlock): Likewise.
> >         (__gthread_rwlock_unlock): Likewise.
> >         * gthr-single.h (__GTHREAD_INLINE): New macro.
> >         (__gthread_active_p): Mark as __GTHREAD_INLINE instead of static.
> >         (__gthread_once): Likewise.
> >         (__gthread_key_create): Likewise.
> >         (__gthread_key_delete): Likewise.
> >         (__gthread_getspecific): Likewise.
> >         (__gthread_setspecific): Likewise.
> >         (__gthread_mutex_destroy): Likewise.
> >         (__gthread_mutex_lock): Likewise.
> >         (__gthread_mutex_trylock): Likewise.
> >         (__gthread_mutex_unlock): Likewise.
> >         (__gthread_recursive_mutex_lock): Likewise.
> >         (__gthread_recursive_mutex_trylock): Likewise.
> >         (__gthread_recursive_mutex_unlock): Likewise.
> >         (__gthread_recursive_mutex_destroy): Likewise.

I'm worried about ABI consequences of these changes.
From what I can see, this doesn't change anything important for C,
the inlines are still static inline and the conversion of global static
vars to function-local in static inline still keeps those static.

But for C++ this means significant changes.
Say
_ZZ16__gthread_activevE20__gthread_active_var
etc. will now be STB_GNU_UNIQUE symbol, exported from whatever shared
libraries and binaries are compiled with C++ and include those headers
and actually use them somewhere.

On one side, it has benefits (e.g. every TU won't separately test and
store whether the threads are active or not), on the other side it can
prevent dlclose of some shared libraries and create interdependencies
between libraries.

So, I wonder if we couldn't define the C++ __GTHREAD_INLINE to
static inline __attribute__((__always_inline__)) (or at least when
using a compiler which supports the attribute, we can now test it
using preprocessor...).  And whether similarly we couldn't use
__attribute__((__visibility__ ("hidden"))) on the static block scope
vars for C++ (again, if compiler supports that), so that the changes
don't affect ABI of C++ libraries.

	Jakub
Jonathan Wakely Sept. 25, 2024, 10:47 a.m. UTC | #3
On Wed, 25 Sept 2024 at 11:29, Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Wed, Sep 25, 2024 at 10:43:50AM +0100, Jonathan Wakely wrote:
> > > libgcc/ChangeLog:
> > >
> > >         * gthr-posix.h (__GTHREAD_INLINE): New macro.
> > >         (__gthread_active): Convert from variable to function.
> > >         (__gthread_trigger): Mark as __GTHREAD_INLINE instead of static.
> > >         (__gthread_active_p): Likewise.
> > >         (__gthread_create): Likewise.
> > >         (__gthread_join): Likewise.
> > >         (__gthread_detach): Likewise.
> > >         (__gthread_equal): Likewise.
> > >         (__gthread_self): Likewise.
> > >         (__gthread_yield): Likewise.
> > >         (__gthread_once): Likewise.
> > >         (__gthread_key_create): Likewise.
> > >         (__gthread_key_delete): Likewise.
> > >         (__gthread_getspecific): Likewise.
> > >         (__gthread_setspecific): Likewise.
> > >         (__gthread_mutex_init_function): Likewise.
> > >         (__gthread_mutex_destroy): Likewise.
> > >         (__gthread_mutex_lock): Likewise.
> > >         (__gthread_mutex_trylock): Likewise.
> > >         (__gthread_mutex_timedlock): Likewise.
> > >         (__gthread_mutex_unlock): Likewise.
> > >         (__gthread_recursive_mutex_init_function): Likewise.
> > >         (__gthread_recursive_mutex_lock): Likewise.
> > >         (__gthread_recursive_mutex_trylock): Likewise.
> > >         (__gthread_recursive_mutex_timedlock): Likewise.
> > >         (__gthread_recursive_mutex_unlock): Likewise.
> > >         (__gthread_recursive_mutex_destroy): Likewise.
> > >         (__gthread_cond_init_function): Likewise.
> > >         (__gthread_cond_broadcast): Likewise.
> > >         (__gthread_cond_signal): Likewise.
> > >         (__gthread_cond_wait): Likewise.
> > >         (__gthread_cond_timedwait): Likewise.
> > >         (__gthread_cond_wait_recursive): Likewise.
> > >         (__gthread_cond_destroy): Likewise.
> > >         (__gthread_rwlock_rdlock): Likewise.
> > >         (__gthread_rwlock_tryrdlock): Likewise.
> > >         (__gthread_rwlock_wrlock): Likewise.
> > >         (__gthread_rwlock_trywrlock): Likewise.
> > >         (__gthread_rwlock_unlock): Likewise.
> > >         * gthr-single.h (__GTHREAD_INLINE): New macro.
> > >         (__gthread_active_p): Mark as __GTHREAD_INLINE instead of static.
> > >         (__gthread_once): Likewise.
> > >         (__gthread_key_create): Likewise.
> > >         (__gthread_key_delete): Likewise.
> > >         (__gthread_getspecific): Likewise.
> > >         (__gthread_setspecific): Likewise.
> > >         (__gthread_mutex_destroy): Likewise.
> > >         (__gthread_mutex_lock): Likewise.
> > >         (__gthread_mutex_trylock): Likewise.
> > >         (__gthread_mutex_unlock): Likewise.
> > >         (__gthread_recursive_mutex_lock): Likewise.
> > >         (__gthread_recursive_mutex_trylock): Likewise.
> > >         (__gthread_recursive_mutex_unlock): Likewise.
> > >         (__gthread_recursive_mutex_destroy): Likewise.
>
> I'm worried about ABI consequences of these changes.
> From what I can see, this doesn't change anything important for C,
> the inlines are still static inline and the conversion of global static
> vars to function-local in static inline still keeps those static.
>
> But for C++ this means significant changes.
> Say
> _ZZ16__gthread_activevE20__gthread_active_var
> etc. will now be STB_GNU_UNIQUE symbol, exported from whatever shared
> libraries and binaries are compiled with C++ and include those headers
> and actually use them somewhere.

I don't think that applies for HPUX or Solaris, but maybe does for
FreeBSD (and it looks like those are the only targets affected by the
__gthread_active_var changes).

> On one side, it has benefits (e.g. every TU won't separately test and
> store whether the threads are active or not), on the other side it can
> prevent dlclose of some shared libraries and create interdependencies
> between libraries.
>
> So, I wonder if we couldn't define the C++ __GTHREAD_INLINE to
> static inline __attribute__((__always_inline__)) (or at least when
> using a compiler which supports the attribute, we can now test it
> using preprocessor...).

I think that would be a nice improvement for the gthread wrapper
functions even without the concern about __gthread_active_var.

>  And whether similarly we couldn't use
> __attribute__((__visibility__ ("hidden"))) on the static block scope
> vars for C++ (again, if compiler supports that), so that the changes
> don't affect ABI of C++ libraries.

That sounds good too.
Jonathan Wakely Sept. 25, 2024, 11:18 a.m. UTC | #4
On Wed, 25 Sept 2024 at 11:47, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On Wed, 25 Sept 2024 at 11:29, Jakub Jelinek <jakub@redhat.com> wrote:
> >
> > On Wed, Sep 25, 2024 at 10:43:50AM +0100, Jonathan Wakely wrote:
> > > > libgcc/ChangeLog:
> > > >
> > > >         * gthr-posix.h (__GTHREAD_INLINE): New macro.
> > > >         (__gthread_active): Convert from variable to function.
> > > >         (__gthread_trigger): Mark as __GTHREAD_INLINE instead of static.
> > > >         (__gthread_active_p): Likewise.
> > > >         (__gthread_create): Likewise.
> > > >         (__gthread_join): Likewise.
> > > >         (__gthread_detach): Likewise.
> > > >         (__gthread_equal): Likewise.
> > > >         (__gthread_self): Likewise.
> > > >         (__gthread_yield): Likewise.
> > > >         (__gthread_once): Likewise.
> > > >         (__gthread_key_create): Likewise.
> > > >         (__gthread_key_delete): Likewise.
> > > >         (__gthread_getspecific): Likewise.
> > > >         (__gthread_setspecific): Likewise.
> > > >         (__gthread_mutex_init_function): Likewise.
> > > >         (__gthread_mutex_destroy): Likewise.
> > > >         (__gthread_mutex_lock): Likewise.
> > > >         (__gthread_mutex_trylock): Likewise.
> > > >         (__gthread_mutex_timedlock): Likewise.
> > > >         (__gthread_mutex_unlock): Likewise.
> > > >         (__gthread_recursive_mutex_init_function): Likewise.
> > > >         (__gthread_recursive_mutex_lock): Likewise.
> > > >         (__gthread_recursive_mutex_trylock): Likewise.
> > > >         (__gthread_recursive_mutex_timedlock): Likewise.
> > > >         (__gthread_recursive_mutex_unlock): Likewise.
> > > >         (__gthread_recursive_mutex_destroy): Likewise.
> > > >         (__gthread_cond_init_function): Likewise.
> > > >         (__gthread_cond_broadcast): Likewise.
> > > >         (__gthread_cond_signal): Likewise.
> > > >         (__gthread_cond_wait): Likewise.
> > > >         (__gthread_cond_timedwait): Likewise.
> > > >         (__gthread_cond_wait_recursive): Likewise.
> > > >         (__gthread_cond_destroy): Likewise.
> > > >         (__gthread_rwlock_rdlock): Likewise.
> > > >         (__gthread_rwlock_tryrdlock): Likewise.
> > > >         (__gthread_rwlock_wrlock): Likewise.
> > > >         (__gthread_rwlock_trywrlock): Likewise.
> > > >         (__gthread_rwlock_unlock): Likewise.
> > > >         * gthr-single.h (__GTHREAD_INLINE): New macro.
> > > >         (__gthread_active_p): Mark as __GTHREAD_INLINE instead of static.
> > > >         (__gthread_once): Likewise.
> > > >         (__gthread_key_create): Likewise.
> > > >         (__gthread_key_delete): Likewise.
> > > >         (__gthread_getspecific): Likewise.
> > > >         (__gthread_setspecific): Likewise.
> > > >         (__gthread_mutex_destroy): Likewise.
> > > >         (__gthread_mutex_lock): Likewise.
> > > >         (__gthread_mutex_trylock): Likewise.
> > > >         (__gthread_mutex_unlock): Likewise.
> > > >         (__gthread_recursive_mutex_lock): Likewise.
> > > >         (__gthread_recursive_mutex_trylock): Likewise.
> > > >         (__gthread_recursive_mutex_unlock): Likewise.
> > > >         (__gthread_recursive_mutex_destroy): Likewise.
> >
> > I'm worried about ABI consequences of these changes.
> > From what I can see, this doesn't change anything important for C,
> > the inlines are still static inline and the conversion of global static
> > vars to function-local in static inline still keeps those static.
> >
> > But for C++ this means significant changes.
> > Say
> > _ZZ16__gthread_activevE20__gthread_active_var
> > etc. will now be STB_GNU_UNIQUE symbol, exported from whatever shared
> > libraries and binaries are compiled with C++ and include those headers
> > and actually use them somewhere.
>
> I don't think that applies for HPUX or Solaris, but maybe does for
> FreeBSD (and it looks like those are the only targets affected by the
> __gthread_active_var changes).
>
> > On one side, it has benefits (e.g. every TU won't separately test and
> > store whether the threads are active or not), on the other side it can
> > prevent dlclose of some shared libraries and create interdependencies
> > between libraries.
> >
> > So, I wonder if we couldn't define the C++ __GTHREAD_INLINE to
> > static inline __attribute__((__always_inline__)) (or at least when
> > using a compiler which supports the attribute, we can now test it
> > using preprocessor...).
>
> I think that would be a nice improvement for the gthread wrapper
> functions even without the concern about __gthread_active_var.
>
> >  And whether similarly we couldn't use
> > __attribute__((__visibility__ ("hidden"))) on the static block scope
> > vars for C++ (again, if compiler supports that), so that the changes
> > don't affect ABI of C++ libraries.
>
> That sounds good too.

Can you use visibility attributes on a local static? I get a warning
that it's ignored.
Jakub Jelinek Sept. 25, 2024, 11:30 a.m. UTC | #5
On Wed, Sep 25, 2024 at 12:18:07PM +0100, Jonathan Wakely wrote:
> > >  And whether similarly we couldn't use
> > > __attribute__((__visibility__ ("hidden"))) on the static block scope
> > > vars for C++ (again, if compiler supports that), so that the changes
> > > don't affect ABI of C++ libraries.
> >
> > That sounds good too.
> 
> Can you use visibility attributes on a local static? I get a warning
> that it's ignored.

Indeed :(

And #pragma GCC visibility push(hidden)/#pragma GCC visibility pop around
just the static block scope var definition does nothing.
If it is around the whole inline function though, then it seems to work.
Though, unsure if we want that around the whole header; wonder what it would
do with the weakrefs.

	Jakub
Nathaniel Shead Sept. 26, 2024, 3:46 a.m. UTC | #6
On Wed, Sep 25, 2024 at 01:30:55PM +0200, Jakub Jelinek wrote:
> On Wed, Sep 25, 2024 at 12:18:07PM +0100, Jonathan Wakely wrote:
> > > >  And whether similarly we couldn't use
> > > > __attribute__((__visibility__ ("hidden"))) on the static block scope
> > > > vars for C++ (again, if compiler supports that), so that the changes
> > > > don't affect ABI of C++ libraries.
> > >
> > > That sounds good too.
> > 
> > Can you use visibility attributes on a local static? I get a warning
> > that it's ignored.
> 
> Indeed :(
> 
> And #pragma GCC visibility push(hidden)/#pragma GCC visibility pop around
> just the static block scope var definition does nothing.
> If it is around the whole inline function though, then it seems to work.
> Though, unsure if we want that around the whole header; wonder what it would
> do with the weakrefs.
> 
> 	Jakub
> 

Thanks for the thoughts.  WRT visibility, it looks like the main gthr.h
surrounds the whole function in a

  #ifndef HIDE_EXPORTS
  #pragma GCC visibility push(default)
  #endif

block, though I can't quite work out what the purpose of that is here
(since everything is currently internal linkage to start with).

But it sounds like doing something like

  #ifdef __has_attribute
  # if __has_attribute(__always_inline__)
  #  define __GTHREAD_ALWAYS_INLINE __attribute__((__always_inline__))
  # endif
  #endif
  #ifndef __GTHREAD_ALWAYS_INLINE
  # define __GTHREAD_ALWAYS_INLINE
  #endif

  #ifdef __cplusplus
  # define __GTHREAD_INLINE inline __GTHREAD_ALWAYS_INLINE
  #else
  # define __GTHREAD_INLINE static inline
  #endif

and then marking maybe even just the new inline functions with
visibility hidden should be OK?

Nathaniel
diff mbox series

Patch

diff --git a/libgcc/gthr-posix.h b/libgcc/gthr-posix.h
index 82e8f9ffcf6..557bae7aaaa 100644
--- a/libgcc/gthr-posix.h
+++ b/libgcc/gthr-posix.h
@@ -44,6 +44,12 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 # endif
 #endif
 
+#ifdef __cplusplus
+# define __GTHREAD_INLINE inline
+#else
+# define __GTHREAD_INLINE static inline
+#endif
+
 typedef pthread_t __gthread_t;
 typedef pthread_key_t __gthread_key_t;
 typedef pthread_once_t __gthread_once_t;
@@ -182,22 +188,27 @@  __gthrw(pthread_setschedparam)
 
 #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
 
-static volatile int __gthread_active = -1;
+__GTHREAD_INLINE volatile int *
+__gthread_active (void)
+{
+  static volatile int __gthread_active_var = -1;
+  return &__gthread_active_var;
+}
 
-static void
+__GTHREAD_INLINE void
 __gthread_trigger (void)
 {
-  __gthread_active = 1;
+  *__gthread_active () = 1;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_active_p (void)
 {
   static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
   static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
 
   /* Avoid reading __gthread_active twice on the main code path.  */
-  int __gthread_active_latest_value = __gthread_active;
+  int __gthread_active_latest_value = *__gthread_active ();
 
   /* This test is not protected to avoid taking a lock on the main code
      path so every update of __gthread_active in a threaded program must
@@ -214,10 +225,10 @@  __gthread_active_p (void)
 	}
 
       /* Make sure we'll never enter this block again.  */
-      if (__gthread_active < 0)
-	__gthread_active = 0;
+      if (*__gthread_active () < 0)
+	*__gthread_active () = 0;
 
-      __gthread_active_latest_value = __gthread_active;
+      __gthread_active_latest_value = *__gthread_active ();
     }
 
   return __gthread_active_latest_value != 0;
@@ -257,7 +268,7 @@  __gthrw2(__gthrw_(__pthread_key_create),
 # define GTHR_ACTIVE_PROXY	__gthrw_(pthread_cancel)
 #endif
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_active_p (void)
 {
   static void *const __gthread_active_ptr
@@ -288,20 +299,25 @@  __gthread_active_p (void)
 
 #if defined(__hppa__) && defined(__hpux__)
 
-static volatile int __gthread_active = -1;
+__GTHREAD_INLINE volatile int *
+__gthread_active (void)
+{
+  static volatile int __gthread_active_var = -1;
+  return &__gthread_active_var;
+}
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_active_p (void)
 {
   /* Avoid reading __gthread_active twice on the main code path.  */
-  int __gthread_active_latest_value = __gthread_active;
+  int __gthread_active_latest_value = *__gthread_active ();
   size_t __s;
 
   if (__builtin_expect (__gthread_active_latest_value < 0, 0))
     {
       pthread_default_stacksize_np (0, &__s);
-      __gthread_active = __s ? 1 : 0;
-      __gthread_active_latest_value = __gthread_active;
+      *__gthread_active () = __s ? 1 : 0;
+      __gthread_active_latest_value = *__gthread_active ();
     }
 
   return __gthread_active_latest_value != 0;
@@ -309,7 +325,7 @@  __gthread_active_p (void)
 
 #else /* not hppa-hpux */
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_active_p (void)
 {
   return 1;
@@ -669,44 +685,44 @@  __gthread_objc_condition_signal (objc_condition_t condition)
 
 #else /* _LIBOBJC */
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_create (__gthread_t *__threadid, void *(*__func) (void*),
 		  void *__args)
 {
   return __gthrw_(pthread_create) (__threadid, NULL, __func, __args);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_join (__gthread_t __threadid, void **__value_ptr)
 {
   return __gthrw_(pthread_join) (__threadid, __value_ptr);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_detach (__gthread_t __threadid)
 {
   return __gthrw_(pthread_detach) (__threadid);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_equal (__gthread_t __t1, __gthread_t __t2)
 {
   return __gthrw_(pthread_equal) (__t1, __t2);
 }
 
-static inline __gthread_t
+__GTHREAD_INLINE __gthread_t
 __gthread_self (void)
 {
   return __gthrw_(pthread_self) ();
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_yield (void)
 {
   return __gthrw_(sched_yield) ();
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_once (__gthread_once_t *__once, void (*__func) (void))
 {
   if (__gthread_active_p ())
@@ -715,38 +731,38 @@  __gthread_once (__gthread_once_t *__once, void (*__func) (void))
     return -1;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
 {
   return __gthrw_(pthread_key_create) (__key, __dtor);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_key_delete (__gthread_key_t __key)
 {
   return __gthrw_(pthread_key_delete) (__key);
 }
 
-static inline void *
+__GTHREAD_INLINE void *
 __gthread_getspecific (__gthread_key_t __key)
 {
   return __gthrw_(pthread_getspecific) (__key);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
 {
   return __gthrw_(pthread_setspecific) (__key, __ptr);
 }
 
-static inline void
+__GTHREAD_INLINE void
 __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
 {
   if (__gthread_active_p ())
     __gthrw_(pthread_mutex_init) (__mutex, NULL);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
 {
   if (__gthread_active_p ())
@@ -755,7 +771,7 @@  __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
     return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_mutex_lock (__gthread_mutex_t *__mutex)
 {
   if (__gthread_active_p ())
@@ -764,7 +780,7 @@  __gthread_mutex_lock (__gthread_mutex_t *__mutex)
     return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
 {
   if (__gthread_active_p ())
@@ -774,7 +790,7 @@  __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
 }
 
 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
-static inline int
+__GTHREAD_INLINE int
 __gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
 			   const __gthread_time_t *__abs_timeout)
 {
@@ -785,7 +801,7 @@  __gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
 }
 #endif
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
 {
   if (__gthread_active_p ())
@@ -796,7 +812,7 @@  __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
 
 #if !defined( PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) \
   || defined(_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC)
-static inline int
+__GTHREAD_INLINE int
 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
 {
   if (__gthread_active_p ())
@@ -818,20 +834,20 @@  __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
 }
 #endif
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
 {
   return __gthread_mutex_lock (__mutex);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
 {
   return __gthread_mutex_trylock (__mutex);
 }
 
 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
-static inline int
+__GTHREAD_INLINE int
 __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
 				     const __gthread_time_t *__abs_timeout)
 {
@@ -839,20 +855,20 @@  __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
 }
 #endif
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
 {
   return __gthread_mutex_unlock (__mutex);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
 {
   return __gthread_mutex_destroy (__mutex);
 }
 
 #ifdef _GTHREAD_USE_COND_INIT_FUNC
-static inline void
+__GTHREAD_INLINE void
 __gthread_cond_init_function (__gthread_cond_t *__cond)
 {
   if (__gthread_active_p ())
@@ -860,46 +876,46 @@  __gthread_cond_init_function (__gthread_cond_t *__cond)
 }
 #endif
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_cond_broadcast (__gthread_cond_t *__cond)
 {
   return __gthrw_(pthread_cond_broadcast) (__cond);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_cond_signal (__gthread_cond_t *__cond)
 {
   return __gthrw_(pthread_cond_signal) (__cond);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
 {
   return __gthrw_(pthread_cond_wait) (__cond, __mutex);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
 			  const __gthread_time_t *__abs_timeout)
 {
   return __gthrw_(pthread_cond_timedwait) (__cond, __mutex, __abs_timeout);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_cond_wait_recursive (__gthread_cond_t *__cond,
 			       __gthread_recursive_mutex_t *__mutex)
 {
   return __gthread_cond_wait (__cond, __mutex);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_cond_destroy (__gthread_cond_t* __cond)
 {
   return __gthrw_(pthread_cond_destroy) (__cond);
 }
 
 #ifndef __cplusplus
-static inline int
+__GTHREAD_INLINE int
 __gthread_rwlock_rdlock (__gthread_rwlock_t *__rwlock)
 {
   if (__gthread_active_p ())
@@ -908,7 +924,7 @@  __gthread_rwlock_rdlock (__gthread_rwlock_t *__rwlock)
     return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_rwlock_tryrdlock (__gthread_rwlock_t *__rwlock)
 {
   if (__gthread_active_p ())
@@ -917,7 +933,7 @@  __gthread_rwlock_tryrdlock (__gthread_rwlock_t *__rwlock)
     return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_rwlock_wrlock (__gthread_rwlock_t *__rwlock)
 {
   if (__gthread_active_p ())
@@ -926,7 +942,7 @@  __gthread_rwlock_wrlock (__gthread_rwlock_t *__rwlock)
     return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_rwlock_trywrlock (__gthread_rwlock_t *__rwlock)
 {
   if (__gthread_active_p ())
@@ -935,7 +951,7 @@  __gthread_rwlock_trywrlock (__gthread_rwlock_t *__rwlock)
     return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_rwlock_unlock (__gthread_rwlock_t *__rwlock)
 {
   if (__gthread_active_p ())
diff --git a/libgcc/gthr-single.h b/libgcc/gthr-single.h
index 8ee6b170840..0473daaf89d 100644
--- a/libgcc/gthr-single.h
+++ b/libgcc/gthr-single.h
@@ -38,6 +38,12 @@  typedef int __gthread_recursive_mutex_t;
 #define __GTHREAD_MUTEX_INIT_FUNCTION(mx) do {} while (0)
 #define __GTHREAD_RECURSIVE_MUTEX_INIT 0
 
+#ifdef __cplusplus
+# define __GTHREAD_INLINE inline
+#else
+# define __GTHREAD_INLINE static inline
+#endif
+
 #define UNUSED __attribute__((__unused__))
 
 #ifdef _LIBOBJC
@@ -207,85 +213,85 @@  __gthread_objc_condition_signal (objc_condition_t condition UNUSED)
 
 #else /* _LIBOBJC */
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_active_p (void)
 {
   return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_once (__gthread_once_t *__once UNUSED, void (*__func) (void) UNUSED)
 {
   return 0;
 }
 
-static inline int UNUSED
+__GTHREAD_INLINE int UNUSED
 __gthread_key_create (__gthread_key_t *__key UNUSED, void (*__func) (void *) UNUSED)
 {
   return 0;
 }
 
-static int UNUSED
+__GTHREAD_INLINE int UNUSED
 __gthread_key_delete (__gthread_key_t __key UNUSED)
 {
   return 0;
 }
 
-static inline void *
+__GTHREAD_INLINE void *
 __gthread_getspecific (__gthread_key_t __key UNUSED)
 {
   return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_setspecific (__gthread_key_t __key UNUSED, const void *__v UNUSED)
 {
   return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_mutex_destroy (__gthread_mutex_t *__mutex UNUSED)
 {
   return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_mutex_lock (__gthread_mutex_t *__mutex UNUSED)
 {
   return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_mutex_trylock (__gthread_mutex_t *__mutex UNUSED)
 {
   return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_mutex_unlock (__gthread_mutex_t *__mutex UNUSED)
 {
   return 0;
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
 {
   return __gthread_mutex_lock (__mutex);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
 {
   return __gthread_mutex_trylock (__mutex);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
 {
   return __gthread_mutex_unlock (__mutex);
 }
 
-static inline int
+__GTHREAD_INLINE int
 __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
 {
   return __gthread_mutex_destroy (__mutex);
diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
index 13273afa9d2..9b1c2b4eb3d 100644
--- a/libstdc++-v3/include/bits/shared_ptr.h
+++ b/libstdc++-v3/include/bits/shared_ptr.h
@@ -1160,9 +1160,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if __cpp_variable_templates
   template<typename _Tp>
-    static constexpr bool __is_shared_ptr = false;
+    constexpr bool __is_shared_ptr = false;
   template<typename _Tp>
-    static constexpr bool __is_shared_ptr<shared_ptr<_Tp>> = true;
+    constexpr bool __is_shared_ptr<shared_ptr<_Tp>> = true;
 #endif
 
   /// @} relates shared_ptr
diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h
index edcff78bff9..182173aa857 100644
--- a/libstdc++-v3/include/bits/unique_ptr.h
+++ b/libstdc++-v3/include/bits/unique_ptr.h
@@ -1157,9 +1157,9 @@  namespace __detail
 
 #if __cpp_variable_templates
   template<typename _Tp>
-    static constexpr bool __is_unique_ptr = false;
+    constexpr bool __is_unique_ptr = false;
   template<typename _Tp, typename _Del>
-    static constexpr bool __is_unique_ptr<unique_ptr<_Tp, _Del>> = true;
+    constexpr bool __is_unique_ptr<unique_ptr<_Tp, _Del>> = true;
 #endif
 
   /// @} group pointer_abstractions
diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
index 6ce7d89ca3f..437453eaa44 100644
--- a/libstdc++-v3/include/std/future
+++ b/libstdc++-v3/include/std/future
@@ -1526,7 +1526,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Signature, typename _Fn,
 	   typename _Alloc = std::allocator<int>>
-    static shared_ptr<__future_base::_Task_state_base<_Signature>>
+    shared_ptr<__future_base::_Task_state_base<_Signature>>
     __create_task_state(_Fn&& __fn, const _Alloc& __a = _Alloc())
     {
       typedef typename decay<_Fn>::type _Fn2;
diff --git a/libstdc++-v3/include/std/shared_mutex b/libstdc++-v3/include/std/shared_mutex
index 1b6478f30c3..7e7941dd7a1 100644
--- a/libstdc++-v3/include/std/shared_mutex
+++ b/libstdc++-v3/include/std/shared_mutex
@@ -72,7 +72,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #ifdef __gthrw
 #define _GLIBCXX_GTHRW(name) \
   __gthrw(pthread_ ## name); \
-  static inline int \
+  inline int \
   __glibcxx_ ## name (pthread_rwlock_t *__rwlock) \
   { \
     if (__gthread_active_p ()) \
@@ -88,7 +88,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 # ifndef PTHREAD_RWLOCK_INITIALIZER
   _GLIBCXX_GTHRW(rwlock_destroy)
   __gthrw(pthread_rwlock_init);
-  static inline int
+  inline int
   __glibcxx_rwlock_init (pthread_rwlock_t *__rwlock)
   {
     if (__gthread_active_p ())
@@ -99,7 +99,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 # endif
 # if _GTHREAD_USE_MUTEX_TIMEDLOCK
    __gthrw(pthread_rwlock_timedrdlock);
-  static inline int
+  inline int
   __glibcxx_rwlock_timedrdlock (pthread_rwlock_t *__rwlock,
 				const timespec *__ts)
   {
@@ -109,7 +109,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return 0;
   }
    __gthrw(pthread_rwlock_timedwrlock);
-  static inline int
+  inline int
   __glibcxx_rwlock_timedwrlock (pthread_rwlock_t *__rwlock,
 				const timespec *__ts)
   {
@@ -120,33 +120,33 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   }
 # endif
 #else
-  static inline int
+  inline int
   __glibcxx_rwlock_rdlock (pthread_rwlock_t *__rwlock)
   { return pthread_rwlock_rdlock (__rwlock); }
-  static inline int
+  inline int
   __glibcxx_rwlock_tryrdlock (pthread_rwlock_t *__rwlock)
   { return pthread_rwlock_tryrdlock (__rwlock); }
-  static inline int
+  inline int
   __glibcxx_rwlock_wrlock (pthread_rwlock_t *__rwlock)
   { return pthread_rwlock_wrlock (__rwlock); }
-  static inline int
+  inline int
   __glibcxx_rwlock_trywrlock (pthread_rwlock_t *__rwlock)
   { return pthread_rwlock_trywrlock (__rwlock); }
-  static inline int
+  inline int
   __glibcxx_rwlock_unlock (pthread_rwlock_t *__rwlock)
   { return pthread_rwlock_unlock (__rwlock); }
-  static inline int
+  inline int
   __glibcxx_rwlock_destroy(pthread_rwlock_t *__rwlock)
   { return pthread_rwlock_destroy (__rwlock); }
-  static inline int
+  inline int
   __glibcxx_rwlock_init(pthread_rwlock_t *__rwlock)
   { return pthread_rwlock_init (__rwlock, NULL); }
 # if _GTHREAD_USE_MUTEX_TIMEDLOCK
-  static inline int
+  inline int
   __glibcxx_rwlock_timedrdlock (pthread_rwlock_t *__rwlock,
 				const timespec *__ts)
   { return pthread_rwlock_timedrdlock (__rwlock, __ts); }
-  static inline int
+  inline int
   __glibcxx_rwlock_timedwrlock (pthread_rwlock_t *__rwlock,
 				const timespec *__ts)
   { return pthread_rwlock_timedwrlock (__rwlock, __ts); }