2 Copyright (C) 2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Bruno Haible <bruno@clisp.org>, 2002.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 #define __clone __no_broken_clone_decl
23 #include <sys/rfork.h>
27 #include <getosreldate.h>
30 /* __start_thread (flags, child_stack, fn, arg)
31 is roughly equivalent to
33 int retval = __rfork (flags);
36 // Here we are in the child thread.
37 %stackpointer = child_stack;
42 but it cannot be done in portable C because it must access fn and arg
43 after having replaced the stack pointer. */
45 extern int __start_thread (int flags
, void *child_stack
,
46 int (*fn
) (void *), void *arg
);
48 int __clone (int (*fn
) (void *), void *child_stack
, int flags
, void *arg
)
50 int rfork_flags
= RFPROC
;
52 if (fn
== NULL
|| child_stack
== NULL
)
58 /* This implementation of clone() does not support all Linux flags. */
59 if (flags
& ~(CSIGNAL
| CLONE_VM
| CLONE_FS
| CLONE_FILES
| CLONE_SIGHAND
60 | CLONE_VFORK
| CLONE_SYSVSEM
))
66 if ((flags
& CSIGNAL
) != SIGCHLD
)
68 if (__kernel_getosreldate() >= 802510)
69 /* we slightly cheat here, */
70 /* the 9.x snapshot prior to r223966 does not support it too */
72 if ((flags
& CSIGNAL
) & ~RFTSIGMASK
)
77 rfork_flags
|= (RFTSIGZMB
| RFTSIGFLAGS(flags
& CSIGNAL
));
81 if ((flags
& CSIGNAL
) & ~RFTHPNMASK
)
86 if ((flags
& CSIGNAL
) == 0)
87 rfork_flags
|= (RFLINUXTHPN
| ((SIGCHLD
) << RFTHPNSHIFT
));
89 rfork_flags
|= (RFLINUXTHPN
| ((flags
& CSIGNAL
) << RFTHPNSHIFT
));
96 /* Sharing the filesystem related info (umask, cwd, root dir)
97 is not supported by rfork. Ignore this; let's hope programs
98 will set their umask and cwd before spawning threads. */
101 if (flags
& CLONE_SYSVSEM
)
102 /* Ignore this; it has been introduced into linuxthreads in post 2.4 glibc */
105 if (!(flags
& CLONE_FILES
))
106 rfork_flags
|= RFFDG
;
108 if (flags
& CLONE_SIGHAND
)
110 rfork_flags
|= RFSIGSHARE
;
111 /* Also set the undocumented flag RFTHREAD. It has the effect that when
112 the thread leader exits, all threads belonging to it are killed. */
113 rfork_flags
|= RFTHREAD
;
116 if (flags
& CLONE_VFORK
)
117 rfork_flags
|= RFPPWAIT
;
119 return __start_thread (rfork_flags
, child_stack
, fn
, arg
);
122 weak_alias (__clone
, clone
)