]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/raw-clone.h
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / basic / raw-clone.h
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 #pragma once
3
4 /***
5 This file is part of systemd.
6
7 Copyright 2010 Lennart Poettering
8 Copyright 2016 Michael Karcher
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <sched.h>
24 #include <sys/syscall.h>
25
26 #include "log.h"
27 #include "macro.h"
28
29 /**
30 * raw_clone() - uses clone to create a new process with clone flags
31 * @flags: Flags to pass to the clone system call
32 *
33 * Uses the clone system call to create a new process with the cloning
34 * flags and termination signal passed in the flags parameter. Opposed
35 * to glibc's clone funtion, using this function does not set up a
36 * separate stack for the child, but relies on copy-on-write semantics
37 * on the one stack at a common virtual address, just as fork does.
38 *
39 * To obtain copy-on-write semantics, flags must not contain CLONE_VM,
40 * and thus CLONE_THREAD and CLONE_SIGHAND (which require CLONE_VM) are
41 * not usabale.
42 * Additionally, as this function does not pass the ptid, newtls and ctid
43 * parameters to the kernel, flags must not contain CLONE_PARENT_SETTID,
44 * CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID or CLONE_SETTLS.
45 *
46 * Returns: 0 in the child process and the child process id in the parent.
47 */
48 static inline int raw_clone(unsigned long flags) {
49 assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
50 CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0);
51 #if defined(__s390x__) || defined(__s390__) || defined(__CRIS__)
52 /* On s390/s390x and cris the order of the first and second arguments
53 * of the raw clone() system call is reversed. */
54 return (int) syscall(__NR_clone, NULL, flags);
55 #elif defined(__sparc__) && defined(__arch64__)
56 {
57 /**
58 * sparc64 always returns the other process id in %o0, and
59 * a boolean flag whether this is the child or the parent in
60 * %o1. Inline assembly is needed to get the flag returned
61 * in %o1.
62 */
63 int in_child;
64 int child_pid;
65 asm volatile("mov %2, %%g1\n\t"
66 "mov %3, %%o0\n\t"
67 "mov 0 , %%o1\n\t"
68 "t 0x6d\n\t"
69 "mov %%o1, %0\n\t"
70 "mov %%o0, %1" :
71 "=r"(in_child), "=r"(child_pid) :
72 "i"(__NR_clone), "r"(flags) :
73 "%o1", "%o0", "%g1" );
74 if (in_child)
75 return 0;
76 else
77 return child_pid;
78 }
79 #else
80 return (int) syscall(__NR_clone, flags, NULL);
81 #endif
82 }