Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */ 2 : #pragma once 3 : 4 : /*** 5 : Copyright © 2016 Michael Karcher 6 : ***/ 7 : 8 : #include <errno.h> 9 : #include <sched.h> 10 : #include <sys/syscall.h> 11 : 12 : #include "log.h" 13 : #include "macro.h" 14 : 15 : /** 16 : * raw_clone() - uses clone to create a new process with clone flags 17 : * @flags: Flags to pass to the clone system call 18 : * 19 : * Uses the clone system call to create a new process with the cloning flags and termination signal passed in the flags 20 : * parameter. Opposed to glibc's clone function, using this function does not set up a separate stack for the child, but 21 : * relies on copy-on-write semantics on the one stack at a common virtual address, just as fork does. 22 : * 23 : * To obtain copy-on-write semantics, flags must not contain CLONE_VM, and thus CLONE_THREAD and CLONE_SIGHAND (which 24 : * require CLONE_VM) are not usable. 25 : * 26 : * Additionally, as this function does not pass the ptid, newtls and ctid parameters to the kernel, flags must not 27 : * contain CLONE_PARENT_SETTID, CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID or CLONE_SETTLS. 28 : * 29 : * Returns: 0 in the child process and the child process id in the parent. 30 : */ 31 2 : static inline pid_t raw_clone(unsigned long flags) { 32 : pid_t ret; 33 : 34 2 : assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID| 35 : CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0); 36 : #if defined(__s390x__) || defined(__s390__) || defined(__CRIS__) 37 : /* On s390/s390x and cris the order of the first and second arguments 38 : * of the raw clone() system call is reversed. */ 39 : ret = (pid_t) syscall(__NR_clone, NULL, flags); 40 : #elif defined(__sparc__) 41 : { 42 : /** 43 : * sparc always returns the other process id in %o0, and 44 : * a boolean flag whether this is the child or the parent in 45 : * %o1. Inline assembly is needed to get the flag returned 46 : * in %o1. 47 : */ 48 : int in_child, child_pid, error; 49 : 50 : asm volatile("mov %3, %%g1\n\t" 51 : "mov %4, %%o0\n\t" 52 : "mov 0 , %%o1\n\t" 53 : #if defined(__arch64__) 54 : "t 0x6d\n\t" 55 : #else 56 : "t 0x10\n\t" 57 : #endif 58 : "addx %%g0, 0, %2\n\t" 59 : "mov %%o1, %0\n\t" 60 : "mov %%o0, %1" : 61 : "=r"(in_child), "=r"(child_pid), "=r"(error) : 62 : "i"(__NR_clone), "r"(flags) : 63 : "%o1", "%o0", "%g1", "cc" ); 64 : 65 : if (error) { 66 : errno = child_pid; 67 : ret = -1; 68 : } else 69 : ret = in_child ? 0 : child_pid; 70 : } 71 : #else 72 2 : ret = (pid_t) syscall(__NR_clone, flags, NULL); 73 : #endif 74 : 75 2 : if (ret == 0) 76 0 : reset_cached_pid(); 77 : 78 2 : return ret; 79 : }