tools/nolibc: Provide vfork()

To allow testing of vfork() support in the arm64 basic-gcs test provide an
implementation for nolibc, using the vfork() syscall if one is available
and otherwise clone3(). We implement in terms of clone3() since the order
of the arguments for clone() varies between architectures.

As for fork() SPARC returns the parent PID rather than 0 in the child
for vfork() so needs custom handling.

Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20250703-arm64-gcs-vfork-exit-v3-2-1e9a9d2ddbbe@kernel.org
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
This commit is contained in:
Mark Brown 2025-07-03 17:00:16 +01:00 committed by Thomas Weißschuh
parent 8c11625afb
commit fb476dfb13
2 changed files with 45 additions and 0 deletions

View file

@ -188,4 +188,20 @@ pid_t sys_fork(void)
}
#define sys_fork sys_fork
static __attribute__((unused))
pid_t sys_vfork(void)
{
pid_t parent, ret;
parent = getpid();
ret = my_syscall0(__NR_vfork);
/* The syscall returns the parent pid in the child instead of 0 */
if (ret == parent)
return 0;
else
return ret;
}
#define sys_vfork sys_vfork
#endif /* _NOLIBC_ARCH_SPARC_H */

View file

@ -22,6 +22,7 @@
#include <linux/time.h>
#include <linux/auxvec.h>
#include <linux/fcntl.h> /* for O_* and AT_* */
#include <linux/sched.h> /* for clone_args */
#include <linux/stat.h> /* for statx() */
#include "errno.h"
@ -340,6 +341,34 @@ pid_t fork(void)
return __sysret(sys_fork());
}
#ifndef sys_vfork
static __attribute__((unused))
pid_t sys_vfork(void)
{
#if defined(__NR_vfork)
return my_syscall0(__NR_vfork);
#elif defined(__NR_clone3)
/*
* clone() could be used but has different argument orders per
* architecture.
*/
struct clone_args args = {
.flags = CLONE_VM | CLONE_VFORK,
.exit_signal = SIGCHLD,
};
return my_syscall2(__NR_clone3, &args, sizeof(args));
#else
return __nolibc_enosys(__func__);
#endif
}
#endif
static __attribute__((unused))
pid_t vfork(void)
{
return __sysret(sys_vfork());
}
/*
* int fsync(int fd);