chiark / gitweb /
Prep v238: Remove obsolete sources and add missing new ones.
[elogind.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 flags and termination signal passed in the flags
34  * parameter. Opposed to glibc's clone funtion, using this function does not set up a separate stack for the child, but
35  * relies on copy-on-write semantics on the one stack at a common virtual address, just as fork does.
36  *
37  * To obtain copy-on-write semantics, flags must not contain CLONE_VM, and thus CLONE_THREAD and CLONE_SIGHAND (which
38  * require CLONE_VM) are not usable.
39  *
40  * Additionally, as this function does not pass the ptid, newtls and ctid parameters to the kernel, flags must not
41  * contain CLONE_PARENT_SETTID, CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID or CLONE_SETTLS.
42  *
43  * Returns: 0 in the child process and the child process id in the parent.
44  */
45 static inline pid_t raw_clone(unsigned long flags) {
46         pid_t ret;
47
48         assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
49                          CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0);
50 #if defined(__s390x__) || defined(__s390__) || defined(__CRIS__)
51         /* On s390/s390x and cris the order of the first and second arguments
52          * of the raw clone() system call is reversed. */
53         ret = (pid_t) syscall(__NR_clone, NULL, flags);
54 #elif defined(__sparc__) && defined(__arch64__)
55         {
56                 /**
57                  * sparc64 always returns the other process id in %o0, and
58                  * a boolean flag whether this is the child or the parent in
59                  * %o1. Inline assembly is needed to get the flag returned
60                  * in %o1.
61                  */
62                 int in_child, child_pid;
63
64                 asm volatile("mov %2, %%g1\n\t"
65                              "mov %3, %%o0\n\t"
66                              "mov 0 , %%o1\n\t"
67                              "t 0x6d\n\t"
68                              "mov %%o1, %0\n\t"
69                              "mov %%o0, %1" :
70                              "=r"(in_child), "=r"(child_pid) :
71                              "i"(__NR_clone), "r"(flags) :
72                              "%o1", "%o0", "%g1" );
73
74                 ret = in_child ? 0 : child_pid;
75         }
76 #else
77         ret = (pid_t) syscall(__NR_clone, flags, NULL);
78 #endif
79
80         if (ret == 0)
81                 reset_cached_pid();
82
83         return ret;
84 }