Changeset 3438 for trunk/src/kash/jobs.c


Ignore:
Timestamp:
Sep 9, 2020, 10:01:39 PM (5 years ago)
Author:
bird
Message:

kash: Hammering on threaded mode.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kash/jobs.c

    r3437 r3438  
    6464#include "error.h"
    6565#include "mystring.h"
     66#include "init.h"
    6667#include "shinstance.h"
    6768
     
    7980STATIC void freejob(shinstance *, struct job *);
    8081STATIC struct job *getjob(shinstance *, const char *, int);
    81 STATIC int dowait(shinstance *, int, struct job *);
    82 STATIC int waitproc(shinstance *, int, struct job *, int *);
     82STATIC shpid dowait(shinstance *, int, struct job *);
     83STATIC shpid waitproc(shinstance *, int, struct job *, int *);
    8384STATIC void cmdtxt(shinstance *, union node *);
    8485STATIC void cmdlist(shinstance *, union node *, int);
    8586STATIC void cmdputs(shinstance *, const char *);
     87STATIC shpid forkparent(shinstance *psh, struct job *jp, union node *n, int mode, shpid pid);
     88STATIC void forkchild(shinstance *psh, shpid pgrp, union node *n, int mode);
    8689#ifdef KASH_USE_FORKSHELL2
    87 static int forkparent(shinstance *psh, struct job *jp, union node *n, int mode, pid_t pid);
    88 static void forkchild(shinstance *psh, struct job *jp, union node *n, int mode);
     90# ifndef SH_FORKED_MODE
     91struct forkshell2args
     92{
     93        shinstance *psh;
     94        int mode;
     95        shpid pgrp;     /**< The forkchild() pgrp argument (-1 if not in group). */
     96        union node *n;
     97        void *argp;     /**< Points to child callback data following this structure. */
     98        int (* child)(shinstance *, union node *, void *);
     99        struct stackmark smark; /* do we need this? */
     100};
     101static int forkshell2_thread(shinstance *psh, void *argp);
     102# endif
    89103#endif
    90104
     
    328342        if (mode & SHOW_PGID) {
    329343                /* just output process (group) id of pipeline */
    330                 outfmt(out, "%ld\n", (long)jp->ps->pid);
     344                outfmt(out, "%" SHPID_PRI "\n", jp->ps->pid);
    331345                return;
    332346        }
     
    382396                col = strlen(s);
    383397                if (mode & SHOW_PID) {
    384                         fmtstr(s + col, 16, "%ld ", (long)ps->pid);
     398                        fmtstr(s + col, 16, "%" SHPID_PRI " ", ps->pid);
    385399                             col += strlen(s + col);
    386400                }
     
    475489        int jobno;
    476490        struct job *jp;
    477         int silent = 0, gotpid;
     491        int silent = 0;
     492        shpid gotpid;
    478493
    479494        TRACE((psh, "showjobs(%x) called\n", mode));
     
    607622        jp = getjob(psh, *psh->argptr, 0);
    608623        for (i = 0 ; i < jp->nprocs ; ) {
    609                 out1fmt(psh, "%ld", (long)jp->ps[i].pid);
     624                out1fmt(psh, "%" SHPID_PRI, jp->ps[i].pid);
    610625                out1c(psh, ++i < jp->nprocs ? ' ' : '\n');
    611626        }
     
    613628}
    614629
    615 int
     630shpid
    616631getjobpgrp(shinstance *psh, const char *name)
    617632{
     
    785800
    786801#ifndef KASH_USE_FORKSHELL2
    787 int
     802shpid
    788803forkshell(shinstance *psh, struct job *jp, union node *n, int mode)
    789804{
     
    798813                return -1; /* won't get here */
    799814        case 0:
    800                 forkchild(psh, jp, n, mode);
     815                forkchild(psh, jp == NULL || jp->nprocs == 0 ? -1 : jp->ps[0].pid, n, mode);
    801816                return 0;
    802817        default:
     
    805820}
    806821#else /* KASH_USE_FORKSHELL2 */
    807 int forkshell2(struct shinstance *psh, struct job *jp, union node *n, int mode,
     822shpid
     823forkshell2(shinstance *psh, struct job *jp, union node *n, int mode,
    808824               int (*child)(struct shinstance *, void *, union node *),
    809825               union node *nchild, void *argp, size_t arglen,
    810826               void (*setupchild)(struct shinstance *, struct shinstance *, void *))
    811827{
    812         pid_t pid;
    813 
    814         TRACE((psh, "forkshell2(%%%d, %p, %d, %p, %p, %p, %d) called\n", jp - psh->jobtab, n, mode, child, nchild, argp, (int)arglen));
     828        shpid pid;
     829
     830# ifdef SH_FORKED_MODE
     831        /*
     832         * fork variant.
     833         */
    815834        pid = sh_fork(psh);
    816835        if (pid == 0)
    817836        {
    818837                /* child */
    819                 forkchild(psh, jp, n, mode);
    820                 sh_exit(psh, child(psh, nchild, argp));
     838                forkchild(psh, jp == NULL || jp->nprocs == 0 ? -1 : jp->ps[0].pid, n, mode);
     839                sh__exit(psh, child(psh, nchild, argp));
    821840                return 0;
    822841        }
     
    831850        error(psh, "Cannot fork");
    832851        return -1; /* won't get here */
    833 }
    834 #endif
    835 
    836 #ifdef KASH_USE_FORKSHELL2
    837 static
    838 #endif
    839 int
    840 forkparent(shinstance *psh, struct job *jp, union node *n, int mode, pid_t pid)
    841 {
    842         int pgrp;
     852
     853# else
     854        /*
     855         * Clone the shell and start a thread to service the subshell.
     856         */
     857        struct shinstance *pshchild;
     858
     859        TRACE((psh, "forkshell2(%%%d, %p, %d, %p, %p, %p, %d) called\n",
     860                   jp - psh->jobtab, n, mode, child, nchild, argp, (int)arglen));
     861
     862        pshchild = sh_create_child_shell(psh);
     863        if (pshchild) {
     864                /* pack arguments */
     865                struct forkshell2args *args = (struct forkshell2args *)sh_calloc(pshchild, sizeof(*args) + arglen, 1);
     866                args->psh = pshchild;
     867                args->argp = memcpy(args + 1, argp, arglen);
     868                args->child = child;
     869                args->mode = mode;
     870                args->pgrp = jp == NULL || jp->nprocs == 0 ? -1 : jp->ps[0].pid;
     871                setstackmark(pshchild, &args->smark);
     872                args->n = copyparsetree(pshchild, n);
     873                if (setupchild)
     874                        setupchild(pshchild, psh, args->argp);
     875
     876                /* start the thread */
     877                pid = sh_thread_start(psh, pshchild, forkshell2_thread, args);
     878                if (pid >= 0)
     879                        return forkparent(psh, jp, n, mode, pid);
     880                error(psh, "sh_start_child_thread failed (%d)!", (int)pid);
     881        }
     882        else
     883                error(psh, "sh_create_child_shell failed!");
     884        return -1;
     885# endif
     886}
     887#endif
     888
     889static shpid
     890forkparent(shinstance *psh, struct job *jp, union node *n, int mode, shpid pid)
     891{
     892        shpid pgrp;
    843893
    844894        if (psh->rootshell && mode != FORK_NOJOB && mflag(psh)) {
     
    860910                        commandtext(psh, ps, n);
    861911        }
    862         TRACE((psh, "In parent shell:  child = %d\n", pid));
     912        TRACE((psh, "In parent shell:  child = %" SHPID_PRI "\n", pid));
    863913        return pid;
    864914}
    865915
    866 #ifdef KASH_USE_FORKSHELL2
    867 static
    868 #endif
    869 void
    870 forkchild(shinstance *psh, struct job *jp, union node *n, int mode)
     916static void
     917forkchild(shinstance *psh, shpid pgrp, union node *n, int mode)
    871918{
    872919        int wasroot;
    873         int pgrp;
    874920        const char *devnull = _PATH_DEVNULL;
    875921        const char *nullerr = "Can't open %s";
    876922
    877923        wasroot = psh->rootshell;
    878         TRACE((psh, "Child shell %d\n", sh_getpid(psh)));
     924        TRACE((psh, "Child shell %" SHPID_PRI "\n", sh_getpid(psh)));
    879925        psh->rootshell = 0;
    880926
     
    884930        psh->jobctl = 0;                /* do job control only in root shell */
    885931        if (wasroot && mode != FORK_NOJOB && mflag(psh)) {
    886                 if (jp == NULL || jp->nprocs == 0)
     932                if (pgrp == -1)
    887933                        pgrp = sh_getpid(psh);
    888                 else
    889                         pgrp = jp->ps[0].pid;
    890934                /* This can fail because we are doing it in the parent also.
    891935                   And we must ignore SIGTTOU at this point or we'll be stopped! */
     
    898942                setsignal(psh, SIGTSTP);
    899943                setsignal(psh, SIGTTOU);
    900         } else if (mode == FORK_BG) {
     944        } else
     945#endif
     946        if (mode == FORK_BG) {
    901947                ignoresig(psh, SIGINT);
    902948                ignoresig(psh, SIGQUIT);
    903                 if ((jp == NULL || jp->nprocs == 0) &&
    904                     ! fd0_redirected_p(psh)) {
     949                if (pgrp == -1 && ! fd0_redirected_p(psh)) {
    905950                        shfile_close(&psh->fdtab, 0);
    906951                        if (shfile_open(&psh->fdtab, devnull, O_RDONLY, 0) != 0)
     
    908953                }
    909954        }
    910 #else
    911         if (mode == FORK_BG) {
    912                 ignoresig(psh, SIGINT);
    913                 ignoresig(psh, SIGQUIT);
    914                 if ((jp == NULL || jp->nprocs == 0) &&
    915                     ! fd0_redirected_p(psh)) {
    916                         shfile_close(&psh->fdtab, 0);
    917                         if (shfile_open(&psh->fdtab, devnull, O_RDONLY, 0) != 0)
    918                                 error(psh, nullerr, devnull);
    919                 }
    920         }
    921 #endif
    922955        if (wasroot && iflag(psh)) {
    923956                setsignal(psh, SIGINT);
     
    928961        psh->jobs_invalid = 1;
    929962}
     963
     964#if defined(KASH_USE_FORKSHELL2) && !defined(SH_FORKED_MODE)
     965/** thread procedure */
     966static int forkshell2_thread(shinstance *psh, void *argp)
     967{
     968        struct forkshell2args * volatile volargs = (struct forkshell2args *)argp;
     969        struct jmploc jmp;
     970        TRACE2((psh, "forkshell2_thread:\n"));
     971
     972        if (setjmp(jmp.loc) == 0) {
     973                struct forkshell2args * const args = volargs;
     974
     975                forkchild(psh, args->pgrp, args->n, args->mode);
     976
     977                psh->handler = &jmp;
     978                return args->child(psh, args->n, args->argp);
     979        }
     980
     981        /*
     982         * (We longjmp'ed here.)
     983         *
     984         * This is copied from main() and simplified:
     985         */
     986        for (;;) {
     987                psh = volargs->psh; /* longjmp paranoia */
     988
     989                if (psh->exception != EXSHELLPROC) {
     990                        if (psh->exception == EXEXEC)
     991                                psh->exitstatus = psh->exerrno;
     992                        else if (psh->exception == EXERROR)
     993                                psh->exitstatus = 2;
     994                        TRACE2((psh, "forkshell2_thread: exception=%d -> exitshell2(,%d)\n", psh->exception, psh->exitstatus));
     995                        return exitshell2(psh, psh->exitstatus);
     996                }
     997
     998                /* EXSHELLPROC - tryexec gets us here and it wants to run a program
     999                   hoping (?) it's a shell script.  We must reset the shell state and
     1000                   turn ourselves into a root shell before doing so. */
     1001                TRACE2((psh, "forkshell2_thread: exception=EXSHELLPROC\n"));
     1002                psh->rootpid = /*getpid()*/ psh->pid;
     1003                psh->rootshell = 1;
     1004                psh->minusc = NULL;
     1005
     1006                reset(psh);
     1007                popstackmark(psh, &volargs->smark);
     1008
     1009                FORCEINTON;                             /* enable interrupts */
     1010
     1011                /* state3: */
     1012                if (sflag(psh) == 0) {
     1013# ifdef SIGTSTP
     1014                        static int sigs[] =  { SIGINT, SIGQUIT, SIGHUP, SIGPIPE, SIGTSTP };
     1015# else
     1016                        static int sigs[] =  { SIGINT, SIGQUIT, SIGHUP, SIGPIPE };
     1017# endif
     1018                        unsigned i;
     1019                        for (i = 0; i < K_ELEMENTS(sigs); i++)
     1020                                setsignal(psh, sigs[i]);
     1021                }
     1022
     1023                if (setjmp(jmp.loc) == 0) {
     1024                        psh->handler = &jmp;
     1025                        cmdloop(psh, 1);
     1026                        TRACE2((psh, "forkshell2_thread: cmdloop returned -> exitshell2(,%d)\n", psh->exitstatus));
     1027                        return exitshell2(psh, psh->exitstatus);
     1028                }
     1029        }
     1030}
     1031#endif
     1032
    9301033
    9311034/*
     
    9521055{
    9531056#if JOBS
    954         int mypgrp = sh_getpgrp(psh);
     1057        shpid mypgrp = sh_getpgrp(psh);
    9551058#endif
    9561059        int status;
     
    10091112 */
    10101113
    1011 STATIC int
     1114STATIC shpid
    10121115dowait(shinstance *psh, int block, struct job *job)
    10131116{
    1014         int pid;
     1117        shpid pid;
    10151118        int status;
    10161119        struct procstat *sp;
     
    10231126        do {
    10241127                pid = waitproc(psh, block, job, &status);
    1025                 TRACE((psh, "wait returns pid %d, status %d\n", pid, status));
     1128                TRACE((psh, "wait returns pid %" SHPID_PRI ", status %d\n", pid, status));
    10261129        } while (pid == -1 && errno == EINTR && psh->gotsig[SIGINT - 1] == 0);
    10271130        if (pid <= 0)
     
    10371140                                        continue;
    10381141                                if (sp->pid == pid) {
    1039                                         TRACE((psh, "Job %d: changing status of proc %d from 0x%x to 0x%x\n", jp - psh->jobtab + 1, pid, sp->status, status));
     1142                                        TRACE((psh, "Job %d: changing status of proc %" SHPID_PRI " from 0x%x to 0x%x\n",
     1143                                                   jp - psh->jobtab + 1, pid, sp->status, status));
    10401144                                        sp->status = status;
    10411145                                        thisjob = jp;
     
    10861190 * rather than blocking.
    10871191 */
    1088 STATIC int
     1192STATIC shpid
    10891193waitproc(shinstance *psh, int block, struct job *jp, int *status)
    10901194{
Note: See TracChangeset for help on using the changeset viewer.