diff --git a/binfmt/Kconfig b/binfmt/Kconfig index 4e47626cbc..58638a9d0c 100644 --- a/binfmt/Kconfig +++ b/binfmt/Kconfig @@ -28,9 +28,23 @@ config PATH_INITIAL The initial value of the PATH variable. This is the colon-separated list of absolute paths. E.g., "/bin:/usr/bin:/sbin" +config BINFMT_LOADABLE + bool + default n + ---help--- + Automatically selected if a loadable binary format is selected. + +config PIC + bool + default n + ---help--- + Automatically selected if the binary format requires position + independent operation. + config NXFLAT bool "Enable the NXFLAT Binary Format" default n + select BINFMT_LOADABLE select PIC ---help--- Enable support for the NXFLAT binary format. Default: n @@ -42,6 +56,7 @@ endif config ELF bool "Enable the ELF Binary Format" default n + select BINFMT_LOADABLE select LIBC_ARCH_ELF ---help--- Enable support for the ELF binary format. Default: n @@ -96,10 +111,6 @@ endif endif -config PIC - bool - default n - config BINFMT_CONSTRUCTORS bool "C++ Static Constructor Support" default n diff --git a/binfmt/Makefile b/binfmt/Makefile index 7240ca9b15..091276c860 100644 --- a/binfmt/Makefile +++ b/binfmt/Makefile @@ -1,7 +1,8 @@ ############################################################################ # nxflat/Makefile # -# Copyright (C) 2007-2009, 2012-2016 Gregory Nutt. All rights reserved. +# Copyright (C) 2007-2009, 2012-2016, 2018 Gregory Nutt. All rights +# reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -52,8 +53,8 @@ ifeq ($(CONFIG_BINFMT_EXEPATH),y) BINFMT_CSRCS += binfmt_exepath.c endif -ifeq ($(CONFIG_SCHED_HAVE_PARENT),y) -BINFMT_CSRCS += binfmt_schedunload.c +ifeq ($(CONFIG_BINFMT_LOADABLE),y) +BINFMT_CSRCS += binfmt_exit.c endif ifeq ($(CONFIG_LIBC_EXECFUNCS),y) diff --git a/binfmt/binfmt.h b/binfmt/binfmt.h index 84775cfbd9..9046cc9cf7 100644 --- a/binfmt/binfmt.h +++ b/binfmt/binfmt.h @@ -106,7 +106,7 @@ int dump_module(FAR const struct binary_s *bin); * argv - Argument list * * Returned Value: - * Zero (OK) on sucess; a negater erro value on failure. + * Zero (OK) on success; a negater errno value on failure. * ****************************************************************************/ diff --git a/binfmt/binfmt_exec.c b/binfmt/binfmt_exec.c index d6ecd57dff..6aed5ebf65 100644 --- a/binfmt/binfmt_exec.c +++ b/binfmt/binfmt_exec.c @@ -1,7 +1,8 @@ /**************************************************************************** * binfmt/binfmt_exec.c * - * Copyright (C) 2009, 2013-2014, 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2009, 2013-2014, 2017-2018 Gregory Nutt. All rights + * reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -44,6 +45,7 @@ #include #include +#include #include #include "binfmt.h" @@ -59,9 +61,8 @@ * * Description: * This is a convenience function that wraps load_ and exec_module into - * one call. If CONFIG_SCHED_ONEXIT and CONFIG_SCHED_HAVE_PARENT are - * also defined, this function will automatically call schedule_unload() - * to unload the module when task exits. + * one call. If CONFIG_BINFMT_LOADABLE is defined, this function will + * schedule to unload the module when task exits. * * This non-standard, NuttX function is similar to execv() and * posix_spawn() but differs in the following ways; @@ -91,9 +92,9 @@ * process cannot provide any meaning symbolic information for use in * linking a different process. * - * NOTE: This function is flawed and useless without CONFIG_SCHED_ONEXIT - * and CONFIG_SCHED_HAVE_PARENT because without those features there is - * then no mechanism to unload the module once it exits. + * NOTE: This function is flawed and useless without CONFIG_BINFMT_LOADABLE + * because without that features there is then no mechanism to unload the + * module once it exits. * * Input Parameters: * filename - The path to the program to be executed. If @@ -173,20 +174,22 @@ int exec(FAR const char *filename, FAR char * const *argv, if (pid < 0) { errcode = -pid; - berr("ERROR: Failed to execute program '%s': %d\n", filename, errcode); + berr("ERROR: Failed to execute program '%s': %d\n", + filename, errcode); goto errout_with_lock; } -#if defined(CONFIG_SCHED_ONEXIT) && defined(CONFIG_SCHED_HAVE_PARENT) +#ifdef CONFIG_BINFMT_LOADABLE /* Set up to unload the module (and free the binary_s structure) * when the task exists. */ - ret = schedule_unload(pid, bin); + 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 */ diff --git a/binfmt/binfmt_execmodule.c b/binfmt/binfmt_execmodule.c index d6c89fdff8..9e161c01e7 100644 --- a/binfmt/binfmt_execmodule.c +++ b/binfmt/binfmt_execmodule.c @@ -82,7 +82,7 @@ * the new task's main function is called. * * Input Parameters: - * loadinfo - Load state information + * arg - Argument is instance of load state info structure cast to void *. * * Returned Value: * 0 (OK) is returned on success and a negated errno is returned on diff --git a/binfmt/binfmt_exit.c b/binfmt/binfmt_exit.c new file mode 100644 index 0000000000..bfed1b1f96 --- /dev/null +++ b/binfmt/binfmt_exit.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * binfmt/binfmt_exit.c + * + * Copyright (C) 2013, 2016-2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "binfmt.h" + +#ifdef CONFIG_BINFMT_LOADABLE + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: binfmt_exit + * + * Description: + * This function may be called when a tasked loaded into RAM exits. + * This function will unload the module when the task exits and reclaim + * all resources used by the module. + * + * Input Parameters: + * bin - This structure must have been allocated with kmm_malloc() and must + * persist until the task unloads + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int binfmt_exit(FAR struct binary_s *bin) +{ + int ret; + + DEBUGASSERT(bin != NULL); + + /* Unload the module */ + + ret = unload_module(bin); + if (ret < 0) + { + berr("ERROR: unload_module() failed: %d\n", ret); + } + + /* Free the load structure */ + + kmm_free(bin); + return ret; +} + +#endif /* CONFIG_BINFMT_LOADABLE */ diff --git a/binfmt/binfmt_schedunload.c b/binfmt/binfmt_schedunload.c deleted file mode 100644 index 1996acd107..0000000000 --- a/binfmt/binfmt_schedunload.c +++ /dev/null @@ -1,319 +0,0 @@ -/**************************************************************************** - * binfmt/binfmt_schedunload.c - * - * Copyright (C) 2013, 2016-2017 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "binfmt.h" - -#if !defined(CONFIG_BINFMT_DISABLE) && defined(CONFIG_SCHED_HAVE_PARENT) - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -FAR struct binary_s *g_unloadhead; - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: unload_list_add - * - * Description: - * If CONFIG_SCHED_HAVE_PARENT is defined then schedul_unload() will - * manage instances of struct binary_s allocated with kmm_malloc. It - * will keep the binary data in a link list and when SIGCHLD is received - * (meaning that the task has exit'ed, schedul_unload() will find the - * data, unload the module, and free the structure. - * - * This function will add one structure to the linked list - * - * Input Parameters: - * pid - The task ID of the child task - * bin - This structure must have been allocated with kmm_malloc() and must - * persist until the task unloads - * - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void unload_list_add(pid_t pid, FAR struct binary_s *bin) -{ - irqstate_t flags; - - /* Save the PID in the structure so that we recover it later */ - - bin->pid = pid; - - /* Disable deliver of any signals while we muck with the list. The - * graceful way to do this would be block delivery of SIGCHLD would be - * with nxsig_procmask. Here we do it the quick'n'dirty way by just - * disabling interrupts. - */ - - flags = enter_critical_section(); - bin->flink = g_unloadhead; - g_unloadhead = bin; - leave_critical_section(flags); -} - -/**************************************************************************** - * Name: unload_list_remove - * - * Description: - * If CONFIG_SCHED_HAVE_PARENT is defined then schedul_unload() will - * manage instances of struct binary_s allocated with kmm_malloc. It - * will keep the binary data in a link list and when SIGCHLD is received - * (meaning that the task has exit'ed, schedul_unload() will find the - * data, unload the module, and free the structure. - * - * This function will remove one structure to the linked list - * - * Input Parameters: - * pid - The task ID of the child task - * - * Returned Value: - * On success, the load structure is returned. NULL is returned on - * failure. - * - ****************************************************************************/ - -static FAR struct binary_s *unload_list_remove(pid_t pid) -{ - FAR struct binary_s *curr; - FAR struct binary_s *prev; - - /* Note the asymmetry. We do not have to disable interrupts here because - * the main thread cannot run while we are in the interrupt handler. Here, - * it should be sufficient to disable pre-emption so that no other thread - * can run. - */ - - sched_lock(); - - /* Find the structure in the unload list with the matching PID */ - - for (prev = NULL, curr = g_unloadhead; - curr && (curr->pid != pid); - prev = curr, curr = curr->flink); - - /* Did we find it? It must be there. Hmmm.. we should probably ASSERT if - * we do not! - */ - - if (curr) - { - /* Was there another entry before this one? */ - - if (prev) - { - /* Yes.. remove the current entry from after the previous entry */ - - prev->flink = curr->flink; - } - else - { - /* No.. remove the current entry from the head of the list */ - - g_unloadhead = curr->flink; - } - - /* Nullify the forward link ... superstitious */ - - curr->flink = NULL; - } - - sched_unlock(); - return curr; -} - -/**************************************************************************** - * Name: unload_callback - * - * Description: - * If CONFIG_SCHED_HAVE_PARENT is defined, this function may be called to - * automatically unload the module when task exits. It assumes that - * bin was allocated with kmm_malloc() or friends and will also automatically - * free the structure with kmm_free() when the task exists. - * - * Input Parameters: - * pid - The ID of the task that just exited - * arg - A reference to the load structure cast to FAR void * - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void unload_callback(int signo, siginfo_t *info, void *ucontext) -{ - FAR struct binary_s *bin; - int ret; - - /* Sanity checking */ - - if (!info || signo != SIGCHLD) - { - berr("ERROR:Bad signal callback: signo=%d info=%p\n", signo, info); - return; - } - - /* Get the load information for this pid */ - - bin = unload_list_remove(info->si_pid); - if (!bin) - { - berr("ERROR: Could not find load info for PID=%d\n", info->si_pid); - return; - } - - /* Unload the module */ - - ret = unload_module(bin); - if (ret < 0) - { - berr("ERROR: unload_module() failed: %d\n", ret); - } - - /* Free the load structure */ - - kmm_free(bin); -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: schedule_unload - * - * Description: - * If CONFIG_SCHED_HAVE_PARENT is defined, this function may be called by - * the parent of the newly created task to automatically unload the - * module when the task exits. This assumes that (1) the caller is the - * parent of the created task, (2) that bin was allocated with kmm_malloc() - * or friends. It will also automatically free the structure with kmm_free() - * after unloading the module. - * - * Input Parameters: - * pid - The task ID of the child task - * bin - This structure must have been allocated with kmm_malloc() and must - * persist until the task unloads - * - * Returned Value: - * This is a NuttX internal function so it follows the convention that - * 0 (OK) is returned on success and a negated errno is returned on - * failure. - * - * On failures, the 'bin' structure will not be deallocated and the - * module not not be unloaded. - * - ****************************************************************************/ - -int schedule_unload(pid_t pid, FAR struct binary_s *bin) -{ - struct sigaction act; - struct sigaction oact; - sigset_t set; - irqstate_t flags; - int ret; - - /* Make sure that SIGCHLD is unmasked */ - - (void)sigemptyset(&set); - (void)sigaddset(&set, SIGCHLD); - ret = nxsig_procmask(SIG_UNBLOCK, &set, NULL); - if (ret < 0) - { - berr("ERROR: nxsig_procmask failed: %d\n", ret); - return ret; - } - - /* Add the structure to the list. We want to do this *before* connecting - * the signal handler. This does, however, make error recovery more - * complex if sigaction() fails below because then we have to remove the - * unload structure for the list in an unexpected context. - */ - - unload_list_add(pid, bin); - - /* Register the SIGCHLD handler */ - - act.sa_sigaction = unload_callback; - act.sa_flags = SA_SIGINFO; - - (void)sigfillset(&act.sa_mask); - (void)sigdelset(&act.sa_mask, SIGCHLD); - - ret = sigaction(SIGCHLD, &act, &oact); - if (ret != OK) - { - /* The errno value will get trashed by the following debug output */ - - ret = -get_errno(); - berr("ERROR: sigaction failed: %d\n" , ret); - - /* Emergency removal from the list */ - - flags = enter_critical_section(); - if (unload_list_remove(pid) != bin) - { - berr("ERROR: Failed to remove structure\n"); - } - - leave_critical_section(flags); - } - - return ret; -} - -#endif /* !CONFIG_BINFMT_DISABLE && CONFIG_SCHED_HAVE_PARENT */ - diff --git a/binfmt/binfmt_unloadmodule.c b/binfmt/binfmt_unloadmodule.c index 8c472f5fe5..bf1711c36c 100644 --- a/binfmt/binfmt_unloadmodule.c +++ b/binfmt/binfmt_unloadmodule.c @@ -63,7 +63,7 @@ * Execute C++ static constructors. * * Input Parameters: - * loadinfo - Load state information + * binp - Load state information * * Returned Value: * 0 (OK) is returned on success and a negated errno is returned on diff --git a/include/nuttx/binfmt/binfmt.h b/include/nuttx/binfmt/binfmt.h index ab238a2d6c..cb5150555c 100644 --- a/include/nuttx/binfmt/binfmt.h +++ b/include/nuttx/binfmt/binfmt.h @@ -260,41 +260,13 @@ int unload_module(FAR struct binary_s *bin); int exec_module(FAR const struct binary_s *bin); -/**************************************************************************** - * Name: schedule_unload - * - * Description: - * If CONFIG_SCHED_HAVE_PARENT is defined, this function may be called by - * the parent of the newly created task to automatically unload the - * module when the task exits. This assumes that (1) the caller is the - * parent of the created task, (2) that bin was allocated with kmm_malloc() - * or friends. It will also automatically free the structure with - * kmm_free() after unloading the module. - * - * Input Parameters: - * pid - The task ID of the child task - * bin - This structure must have been allocated with kmm_malloc() and must - * persist until the task unloads - * - * Returned Value: - * This is a NuttX internal function so it follows the convention that - * 0 (OK) is returned on success and a negated errno is returned on - * failure. - * - ****************************************************************************/ - -#ifdef CONFIG_SCHED_HAVE_PARENT -int schedule_unload(pid_t pid, FAR struct binary_s *bin); -#endif - /**************************************************************************** * Name: exec * * Description: * This is a convenience function that wraps load_ and exec_module into - * one call. If CONFIG_SCHED_ONEXIT and CONFIG_SCHED_HAVE_PARENT are - * also defined, this function will automatically call schedule_unload() - * to unload the module when task exits. + * one call. If CONFIG_BINFMT_LOADABLE is defined, this function will + * schedule to unload the module when task exits. * * This non-standard, NuttX function is similar to execv() and * posix_spawn() but differs in the following ways; @@ -316,7 +288,7 @@ int schedule_unload(pid_t pid, FAR struct binary_s *bin); * The interface is available in the FLAT build mode although it is not * really necessary in that case. It is currently used by some example * code under the apps/ that that generate their own symbol tables for - * linking test programs. So althought it is not necessary, it can still + * linking test programs. So although it is not necessary, it can still * be useful. * * The interface would be completely useless and will not be supported in @@ -324,9 +296,9 @@ int schedule_unload(pid_t pid, FAR struct binary_s *bin); * process cannot provide any meaning symbolic information for use in * linking a different process. * - * NOTE: This function is flawed and useless without CONFIG_SCHED_ONEXIT - * and CONFIG_SCHED_HAVE_PARENT because without those features there is - * then no mechanism to unload the module once it exits. + * NOTE: This function is flawed and useless without CONFIG_BINFMT_LOADABLE + * because without that features there is then no mechanism to unload the + * module once it exits. * * Input Parameters: * filename - The path to the program to be executed. If @@ -352,6 +324,29 @@ int schedule_unload(pid_t pid, FAR struct binary_s *bin); int exec(FAR const char *filename, FAR char * const *argv, FAR const struct symtab_s *exports, int nexports); +/**************************************************************************** + * Name: binfmt_exit + * + * Description: + * This function may be called when a tasked loaded into RAM exits. + * This function will unload the module when the task exits and reclaim + * all resources used by the module. + * + * Input Parameters: + * bin - This structure must have been allocated with kmm_malloc() and must + * persist until the task unloads + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_BINFMT_LOADABLE +int binfmt_exit(FAR struct binary_s *bin); +#endif + /**************************************************************************** * Name: exepath_init * diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 507aa9804f..2d6b9ac11c 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -421,6 +421,10 @@ struct dspace_s struct join_s; /* Forward reference */ /* Defined in sched/pthread/pthread.h */ #endif +#ifdef CONFIG_BINFMT_LOADABLE +struct binary_s; /* Forward reference */ + /* Defined in include/nuttx/binfmt/binfmt.h */ +#endif struct task_group_s { @@ -466,6 +470,12 @@ struct task_group_s # endif #endif +#ifdef CONFIG_BINFMT_LOADABLE + /* Loadable module support ****************************************************/ + + FAR struct binary_s *tg_bininfo; /* Describes resources used by program */ +#endif + #ifdef CONFIG_SCHED_HAVE_PARENT /* Child exit status **********************************************************/ @@ -866,6 +876,31 @@ FAR struct task_tcb_s *task_vforksetup(start_t retaddr); pid_t task_vforkstart(FAR struct task_tcb_s *child); void task_vforkabort(FAR struct task_tcb_s *child, int errcode); +/**************************************************************************** + * Name: group_exitinfo + * + * Description: + * This function may be called to when a task is loaded into memory. It + * will setup the to automatically unload the module when the task exits. + * + * Input Parameters: + * pid - The task ID of the newly loaded task + * bininfo - This structure allocated with kmm_malloc(). This memory + * persists until the task exits and will be used unloads + * the module from memory. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_BINFMT_LOADABLE +struct binary_s; /* Forward reference */ +int group_exitinfo(pid_t pid, FAR struct binary_s *bininfo); +#endif + /******************************************************************************** * Name: sched_resume_scheduler * diff --git a/sched/group/Make.defs b/sched/group/Make.defs index 91a025e1fd..5cf67634c2 100644 --- a/sched/group/Make.defs +++ b/sched/group/Make.defs @@ -52,6 +52,10 @@ ifeq ($(CONFIG_ARCH_ADDRENV),y) CSRCS += group_addrenv.c endif +ifeq ($(CONFIG_BINFMT_LOADABLE),y) +CSRCS += group_exitinfo.c +endif + ifneq ($(CONFIG_DISABLE_SIGNALS),y) CSRCS += group_signal.c endif diff --git a/sched/group/group_exitinfo.c b/sched/group/group_exitinfo.c new file mode 100644 index 0000000000..2eb3d38cd3 --- /dev/null +++ b/sched/group/group_exitinfo.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * sched/group/group_exitinfo.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "sched/sched.h" +#include "group/group.h" + +#ifdef CONFIG_BINFMT_LOADABLE + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: group_exitinfo + * + * Description: + * This function may be called to when a task is loaded into memory. It + * will setup the to automatically unload the module when the task exits. + * + * Input Parameters: + * pid - The task ID of the newly loaded task + * bininfo - This structure allocated with kmm_malloc(). This memory + * persists until the task exits and will be used unloads + * the module from memory. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int group_exitinfo(pid_t pid, FAR struct binary_s *bininfo) +{ + FAR struct tcb_s *tcb; + FAR struct task_group_s *group; + irqstate_t flags; + + DEBUGASSERT(bin != NULL); + flags = spin_lock_irqsave(); + + /* Get the TCB associated with the PID */ + + tcb = sched_gettcb(pid); + if (tcb == NULL) + { + spin_unlock_irqrestore(flags); + return -ESRCH; + } + + /* Get the group that this task belongs to */ + + group = tcb->group; + DEBUGASSERT(group != NULL && group->tg_bininfo == NULL); + + /* Save the binary info for use when the task exits */ + + group->tg_bininfo = bininfo; + return OK; +} + +#endif /* CONFIG_BINFMT_LOADABLE */ diff --git a/sched/group/group_leave.c b/sched/group/group_leave.c index b7c30bf28b..5bfd83da63 100644 --- a/sched/group/group_leave.c +++ b/sched/group/group_leave.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/group/group_leave.c * - * Copyright (C) 2013-2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2013-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -49,6 +49,10 @@ #include #include +#ifdef CONFIG_BINFMT_LOADABLE +# include +#endif + #include "environ/environ.h" #include "signal/signal.h" #include "pthread/pthread.h" @@ -260,6 +264,19 @@ static inline void group_release(FAR struct task_group_s *group) # endif #endif +#ifdef CONFIG_BINFMT_LOADABLE + /* If the exiting task was loaded into RAM from a file, then we need to + * lease all of the memory resource when the last thread exits the task + * group. + */ + + if (group->tg_bininfo != NULL) + { + binfmt_exit(group->tg_bininfo); + group->tg_bininfo = NULL; + } +#endif + #if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT) /* If there are threads waiting for this group to be freed, then we cannot * yet free the memory resources. Instead just mark the group deleted diff --git a/sched/sched/sched_waitpid.c b/sched/sched/sched_waitpid.c index 70dd8540b0..9561dde19f 100644 --- a/sched/sched/sched_waitpid.c +++ b/sched/sched/sched_waitpid.c @@ -239,7 +239,7 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options) /* Then wait for the task to exit */ - if (options & WNOHANG) + if ((options & WNOHANG) != 0) { /* Don't wait if status is not available */