From c06adf06b8dd58009169676632fe66156ebb9e56 Mon Sep 17 00:00:00 2001 From: "chao.an" Date: Thu, 20 Feb 2020 20:16:32 +0800 Subject: [PATCH] binfmt/exec: Make the spawn attribute take effect --- binfmt/binfmt_exec.c | 237 +++++++++++++++++++++------------- include/nuttx/binfmt/binfmt.h | 35 +++++ sched/task/task_posixspawn.c | 2 +- 3 files changed, 180 insertions(+), 94 deletions(-) diff --git a/binfmt/binfmt_exec.c b/binfmt/binfmt_exec.c index 7855f6ea70..b280a26594 100644 --- a/binfmt/binfmt_exec.c +++ b/binfmt/binfmt_exec.c @@ -56,6 +56,149 @@ * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: exec_spawn + * + * Description: + * exec() configurable version, delivery the spawn attribute if this + * process has special customization. + * + * Input Parameters: + * filename - The path to the program to be executed. If + * CONFIG_LIB_ENVPATH is defined in the configuration, then + * this may be a relative path from the current working + * directory. Otherwise, path must be the absolute path to the + * program. + * argv - A pointer to an array of string arguments. The end of the + * array is indicated with a NULL entry. + * exports - The address of the start of the caller-provided symbol + * table. This symbol table contains the addresses of symbols + * exported by the caller and made available for linking the + * module into the system. + * nexports - The number of symbols in the exports table. + * attr - The spawn attributes. + * + * Returned Value: + * This is an end-user function, so it follows the normal convention: + * It returns the PID of the exec'ed module. On failure, it returns + * -1 (ERROR) and sets errno appropriately. + * + ****************************************************************************/ + +int exec_spawn(FAR const char *filename, FAR char * const *argv, + FAR const struct symtab_s *exports, int nexports, + FAR const posix_spawnattr_t *attr) +{ + FAR struct binary_s *bin; + int pid; + int errcode; + int ret; + + /* Allocate the load information */ + + bin = (FAR struct binary_s *)kmm_zalloc(sizeof(struct binary_s)); + if (!bin) + { + berr("ERROR: Failed to allocate binary_s\n"); + errcode = ENOMEM; + goto errout; + } + + /* Initialize the binary structure */ + + bin->filename = filename; + bin->exports = exports; + bin->nexports = nexports; + + /* Copy the argv[] list */ + + ret = binfmt_copyargv(bin, argv); + if (ret < 0) + { + errcode = -ret; + berr("ERROR: Failed to copy argv[]: %d\n", errcode); + goto errout_with_bin; + } + + /* Load the module into memory */ + + ret = load_module(bin); + if (ret < 0) + { + errcode = -ret; + berr("ERROR: Failed to load program '%s': %d\n", filename, errcode); + goto errout_with_argv; + } + + /* Update the spawn attribute */ + + if (attr) + { + if (attr->priority > 0) + { + bin->priority = attr->priority; + } + + if (attr->stacksize > 0) + { + bin->stacksize = attr->stacksize; + } + } + + /* Disable pre-emption so that the executed module does + * not return until we get a chance to connect the on_exit + * handler. + */ + + sched_lock(); + + /* Then start the module */ + + pid = exec_module(bin); + if (pid < 0) + { + errcode = -pid; + berr("ERROR: Failed to execute program '%s': %d\n", + filename, errcode); + goto errout_with_lock; + } + +#ifdef CONFIG_BINFMT_LOADABLE + /* Set up to unload the module (and free the binary_s structure) + * when the task exists. + */ + + ret = group_exitinfo(pid, bin); + if (ret < 0) + { + berr("ERROR: Failed to schedule unload '%s': %d\n", filename, ret); + } + +#else + /* Free the binary_s structure here */ + + binfmt_freeargv(bin); + kmm_free(bin); + + /* TODO: How does the module get unloaded in this case? */ + +#endif + + sched_unlock(); + return pid; + +errout_with_lock: + sched_unlock(); + unload_module(bin); +errout_with_argv: + binfmt_freeargv(bin); +errout_with_bin: + kmm_free(bin); +errout: + set_errno(errcode); + return ERROR; +} + /**************************************************************************** * Name: exec * @@ -120,99 +263,7 @@ int exec(FAR const char *filename, FAR char * const *argv, FAR const struct symtab_s *exports, int nexports) { - FAR struct binary_s *bin; - int pid; - int errcode; - int ret; - - /* Allocate the load information */ - - bin = (FAR struct binary_s *)kmm_zalloc(sizeof(struct binary_s)); - if (!bin) - { - berr("ERROR: Failed to allocate binary_s\n"); - errcode = ENOMEM; - goto errout; - } - - /* Initialize the binary structure */ - - bin->filename = filename; - bin->exports = exports; - bin->nexports = nexports; - - /* Copy the argv[] list */ - - ret = binfmt_copyargv(bin, argv); - if (ret < 0) - { - errcode = -ret; - berr("ERROR: Failed to copy argv[]: %d\n", errcode); - goto errout_with_bin; - } - - /* Load the module into memory */ - - ret = load_module(bin); - if (ret < 0) - { - errcode = -ret; - berr("ERROR: Failed to load program '%s': %d\n", filename, errcode); - goto errout_with_argv; - } - - /* Disable pre-emption so that the executed module does - * not return until we get a chance to connect the on_exit - * handler. - */ - - sched_lock(); - - /* Then start the module */ - - pid = exec_module(bin); - if (pid < 0) - { - errcode = -pid; - berr("ERROR: Failed to execute program '%s': %d\n", - filename, errcode); - goto errout_with_lock; - } - -#ifdef CONFIG_BINFMT_LOADABLE - /* Set up to unload the module (and free the binary_s structure) - * when the task exists. - */ - - ret = group_exitinfo(pid, bin); - if (ret < 0) - { - berr("ERROR: Failed to schedule unload '%s': %d\n", filename, ret); - } - -#else - /* Free the binary_s structure here */ - - binfmt_freeargv(bin); - kmm_free(bin); - - /* TODO: How does the module get unloaded in this case? */ - -#endif - - sched_unlock(); - return pid; - -errout_with_lock: - sched_unlock(); - unload_module(bin); -errout_with_argv: - binfmt_freeargv(bin); -errout_with_bin: - kmm_free(bin); -errout: - set_errno(errcode); - return ERROR; + return exec_spawn(filename, argv, exports, nexports, NULL); } #endif /* !CONFIG_BINFMT_DISABLE */ diff --git a/include/nuttx/binfmt/binfmt.h b/include/nuttx/binfmt/binfmt.h index 88b2d409b8..b3f22ec87a 100644 --- a/include/nuttx/binfmt/binfmt.h +++ b/include/nuttx/binfmt/binfmt.h @@ -42,6 +42,8 @@ #include +#include + #include #include @@ -313,6 +315,39 @@ int exec_module(FAR const struct binary_s *bin); int exec(FAR const char *filename, FAR char * const *argv, FAR const struct symtab_s *exports, int nexports); +/**************************************************************************** + * Name: exec_spawn + * + * Description: + * exec() configurable version, delivery the spawn attribute if this + * process has special customization. + * + * Input Parameters: + * filename - The path to the program to be executed. If + * CONFIG_LIB_ENVPATH is defined in the configuration, then + * this may be a relative path from the current working + * directory. Otherwise, path must be the absolute path to the + * program. + * argv - A pointer to an array of string arguments. The end of the + * array is indicated with a NULL entry. + * exports - The address of the start of the caller-provided symbol + * table. This symbol table contains the addresses of symbols + * exported by the caller and made available for linking the + * module into the system. + * nexports - The number of symbols in the exports table. + * attr - The spawn attributes. + * + * Returned Value: + * This is an end-user function, so it follows the normal convention: + * It returns the PID of the exec'ed module. On failure, it returns + * -1 (ERROR) and sets errno appropriately. + * + ****************************************************************************/ + +int exec_spawn(FAR const char *filename, FAR char * const *argv, + FAR const struct symtab_s *exports, int nexports, + FAR const posix_spawnattr_t *attr); + /**************************************************************************** * Name: binfmt_exit * diff --git a/sched/task/task_posixspawn.c b/sched/task/task_posixspawn.c index 88cac9f91d..c559e2c8d0 100644 --- a/sched/task/task_posixspawn.c +++ b/sched/task/task_posixspawn.c @@ -120,7 +120,7 @@ static int nxposix_spawn_exec(FAR pid_t *pidp, FAR const char *path, /* Start the task */ - pid = exec(path, (FAR char * const *)argv, symtab, nsymbols); + pid = exec_spawn(path, (FAR char * const *)argv, symtab, nsymbols, attr); if (pid < 0) { ret = get_errno();