This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Linux: Implement per-thread file system attributes


On 6/7/19 12:41 PM, Florian Weimer wrote:
> [Compared to the previous version, this fixes the hppa build by updating
> its own copy of pthread.h.  It also addresses the rebase conflicts due
> to other new functions.  This is still the version with the “sticky”
> behavior.]
> 
> This commit adds the functions pthread_attr_setperthreadfs_np and
> pthread_attr_getperthreadfs_np.
> 
> The implementation is based on suppressing the CLONE_FS clone flag when
> creating the new thread.  The new flag is sticky and is applied to
> all threads created from a thread with the PTHREAD_PER_THREAD_NP
> attribute.
> 

Please post v2 with a new test case to cover the inherited flag check.
- pthread_attr_getperthreadfs_np.c code change.
- comments added to test case.
- New test.

I would like to see a new test which does:
- From main start a thread.
- In the new thread set per-thread fs, which is now sticky.
- Create an attr with per-process fs, and then start a new thread with that.
- In thread 2 use pthread_getattr_np and verify the resulting attr shows
  that per-thread fs as indeed sticky and the value seen is per-thread fs.

This test shows things get copied properly from thread-to-thread and are
visible to pthread_getattr_np properly.


> 2019-06-07  Florian Weimer  <fweimer@redhat.com>
> 
> 	Linux: Implement per-thread file system attributes.
> 	* manual/threads.texi (Enabling Per-Thread Properties): New
> 	section.
> 	(Non-POSIX Extensions): Reference it.
> 	* nptl/Makefile (routines): Add pthread_attr_setperthreadfs_np,
> 	pthread_attr_getperthreadfs_np.
> 	(tests): Add tst-pthread-perthreadfs,
> 	tst-pthread-perthreadfs-chroot.
> 	* nptl/Versions (GLIBC_2.30): Export
> 	pthread_attr_setperthreadfs_np, pthread_attr_getperthreadfs_np.
> 	* nptl/pthread_attr_setperthreadfs_np.c: New file
> 	* nptl/pthread_attr_getperthreadfs_np.c: Likewise.
> 	* nptl/pthread_create.c (__pthread_create_2_1): Use
> 	ATTR_FLAGS_IGNORED_ATTR and ATTR_FLAGS_INHERITED to compute the
> 	flags for the new thread.
> 	* nptl/tst-pthread-perthreadfs.c: Likewise.
> 	* nptl/tst-pthread-perthreadfs-chroot.c: Likewise.
> 	* sysdeps/nptl/internaltypes.h (ATTR_FLAG_PERTHREADFS)
> 	(ATTR_FLAGS_IGNORED_ATTR, ATTR_FLAGS_INHERITED): Define.
> 	* sysdeps/unix/sysv/linux/createthread.c (create_thread): Use it.
> 	* sysdeps/nptl/pthread.h
> 	(PTHREAD_PER_PROCESS_NP, PTHREAD_PER_THREAD_NP): Define.
> 	(pthread_attr_setperthreadfs_np, pthread_attr_getperthreadfs_np):
> 	Declare.
> 	* sysdeps/unix/sysv/linux/hppa/pthread.h
> 	(PTHREAD_PER_PROCESS_NP, PTHREAD_PER_THREAD_NP): Define.
> 	(pthread_attr_setperthreadfs_np, pthread_attr_getperthreadfs_np):
> 	Declare.
> 	* support/Makefile (libsupport-routines): Add xchdir, xfchdir.
> 	* support/xunistd.h (xchdir, xfchdir): Declare.
> 	* support/xchdir.c: New file.
> 	* support/xfchdir.c: Likewise.
> 	* sysdeps/unix/sysv/linux/aarch64/libc.abilist (GLIBC_2.30): Add
> 	pthread_attr_setperthreadfs_np, pthread_attr_getperthreadfs_np.
> 	* sysdeps/unix/sysv/linux/alpha/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/arm/libc.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/csky/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/hppa/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/i386/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/microblaze/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/nios2/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/sh/libc.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist (GLIBC_2.30):
> 	Likewise.
> 
> diff --git a/NEWS b/NEWS
> index 00f9e855a2..f320675f7c 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -34,6 +34,11 @@ Major new features:
>    pointer subtraction within the allocated object, where results might
>    overflow the ptrdiff_t type.
>  
> +* On Linux, it is now possible to create threads with per-thread current
> +  directory, umask, and file system root.  The functions
> +  pthread_attr_setperthreadfs_np and pthread_attr_getperthreadfs_np have
> +  been added in support of that.

OK.

> +
>  Deprecated and removed features, and other changes affecting compatibility:
>  
>  * The functions clock_gettime, clock_getres, clock_settime,
> diff --git a/manual/threads.texi b/manual/threads.texi
> index 87fda7d8e7..60c15a8d15 100644
> --- a/manual/threads.texi
> +++ b/manual/threads.texi
> @@ -625,6 +625,7 @@ the standard.
>  @menu
>  * Default Thread Attributes::             Setting default attributes for
>  					  threads in a process.
> +* Enabling Per-Thread Properties::        Additional per-thread properties.

OK.

>  @end menu
>  
>  @node Default Thread Attributes
> @@ -669,6 +670,100 @@ The system does not have sufficient memory.
>  @end table
>  @end deftypefun
>  
> +@node Enabling Per-Thread Properties
> +@subsubsection Enabling Additional Per-Thread Properties
> +
> +POSIX mandates that the current directory, file system root, umask
> +value, and the current user and group IDs are process-global
> +properties.  For example, if a thread calls the @code{chdir} function
> +to change to a different directory, all threads are eventually
> +affected by this change.  @Theglibc{} implements an extension which
> +allows threads to be created which do not share these properties with
> +the rest of the process.

OK.

> +
> +The desired behavior is specified at the time the thread is created,
> +using the thread attribute.  The following constants are used to
> +update the attribute:

OK.

> +
> +@vtable @code
> +@item PTHREAD_PER_PROCESS_NP
> +@standards{GNU, pthread.h}
> +This property in question is globally shared across the entire process.
> +This is the default.

OK.

> +
> +@item PTHREAD_PER_THREAD_NP
> +@standards{GNU, pthread.h}
> +This property in question is thread-specific.

OK.

> +@end vtable
> +
> +The @code{PTHREAD_PER_THREAD_NP} flag is sticky, in the sense that all
> +threads created by a thread created with this flag have per-thread
> +properties, even if they are created with the matching thread
> +attribute set to the @code{PTHREAD_PER_PROCESS_NP} flag.  If an
> +application wants to create new threads sharing properties with the
> +main thread, it should create a service thread early (perhaps from an
> +ELF constructor) and create these threads using this service thread.
> +

OK

> +Per-thread properties can be set and examined for an attribute using
> +the functions below.
> +
> +@deftypefun int pthread_attr_setperthreadfs_np (pthread_attr_t *@var{attr}, int @var{scope})
> +@standards{GNU, pthread.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +Change whether the following properties related to file system access
> +are made thread-specific when a new thread is created using the
> +attribute @var{attr}:
> +
> +@itemize @bullet
> +@item
> +@cindex current directiry as a per-thread property
> +@cindex per-thread current directory
> +@cindex thread-specific current directory
> +current directory (as changed by @code{chdir} and related functions)
> +
> +@item
> +@cindex @code{chroot} as a per-thread property
> +@cindex per-thread @code{chroot}
> +@cindex thread-specific @code{chroot}
> +file system root (as changed by @code{chroot})
> +
> +@item
> +@cindex umask as a per-thread property
> +@cindex per-thread @code{umask}
> +@cindex thread-specific @code{umask}
> +umask value (as changed by the function of the same name)
> +@end itemize
> +
> +This function returns zero on success.  @var{scope} must be one of the
> +constants @code{PTHREAD_PER_PROCESS_NP} or
> +@code{PTHREAD_PER_THREAD_NP}, otherwise the function returns
> +@code{EINVAL}.

OK.

> +
> +If @var{scope} is @code{PTHREAD_PER_THREAD_NP}, the attribute will
> +cause the properties listed above to be specific to the thread.  The
> +initial values of these properties are copied from the creating
> +thread, at thread creation time.
> +

OK.

> +If a thread that has been created with the
> +@code{PTHREAD_PER_THREAD_NP} flag creates further threads, these
> +threads are implicitly created with the @code{PTHREAD_PER_THREAD_NP}
> +flag, ignoring the value of this thread creation attribute.
> +(If this behavior is not desirable, it is possible to call
> +@samp{unshare (CLONE_FS)} from the new thread instead of creating it
> +with the @code{PTHREAD_PER_THREAD_NP} flag.)
> +

OK.

> +This function is a GNU extension and specific to Linux.
> +@end deftypefun
> +
> +@deftypefun int pthread_attr_getperthreadfs_np (pthread_attr_t *restrict @var{attr}, int *restrict @var{scope})
> +@standards{GNU, pthread.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +Obtain the per-thread status of the file system properties in
> +@var{attr} and store it in the location @var{scope}.
> +

OK.

> +This function is a GNU extension and specific to Linux.
> +@end deftypefun

OK.

> +
>  @c FIXME these are undocumented:
>  @c pthread_atfork
>  @c pthread_attr_destroy
> diff --git a/nptl/Makefile b/nptl/Makefile
> index de312b3477..1374838339 100644
> --- a/nptl/Makefile
> +++ b/nptl/Makefile
> @@ -30,7 +30,8 @@ extra-libs-others := $(extra-libs)
>  routines = alloca_cutoff forward libc-lowlevellock libc-cancellation \
>  	   libc-cleanup libc_pthread_init libc_multiple_threads \
>  	   register-atfork pthread_atfork pthread_self thrd_current \
> -	   thrd_equal thrd_sleep thrd_yield
> +	   thrd_equal thrd_sleep thrd_yield \
> +	   pthread_attr_setperthreadfs_np pthread_attr_getperthreadfs_np

OK. Two new functions.

>  shared-only-routines = forward
>  static-only-routines = pthread_atfork
>  
> @@ -321,7 +322,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
>  	tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \
>  	tst-rwlock-pwn \
>  	tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall \
> -	tst-unwind-thread
> +	tst-unwind-thread \
> +	tst-pthread-perthreadfs tst-pthread-perthreadfs-chroot

OK. Two new tests.

>  
>  tests-internal := tst-rwlock19 tst-rwlock20 \
>  		  tst-sem11 tst-sem12 tst-sem13 \
> diff --git a/nptl/Versions b/nptl/Versions
> index e7f691da7a..817fec04f3 100644
> --- a/nptl/Versions
> +++ b/nptl/Versions
> @@ -32,6 +32,10 @@ libc {
>    GLIBC_2.28 {
>      thrd_current; thrd_equal; thrd_sleep; thrd_yield;
>    }
> +  GLIBC_2.30 {
> +    pthread_attr_setperthreadfs_np;
> +    pthread_attr_getperthreadfs_np;

OK.

> +  }
>    GLIBC_PRIVATE {
>      __libc_alloca_cutoff;
>      # Internal libc interface to libpthread
> diff --git a/nptl/pthread_attr_getperthreadfs_np.c b/nptl/pthread_attr_getperthreadfs_np.c
> new file mode 100644
> index 0000000000..6670939101
> --- /dev/null
> +++ b/nptl/pthread_attr_getperthreadfs_np.c
> @@ -0,0 +1,29 @@
> +/* Read the private file system flag in thread attributes.
> +   Copyright (C) 2019 Free Software Foundation, Inc.

OK.

> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <pthread.h>
> +#include <internaltypes.h>
> +
> +int
> +pthread_attr_getperthreadfs_np (const pthread_attr_t *__restrict attr,
> +                                int *__restrict scope)
> +{
> +  struct pthread_attr *iattr = (struct pthread_attr *) attr;
> +  *scope = (iattr->flags & ATTR_FLAG_PERTHREADFS) != 0;

The '!= 0' is a bit mystical, I would rather see someting like this:

if (iattr->flags & ATTR_FLAG_PERTHREADFS == 0)
  *scope = PTHREAD_PER_PROCESS_NP;
else
  *socpe = PTHREAD_PER_THREAD_NP;

Which makes it similar to the code in pthread_attr_setperthreadfs_np.

The compiler should optimize this to the same thing.

> +  return 0;

OK.

> +}
> diff --git a/nptl/pthread_attr_setperthreadfs_np.c b/nptl/pthread_attr_setperthreadfs_np.c
> new file mode 100644
> index 0000000000..2d274cb144
> --- /dev/null
> +++ b/nptl/pthread_attr_setperthreadfs_np.c
> @@ -0,0 +1,39 @@
> +/* Change the private file system flag in thread attributes.
> +   Copyright (C) 2019 Free Software Foundation, Inc.

OK.

> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <pthread.h>
> +#include <internaltypes.h>
> +#include <errno.h>
> +
> +int
> +pthread_attr_setperthreadfs_np (pthread_attr_t *attr, int scope)
> +{
> +  struct pthread_attr *iattr = (struct pthread_attr *) attr;
> +  switch (scope)
> +    {
> +    case PTHREAD_PER_PROCESS_NP:
> +      iattr->flags &= ~ATTR_FLAG_PERTHREADFS;

OK.

> +      return 0;
> +      break;
> +    case PTHREAD_PER_THREAD_NP:
> +      iattr->flags |= ATTR_FLAG_PERTHREADFS;

OK.

> +      return 0;
> +    default:
> +      return EINVAL;
> +    }
> +}

OK.

> diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
> index 18b7bbe765..0002fa7299 100644
> --- a/nptl/pthread_create.c
> +++ b/nptl/pthread_create.c
> @@ -693,8 +693,8 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
>  
>    /* Copy the thread attribute flags.  */
>    struct pthread *self = THREAD_SELF;
> -  pd->flags = ((iattr->flags & ~(ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))
> -	       | (self->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)));
> +  pd->flags = ((iattr->flags & ~ATTR_FLAGS_IGNORED_ATTR)
> +	       | (self->flags & ATTR_FLAGS_INHERITED));

OK. Simplifies handling of flags we ignore using ATTR_FLAGS_IGNORED_ATTR, and that looks good.

>  
>    /* Initialize the field for the ID of the thread which is waiting
>       for us.  This is a self-reference in case the thread is created
> diff --git a/nptl/tst-pthread-perthreadfs-chroot.c b/nptl/tst-pthread-perthreadfs-chroot.c
> new file mode 100644
> index 0000000000..094c291baa
> --- /dev/null
> +++ b/nptl/tst-pthread-perthreadfs-chroot.c
> @@ -0,0 +1,255 @@
> +/* Test per-thread file system attributes, chroot version.
> +   Copyright (C) 2019 Free Software Foundation, Inc.

OK.

> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +/* This thread is separate from tst-pthread-perthreadfs because it
> +   requires chroot support.  */
> +
> +#include <fcntl.h>
> +#include <pthread.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <support/check.h>
> +#include <support/namespace.h>
> +#include <support/support.h>
> +#include <support/temp_file.h>
> +#include <support/xthread.h>
> +#include <support/xunistd.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
> +
> +/* Paths for chroot operations.  */
> +static char *chroot_1;
> +static char *chroot_2;
> +static char *chroot_3;
> +
> +/* These paths are used for recognizing chroots.  */
> +static const char *const chroot_1_marker = "/chroot-1-marker";
> +static const char *const chroot_2_marker = "/chroot-2-marker";
> +
> +/* Directory available in the chroot for a second chroot call.  */
> +static const char *const next_chroot = "/next_chroot";
> +
> +/* Return 0 for no chroot, 1 for first chroot, 2 for second chroot, or
> +   -1 for error.  */
> +static int
> +which_chroot (void)
> +{
> +  /* If the full (out-of-chroot) path is present, we are not in a
> +     chroot.  */
> +  if (access (chroot_1, F_OK) == 0)
> +    return 0;
> +  if (access (chroot_1_marker, F_OK) == 0)
> +    return 1;
> +  if (access (chroot_2_marker, F_OK) == 0)
> +    return 2;
> +  return -1;
> +}
> +
> +/* Thread attribute requesting per-thread file system attributes.  */
> +pthread_attr_t attr_perthreadfs;
> +
> +/* Used to synchronize operations among the threads.  This is needed
> +   so that the chroot changes happen in the expected order.  */
> +static pthread_barrier_t barrier;
> +
> +static void *
> +thread_which_chroot_helper (void *closure)
> +{
> +  int *result = closure;
> +  *result = which_chroot ();
> +  return NULL;
> +}
> +
> +static void *
> +thread_which_chroot_helper_perthread (void *closure)
> +{
> +  int *result = closure;
> +  *result = which_chroot ();
> +  if (*result == 0)
> +    /* No /next-chroot available without a first chroot.  */
> +    xchroot (chroot_3);
> +  else
> +    xchroot (next_chroot);
> +  return NULL;
> +}
> +
> +/* Determine the current chroot on another thread.  */
> +static int
> +thread_which_chroot (void)
> +{
> +  int result1;
> +  pthread_t thr = xpthread_create (NULL, thread_which_chroot_helper, &result1);
> +  xpthread_join (thr);
> +  /* Same using per-thread attributes.  They are supposed to be equal.
> +     Also change the chroot to check isolation.  */
> +  int result2;
> +  thr = xpthread_create (&attr_perthreadfs,
> +                         thread_which_chroot_helper_perthread, &result2);
> +  xpthread_join (thr);
> +  TEST_COMPARE (result1, result2);
> +  return result1;
> +}
> +
> +/* Verify that the file system attributes for the current thread are
> +   as expected.  */
> +static void
> +check_attributes (const char *where, int expected_chroot)
> +{
> +  printf ("info: reading file attributes in %s\n", where);
> +  TEST_COMPARE (which_chroot (), expected_chroot);
> +  TEST_COMPARE (thread_which_chroot (), expected_chroot);
> +}
> +
> +/* Thread function launched with per-thread file system
> +   attributes.  */
> +static void *
> +thread_perthreadfs (void *closure)
> +{
> +  puts ("info: changing file attributes in thread_perthreadfs");
> +  xchroot (chroot_1);
> +  check_attributes ("thread_perthreadfs", 1);
> +
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes read in thread_sharedfs here.  */
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes read in main thread here.  */
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes changed in thread_sharedfs here.  */
> +  pthread_barrier_wait (&barrier);
> +
> +  check_attributes ("thread_perthreadfs", 1);
> +
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes read in main thread here.  */
> +  pthread_barrier_wait (&barrier);
> +  return NULL;
> +}
> +
> +/* Thread function launched with shared file system attributes.  */
> +static void *
> +thread_sharedfs (void *closure)
> +{
> +  /* Wait for thread_perthreadfs to update chroot.  */
> +  pthread_barrier_wait (&barrier);
> +
> +  check_attributes ("thread_sharedfs", 0);
> +
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes read in main thread here.  */
> +  pthread_barrier_wait (&barrier);
> +
> +  puts ("info: changing file attributes in thread_sharedfs");
> +  xchroot (chroot_2);
> +  check_attributes ("thread_sharedfs", 2);
> +
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes read in thread_perthreadfs here.  */
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes read in main thread here.  */
> +  pthread_barrier_wait (&barrier);
> +  return NULL;
> +}
> +
> +static int
> +do_test (void)
> +{
> +  support_become_root ();
> +  if (!support_can_chroot ())
> +    FAIL_UNSUPPORTED ("chroot not supported");
> +
> +  /* Used to revert the effect of chroot.  */
> +  int original_chroot_fd = xopen ("/", O_DIRECTORY | O_RDONLY, 0);

OK.

> +
> +  TEST_COMPARE (access (chroot_1_marker, F_OK), -1);
> +  TEST_COMPARE (access (chroot_2_marker, F_OK), -1);
> +  TEST_COMPARE (access (next_chroot, F_OK), -1);
> +
> +  chroot_1 = support_create_temp_directory
> +    ("tst-pthread-perthreadfs-chroot-1-");
> +  chroot_2 = support_create_temp_directory
> +    ("tst-pthread-perthreadfs-chroot-2-");
> +  chroot_3 = support_create_temp_directory
> +    ("tst-pthread-perthreadfs-chroot-3-");
> +  {
> +    char *path = xasprintf ("%s%s", chroot_1, chroot_1_marker);
> +    xmkdir (path, 0777);
> +    add_temp_file (path);
> +    free (path);
> +
> +    path = xasprintf ("%s%s", chroot_1, next_chroot);
> +    xmkdir (path, 0777);
> +    add_temp_file (path);
> +    free (path);
> +
> +    path = xasprintf ("%s%s", chroot_2, chroot_2_marker);
> +    xmkdir (path, 0777);
> +    add_temp_file (path);
> +    free (path);
> +
> +    path = xasprintf ("%s%s", chroot_2, next_chroot);
> +    xmkdir (path, 0777);
> +    add_temp_file (path);
> +    free (path);
> +  }
> +  TEST_COMPARE (which_chroot (), 0);
> +
> +  xpthread_barrier_init (&barrier, NULL, 3);
> +  xpthread_attr_init (&attr_perthreadfs);
> +  TEST_COMPARE (pthread_attr_setperthreadfs_np (&attr_perthreadfs,
> +                                                PTHREAD_PER_THREAD_NP), 0);

OK.

> +
> +  pthread_t thr1 = xpthread_create (&attr_perthreadfs,
> +                                    thread_perthreadfs, NULL);
> +  pthread_t thr2 = xpthread_create (NULL, thread_sharedfs, NULL);
> +
> +  /* Wait for thread_perthreadfs to update chroot.  */
> +  xpthread_barrier_wait (&barrier);
> +  /* File attributes read thread_sharedfs here.  */
> +  xpthread_barrier_wait (&barrier);
> +
> +  check_attributes ("main thread", 0);

OK.

> +
> +  xpthread_barrier_wait (&barrier);
> +  /* File attributes changed thread_sharedfs here.  */
> +  xpthread_barrier_wait (&barrier);
> +  /* File attributes read in thread_perthreadfs here.  */
> +  xpthread_barrier_wait (&barrier);
> +
> +  check_attributes ("main thread", 2);
> +

OK.

> +  xpthread_barrier_wait (&barrier);
> +
> +  xpthread_join (thr2);
> +  xpthread_join (thr1);

OK.

> +
> +  xpthread_attr_destroy (&attr_perthreadfs);
> +  xpthread_barrier_destroy (&barrier);
> +
> +  free (chroot_3);
> +  free (chroot_2);
> +  free (chroot_1);
> +
> +  xfchdir (original_chroot_fd);
> +  xclose (original_chroot_fd);
> +  xchroot (".");
> +
> +  return 0;
> +}

OK.

> +
> +#include <support/test-driver.c>
> diff --git a/nptl/tst-pthread-perthreadfs.c b/nptl/tst-pthread-perthreadfs.c
> new file mode 100644
> index 0000000000..81cf315c97
> --- /dev/null
> +++ b/nptl/tst-pthread-perthreadfs.c
> @@ -0,0 +1,280 @@
> +/* Test per-thread file system attributes.
> +   Copyright (C) 2019 Free Software Foundation, Inc.

OK.

> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <errno.h>
> +#include <pthread.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <support/check.h>
> +#include <support/temp_file.h>
> +#include <support/xthread.h>
> +#include <support/xunistd.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
> +
> +/* Original values in the parent process.  */
> +static char *original_cwd;
> +static mode_t original_umask;
> +
> +/* New values for the attributes, distinct from the old.  */
> +static char *new_cwd_1;
> +static char *new_cwd_2;
> +static mode_t new_umask_1;
> +static mode_t new_umask_2;
> +
> +/* Thread attribute requesting per-thread file system attributes.  */
> +pthread_attr_t attr_perthreadfs;
> +
> +/* Used to synchronize operations among the threads.  This is needed
> +   so that the attribute changes happen in the expected order, and
> +   that get_umask_unlocked can be used safely.  */
> +static pthread_barrier_t barrier;
> +
> +/* Linux does not have getumask, so use synchronization and the umask
> +   system call to read the value.  */
> +static mode_t
> +get_umask_unlocked (void)
> +{
> +  mode_t mask = umask (0);
> +  TEST_COMPARE (umask (mask), 0);
> +  return mask;
> +}
> +
> +static void *
> +thread_get_pwd_helper (void *closure)
> +{
> +  char *result = get_current_dir_name ();
> +  if (closure != NULL)
> +    xchdir (closure);
> +  return result;
> +}
> +
> +/* Obtain the current directory on another thread.  */
> +static char *
> +thread_get_pwd (void)
> +{
> +  pthread_t thr = xpthread_create (NULL, thread_get_pwd_helper, NULL);
> +  char *path1 = xpthread_join (thr);
> +  /* Same using per-thread attributes.  They are supposed to be equal.
> +     Also change the current directory to check isolation.  */
> +  thr = xpthread_create (&attr_perthreadfs,
> +                         thread_get_pwd_helper, (char *) "/");
> +  char *path2 = xpthread_join (thr);
> +  TEST_COMPARE_STRING (path1, path2);
> +  free (path2);
> +  return path1;
> +}
> +
> +static void *
> +thread_get_umask_helper (void *closure)
> +{
> +  mode_t *pmask = closure;
> +  *pmask = get_umask_unlocked ();
> +  return NULL;
> +}
> +
> +static void *
> +thread_get_umask_helper_perthread (void *closure)
> +{
> +  mode_t *pmask = closure;
> +  *pmask = get_umask_unlocked ();
> +  /* Check isolation.  This bit pattern is not used anywhere else.  */
> +  TEST_COMPARE (umask (*pmask ^ 0101), *pmask);
> +  return NULL;
> +}
> +
> +/* Obtain the current umask on another thread.  */
> +static mode_t
> +thread_get_umask_unlocked (void)
> +{
> +  mode_t mask1;
> +  pthread_t thr = xpthread_create (NULL, thread_get_umask_helper, &mask1);
> +  xpthread_join (thr);
> +  mode_t mask2;
> +  thr = xpthread_create (&attr_perthreadfs,
> +                         thread_get_umask_helper_perthread, &mask2);
> +  xpthread_join (thr);
> +  TEST_COMPARE (mask1, mask2);
> +  return mask1;
> +}
> +
> +/* Verify that the file system attributes for the current thread are
> +   as expected.  */
> +static void
> +check_attributes (const char *where, mode_t expected_umask,
> +                  const char *expected_cwd)
> +{
> +  printf ("info: reading file attributes in %s\n", where);
> +  TEST_COMPARE (get_umask_unlocked (), expected_umask);
> +  TEST_COMPARE (thread_get_umask_unlocked (), expected_umask);
> +  char *cwd = get_current_dir_name ();
> +  TEST_COMPARE_STRING (cwd, expected_cwd);
> +  free (cwd);
> +  cwd = thread_get_pwd ();
> +  TEST_COMPARE_STRING (cwd, expected_cwd);
> +  free (cwd);
> +}
> +
> +/* Thread function launched with per-thread file system
> +   attributes.  */
> +static void *
> +thread_perthreadfs (void *closure)
> +{
> +  puts ("info: changing file attributes in thread_perthreadfs");
> +  xchdir (new_cwd_1);
> +  TEST_COMPARE (umask (new_umask_1), original_umask);
> +  check_attributes ("thread_perthreadfs", new_umask_1, new_cwd_1);
> +
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes read in thread_sharedfs here.  */
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes read in main thread here.  */
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes changed in thread_sharedfs here.  */
> +  pthread_barrier_wait (&barrier);
> +
> +  check_attributes ("thread_perthreadfs", new_umask_1, new_cwd_1);
> +
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes read in main thread here.  */
> +  pthread_barrier_wait (&barrier);
> +  return NULL;
> +}
> +
> +/* Launched with te PTHREAD_PER_THREAD_NP, but runs the actual test on
> +   a PTHREAD_PER_PROCESS_NP thread.  */
> +static void *
> +thread_perthreadfs_indirect (void *closure)
> +{
> +  return xpthread_join (xpthread_create (NULL, thread_perthreadfs, closure));
> +}
> +
> +/* Thread function launched with shared file system attributes.  */
> +static void *
> +thread_sharedfs (void *closure)
> +{
> +  /* Wait for thread_perthreadfs to update current directory and
> +     umask.  */
> +  pthread_barrier_wait (&barrier);
> +
> +  check_attributes ("thread_sharedfs", original_umask, original_cwd);
> +
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes read in main thread here.  */
> +  pthread_barrier_wait (&barrier);
> +
> +  puts ("info: changing file attributes in thread_sharedfs");
> +  TEST_COMPARE (umask (new_umask_2), original_umask);
> +  xchdir (new_cwd_2);
> +  check_attributes ("thread_sharedfs", new_umask_2, new_cwd_2);
> +
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes read in thread_perthreadfs here.  */
> +  pthread_barrier_wait (&barrier);
> +  /* File attributes read in main thread here.  */
> +  pthread_barrier_wait (&barrier);
> +  return NULL;
> +}
> +
> +static int
> +do_test (void)
> +{
> +  original_cwd = get_current_dir_name ();
> +  TEST_VERIFY_EXIT (original_cwd != NULL);
> +  original_umask = get_umask_unlocked ();
> +
> +  new_cwd_1 = support_create_temp_directory ("tst-pthread-perthreadfs-1-");
> +  new_cwd_2 = support_create_temp_directory ("tst-pthread-perthreadfs-2-");
> +  /* Arbitrary bit pattern change to obtain distinct values, so that
> +     it is possible to check for actual changes.  */
> +  new_umask_1 = original_umask ^ 0111;
> +  new_umask_2 = original_umask ^ 0222;
> +
> +  xpthread_barrier_init (&barrier, NULL, 3);
> +  xpthread_attr_init (&attr_perthreadfs);
> +  {

Each of these tests should havea 1 comment explaining intent.

/* Test: Default is PTHREAD_PER_PROCESS_NP.  */

> +    int scope = -1;
> +    TEST_COMPARE (pthread_attr_getperthreadfs_np (&attr_perthreadfs, &scope),
> +                  0);
> +    TEST_COMPARE (scope, PTHREAD_PER_PROCESS_NP);

/* Test: Set and get compares the same.  */

> +    TEST_COMPARE (pthread_attr_setperthreadfs_np (&attr_perthreadfs,
> +                                                  PTHREAD_PER_THREAD_NP), 0);
> +    scope = -1;
> +    TEST_COMPARE (pthread_attr_getperthreadfs_np (&attr_perthreadfs, &scope),
> +                  0);
> +    TEST_COMPARE (scope, PTHREAD_PER_THREAD_NP);

/* Test: Invalid scope returns EINVAL.  */

> +
> +    TEST_COMPARE (pthread_attr_setperthreadfs_np (&attr_perthreadfs, 2),
> +                  EINVAL);
> +    scope = -1;
> +    TEST_COMPARE (pthread_attr_getperthreadfs_np (&attr_perthreadfs, &scope),
> +                  0);
> +    TEST_COMPARE (scope, PTHREAD_PER_THREAD_NP);

OK.

> +  }
> +
> +  /* Two test runs, once with perthreadsfs set to
> +     PTHREAD_PER_THREAD_NP directly, once indirectly via inheritance
> +     from the current (overriding the PTHREAD_PER_PROCESS_NP
> +     default).  */

OK.

> +  for (int do_indirect = 0; do_indirect < 2;  ++do_indirect)
> +    {
> +      printf ("info: test iteration with do_indirect == %d\n", do_indirect);
> +      pthread_t thr1;
> +      if (do_indirect)
> +        thr1 = xpthread_create (&attr_perthreadfs,
> +                                thread_perthreadfs_indirect, NULL);
> +      else
> +        thr1 = xpthread_create (&attr_perthreadfs, thread_perthreadfs, NULL);
> +      pthread_t thr2 = xpthread_create (NULL, thread_sharedfs, NULL);
> +
> +      /* Wait for thread_perthreadfs to update current directory and
> +         umask.  */
> +      xpthread_barrier_wait (&barrier);
> +      /* File attributes read thread_sharedfs here.  */
> +      xpthread_barrier_wait (&barrier);
> +
> +      check_attributes ("main thread", original_umask, original_cwd);
> +
> +      xpthread_barrier_wait (&barrier);
> +      /* File attributes changed thread_sharedfs here.  */
> +      xpthread_barrier_wait (&barrier);
> +      /* File attributes read in thread_perthreadfs here.  */
> +      xpthread_barrier_wait (&barrier);
> +
> +      check_attributes ("main thread", new_umask_2, new_cwd_2);
> +
> +      xpthread_barrier_wait (&barrier);
> +
> +      xpthread_join (thr2);
> +      xpthread_join (thr1);
> +
> +      xchdir (original_cwd);
> +      umask (original_umask);
> +    }
> +
> +  xpthread_attr_destroy (&attr_perthreadfs);
> +  xpthread_barrier_destroy (&barrier);
> +
> +  free (new_cwd_2);
> +  free (new_cwd_1);
> +  free (original_cwd);
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>
> diff --git a/support/Makefile b/support/Makefile
> index 56c1ed43bb..774b0a692a 100644
> --- a/support/Makefile
> +++ b/support/Makefile
> @@ -80,6 +80,7 @@ libsupport-routines = \
>    xasprintf \
>    xbind \
>    xcalloc \
> +  xchdir \

OK.

>    xchroot \
>    xclock_gettime \
>    xclose \
> @@ -88,6 +89,7 @@ libsupport-routines = \
>    xdlfcn \
>    xdlmopen \
>    xdup2 \
> +  xfchdir \

OK.

>    xfclose \
>    xfopen \
>    xfork \
> diff --git a/support/xchdir.c b/support/xchdir.c
> new file mode 100644
> index 0000000000..a2f728f5df
> --- /dev/null
> +++ b/support/xchdir.c
> @@ -0,0 +1,28 @@
> +/* chdir with error checking.
> +   Copyright (C) 2017-2019 Free Software Foundation, Inc.

New file? Copyright 2019.

> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <support/check.h>
> +#include <support/xunistd.h>
> +#include <sys/stat.h>
> +
> +void
> +xchdir (const char *path)
> +{
> +  if (chdir (path) != 0)
> +    FAIL_EXIT1 ("chdir (\"%s\"): %m", path);

OK.

> +}
> diff --git a/support/xfchdir.c b/support/xfchdir.c
> new file mode 100644
> index 0000000000..76c5f655bb
> --- /dev/null
> +++ b/support/xfchdir.c
> @@ -0,0 +1,28 @@
> +/* fchdir with error checking.
> +   Copyright (C) 2017-2019 Free Software Foundation, Inc.

New file? Copyright 2019.

> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <support/check.h>
> +#include <support/xunistd.h>
> +#include <sys/stat.h>
> +
> +void
> +xfchdir (int fd)
> +{
> +  if (fchdir (fd) != 0)
> +    FAIL_EXIT1 ("fchdir (%d): %m", fd);

OK.

> +}
> diff --git a/support/xunistd.h b/support/xunistd.h
> index 338eb86a1b..b470d99be1 100644
> --- a/support/xunistd.h
> +++ b/support/xunistd.h
> @@ -38,6 +38,8 @@ int xopen (const char *path, int flags, mode_t);
>  void xstat (const char *path, struct stat64 *);
>  void xfstat (int fd, struct stat64 *);
>  void xmkdir (const char *path, mode_t);
> +void xchdir (const char *path);
> +void xfchdir (int);

OK.

>  void xchroot (const char *path);
>  void xunlink (const char *path);
>  long xsysconf (int name);
> diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h
> index 53d037e0f1..5ad56908b5 100644
> --- a/sysdeps/nptl/internaltypes.h
> +++ b/sysdeps/nptl/internaltypes.h
> @@ -48,6 +48,18 @@ struct pthread_attr
>  #define ATTR_FLAG_OLDATTR		0x0010
>  #define ATTR_FLAG_SCHED_SET		0x0020
>  #define ATTR_FLAG_POLICY_SET		0x0040
> +#define ATTR_FLAG_PERTHREADFS		0x0080

OK.

> +
> +/* These flags are not copied from the thread attribute at
> +   pthread_create time.  */
> +#define ATTR_FLAGS_IGNORED_ATTR \
> +  (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)

OK.

> +
> +/* These flags are inherited from the current thread during
> +   pthread_create even if they are not specified in the thread
> +   attribute.  */
> +#define ATTR_FLAGS_INHERITED \
> +  ATTR_FLAG_PERTHREADFS

OK.

>  
>  
>  /* Mutex attribute data structure.  */
> diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
> index 704a3c48d6..37073e3ce7 100644
> --- a/sysdeps/nptl/pthread.h
> +++ b/sysdeps/nptl/pthread.h
> @@ -181,7 +181,16 @@ enum
>  #define PTHREAD_PROCESS_SHARED  PTHREAD_PROCESS_SHARED
>  };
>  
> -
> +#ifdef __USE_GNU
> +/* Thread-private or process-global flag.  */
> +enum
> +{
> + PTHREAD_PER_PROCESS_NP,
> +# define PTHREAD_PER_PROCESS_NP PTHREAD_PER_PROCESS_NP
> + PTHREAD_PER_THREAD_NP
> +# define PTHREAD_PER_THREAD_NP PTHREAD_PER_THREAD_NP
> +};
> +#endif /* __USE_GNU */
>  
>  /* Conditional variable handling.  */
>  #define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } }
> @@ -406,6 +415,21 @@ extern int pthread_attr_getaffinity_np (const pthread_attr_t *__attr,
>  					cpu_set_t *__cpuset)
>       __THROW __nonnull ((1, 3));
>  
> +
> +/* Control the flag in ATTR whether the thread has its own current
> +   directory, file system root, and umask attribute.  SCOPE must be
> +   PTHREAD_PER_PROCESS_NP or PTHREAD_PER_THREAD_NP.  By default, new
> +   threads share these attributes with their creating thread
> +   (PTHREAD_PER_PROCESS_NP).  */
> +int pthread_attr_setperthreadfs_np (pthread_attr_t *__attr, int __scope)
> +  __THROW __nonnull ((1));
> +
> +/* Set *SCOPE to PTHREAD_PER_PROCESS_NP or PTHREAD_PER_THREAD_NP,
> +   depending on the state of *ATTR.  */
> +int pthread_attr_getperthreadfs_np (const pthread_attr_t *__restrict __attr,
> +				    int *__restrict __scope)
> +  __THROW __nonnull ((1, 2));
> +
>  /* Get the default attributes used by pthread_create in this process.  */
>  extern int pthread_getattr_default_np (pthread_attr_t *__attr)
>       __THROW __nonnull ((1));
> diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> index a4c31932cb..2635e16f5e 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> @@ -2143,5 +2143,7 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> index fe85a35620..12227b9800 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> @@ -2218,6 +2218,8 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
> index bc3df8dcea..6d09148e1d 100644
> --- a/sysdeps/unix/sysv/linux/arm/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
> @@ -128,6 +128,8 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _Exit F
> diff --git a/sysdeps/unix/sysv/linux/createthread.c b/sysdeps/unix/sysv/linux/createthread.c
> index 579bd94743..177e14e9ae 100644
> --- a/sysdeps/unix/sysv/linux/createthread.c
> +++ b/sysdeps/unix/sysv/linux/createthread.c
> @@ -66,7 +66,9 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
>  
>       CLONE_VM, CLONE_FS, CLONE_FILES
>  	These flags select semantics with shared address space and
> -	file descriptors according to what POSIX requires.
> +	file descriptors according to what POSIX requires.  CLONE_FS
> +	is optional; it can be controlled using the function
> +	pthread_attr_setperthreadfs_np.

OK.

>  
>       CLONE_SIGHAND, CLONE_THREAD
>  	This flag selects the POSIX signal semantics and various
> @@ -90,11 +92,13 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
>  
>       The termination signal is chosen to be zero which means no signal
>       is sent.  */
> -  const int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SYSVSEM
> -			   | CLONE_SIGHAND | CLONE_THREAD
> -			   | CLONE_SETTLS | CLONE_PARENT_SETTID
> -			   | CLONE_CHILD_CLEARTID
> -			   | 0);
> +  int clone_flags = (CLONE_VM | CLONE_FILES | CLONE_SYSVSEM
> +		     | CLONE_SIGHAND | CLONE_THREAD
> +		     | CLONE_SETTLS | CLONE_PARENT_SETTID
> +		     | CLONE_CHILD_CLEARTID
> +		     | 0);
> +  if ((attr->flags & ATTR_FLAG_PERTHREADFS) == 0)
> +    clone_flags |= CLONE_FS;

OK.

>  
>    TLS_DEFINE_INIT_TP (tp, pd);
>  
> diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
> index 9b3cee65bb..5ee091972b 100644
> --- a/sysdeps/unix/sysv/linux/csky/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
> @@ -2087,5 +2087,7 @@ GLIBC_2.29 xprt_register F
>  GLIBC_2.29 xprt_unregister F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> index 75edece94a..844eaf539b 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> @@ -2039,6 +2039,8 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/hppa/pthread.h b/sysdeps/unix/sysv/linux/hppa/pthread.h
> index 45e706c037..b80c84c0b7 100644
> --- a/sysdeps/unix/sysv/linux/hppa/pthread.h
> +++ b/sysdeps/unix/sysv/linux/hppa/pthread.h
> @@ -158,6 +158,16 @@ enum
>  #define PTHREAD_PROCESS_SHARED  PTHREAD_PROCESS_SHARED
>  };
>  
> +#ifdef __USE_GNU
> +/* Thread-private or process-global flag.  */
> +enum
> +{
> + PTHREAD_PER_PROCESS_NP,
> +# define PTHREAD_PER_PROCESS_NP PTHREAD_PER_PROCESS_NP
> + PTHREAD_PER_THREAD_NP
> +# define PTHREAD_PER_THREAD_NP PTHREAD_PER_THREAD_NP
> +};
> +#endif /* __USE_GNU */
>  
>  /* Conditional variable handling.  */
>  #define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } }
> @@ -382,6 +392,21 @@ extern int pthread_attr_getaffinity_np (const pthread_attr_t *__attr,
>  					cpu_set_t *__cpuset)
>       __THROW __nonnull ((1, 3));
>  
> +
> +/* Control the flag in ATTR whether the thread has its own current
> +   directory, file system root, and umask attribute.  SCOPE must be
> +   PTHREAD_PER_PROCESS_NP or PTHREAD_PER_THREAD_NP.  By default, new
> +   threads share these attributes with their creating thread
> +   (PTHREAD_PER_PROCESS_NP).  */
> +int pthread_attr_setperthreadfs_np (pthread_attr_t *__attr, int __scope)
> +  __THROW __nonnull ((1));

OK.

> +
> +/* Set *SCOPE to PTHREAD_PER_PROCESS_NP or PTHREAD_PER_THREAD_NP,
> +   depending on the state of *ATTR.  */
> +int pthread_attr_getperthreadfs_np (const pthread_attr_t *__restrict __attr,
> +				    int *__restrict __scope)
> +  __THROW __nonnull ((1, 2));

OK.

> +
>  /* Get the default attributes used by pthread_create in this process.  */
>  extern int pthread_getattr_default_np (pthread_attr_t *__attr)
>       __THROW __nonnull ((1));
> diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
> index edeaf8e722..efd8cb1685 100644
> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
> @@ -2205,6 +2205,8 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> index b5d460eeb2..7f34f4d1e6 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> @@ -2071,6 +2071,8 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> index 05633b3cb8..34d5f6c91a 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> @@ -129,6 +129,8 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _Exit F
> diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> index 47eb7b4608..71882c6e23 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> @@ -2148,6 +2148,8 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> index f7ced487f7..4f605fa67a 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> @@ -2135,5 +2135,7 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> index e49dc4272e..62790b0a64 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> @@ -2122,6 +2122,8 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> index daa3b60c5b..eb2ae61601 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> @@ -2120,6 +2120,8 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> index 457ce0b6f2..9cf1462270 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> @@ -2128,6 +2128,8 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> index 63d5c03bfb..d116e7180e 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> @@ -2122,6 +2122,8 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> index 7fec0c9670..0e8d5bfcc7 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> @@ -2176,5 +2176,7 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> index 9200a54309..16e66c2fa4 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> @@ -2178,6 +2178,8 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> index ef7779905f..fff0295a63 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> @@ -2211,6 +2211,8 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> index 2860df8ebc..808f021335 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> @@ -2041,6 +2041,8 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> index 2229a1dcc0..a894bc49be 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> @@ -2245,5 +2245,7 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> index 31010e6cf7..e220b0fd0c 100644
> --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> @@ -2105,5 +2105,7 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> index 576295deff..1567d2ff1d 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> @@ -2173,6 +2173,8 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> index abf0473683..f9d88d588e 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> @@ -2077,6 +2077,8 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
> index 41977f6e9c..affd74df4c 100644
> --- a/sysdeps/unix/sysv/linux/sh/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
> @@ -2043,6 +2043,8 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> index 3d2f00ca52..c12cc83bb2 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> @@ -2167,6 +2167,8 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> index 2f20643e8e..37c9dff44c 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> @@ -2094,6 +2094,8 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> index 59f85d9373..71b7cc4ff9 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> @@ -2052,6 +2052,8 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> index 67a4e238d6..573fc2e01c 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> @@ -2151,5 +2151,7 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 pthread_attr_getperthreadfs_np F
> +GLIBC_2.30 pthread_attr_setperthreadfs_np F

OK.

>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> 


-- 
Cheers,
Carlos.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]