On 2012/08/10 18:13, Konstantin Belousov wrote:
On Thu, Aug 09, 2012 at 02:08:50PM +0300, Konstantin Belousov wrote:
Third alternative, which seems to be even better, is to restore
single-threading of the parent for vfork().
single-threading is slow for large threaded process, don't know if it
is necessary for vfork(), POSIX says nothing about threaded process.

I mean this patch.


diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 6cb95cd..e59ee21 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -756,7 +756,7 @@ fork1(struct thread *td, int flags, int pages, struct proc 
**procp,
        struct thread *td2;
        struct vmspace *vm2;
        vm_ooffset_t mem_charged;
-       int error;
+       int error, single_threaded;
        static int curfail;
        static struct timeval lastfail;
  #ifdef PROCDESC
@@ -815,6 +815,19 @@ fork1(struct thread *td, int flags, int pages, struct proc 
**procp,
        }
  #endif
+ if (((p1->p_flag & (P_HADTHREADS | P_SYSTEM)) == P_HADTHREADS) &&
+           (flags & RFPPWAIT) != 0) {
+               PROC_LOCK(p1);
+               if (thread_single(SINGLE_BOUNDARY)) {
+                       PROC_UNLOCK(p1);
+                       error = ERESTART;
+                       goto fail2;
+               }
+               PROC_UNLOCK(p1);
+               single_threaded = 1;
+       } else
+               single_threaded = 0;
+
        mem_charged = 0;
        vm2 = NULL;
        if (pages == 0)
@@ -945,6 +958,12 @@ fail1:
        if (vm2 != NULL)
                vmspace_free(vm2);
        uma_zfree(proc_zone, newproc);
+       if (single_threaded) {
+               PROC_LOCK(p1);
+               thread_single_end();
+               PROC_UNLOCK(p1);
+       }
+fail2:
  #ifdef PROCDESC
        if (((flags & RFPROCDESC) != 0) && (fp_procdesc != NULL)) {
                fdclose(td->td_proc->p_fd, fp_procdesc, *procdescp, td);
diff --git a/tools/test/pthread_vfork/pthread_vfork_test.c 
b/tools/test/pthread_vfork/pthread_vfork_test.c
index e004727..88956c2 100644
--- a/tools/test/pthread_vfork/pthread_vfork_test.c
+++ b/tools/test/pthread_vfork/pthread_vfork_test.c
@@ -29,6 +29,8 @@
  #include <sys/cdefs.h>
  __FBSDID("$FreeBSD$");
+#include <sys/types.h>
+#include <sys/wait.h>
  #include <err.h>
  #include <pthread.h>
  #include <signal.h>
@@ -39,10 +41,11 @@ __FBSDID("$FreeBSD$");
#define NUM_THREADS 100 -void *
-vfork_test(void *threadid)
+static void *
+vfork_test(void *threadid __unused)
  {
-       pid_t pid;
+       pid_t pid, wpid;
+       int status;
for (;;) {
                pid = vfork();
@@ -50,10 +53,20 @@ vfork_test(void *threadid)
                        _exit(0);
                else if (pid == -1)
                        err(1, "Failed to vfork");
+               else {
+                       wpid = waitpid(pid, &status, 0);
+                       if (wpid == -1)
+                               err(1, "waitpid");
+               }
        }
        return (NULL);
  }
+static void
+sighandler(int signo __unused)
+{
+}
+
  /*
   * This program invokes multiple threads and each thread calls
   * vfork() system call.
@@ -63,19 +76,24 @@ main(void)
  {
        pthread_t threads[NUM_THREADS];
        struct sigaction reapchildren;
+       sigset_t sigchld_mask;
        int rc, t;
memset(&reapchildren, 0, sizeof(reapchildren));
-       reapchildren.sa_handler = SIG_IGN;
-
-       /* Automatically reap zombies. */
+       reapchildren.sa_handler = sighandler;
        if (sigaction(SIGCHLD, &reapchildren, NULL) == -1)
                err(1, "Could not sigaction(SIGCHLD)");
+ sigemptyset(&sigchld_mask);
+       sigaddset(&sigchld_mask, SIGCHLD);
+       if (sigprocmask(SIG_BLOCK, &sigchld_mask, NULL) == -1)
+               err(1, "sigprocmask");
+
        for (t = 0; t < NUM_THREADS; t++) {
                rc = pthread_create(&threads[t], NULL, vfork_test, (void *)t);
                if (rc)
                        errc(1, rc, "pthread_create");
        }
+       pause();
        return (0);
  }


_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"

Reply via email to