mirror of
https://sourceware.org/git/glibc.git
synced 2025-08-01 10:06:57 +03:00
Linux: optimize clone3 internal usage
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. Reviewed-by: Carlos O'Donell <carlos@redhat.com>
This commit is contained in:
committed by
Adhemerval Zanella
parent
1e442efd57
commit
98f9435f33
@ -24,6 +24,11 @@ extern int __clone3 (struct clone_args *__cl_args, size_t __size,
|
|||||||
fall back to clone or clone2. */
|
fall back to clone or clone2. */
|
||||||
extern int __clone_internal (struct clone_args *__cl_args,
|
extern int __clone_internal (struct clone_args *__cl_args,
|
||||||
int (*__func) (void *__arg), void *__arg);
|
int (*__func) (void *__arg), void *__arg);
|
||||||
|
/* clone3 wrapper with a sticky check to avoid re-issuing 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. */
|
/* The fallback code which calls clone/clone2 based on clone3 arguments. */
|
||||||
extern int __clone_internal_fallback (struct clone_args *__cl_args,
|
extern int __clone_internal_fallback (struct clone_args *__cl_args,
|
||||||
int (*__func) (void *__arg),
|
int (*__func) (void *__arg),
|
||||||
|
@ -76,6 +76,28 @@ __clone_internal_fallback (struct clone_args *cl_args,
|
|||||||
return ret;
|
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
|
int
|
||||||
__clone_internal (struct clone_args *cl_args,
|
__clone_internal (struct clone_args *cl_args,
|
||||||
@ -83,7 +105,7 @@ __clone_internal (struct clone_args *cl_args,
|
|||||||
{
|
{
|
||||||
#ifdef HAVE_CLONE3_WRAPPER
|
#ifdef HAVE_CLONE3_WRAPPER
|
||||||
int saved_errno = errno;
|
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)
|
if (ret != -1 || errno != ENOSYS)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -241,4 +241,13 @@
|
|||||||
# define __ASSUME_FUTEX_LOCK_PI2 0
|
# define __ASSUME_FUTEX_LOCK_PI2 0
|
||||||
#endif
|
#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 */
|
#endif /* kernel-features.h */
|
||||||
|
Reference in New Issue
Block a user