diff options
Diffstat (limited to 'nuttx/sched')
-rw-r--r-- | nuttx/sched/Makefile | 4 | ||||
-rw-r--r-- | nuttx/sched/os_internal.h | 1 | ||||
-rw-r--r-- | nuttx/sched/os_start.c | 51 | ||||
-rw-r--r-- | nuttx/sched/sched_free.c | 64 | ||||
-rwxr-xr-x | nuttx/sched/sched_garbage.c | 127 | ||||
-rwxr-xr-x | nuttx/sched/work_internal.h | 32 | ||||
-rwxr-xr-x | nuttx/sched/work_queue.c | 1 | ||||
-rwxr-xr-x | nuttx/sched/work_thread.c | 166 |
8 files changed, 391 insertions, 55 deletions
diff --git a/nuttx/sched/Makefile b/nuttx/sched/Makefile index 3a2512662..ec9923e1c 100644 --- a/nuttx/sched/Makefile +++ b/nuttx/sched/Makefile @@ -38,7 +38,7 @@ ASRCS = AOBJS = $(ASRCS:.S=$(OBJEXT)) -MISC_SRCS = os_start.c get_errno_ptr.c \ +MISC_SRCS = os_start.c get_errno_ptr.c sched_garbage.c \ sched_setupstreams.c sched_getfiles.c sched_getsockets.c sched_getstreams.c \ sched_setupidlefiles.c sched_setuptaskfiles.c sched_setuppthreadfiles.c \ sched_releasefiles.c @@ -136,7 +136,7 @@ TIMER_SRCS = timer_initialize.c timer_create.c timer_delete.c timer_getoverrun.c endif ifeq ($(CONFIG_SCHED_WORKQUEUE),y) -WORK_SRCS = work_queue.c work_cancel.c +WORK_SRCS = work_thread.c work_queue.c work_cancel.c endif IRQ_SRCS = irq_initialize.c irq_attach.c irq_dispatch.c irq_unexpectedisr.c diff --git a/nuttx/sched/os_internal.h b/nuttx/sched/os_internal.h index b07818345..84a2997c7 100644 --- a/nuttx/sched/os_internal.h +++ b/nuttx/sched/os_internal.h @@ -273,5 +273,6 @@ extern int sched_releasefiles(FAR _TCB *tcb); #endif extern int sched_releasetcb(FAR _TCB *tcb); +extern void sched_garbagecollection(void); #endif /* __OS_INTERNAL_H */ diff --git a/nuttx/sched/os_start.c b/nuttx/sched/os_start.c index 8e036a9f9..41fc735e3 100644 --- a/nuttx/sched/os_start.c +++ b/nuttx/sched/os_start.c @@ -61,6 +61,9 @@ #include "clock_internal.h" #include "timer_internal.h" #include "irq_internal.h" +#ifdef CONFIG_SCHED_WORKQUEUE +# include "work_internal.h" +#endif /**************************************************************************** * Definitions @@ -156,6 +159,12 @@ volatile pid_t g_lastpid; pidhash_t g_pidhash[CONFIG_MAX_TASKS]; +/* The task ID of the worker thread */ + +#ifdef CONFIG_SCHED_WORKQUEUE +pid_t g_worker; +#endif + /* This is a table of task lists. This table is indexed by * the task state enumeration type (tstate_t) and provides * a pointer to the associated static task list (if there @@ -423,6 +432,15 @@ void os_start(void) (void)sched_setupidlefiles(&g_idletcb); + /* Start the worker thread that will perform misc garbage clean-up */ + +#ifdef CONFIG_SCHED_WORKQUEUE + g_worker = task_create("work", CONFIG_SCHED_WORKPRIORITY, + CONFIG_SCHED_WORKSTACKSIZE, + (main_t)work_thread, (const char **)NULL); +#endif + ASSERT(g_worker != ERROR); + /* Once the operating system has been initialized, the system must be * started by spawning the user init thread of execution. */ @@ -443,33 +461,14 @@ void os_start(void) sdbg("Beginning Idle Loop\n"); for (;;) { - /* Check if there is anything in the delayed deallocation list. - * If there is deallocate it now. We must have exclusive access - * to the memory manager to do this BUT the idle task cannot - * wait on a semaphore. So we only do the cleanup now if we - * can get the semaphore -- and this should be possible because - * since we are running, no other task is! + /* Peform garbage collection (if it is not being done by the worker + * thread. This cleans-up memory de-allocations that was queued + * because it could not be freed in that execution context (for + * example, if the memory was freed from an interrupt handler). */ - - if (mm_trysemaphore() == 0) - { - while (g_delayeddeallocations.head) - { - /* Remove the first delayed deallocation. */ - - irqstate_t saved_state = irqsave(); - void *address = (void*)sq_remfirst((FAR sq_queue_t*)&g_delayeddeallocations); - irqrestore(saved_state); - - /* Then deallocate it */ - - if (address) - { - free(address); - } - } - mm_givesemaphore(); - } +#ifndef CONFIG_SCHED_WORKQEUE + sched_garbagecollection(); +#endif /* Perform any processor-specific idle state operations */ diff --git a/nuttx/sched/sched_free.c b/nuttx/sched/sched_free.c index 6078cc1b6..afa5e62c9 100644 --- a/nuttx/sched/sched_free.c +++ b/nuttx/sched/sched_free.c @@ -1,7 +1,7 @@ -/************************************************************ - * sched_free.c +/************************************************************************ + * sched/sched_free.c * - * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -14,7 +14,7 @@ * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. - * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * 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. * @@ -31,55 +31,59 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - ************************************************************/ + ************************************************************************/ -/************************************************************ +/************************************************************************ * Included Files - ************************************************************/ + ************************************************************************/ +#include <nuttx/config.h> #include <sys/types.h> -#include <nuttx/kmalloc.h> + #include <queue.h> #include <assert.h> + +#include <nuttx/kmalloc.h> #include <nuttx/arch.h> +#include <nuttx/wqueue.h> #include <nuttx/mm.h> + #include "os_internal.h" -/************************************************************ +/************************************************************************ * Definitions - ************************************************************/ + ************************************************************************/ -/************************************************************ +/************************************************************************ * Private Type Declarations - ************************************************************/ + ************************************************************************/ -/************************************************************ +/************************************************************************ * Global Variables - ************************************************************/ + ************************************************************************/ -/************************************************************ +/************************************************************************ * Private Variables - ************************************************************/ + ************************************************************************/ -/************************************************************ +/************************************************************************ * Private Function Prototypes - ************************************************************/ + ************************************************************************/ -/************************************************************ +/************************************************************************ * Public Functions - ************************************************************/ + ************************************************************************/ -/************************************************************ +/************************************************************************ * Name: sched_free * * Description: - * This function performs deallocations that - * the operating system may need to make. This special - * interface to free is used to handling corner cases - * where the operating system may have to perform deallocations - * from within an interrupt handler. + * This function performs deallocations that the operating system may + * need to make. This special interface to free is used to handling + * corner cases where the operating system may have to perform + * deallocations from within an interrupt handler. * - ************************************************************/ + ************************************************************************/ void sched_free(FAR void *address) { @@ -95,6 +99,12 @@ void sched_free(FAR void *address) irqstate_t saved_state = irqsave(); sq_addlast((FAR sq_entry_t*)address, (sq_queue_t*)&g_delayeddeallocations); + + /* Signal the worker thread that is has some clean up to do */ + +#ifdef CONFIG_SCHED_WORKQUEUE + work_signal(); +#endif irqrestore(saved_state); } else diff --git a/nuttx/sched/sched_garbage.c b/nuttx/sched/sched_garbage.c new file mode 100755 index 000000000..6dc1a5c88 --- /dev/null +++ b/nuttx/sched/sched_garbage.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * sched/work_garbage.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <nuttx/config.h> +#include <sys/types.h> + +#include <stdlib.h> + +#include <nuttx/mm.h> + +#include "os_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: sched_garbagecollection + * + * Description: + * Clean-up memory de-allocations that we queued because they could not + * be freed in that execution context (for example, if the memory was freed + * from an interrupt handler). + * + * This logic may be called from the worker thread (see work_thread.c). + * If, however, CONFIG_SCHED_WORKQUEUE is not defined, then this logic will + * be called from the IDLE thread. It is less optimal for the garbage + * collection to be called from the IDLE thread because it runs at a very + * low priority and could cause false memory out conditions. + * + * Input parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void sched_garbagecollection(void) +{ + /* Check if there is anything in the delayed deallocation list. If there + * is deallocate it now. We must have exclusive access to the memory manager + * to do this BUT the idle task cannot wait on a semaphore. So we only do + * the cleanup now if we can get the semaphore -- and this should be possible + * because if the IDLE thread is running, no other task is! + */ + +#ifdef CONFIG_SCHED_WORKQUEUE + mm_takesemaphore(); +#else + if (mm_trysemaphore() == 0) +#endif + { + while (g_delayeddeallocations.head) + { + /* Remove the first delayed deallocation. */ + + irqstate_t saved_state = irqsave(); + void *address = (void*)sq_remfirst((FAR sq_queue_t*)&g_delayeddeallocations); + irqrestore(saved_state); + + /* Then deallocate it */ + + if (address) + { + free(address); + } + } + mm_givesemaphore(); + } +} + diff --git a/nuttx/sched/work_internal.h b/nuttx/sched/work_internal.h index e86ee0ac2..93ad57271 100755 --- a/nuttx/sched/work_internal.h +++ b/nuttx/sched/work_internal.h @@ -50,6 +50,20 @@ * Pre-Processor Definitions ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_SCHED_WORKPRIORITY +# define CONFIG_SCHED_WORKPRIORITY 50 +#endif + +#ifndef CONFIG_SCHED_WORKPERIODUS +# define CONFIG_SCHED_WORKPERIOD (50*1000) /* 50 milliseconds */ +#endif + +#ifndef CONFIG_SCHED_WORKSTACKSIZE +# define CONFIG_SCHED_WORKSTACKSIZE CONFIG_IDLETHREAD_STACKSIZE +#endif + /**************************************************************************** * Public Types ****************************************************************************/ @@ -68,6 +82,24 @@ extern struct dq_queue_s g_work; * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: work_thread + * + * Description: + * This is the main worker thread that performs actions placed on the work + * queue. It also performs periodic garbage collection (that is performed + * by the idle thread if CONFIG_SCHED_WORKQUEUE is not defined). + * + * Input parameters: + * argc, argv (not used) + * + * Returned Value: + * Does not return + * + ****************************************************************************/ + +extern int work_thread(int argc, char *argv[]); + #endif /* __ASSEMBLY__ */ #endif /* CONFIG_SCHED_WORKQUEUE */ #endif /* __SCHED_WORK_INTERNAL_H */ diff --git a/nuttx/sched/work_queue.c b/nuttx/sched/work_queue.c index 9e8c44e52..46afdc1d8 100755 --- a/nuttx/sched/work_queue.c +++ b/nuttx/sched/work_queue.c @@ -117,6 +117,7 @@ int work_queue(struct work_s *work, worker_t worker, FAR void *arg, uint32 delay flags = irqsave(); work->qtime = g_system_timer; /* Time work queued */ dq_addlast((FAR dq_entry_t *)work, &g_work); + work_signal(); /* Wake up the worker thread */ irqrestore(flags); return OK; } diff --git a/nuttx/sched/work_thread.c b/nuttx/sched/work_thread.c new file mode 100755 index 000000000..4df29dd01 --- /dev/null +++ b/nuttx/sched/work_thread.c @@ -0,0 +1,166 @@ +/**************************************************************************** + * sched/work_thread.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <nuttx/config.h> +#include <sys/types.h> + +#include <unistd.h> +#include <queue.h> +#include <assert.h> +#include <errno.h> +#include <debug.h> + +#include <nuttx/arch.h> +#include <nuttx/wqueue.h> +#include <nuttx/clock.h> + +#include "os_internal.h" +#include "work_internal.h" + +#ifdef CONFIG_SCHED_WORKQUEUE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* The queue of pending work */ + +struct dq_queue_s g_work; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: work_thread + * + * Description: + * This is the main worker thread that performs actions placed on the work + * list. It also performs periodic garbage collection (that is performed + * by the idle thread if CONFIG_SCHED_WORKQUEUE is not defined). + * + * Input parameters: + * argc, argv (not used) + * + * Returned Value: + * Does not return + * + ****************************************************************************/ + +int work_thread(int argc, char *argv[]) +{ + volatile FAR struct work_s *work; + irqstate_t flags; + + /* Loop forever */ + + for (;;) + { + /* Wait awhile to check the work list. We will wait here until either + * the time elapses or until we are awakened by a signal. + */ + + usleep(CONFIG_SCHED_WORKPERIOD); + + /* First, clean-up any delayed memory deallocations */ + + sched_garbagecollection(); + + /* Then process queued work. We need to keep interrupts disabled while + * we process items in the work list. + */ + + flags = irqsave(); + work = (FAR struct work_s *)g_work.head; + while (work) + { + /* Is this work ready? It is ready if there is no delay or if + * the delay has elapsed. + */ + + if (work->delay == 0 || g_system_timer - work->qtime > work->delay) + { + /* Remove the work at the head of the list. And re-enable + * interrupts while the work is performed. + */ + + (void)dq_remfirst(&g_work); + + /* Do the work. Re-enable interrupts while the work is being + * performed... we don't have any idea how long that will take + */ + + irqrestore(flags); + work->worker(work->arg); + + /* Now, unfortunately, since we re-enabled interrupts we have + * to start back at the head of the list. + */ + + flags = irqsave(); + work = (FAR struct work_s *)g_work.head; + } + else + { + /* This one is not ready, try the next in the list. */ + + work = (FAR struct work_s *)work->dq.flink; + } + } + irqrestore(flags); + } + + return OK; /* To keep some compilers happy */ +} +#endif /* CONFIG_SCHED_WORKQUEUE */ |