summaryrefslogtreecommitdiffstats
path: root/sys/i386/linux
diff options
context:
space:
mode:
authorsobomax <sobomax@FreeBSD.org>2005-03-03 16:57:55 +0000
committersobomax <sobomax@FreeBSD.org>2005-03-03 16:57:55 +0000
commit148546007037b5afa82d0db9d471ef618d875512 (patch)
treeba29913230380c4c6bf7753c0c677cca210d631f /sys/i386/linux
parent860c6fe96aececfe576fff79d411679e02e945ad (diff)
downloadFreeBSD-src-148546007037b5afa82d0db9d471ef618d875512.zip
FreeBSD-src-148546007037b5afa82d0db9d471ef618d875512.tar.gz
In linux emulation layer try to detect attempt to use linux_clone() to
create kernel threads and call rfork(2) with RFTHREAD flag set in this case, which puts parent and child into the same threading group. As a result all threads that belong to the same program end up in the same threading group. This is similar to what linuxthreads port does, though in this case we don't have a luxury of having access to the source code and there is no definite way to differentiate linux_clone() called for threading purposes from other uses, so that we have to resort to heuristics. Allow SIGTHR to be delivered between all processes in the same threading group previously it has been blocked for s[ug]id processes. This also should improve locking of the same file descriptor from different threads in programs running under linux compat layer. PR: kern/72922 Reported by: Andriy Gapon <avg@icyb.net.ua> Idea suggested by: rwatson
Diffstat (limited to 'sys/i386/linux')
-rw-r--r--sys/i386/linux/linux_machdep.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c
index ff44a29..23357cd 100644
--- a/sys/i386/linux/linux_machdep.c
+++ b/sys/i386/linux/linux_machdep.c
@@ -314,6 +314,9 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
#define CLONE_FILES 0x400
#define CLONE_SIGHAND 0x800
#define CLONE_PID 0x1000
+#define CLONE_THREAD 0x10000
+
+#define THREADING_FLAGS (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
int
linux_clone(struct thread *td, struct linux_clone_args *args)
@@ -349,6 +352,22 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
if (!(args->flags & CLONE_FILES))
ff |= RFFDG;
+ /*
+ * Attempt to detect when linux_clone(2) is used for creating
+ * kernel threads. Unfortunately despite the existence of the
+ * CLONE_THREAD flag, version of linuxthreads package used in
+ * most popular distros as of beginning of 2005 doesn't make
+ * any use of it. Therefore, this detection relay fully on
+ * empirical observation that linuxthreads sets certain
+ * combination of flags, so that we can make more or less
+ * precise detection and notify the FreeBSD kernel that several
+ * processes are in fact part of the same threading group, so
+ * that special treatment is necessary for signal delivery
+ * between those processes and fd locking.
+ */
+ if ((args->flags & 0xffffff00) == THREADING_FLAGS)
+ ff |= RFTHREAD;
+
error = fork1(td, ff, 0, &p2);
if (error)
return (error);
OpenPOWER on IntegriCloud