Message ID | 20220930192613.3491147-10-adhemerval.zanella@linaro.org |
---|---|
State | New |
Headers | show |
Series | Optimize posix_spawn signal setup with clone3 | expand |
On 9/30/22 15:26, Adhemerval Zanella via Libc-alpha wrote: > Now that clone3 is used on more architectures, add an optimization > to avoid calling when glibc detects that it is no supported by the > kernel. It also adds __ASSUME_CLONE3, which allows skip this > optimization and issue clone3 syscall directly. Please post v3 with changes. Suggest: Add an optimization to avoid calling clone3 when glibc detects that there is no kernel support. It also adds __ASSUME_CLONE3, which allows skipping this optimization and issuing the clone3 syscall directly. > > It does not handle the the small window between 5.3 and 5.5 for > posix_spawn (CLONE_CLEAR_SIGHAND was added in 5.5). > > Checked on x86_64-linux-gnu. > --- > include/clone_internal.h | 5 +++++ > sysdeps/unix/sysv/linux/clone-internal.c | 24 ++++++++++++++++++++++- > sysdeps/unix/sysv/linux/kernel-features.h | 9 +++++++++ > 3 files changed, 37 insertions(+), 1 deletion(-) > > diff --git a/include/clone_internal.h b/include/clone_internal.h > index 320640e64b..385f3c5589 100644 > --- a/include/clone_internal.h > +++ b/include/clone_internal.h > @@ -7,6 +7,11 @@ extern __typeof (clone3) __clone3; > -1 with ENOSYS, fall back to clone or clone2. */ > extern int __clone_internal (struct clone_args *__cl_args, > int (*__func) (void *__arg), void *__arg); > +/* clone3 wrapper with a sticky check to avoid re-issue the syscall if > + it fails with ENOSYS. */ s/re-issue/re-issuing/g > +extern int __clone3_internal (struct clone_args *cl_args, > + int (*func) (void *args), void *arg) > + attribute_hidden; > /* The fallback code which calls clone/clone2 based on clone3 arguments. */ > extern int __clone_internal_fallback (struct clone_args *__cl_args, > int (*__func) (void *__arg), > diff --git a/sysdeps/unix/sysv/linux/clone-internal.c b/sysdeps/unix/sysv/linux/clone-internal.c > index 7bc991e033..39d76733db 100644 > --- a/sysdeps/unix/sysv/linux/clone-internal.c > +++ b/sysdeps/unix/sysv/linux/clone-internal.c > @@ -76,6 +76,28 @@ __clone_internal_fallback (struct clone_args *cl_args, > return ret; > } > > +int > +__clone3_internal (struct clone_args *cl_args, int (*func) (void *args), > + void *arg) > +{ > +#ifdef HAVE_CLONE3_WRAPPER > +# if __ASSUME_CLONE3 > + return __clone3 (cl_args, sizeof (*cl_args), func, arg); > +# else > + static int clone3_supported = 1; > + if (atomic_load_relaxed (&clone3_supported) == 1) > + { > + int ret = __clone3 (cl_args, sizeof (*cl_args), func, arg); > + if (ret != -1 || errno != ENOSYS) > + return ret; > + > + atomic_store_relaxed (&clone3_supported, 0); > + } > +# endif > +#endif > + __set_errno (ENOSYS); > + return -1; > +} > > int > __clone_internal (struct clone_args *cl_args, > @@ -83,7 +105,7 @@ __clone_internal (struct clone_args *cl_args, > { > #ifdef HAVE_CLONE3_WRAPPER > int saved_errno = errno; > - int ret = __clone3 (cl_args, sizeof (*cl_args), func, arg); > + int ret = __clone3_internal (cl_args, func, arg); > if (ret != -1 || errno != ENOSYS) > return ret; > > diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h > index 74adc3956b..4ecd08a98f 100644 > --- a/sysdeps/unix/sysv/linux/kernel-features.h > +++ b/sysdeps/unix/sysv/linux/kernel-features.h > @@ -236,4 +236,13 @@ > # define __ASSUME_FUTEX_LOCK_PI2 0 > #endif > > +/* The clone3 system call was introduced across on most architectures in > + Linux 5.3. Not all ports implements it, so it should be used along > + HAVE_CLONE3_WRAPPER define. */ > +#if __LINUX_KERNEL_VERSION >= 0x050300 > +# define __ASSUME_CLONE3 1 > +#else > +# define __ASSUME_CLONE3 0 > +#endif > + > #endif /* kernel-features.h */
diff --git a/include/clone_internal.h b/include/clone_internal.h index 320640e64b..385f3c5589 100644 --- a/include/clone_internal.h +++ b/include/clone_internal.h @@ -7,6 +7,11 @@ extern __typeof (clone3) __clone3; -1 with ENOSYS, fall back to clone or clone2. */ extern int __clone_internal (struct clone_args *__cl_args, int (*__func) (void *__arg), void *__arg); +/* clone3 wrapper with a sticky check to avoid re-issue the syscall if + it fails with ENOSYS. */ +extern int __clone3_internal (struct clone_args *cl_args, + int (*func) (void *args), void *arg) + attribute_hidden; /* The fallback code which calls clone/clone2 based on clone3 arguments. */ extern int __clone_internal_fallback (struct clone_args *__cl_args, int (*__func) (void *__arg), diff --git a/sysdeps/unix/sysv/linux/clone-internal.c b/sysdeps/unix/sysv/linux/clone-internal.c index 7bc991e033..39d76733db 100644 --- a/sysdeps/unix/sysv/linux/clone-internal.c +++ b/sysdeps/unix/sysv/linux/clone-internal.c @@ -76,6 +76,28 @@ __clone_internal_fallback (struct clone_args *cl_args, return ret; } +int +__clone3_internal (struct clone_args *cl_args, int (*func) (void *args), + void *arg) +{ +#ifdef HAVE_CLONE3_WRAPPER +# if __ASSUME_CLONE3 + return __clone3 (cl_args, sizeof (*cl_args), func, arg); +# else + static int clone3_supported = 1; + if (atomic_load_relaxed (&clone3_supported) == 1) + { + int ret = __clone3 (cl_args, sizeof (*cl_args), func, arg); + if (ret != -1 || errno != ENOSYS) + return ret; + + atomic_store_relaxed (&clone3_supported, 0); + } +# endif +#endif + __set_errno (ENOSYS); + return -1; +} int __clone_internal (struct clone_args *cl_args, @@ -83,7 +105,7 @@ __clone_internal (struct clone_args *cl_args, { #ifdef HAVE_CLONE3_WRAPPER int saved_errno = errno; - int ret = __clone3 (cl_args, sizeof (*cl_args), func, arg); + int ret = __clone3_internal (cl_args, func, arg); if (ret != -1 || errno != ENOSYS) return ret; diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h index 74adc3956b..4ecd08a98f 100644 --- a/sysdeps/unix/sysv/linux/kernel-features.h +++ b/sysdeps/unix/sysv/linux/kernel-features.h @@ -236,4 +236,13 @@ # define __ASSUME_FUTEX_LOCK_PI2 0 #endif +/* The clone3 system call was introduced across on most architectures in + Linux 5.3. Not all ports implements it, so it should be used along + HAVE_CLONE3_WRAPPER define. */ +#if __LINUX_KERNEL_VERSION >= 0x050300 +# define __ASSUME_CLONE3 1 +#else +# define __ASSUME_CLONE3 0 +#endif + #endif /* kernel-features.h */