From owner-svn-src-all@FreeBSD.ORG Sun Apr 7 21:25:15 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 7D86329D; Sun, 7 Apr 2013 21:25:15 +0000 (UTC) (envelope-from jilles@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 609C7B5; Sun, 7 Apr 2013 21:25:15 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r37LPFeZ099179; Sun, 7 Apr 2013 21:25:15 GMT (envelope-from jilles@svn.freebsd.org) Received: (from jilles@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r37LPEbX099174; Sun, 7 Apr 2013 21:25:14 GMT (envelope-from jilles@svn.freebsd.org) Message-Id: <201304072125.r37LPEbX099174@svn.freebsd.org> From: Jilles Tjoelker Date: Sun, 7 Apr 2013 21:25:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r249242 - stable/9/bin/sh X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 07 Apr 2013 21:25:15 -0000 Author: jilles Date: Sun Apr 7 21:25:14 2013 New Revision: 249242 URL: http://svnweb.freebsd.org/changeset/base/249242 Log: MFC r230998,r233792: sh: Use vfork in a few common cases. This uses vfork() for simple commands and command substitutions containing a single simple command, invoking an external program under certain conditions (no redirections or variable assignments, non-interactive shell, no job control). These restrictions limit the amount of code executed in a vforked child. Various incarnations of this patch have been shown to bring performance improvements: http://lists.freebsd.org/pipermail/freebsd-hackers/2012-January/037581.html The use of vfork() can be disabled by setting a variable named SH_DISABLE_VFORK. Modified: stable/9/bin/sh/eval.c stable/9/bin/sh/jobs.c stable/9/bin/sh/jobs.h stable/9/bin/sh/var.c stable/9/bin/sh/var.h Directory Properties: stable/9/bin/sh/ (props changed) Modified: stable/9/bin/sh/eval.c ============================================================================== --- stable/9/bin/sh/eval.c Sun Apr 7 17:54:38 2013 (r249241) +++ stable/9/bin/sh/eval.c Sun Apr 7 21:25:14 2013 (r249242) @@ -906,6 +906,15 @@ evalcommand(union node *cmd, int flags, if (pipe(pip) < 0) error("Pipe call failed: %s", strerror(errno)); } + if (cmdentry.cmdtype == CMDNORMAL && + cmd->ncmd.redirect == NULL && + varlist.list == NULL && + (mode == FORK_FG || mode == FORK_NOJOB) && + !disvforkset() && !iflag && !mflag) { + vforkexecshell(jp, argv, environment(), path, + cmdentry.u.index, flags & EV_BACKCMD ? pip : NULL); + goto parent; + } if (forkshell(jp, cmd, mode) != 0) goto parent; /* at end of routine */ if (flags & EV_BACKCMD) { Modified: stable/9/bin/sh/jobs.c ============================================================================== --- stable/9/bin/sh/jobs.c Sun Apr 7 17:54:38 2013 (r249241) +++ stable/9/bin/sh/jobs.c Sun Apr 7 21:25:14 2013 (r249242) @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #undef CEOF /* syntax.h redefines this */ #endif #include "redir.h" +#include "exec.h" #include "show.h" #include "main.h" #include "parser.h" @@ -884,6 +885,54 @@ forkshell(struct job *jp, union node *n, } +pid_t +vforkexecshell(struct job *jp, char **argv, char **envp, const char *path, int idx, int pip[2]) +{ + pid_t pid; + struct jmploc jmploc; + struct jmploc *savehandler; + + TRACE(("vforkexecshell(%%%td, %s, %p) called\n", jp - jobtab, argv[0], + (void *)pip)); + INTOFF; + flushall(); + savehandler = handler; + pid = vfork(); + if (pid == -1) { + TRACE(("Vfork failed, errno=%d\n", errno)); + INTON; + error("Cannot fork: %s", strerror(errno)); + } + if (pid == 0) { + TRACE(("Child shell %d\n", (int)getpid())); + if (setjmp(jmploc.loc)) + _exit(exception == EXEXEC ? exerrno : 2); + if (pip != NULL) { + close(pip[0]); + if (pip[1] != 1) { + dup2(pip[1], 1); + close(pip[1]); + } + } + handler = &jmploc; + shellexec(argv, envp, path, idx); + } + handler = savehandler; + if (jp) { + struct procstat *ps = &jp->ps[jp->nprocs++]; + ps->pid = pid; + ps->status = -1; + ps->cmd = nullstr; + jp->foreground = 1; +#if JOBS + setcurjob(jp); +#endif + } + INTON; + TRACE(("In parent shell: child = %d\n", (int)pid)); + return pid; +} + /* * Wait for job to finish. Modified: stable/9/bin/sh/jobs.h ============================================================================== --- stable/9/bin/sh/jobs.h Sun Apr 7 17:54:38 2013 (r249241) +++ stable/9/bin/sh/jobs.h Sun Apr 7 21:25:14 2013 (r249242) @@ -91,6 +91,7 @@ void setjobctl(int); void showjobs(int, int); struct job *makejob(union node *, int); pid_t forkshell(struct job *, union node *, int); +pid_t vforkexecshell(struct job *, char **, char **, const char *, int, int []); int waitforjob(struct job *, int *); int stoppedjobs(void); int backgndpidset(void); Modified: stable/9/bin/sh/var.c ============================================================================== --- stable/9/bin/sh/var.c Sun Apr 7 17:54:38 2013 (r249241) +++ stable/9/bin/sh/var.c Sun Apr 7 21:25:14 2013 (r249242) @@ -94,6 +94,7 @@ struct var vps2; struct var vps4; struct var vvers; static struct var voptind; +struct var vdisvfork; int forcelocal; @@ -125,6 +126,8 @@ static const struct varinit varinit[] = #endif { &voptind, 0, "OPTIND=1", getoptsreset }, + { &vdisvfork, VUNSET, "SH_DISABLE_VFORK=", + NULL }, { NULL, 0, NULL, NULL } }; Modified: stable/9/bin/sh/var.h ============================================================================== --- stable/9/bin/sh/var.h Sun Apr 7 17:54:38 2013 (r249241) +++ stable/9/bin/sh/var.h Sun Apr 7 21:25:14 2013 (r249242) @@ -79,6 +79,7 @@ extern struct var vppid; extern struct var vps1; extern struct var vps2; extern struct var vps4; +extern struct var vdisvfork; #ifndef NO_HISTORY extern struct var vhistsize; extern struct var vterm; @@ -109,6 +110,7 @@ extern int initial_localeisutf8; #endif #define mpathset() ((vmpath.flags & VUNSET) == 0) +#define disvforkset() ((vdisvfork.flags & VUNSET) == 0) void initvar(void); void setvar(const char *, const char *, int);