[07/19] nptl: Add __pthread_attr_copy for copying pthread_attr_t objects
Commit Message
Also add the private type union pthread_attr_transparent, to reduce
the amount of casting that is required.
---
nptl/Makefile | 1 +
nptl/Versions | 1 +
nptl/pthreadP.h | 6 ++++
nptl/pthread_attr_copy.c | 57 ++++++++++++++++++++++++++++++++++++
sysdeps/nptl/internaltypes.h | 7 +++++
5 files changed, 72 insertions(+)
create mode 100644 nptl/pthread_attr_copy.c
Comments
On 5/19/20 6:44 AM, Florian Weimer via Libc-alpha wrote:
> Also add the private type union pthread_attr_transparent, to reduce
> the amount of casting that is required.
OK for master.
Tested clean on x86_64 and i686.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
> ---
> nptl/Makefile | 1 +
> nptl/Versions | 1 +
> nptl/pthreadP.h | 6 ++++
> nptl/pthread_attr_copy.c | 57 ++++++++++++++++++++++++++++++++++++
> sysdeps/nptl/internaltypes.h | 7 +++++
> 5 files changed, 72 insertions(+)
> create mode 100644 nptl/pthread_attr_copy.c
>
> diff --git a/nptl/Makefile b/nptl/Makefile
> index 0dd8800f19..b4aaad0f20 100644
> --- a/nptl/Makefile
> +++ b/nptl/Makefile
> @@ -39,6 +39,7 @@ routines = \
> old_pthread_cond_destroy \
> old_pthread_cond_init \
> pthread_atfork \
> + pthread_attr_copy \
OK
> pthread_attr_destroy \
> pthread_attr_getdetachstate \
> pthread_attr_getinheritsched \
> diff --git a/nptl/Versions b/nptl/Versions
> index 65f0c077da..4c7b43354d 100644
> --- a/nptl/Versions
> +++ b/nptl/Versions
> @@ -60,6 +60,7 @@ libc {
> __pthread_cond_destroy; __pthread_cond_init;
> __pthread_attr_setaffinity_np;
> __pthread_attr_init; __pthread_attr_destroy;
> + __pthread_attr_copy;
OK.
> }
> }
>
> diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
> index f218b01574..41b693d034 100644
> --- a/nptl/pthreadP.h
> +++ b/nptl/pthreadP.h
> @@ -580,6 +580,12 @@ extern void __wait_lookup_done (void) attribute_hidden;
> # define PTHREAD_STATIC_FN_REQUIRE(name) __asm (".globl " #name);
> #endif
>
> +/* Make a deep copy of the attribute *SOURCE in *TARGET. *TARGET is
> + not assumed to have been initialized. Returns 0 on success, or a
> + positive error code otherwise. */
> +int __pthread_attr_copy (pthread_attr_t *target, const pthread_attr_t *source);
> +libc_hidden_proto (__pthread_attr_copy)
OK.
> +
> /* Returns 0 if POL is a valid scheduling policy. */
> static inline int
> check_sched_policy_attr (int pol)
> diff --git a/nptl/pthread_attr_copy.c b/nptl/pthread_attr_copy.c
> new file mode 100644
> index 0000000000..77a1a43eeb
> --- /dev/null
> +++ b/nptl/pthread_attr_copy.c
> @@ -0,0 +1,57 @@
> +/* Deep copy of a pthread_attr_t object.
> + Copyright (C) 2020 Free Software Foundation, Inc.
> + 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <errno.h>
> +#include <pthreadP.h>
> +#include <stdlib.h>
> +
> +int
> +__pthread_attr_copy (pthread_attr_t *target, const pthread_attr_t *source)
> +{
> + /* Avoid overwriting *TARGET until all allocations have
> + succeeded. */
> + union pthread_attr_transparent temp;
> + temp.external = *source;
> +
> + /* Force new allocation. This function has full ownership of temp. */
> + temp.internal.cpuset = NULL;
> + temp.internal.cpusetsize = 0;
> +
> + int ret = 0;
> +
> + struct pthread_attr *isource = (struct pthread_attr *) source;
> +
> + /* Propagate affinity mask information. */
> + if (isource->cpusetsize > 0)
> + ret = __pthread_attr_setaffinity_np (&temp.external,
> + isource->cpusetsize,
> + isource->cpuset);
> +
> + if (ret != 0)
> + {
> + /* Deallocate because we have ownership. */
> + __pthread_attr_destroy (&temp.external);
> + return ret;
> + }
> +
> + /* Transfer ownership. *target is not assumed to have been
> + initialized. */
OK. At this point we copy pointers and we no longer own the memory
that was allocated at the extension pointer.
> + *target = temp.external;
> + return 0;
> +}
> +libc_hidden_def (__pthread_attr_copy)
> diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h
> index 71f09b4624..6d06a76baf 100644
> --- a/sysdeps/nptl/internaltypes.h
> +++ b/sysdeps/nptl/internaltypes.h
> @@ -49,6 +49,13 @@ struct pthread_attr
> #define ATTR_FLAG_SCHED_SET 0x0020
> #define ATTR_FLAG_POLICY_SET 0x0040
>
> +/* Used to allocate a pthread_attr_t object which is also accessed
> + internally. */
> +union pthread_attr_transparent
> +{
> + pthread_attr_t external;
> + struct pthread_attr internal;
> +};
OK.
>
> /* Mutex attribute data structure. */
> struct pthread_mutexattr
>
@@ -39,6 +39,7 @@ routines = \
old_pthread_cond_destroy \
old_pthread_cond_init \
pthread_atfork \
+ pthread_attr_copy \
pthread_attr_destroy \
pthread_attr_getdetachstate \
pthread_attr_getinheritsched \
@@ -60,6 +60,7 @@ libc {
__pthread_cond_destroy; __pthread_cond_init;
__pthread_attr_setaffinity_np;
__pthread_attr_init; __pthread_attr_destroy;
+ __pthread_attr_copy;
}
}
@@ -580,6 +580,12 @@ extern void __wait_lookup_done (void) attribute_hidden;
# define PTHREAD_STATIC_FN_REQUIRE(name) __asm (".globl " #name);
#endif
+/* Make a deep copy of the attribute *SOURCE in *TARGET. *TARGET is
+ not assumed to have been initialized. Returns 0 on success, or a
+ positive error code otherwise. */
+int __pthread_attr_copy (pthread_attr_t *target, const pthread_attr_t *source);
+libc_hidden_proto (__pthread_attr_copy)
+
/* Returns 0 if POL is a valid scheduling policy. */
static inline int
check_sched_policy_attr (int pol)
new file mode 100644
@@ -0,0 +1,57 @@
+/* Deep copy of a pthread_attr_t object.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthreadP.h>
+#include <stdlib.h>
+
+int
+__pthread_attr_copy (pthread_attr_t *target, const pthread_attr_t *source)
+{
+ /* Avoid overwriting *TARGET until all allocations have
+ succeeded. */
+ union pthread_attr_transparent temp;
+ temp.external = *source;
+
+ /* Force new allocation. This function has full ownership of temp. */
+ temp.internal.cpuset = NULL;
+ temp.internal.cpusetsize = 0;
+
+ int ret = 0;
+
+ struct pthread_attr *isource = (struct pthread_attr *) source;
+
+ /* Propagate affinity mask information. */
+ if (isource->cpusetsize > 0)
+ ret = __pthread_attr_setaffinity_np (&temp.external,
+ isource->cpusetsize,
+ isource->cpuset);
+
+ if (ret != 0)
+ {
+ /* Deallocate because we have ownership. */
+ __pthread_attr_destroy (&temp.external);
+ return ret;
+ }
+
+ /* Transfer ownership. *target is not assumed to have been
+ initialized. */
+ *target = temp.external;
+ return 0;
+}
+libc_hidden_def (__pthread_attr_copy)
@@ -49,6 +49,13 @@ struct pthread_attr
#define ATTR_FLAG_SCHED_SET 0x0020
#define ATTR_FLAG_POLICY_SET 0x0040
+/* Used to allocate a pthread_attr_t object which is also accessed
+ internally. */
+union pthread_attr_transparent
+{
+ pthread_attr_t external;
+ struct pthread_attr internal;
+};
/* Mutex attribute data structure. */
struct pthread_mutexattr