From 7465dbcf2a4c0a0983d40e5c0f5c057d2ed04125 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sun, 13 Apr 2008 02:25:53 +0000 Subject: [PATCH] ash: speed up NOFORK code in ash by eliminating second find_applet(). some code reduction along the way. function old new delta run_list 1971 1981 +10 run_nofork_applet_prime 181 182 +1 unsetcmd 97 96 -1 delete_cmd_entry 54 53 -1 describe_command 399 397 -2 cmdlookup 152 150 -2 evaltreenr 602 599 -3 evaltree 602 599 -3 clearcmdentry 101 98 -3 cdcmd 675 672 -3 hashcmd 305 301 -4 find_command 933 910 -23 evalcommand 1371 1229 -142 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/11 up/down: 11/-187) Total: -176 bytes --- libbb/vfork_daemon_rexec.c | 11 +++++++++- shell/ash.c | 44 ++++++++++++++++++++------------------ shell/hush.c | 2 +- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 1567d89be..2c4c930b2 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -146,6 +146,15 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char ** memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); /* Finally we can call NOFORK applet's main() */ rc = applet_main[applet_no](argc, tmp_argv); + + /* The whole reason behind nofork_save_area is that _main + * may exit non-locally! For example, in hush Ctrl-Z tries to + * (modulo bugs) to dynamically create child (backgrounded task) + * if it detects that Ctrl-Z was pressed when a NOFORK was running! + * Testcase: interactive "rm -i". + * Don't fool yourself into thinking "and _main() returns + * quickly here" and removing "useless" nofork_save_area code. */ + } else { /* xfunc died in NOFORK applet */ /* in case they meant to return 0... */ if (rc == -2222) @@ -154,7 +163,7 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char ** /* Restoring globals */ restore_nofork_data(old); - return rc; + return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ } int run_nofork_applet(int applet_no, char **argv) diff --git a/shell/ash.c b/shell/ash.c index cc61401d1..409d084cf 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -6828,9 +6828,13 @@ struct builtincmd { #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4) struct cmdentry { - int cmdtype; + smallint cmdtype; /* CMDxxx */ union param { int index; + /* index >= 0 for commands without path (slashes) */ + /* (TODO: what exactly does the value mean? PATH position?) */ + /* index == -1 for commands with slashes */ + /* index == (-2 - applet_no) for NOFORK applets */ const struct builtincmd *cmd; struct funcnode *func; } u; @@ -6867,7 +6871,7 @@ static void find_command(char *, struct cmdentry *, int, const char *); struct tblentry { struct tblentry *next; /* next entry in hash chain */ union param param; /* definition of builtin function */ - short cmdtype; /* index identifying command */ + smallint cmdtype; /* CMDxxx */ char rehash; /* if set, cd done since entry created */ char cmdname[ARB]; /* name of command */ }; @@ -7355,7 +7359,7 @@ describe_command(char *command, int describe_command_verbose) case CMDNORMAL: { int j = entry.u.index; char *p; - if (j == -1) { + if (j < 0) { p = command; } else { do { @@ -8747,22 +8751,17 @@ evalcommand(union node *cmd, int flags) /* Execute the command. */ switch (cmdentry.cmdtype) { default: - #if ENABLE_FEATURE_SH_NOFORK - { - /* TODO: don't rerun find_applet_by_name, find_command - * already did it. Make it save applet_no somewhere */ - int applet_no = find_applet_by_name(argv[0]); + { + /* find_command() encodes applet_no as (-2 - applet_no) */ + int applet_no = (- cmdentry.u.index - 2); if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) { - struct nofork_save_area nofork_save; - listsetvar(varlist.list, VEXPORT|VSTACK); - save_nofork_data(&nofork_save); - /* run _main(), then restore nofork_save_area */ - exitstatus = run_nofork_applet_prime(&nofork_save, applet_no, argv) & 0xff; + /* run _main() */ + exitstatus = run_nofork_applet(applet_no, argv); break; } - } + } #endif /* Fork off a child process if necessary. */ @@ -11618,10 +11617,13 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) } #if ENABLE_FEATURE_SH_STANDALONE - if (find_applet_by_name(name) >= 0) { - entry->cmdtype = CMDNORMAL; - entry->u.index = -1; - return; + { + int applet_no = find_applet_by_name(name); + if (applet_no >= 0) { + entry->cmdtype = CMDNORMAL; + entry->u.index = -2 - applet_no; + return; + } } #endif @@ -12691,7 +12693,7 @@ is_right_associativity(operator prec) || prec == PREC(TOK_CONDITIONAL)); } -typedef struct ARITCH_VAR_NUM { +typedef struct { arith_t val; arith_t contidional_second_val; char contidional_second_val_initialized; @@ -12699,9 +12701,9 @@ typedef struct ARITCH_VAR_NUM { else is variable name */ } v_n_t; -typedef struct CHK_VAR_RECURSIVE_LOOPED { +typedef struct chk_var_recursive_looped_t { const char *var; - struct CHK_VAR_RECURSIVE_LOOPED *next; + struct chk_var_recursive_looped_t *next; } chk_var_recursive_looped_t; static chk_var_recursive_looped_t *prev_chk_var_recursive; diff --git a/shell/hush.c b/shell/hush.c index 545367cb6..aa740f1b4 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1861,7 +1861,7 @@ static int run_pipe(struct pipe *pi) //sp: if (child->sp) argv_expanded = expand_strvec_to_strvec(argv + i); debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]); - rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded) & 0xff; + rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded); free(argv_expanded); restore_redirects(squirrel); debug_printf_exec("run_pipe return %d\n", rcode); -- 2.25.1