chiark / gitweb /
tree-wide: some work-arounds for gcc false positives regarding uninitialized variables
[elogind.git] / src / basic / raw-clone.h
1 #pragma once
2
3 /***
4   This file is part of elogind.
5
6   Copyright 2010 Lennart Poettering
7   Copyright 2016 Michael Karcher
8   elogind is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   elogind is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with elogind; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sched.h>
23 #include <sys/syscall.h>
24
25 #include "log.h"
26 #include "macro.h"
27
28 /**
29  * raw_clone() - uses clone to create a new process with clone flags
30  * @flags: Flags to pass to the clone system call
31  *
32  * Uses the clone system call to create a new process with the cloning
33  * flags and termination signal passed in the flags parameter. Opposed
34  * to glibc's clone funtion, using this function does not set up a
35  * separate stack for the child, but relies on copy-on-write semantics
36  * on the one stack at a common virtual address, just as fork does.
37  *
38  * To obtain copy-on-write semantics, flags must not contain CLONE_VM,
39  * and thus CLONE_THREAD and CLONE_SIGHAND (which require CLONE_VM) are
40  * not usabale.
41  * Additionally, as this function does not pass the ptid, newtls and ctid
42  * parameters to the kernel, flags must not contain CLONE_PARENT_SETTID,
43  * CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID or CLONE_SETTLS.
44  *
45  * Returns: 0 in the child process and the child process id in the parent.
46  */
47 static inline int raw_clone(unsigned long flags) {
48         assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
49                          CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0);
50 #if defined(__s390__) || defined(__CRIS__)
51         /* On s390 and cris the order of the first and second arguments
52          * of the raw clone() system call is reversed. */
53         return (int) 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;
63                 int child_pid;
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                 if (in_child)
74                         return 0;
75                 else
76                         return child_pid;
77         }
78 #else
79         return (int) syscall(__NR_clone, flags, NULL);
80 #endif
81 }