Branch data 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 : 8 : static inline pid_t raw_clone(unsigned long flags) { 32 : : pid_t ret; 33 : : 34 [ - + ]: 8 : 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 : 8 : ret = (pid_t) syscall(__NR_clone, flags, NULL); 73 : : #endif 74 : : 75 [ - + ]: 8 : if (ret == 0) 76 : 0 : reset_cached_pid(); 77 : : 78 : 8 : return ret; 79 : : }