Add support for multiple work queues
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5081 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
6105b42d39
commit
561bea0899
@ -3250,3 +3250,5 @@
|
||||
* sched/work_cancel.c: Fix a bad assertion (reported by Mike Smith)
|
||||
* configs/stm3210e-eval/src/up_idle.c: Correct some power management
|
||||
compilation errors (reported by Diego Sanchez).
|
||||
* include/nuttx/wqueue.h, sched/work*, and others: Added logic to support
|
||||
a second, lower priority work queue (CONFIG_SCHED_LPWORK).
|
||||
|
@ -4068,6 +4068,20 @@ build
|
||||
<code>CONFIG_SIG_SIGWORK</code>: The signal number that will be used to wake-up
|
||||
the worker thread. Default: 4
|
||||
</li>
|
||||
<li>
|
||||
<code>CONFIG_SCHED_LPWORK</code>: If CONFIG_SCHED_WORKQUEUE</code> is defined, then a single work queue is created by default.
|
||||
If <code>CONFIG_SCHED_LPWORK</code> is also defined then an additional, lower-priority work queue will also be created.
|
||||
This lower priority work queue is better suited for more extended processing (such as file system clean-up operations)
|
||||
</li>
|
||||
<li>
|
||||
<code>CONFIG_SCHED_LPWORKPRIORITY</code>: The execution priority of the lower priority worker thread. Default: 50
|
||||
</li>
|
||||
<li>
|
||||
<code>CONFIG_SCHED_LPWORKPERIOD</code>: How often the lower priority worker thread checks for work in units of microseconds. Default: 50*1000 (50 MS).
|
||||
</li>
|
||||
<li>
|
||||
<code>CONFIG_SCHED_LPWORKSTACKSIZE - The stack size allocated for the lower priority worker thread. Default: CONFIG_IDLETHREAD_STACKSIZE.
|
||||
</li>
|
||||
<li>
|
||||
<code>CONFIG_SCHED_WAITPID</code>: Enables the <a href="NuttxUserGuide.html#waitpid"><code>waitpid()</code><a> API
|
||||
</li>
|
||||
|
@ -1,8 +1,8 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/kinetis/kinetis_sdhc.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -2733,7 +2733,7 @@ static void kinetis_callback(void *arg)
|
||||
/* Yes.. queue it */
|
||||
|
||||
fvdbg("Queuing callback to %p(%p)\n", priv->callback, priv->cbarg);
|
||||
(void)work_queue(&priv->cbwork, (worker_t)priv->callback, priv->cbarg, 0);
|
||||
(void)work_queue(HPWORK, &priv->cbwork, (worker_t)priv->callback, priv->cbarg, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,8 +1,8 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/sam3u/sam3u_sdio.c
|
||||
*
|
||||
* Copyright (C) 2010 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2010, 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -2343,7 +2343,7 @@ static void sam3u_callback(void *arg)
|
||||
/* Yes.. queue it */
|
||||
|
||||
fvdbg("Queuing callback to %p(%p)\n", priv->callback, priv->cbarg);
|
||||
(void)work_queue(&priv->cbwork, (worker_t)priv->callback, priv->cbarg, 0);
|
||||
(void)work_queue(HPWORK, &priv->cbwork, (worker_t)priv->callback, priv->cbarg, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2660,7 +2660,7 @@ static void stm32_callback(void *arg)
|
||||
/* Yes.. queue it */
|
||||
|
||||
fvdbg("Queuing callback to %p(%p)\n", priv->callback, priv->cbarg);
|
||||
(void)work_queue(&priv->cbwork, (worker_t)priv->callback, priv->cbarg, 0);
|
||||
(void)work_queue(HPWORK, &priv->cbwork, (worker_t)priv->callback, priv->cbarg, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -361,13 +361,24 @@ defconfig -- This is a configuration file similar to the Linux
|
||||
if memory reclamation is of high priority). If CONFIG_SCHED_WORKQUEUE
|
||||
is enabled, then the following options can also be used:
|
||||
CONFIG_SCHED_WORKPRIORITY - The execution priority of the worker
|
||||
thread. Default: 50
|
||||
thread. Default: 192
|
||||
CONFIG_SCHED_WORKPERIOD - How often the worker thread checks for
|
||||
work in units of microseconds. Default: 50*1000 (50 MS).
|
||||
CONFIG_SCHED_WORKSTACKSIZE - The stack size allocated for the worker
|
||||
thread. Default: CONFIG_IDLETHREAD_STACKSIZE.
|
||||
CONFIG_SIG_SIGWORK - The signal number that will be used to wake-up
|
||||
the worker thread. Default: 4
|
||||
CONFIG_SCHED_LPWORK. If CONFIG_SCHED_WORKQUEUE is defined, then a single
|
||||
work queue is created by default. If CONFIG_SCHED_LPWORK is also defined
|
||||
then an additional, lower-priority work queue will also be created. This
|
||||
lower priority work queue is better suited for more extended processing
|
||||
(such as file system clean-up operations)
|
||||
CONFIG_SCHED_LPWORKPRIORITY - The execution priority of the lower priority
|
||||
worker thread. Default: 50
|
||||
CONFIG_SCHED_LPWORKPERIOD - How often the lower priority worker thread
|
||||
checks for work in units of microseconds. Default: 50*1000 (50 MS).
|
||||
CONFIG_SCHED_LPWORKSTACKSIZE - The stack size allocated for the lower
|
||||
priority worker thread. Default: CONFIG_IDLETHREAD_STACKSIZE.
|
||||
CONFIG_SCHED_WAITPID - Enables the waitpid() API
|
||||
CONFIG_SCHED_ATEXIT - Enables the atexit() API
|
||||
CONFIG_SCHED_ATEXIT_MAX - By default if CONFIG_SCHED_ATEXIT is
|
||||
|
@ -972,7 +972,7 @@ static void tc_worker(FAR void *arg)
|
||||
|
||||
/* Set up the next sample event */
|
||||
|
||||
ret = work_queue(&priv->work, tc_worker, priv, delay);
|
||||
ret = work_queue(HPWORK, &priv->work, tc_worker, priv, delay);
|
||||
ASSERT(ret == 0);
|
||||
}
|
||||
|
||||
@ -1420,7 +1420,7 @@ int arch_tcinitialize(int minor)
|
||||
*/
|
||||
|
||||
priv->state = TC_READY;
|
||||
ret = work_queue(&priv->work, tc_worker, priv, 0);
|
||||
ret = work_queue(HPWORK, &priv->work, tc_worker, priv, 0);
|
||||
if (ret != 0)
|
||||
{
|
||||
idbg("Failed to queue work: %d\n", ret);
|
||||
|
@ -521,7 +521,7 @@ static int ads7843e_schedule(FAR struct ads7843e_dev_s *priv)
|
||||
*/
|
||||
|
||||
DEBUGASSERT(priv->work.worker == NULL);
|
||||
ret = work_queue(&priv->work, ads7843e_worker, priv, 0);
|
||||
ret = work_queue(HPWORK, &priv->work, ads7843e_worker, priv, 0);
|
||||
if (ret != 0)
|
||||
{
|
||||
illdbg("Failed to queue work: %d\n", ret);
|
||||
@ -1179,7 +1179,7 @@ int ads7843e_register(FAR struct spi_dev_s *dev,
|
||||
* availability conditions.
|
||||
*/
|
||||
|
||||
ret = work_queue(&priv->work, ads7843e_worker, priv, 0);
|
||||
ret = work_queue(HPWORK, &priv->work, ads7843e_worker, priv, 0);
|
||||
if (ret != 0)
|
||||
{
|
||||
idbg("Failed to queue work: %d\n", ret);
|
||||
|
@ -195,7 +195,7 @@ static int stmpe811_interrupt(int irq, FAR void *context)
|
||||
* action should be required to protect the work queue.
|
||||
*/
|
||||
|
||||
ret = work_queue(&priv->work, stmpe811_worker, priv, 0);
|
||||
ret = work_queue(HPWORK, &priv->work, stmpe811_worker, priv, 0);
|
||||
if (ret != 0)
|
||||
{
|
||||
illdbg("Failed to queue work: %d\n", ret);
|
||||
|
@ -783,7 +783,7 @@ static void stmpe811_timeout(int argc, uint32_t arg1, ...)
|
||||
* action should be required to protect the work queue.
|
||||
*/
|
||||
|
||||
ret = work_queue(&priv->timeout, stmpe811_timeoutworker, priv, 0);
|
||||
ret = work_queue(HPWORK, &priv->timeout, stmpe811_timeoutworker, priv, 0);
|
||||
if (ret != 0)
|
||||
{
|
||||
illdbg("Failed to queue work: %d\n", ret);
|
||||
|
@ -775,7 +775,7 @@ static int tsc2007_interrupt(int irq, FAR void *context)
|
||||
*/
|
||||
|
||||
DEBUGASSERT(priv->work.worker == NULL);
|
||||
ret = work_queue(&priv->work, tsc2007_worker, priv, 0);
|
||||
ret = work_queue(HPWORK, &priv->work, tsc2007_worker, priv, 0);
|
||||
if (ret != 0)
|
||||
{
|
||||
illdbg("Failed to queue work: %d\n", ret);
|
||||
@ -1316,7 +1316,7 @@ int tsc2007_register(FAR struct i2c_dev_s *dev,
|
||||
* availability conditions.
|
||||
*/
|
||||
|
||||
ret = work_queue(&priv->work, tsc2007_worker, priv, 0);
|
||||
ret = work_queue(HPWORK, &priv->work, tsc2007_worker, priv, 0);
|
||||
if (ret != 0)
|
||||
{
|
||||
idbg("Failed to queue work: %d\n", ret);
|
||||
|
@ -1509,7 +1509,7 @@ static int enc_interrupt(int irq, FAR void *context)
|
||||
* a good thing to do in any event.
|
||||
*/
|
||||
|
||||
return work_queue(&priv->work, enc_worker, (FAR void *)priv, 0);
|
||||
return work_queue(HPWORK, &priv->work, enc_worker, (FAR void *)priv, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -328,7 +328,7 @@ void pm_update(int16_t accum)
|
||||
/* The work will be performed on the worker thread */
|
||||
|
||||
DEBUGASSERT(g_pmglobals.work.worker == NULL);
|
||||
(void)work_queue(&g_pmglobals.work, pm_worker, (FAR void*)((intptr_t)accum), 0);
|
||||
(void)work_queue(HPWORK, &g_pmglobals.work, pm_worker, (FAR void*)((intptr_t)accum), 0);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
#endif /* CONFIG_PM */
|
||||
|
@ -213,7 +213,7 @@ static void rwb_wrstarttimeout(FAR struct rwbuffer_s *rwb)
|
||||
*/
|
||||
|
||||
int ticks = (CONFIG_FS_WRDELAY + CLK_TCK/2) / CLK_TCK;
|
||||
(void)work_queue(&rwb->work, rwb_wrtimeout, (FAR void *)rwb, ticks);
|
||||
(void)work_queue(LPWORK, &rwb->work, rwb_wrtimeout, (FAR void *)rwb, ticks);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -222,7 +222,7 @@ static void rwb_wrstarttimeout(FAR struct rwbuffer_s *rwb)
|
||||
|
||||
static inline void rwb_wrcanceltimeout(struct rwbuffer_s *rwb)
|
||||
{
|
||||
(void)work_cancel(&rwb->work);
|
||||
(void)work_cancel(LPWORK, &rwb->work);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -1674,7 +1674,7 @@ static int usbhost_disconnected(struct usbhost_class_s *class)
|
||||
*/
|
||||
|
||||
DEBUGASSERT(priv->work.worker == NULL);
|
||||
(void)work_queue(&priv->work, usbhost_destroy, priv, 0);
|
||||
(void)work_queue(HPWORK, &priv->work, usbhost_destroy, priv, 0);
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
@ -1,8 +1,8 @@
|
||||
/****************************************************************************
|
||||
* drivers/usbhost/usbhost_skeleton.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -1015,7 +1015,7 @@ static int usbhost_disconnected(struct usbhost_class_s *class)
|
||||
|
||||
uvdbg("Queuing destruction: worker %p->%p\n", priv->work.worker, usbhost_destroy);
|
||||
DEBUGASSERT(priv->work.worker == NULL);
|
||||
(void)work_queue(&priv->work, usbhost_destroy, priv, 0);
|
||||
(void)work_queue(HPWORK, &priv->work, usbhost_destroy, priv, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1786,7 +1786,7 @@ static int usbhost_disconnected(struct usbhost_class_s *class)
|
||||
|
||||
uvdbg("Queuing destruction: worker %p->%p\n", priv->work.worker, usbhost_destroy);
|
||||
DEBUGASSERT(priv->work.worker == NULL);
|
||||
(void)work_queue(&priv->work, usbhost_destroy, priv, 0);
|
||||
(void)work_queue(HPWORK, &priv->work, usbhost_destroy, priv, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -50,6 +50,75 @@
|
||||
/****************************************************************************
|
||||
* Pre-Processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* CONFIG_SCHED_WORKQUEUE. Create a dedicated "worker" thread to
|
||||
* handle delayed processing from interrupt handlers. This feature
|
||||
* is required for some drivers but, if there are not complaints,
|
||||
* can be safely disabled. The worker thread also performs
|
||||
* garbage collection -- completing any delayed memory deallocations
|
||||
* from interrupt handlers. If the worker thread is disabled,
|
||||
* then that clean will be performed by the IDLE thread instead
|
||||
* (which runs at the lowest of priority and may not be appropriate
|
||||
* if memory reclamation is of high priority). If CONFIG_SCHED_WORKQUEUE
|
||||
* is enabled, then the following options can also be used:
|
||||
* CONFIG_SCHED_WORKPRIORITY - The execution priority of the worker
|
||||
* thread. Default: 192
|
||||
* CONFIG_SCHED_WORKPERIOD - How often the worker thread checks for
|
||||
* work in units of microseconds. Default: 50*1000 (50 MS).
|
||||
* CONFIG_SCHED_WORKSTACKSIZE - The stack size allocated for the worker
|
||||
* thread. Default: CONFIG_IDLETHREAD_STACKSIZE.
|
||||
* CONFIG_SIG_SIGWORK - The signal number that will be used to wake-up
|
||||
* the worker thread. Default: 4
|
||||
*
|
||||
* CONFIG_SCHED_LPWORK. If CONFIG_SCHED_WORKQUEUE is defined, then a single
|
||||
* work queue is created by default. If CONFIG_SCHED_LPWORK is also defined
|
||||
* then an additional, lower-priority work queue will also be created. This
|
||||
* lower priority work queue is better suited for more extended processing
|
||||
* (such as file system clean-up operations)
|
||||
* CONFIG_SCHED_LPWORKPRIORITY - The execution priority of the lower priority
|
||||
* worker thread. Default: 50
|
||||
* CONFIG_SCHED_LPWORKPERIOD - How often the lower priority worker thread
|
||||
* checks for work in units of microseconds. Default: 50*1000 (50 MS).
|
||||
* CONFIG_SCHED_LPWORKSTACKSIZE - The stack size allocated for the lower
|
||||
* priority worker thread. Default: CONFIG_IDLETHREAD_STACKSIZE.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_SCHED_WORKPRIORITY
|
||||
# define CONFIG_SCHED_WORKPRIORITY 192
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SCHED_WORKPERIOD
|
||||
# define CONFIG_SCHED_WORKPERIOD (50*1000) /* 50 milliseconds */
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SCHED_WORKSTACKSIZE
|
||||
# define CONFIG_SCHED_WORKSTACKSIZE CONFIG_IDLETHREAD_STACKSIZE
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_LPWORK
|
||||
# ifndef CONFIG_SCHED_LPWORKPRIORITY
|
||||
# define CONFIG_SCHED_LPWORKPRIORITY 50
|
||||
# endif
|
||||
|
||||
# ifndef CONFIG_SCHED_LPWORKPERIOD
|
||||
# define CONFIG_SCHED_LPWORKPERIOD (50*1000) /* 50 milliseconds */
|
||||
# endif
|
||||
|
||||
# ifndef CONFIG_SCHED_LPWORKSTACKSIZE
|
||||
# define CONFIG_SCHED_LPWORKSTACKSIZE CONFIG_IDLETHREAD_STACKSIZE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Work queue IDs (indices). These are both zero if there is only one work
|
||||
* queue.
|
||||
*/
|
||||
|
||||
#define HPWORK 0
|
||||
#ifdef CONFIG_SCHED_LPWORK
|
||||
# define LPWORK 1
|
||||
#else
|
||||
# define LPWORK HPWORK
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
@ -86,10 +155,6 @@ extern "C" {
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/* The task ID of the worker thread */
|
||||
|
||||
EXTERN pid_t g_worker;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
@ -109,6 +174,7 @@ EXTERN pid_t g_worker;
|
||||
* and remove it from the work queue.
|
||||
*
|
||||
* Input parameters:
|
||||
* qid - The work queue ID
|
||||
* work - The work structure to queue
|
||||
* worker - The worker callback to be invoked. The callback will invoked
|
||||
* on the worker thread of execution.
|
||||
@ -122,7 +188,8 @@ EXTERN pid_t g_worker;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN int work_queue(struct work_s *work, worker_t worker, FAR void *arg, uint32_t delay);
|
||||
EXTERN int work_queue(int qid, FAR struct work_s *work, worker_t worker,
|
||||
FAR void *arg, uint32_t delay);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: work_cancel
|
||||
@ -133,6 +200,7 @@ EXTERN int work_queue(struct work_s *work, worker_t worker, FAR void *arg, uint3
|
||||
* again.
|
||||
*
|
||||
* Input parameters:
|
||||
* qid - The work queue ID
|
||||
* work - The previously queue work structure to cancel
|
||||
*
|
||||
* Returned Value:
|
||||
@ -140,7 +208,7 @@ EXTERN int work_queue(struct work_s *work, worker_t worker, FAR void *arg, uint3
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN int work_cancel(struct work_s *work);
|
||||
EXTERN int work_cancel(int qid, FAR struct work_s *work);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: work_signal
|
||||
@ -151,14 +219,14 @@ EXTERN int work_cancel(struct work_s *work);
|
||||
* user to force an immediate re-assessment of pending work.
|
||||
*
|
||||
* Input parameters:
|
||||
* None
|
||||
* qid - The work queue ID
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success, a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define work_signal() kill(g_worker, SIGWORK)
|
||||
EXTERN int work_signal(int qid);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: work_available
|
||||
|
@ -166,6 +166,39 @@ config SIG_SIGWORK
|
||||
The signal number that will be used to wake-up the worker thread.
|
||||
Default: 4
|
||||
|
||||
config SCHED_LPWORK
|
||||
bool "Enable a lower priority worker thread"
|
||||
default n
|
||||
depends on SCHED_WORKQUEUE
|
||||
---help---
|
||||
If SCHED_WORKQUEUE is defined, then a single work queue is created by
|
||||
default. If SCHED_LPWORK is also defined then an additional, lower-
|
||||
priority work queue will also be created. This lower priority work
|
||||
queue is better suited for more extended processing (such as file system
|
||||
clean-up operations)
|
||||
|
||||
config SCHED_LPWORKPRIORITY
|
||||
int "Lower priority worker thread priority"
|
||||
default 192
|
||||
depends on SCHED_LPWORK
|
||||
---help---
|
||||
The execution priority of the lopwer priority worker thread. Default: 192
|
||||
|
||||
config SCHED_LPWORKPERIOD
|
||||
int "Lower priority worker thread period"
|
||||
default 50000
|
||||
depends on SCHED_LPWORK
|
||||
---help---
|
||||
How often the lower priority worker thread checks for work in units
|
||||
of microseconds. Default: 50*1000 (50 MS).
|
||||
|
||||
config SCHED_LPWORKSTACKSIZE
|
||||
int "Lower priority worker thread stack size"
|
||||
default 2048
|
||||
depends on SCHED_LPWORK
|
||||
---help---
|
||||
The stack size allocated for the lower priority worker thread. Default: 2K.
|
||||
|
||||
config SCHED_WAITPID
|
||||
bool "Enable waitpid() API"
|
||||
default n
|
||||
|
@ -141,7 +141,7 @@ TIMER_SRCS = timer_initialize.c timer_create.c timer_delete.c timer_getoverrun.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SCHED_WORKQUEUE),y)
|
||||
WORK_SRCS = work_thread.c work_queue.c work_cancel.c
|
||||
WORK_SRCS = work_thread.c work_queue.c work_cancel.c work_signal.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PAGING),y)
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* sched/os_bringup.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* With extensions by:
|
||||
@ -47,6 +47,7 @@
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/init.h>
|
||||
#include <nuttx/wqueue.h>
|
||||
|
||||
#include "os_internal.h"
|
||||
#ifdef CONFIG_PAGING
|
||||
@ -149,10 +150,23 @@ int os_bringup(void)
|
||||
#ifdef CONFIG_SCHED_WORKQUEUE
|
||||
svdbg("Starting worker thread\n");
|
||||
|
||||
g_worker = KERNEL_THREAD("work", CONFIG_SCHED_WORKPRIORITY,
|
||||
CONFIG_SCHED_WORKSTACKSIZE,
|
||||
(main_t)work_thread, (const char **)NULL);
|
||||
ASSERT(g_worker != ERROR);
|
||||
g_work[HPWORK].pid = KERNEL_THREAD("work0", CONFIG_SCHED_WORKPRIORITY,
|
||||
CONFIG_SCHED_WORKSTACKSIZE,
|
||||
(main_t)work_hpthread, (const char **)NULL);
|
||||
ASSERT(g_work[HPWORK].pid != ERROR);
|
||||
|
||||
/* Start a lower priority worker thread for other, non-critical continuation
|
||||
* tasks
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SCHED_LPWORK
|
||||
svdbg("Starting worker thread\n");
|
||||
|
||||
g_work[LPWORK].pid = KERNEL_THREAD("work1", CONFIG_SCHED_LPWORKPRIORITY,
|
||||
CONFIG_SCHED_LPWORKSTACKSIZE,
|
||||
(main_t)work_lpthread, (const char **)NULL);
|
||||
ASSERT(g_work[LPWORK].pid != ERROR);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Once the operating system has been initialized, the system must be
|
||||
|
@ -1,7 +1,7 @@
|
||||
/************************************************************************
|
||||
* sched/sched_free.c
|
||||
*
|
||||
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -99,7 +99,7 @@ void sched_free(FAR void *address)
|
||||
/* Signal the worker thread that is has some clean up to do */
|
||||
|
||||
#ifdef CONFIG_SCHED_WORKQUEUE
|
||||
work_signal();
|
||||
work_signal(LPWORK);
|
||||
#endif
|
||||
irqrestore(saved_state);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* sched/work_cancel.c
|
||||
*
|
||||
* Copyright (C) 2009-2010 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2009-2010, 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -74,6 +74,7 @@
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: work_cancel
|
||||
*
|
||||
@ -83,6 +84,7 @@
|
||||
* again.
|
||||
*
|
||||
* Input parameters:
|
||||
* qid - The work queue ID
|
||||
* work - The previously queue work structure to cancel
|
||||
*
|
||||
* Returned Value:
|
||||
@ -90,11 +92,12 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int work_cancel(struct work_s *work)
|
||||
int work_cancel(int qid, FAR struct work_s *work)
|
||||
{
|
||||
FAR struct wqueue_s *wqueue = &g_work[qid];
|
||||
irqstate_t flags;
|
||||
|
||||
DEBUGASSERT(work != NULL);
|
||||
DEBUGASSERT(work != NULL && (unsigned)qid < NWORKERS);
|
||||
|
||||
/* Cancelling the work is simply a matter of removing the work structure
|
||||
* from the work queue. This must be done with interrupts disabled because
|
||||
@ -106,18 +109,19 @@ int work_cancel(struct work_s *work)
|
||||
{
|
||||
/* A little test of the integrity of the work queue */
|
||||
|
||||
DEBUGASSERT(work->dq.flink ||(FAR dq_entry_t *)work == g_work.tail);
|
||||
DEBUGASSERT(work->dq.blink ||(FAR dq_entry_t *)work == g_work.head);
|
||||
DEBUGASSERT(work->dq.flink ||(FAR dq_entry_t *)work == wqueue->q.tail);
|
||||
DEBUGASSERT(work->dq.blink ||(FAR dq_entry_t *)work == wqueue->q.head);
|
||||
|
||||
/* Remove the entry from the work queue and make sure that it is
|
||||
* mark as availalbe (i.e., the worker field is nullified).
|
||||
*/
|
||||
|
||||
dq_rem((FAR dq_entry_t *)work, &g_work);
|
||||
dq_rem((FAR dq_entry_t *)work, &wqueue->q);
|
||||
work->worker = NULL;
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SCHED_WORKQUEUE */
|
||||
|
@ -51,51 +51,49 @@
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
#ifndef CONFIG_SCHED_WORKPRIORITY
|
||||
# define CONFIG_SCHED_WORKPRIORITY 50
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SCHED_WORKPERIOD
|
||||
# define CONFIG_SCHED_WORKPERIOD (50*1000) /* 50 milliseconds */
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SCHED_WORKSTACKSIZE
|
||||
# define CONFIG_SCHED_WORKSTACKSIZE CONFIG_IDLETHREAD_STACKSIZE
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DISABLE_SIGNALS
|
||||
# warning "Worker thread support requires signals"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_LPWORK
|
||||
# define NWORKERS 2
|
||||
#else
|
||||
# define NWORKERS 1
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* This structure defines the state on one work queue */
|
||||
|
||||
struct wqueue_s
|
||||
{
|
||||
pid_t pid; /* The task ID of the worker thread */
|
||||
struct dq_queue_s q; /* The queue of pending work */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/* The queue of pending work */
|
||||
/* The state of each work queue */
|
||||
|
||||
extern struct dq_queue_s g_work;
|
||||
|
||||
/* The task ID of the worker thread */
|
||||
|
||||
extern pid_t g_worker;
|
||||
extern struct wqueue_s g_work[NWORKERS];
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: work_thread
|
||||
* Name: work_hpthread and work_lpthread
|
||||
*
|
||||
* 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).
|
||||
* These are the main worker threads that performs actions placed on the
|
||||
* work lists. One thread 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)
|
||||
@ -105,7 +103,11 @@ extern pid_t g_worker;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int work_thread(int argc, char *argv[]);
|
||||
int work_hpthread(int argc, char *argv[]);
|
||||
|
||||
#ifdef CONFIG_SCHED_LPWORK
|
||||
int work_lpthread(int argc, char *argv[]);
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* CONFIG_SCHED_WORKQUEUE */
|
||||
|
@ -76,6 +76,7 @@
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: work_queue
|
||||
*
|
||||
@ -91,6 +92,7 @@
|
||||
* and remove it from the work queue.
|
||||
*
|
||||
* Input parameters:
|
||||
* qid - The work queue ID (index)
|
||||
* work - The work structure to queue
|
||||
* worker - The worker callback to be invoked. The callback will invoked
|
||||
* on the worker thread of execution.
|
||||
@ -104,11 +106,13 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int work_queue(struct work_s *work, worker_t worker, FAR void *arg, uint32_t delay)
|
||||
int work_queue(int qid, FAR struct work_s *work, worker_t worker,
|
||||
FAR void *arg, uint32_t delay)
|
||||
{
|
||||
FAR struct wqueue_s *wqueue = &g_work[qid];
|
||||
irqstate_t flags;
|
||||
|
||||
DEBUGASSERT(work != NULL);
|
||||
DEBUGASSERT(work != NULL && (unsigned)qid < NWORKERS);
|
||||
|
||||
/* First, initialize the work structure */
|
||||
|
||||
@ -123,8 +127,10 @@ int work_queue(struct work_s *work, worker_t worker, FAR void *arg, uint32_t del
|
||||
|
||||
flags = irqsave();
|
||||
work->qtime = clock_systimer(); /* Time work queued */
|
||||
dq_addlast((FAR dq_entry_t *)work, &g_work);
|
||||
work_signal(); /* Wake up the worker thread */
|
||||
|
||||
dq_addlast((FAR dq_entry_t *)work, &wqueue->q);
|
||||
kill(wqueue->pid, SIGWORK); /* Wake up the worker thread */
|
||||
|
||||
irqrestore(flags);
|
||||
return OK;
|
||||
}
|
||||
|
96
sched/work_signal.c
Normal file
96
sched/work_signal.c
Normal file
@ -0,0 +1,96 @@
|
||||
/****************************************************************************
|
||||
* sched/work_signal.c
|
||||
*
|
||||
* Copyright (C) 2009-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* 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 <signal.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/wqueue.h>
|
||||
|
||||
#include "work_internal.h"
|
||||
|
||||
#ifdef CONFIG_SCHED_WORKQUEUE
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Declarations
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
* Name: work_signal
|
||||
*
|
||||
* Description:
|
||||
* Signal the worker thread to process the work queue now. This function
|
||||
* is used internally by the work logic but could also be used by the
|
||||
* user to force an immediate re-assessment of pending work.
|
||||
*
|
||||
* Input parameters:
|
||||
* qid - The work queue ID
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success, a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int work_signal(int qid)
|
||||
{
|
||||
DEBUGASSERT((unsigned)qid < NWORKERS);
|
||||
return kill(g_work[qid].pid, SIGWORK);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SCHED_WORKQUEUE */
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* sched/work_thread.c
|
||||
*
|
||||
* Copyright (C) 2009-2011 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2009-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -67,15 +67,9 @@
|
||||
* Public Variables
|
||||
****************************************************************************/
|
||||
|
||||
/* The queue of pending work */
|
||||
/* The state of each work queue */
|
||||
|
||||
struct dq_queue_s g_work;
|
||||
|
||||
/* The task ID of the worker thread */
|
||||
|
||||
#ifdef CONFIG_SCHED_WORKQUEUE
|
||||
pid_t g_worker;
|
||||
#endif
|
||||
struct wqueue_s g_work[NWORKERS];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Variables
|
||||
@ -85,16 +79,116 @@ pid_t g_worker;
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: work_process
|
||||
*
|
||||
* Description:
|
||||
* This is the logic that performs actions placed on any work list.
|
||||
*
|
||||
* Input parameters:
|
||||
* wqueue - Describes the work queue to be processed
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void work_process(FAR struct wqueue_s *wqueue)
|
||||
{
|
||||
volatile FAR struct work_s *work;
|
||||
worker_t worker;
|
||||
irqstate_t flags;
|
||||
FAR void *arg;
|
||||
uint32_t elapsed;
|
||||
uint32_t remaining;
|
||||
uint32_t next;
|
||||
|
||||
/* Then process queued work. We need to keep interrupts disabled while
|
||||
* we process items in the work list.
|
||||
*/
|
||||
|
||||
next = CONFIG_SCHED_WORKPERIOD / USEC_PER_TICK;
|
||||
flags = irqsave();
|
||||
work = (FAR struct work_s *)wqueue->q.head;
|
||||
while (work)
|
||||
{
|
||||
/* Is this work ready? It is ready if there is no delay or if
|
||||
* the delay has elapsed. qtime is the time that the work was added
|
||||
* to the work queue. It will always be greater than or equal to
|
||||
* zero. Therefore a delay of zero will always execute immediately.
|
||||
*/
|
||||
|
||||
elapsed = clock_systimer() - work->qtime;
|
||||
if (elapsed >= work->delay)
|
||||
{
|
||||
/* Remove the ready-to-execute work from the list */
|
||||
|
||||
(void)dq_rem((struct dq_entry_s *)work, &wqueue->q);
|
||||
|
||||
/* Extract the work description from the entry (in case the work
|
||||
* instance by the re-used after it has been de-queued).
|
||||
*/
|
||||
|
||||
worker = work->worker;
|
||||
arg = work->arg;
|
||||
|
||||
/* Mark the work as no longer being queued */
|
||||
|
||||
work->worker = NULL;
|
||||
|
||||
/* 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);
|
||||
worker(arg);
|
||||
|
||||
/* Now, unfortunately, since we re-enabled interrupts we don't
|
||||
* know the state of the work list and we will have to start
|
||||
* back at the head of the list.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
work = (FAR struct work_s *)wqueue->q.head;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This one is not ready.. will it be ready before the next
|
||||
* scheduled wakeup interval?
|
||||
*/
|
||||
|
||||
remaining = elapsed - work->delay;
|
||||
if (remaining < next)
|
||||
{
|
||||
/* Yes.. Then schedule to wake up when the work is ready */
|
||||
|
||||
next = remaining;
|
||||
}
|
||||
|
||||
/* Then try the next in the list. */
|
||||
|
||||
work = (FAR struct work_s *)work->dq.flink;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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(next * USEC_PER_TICK);
|
||||
irqrestore(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
* Name: work_thread
|
||||
* Name: work_hpthread and work_lpthread
|
||||
*
|
||||
* 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).
|
||||
* These are the main worker threads that performs actions placed on the
|
||||
* work lists. One thread 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)
|
||||
@ -104,30 +198,40 @@ pid_t g_worker;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int work_thread(int argc, char *argv[])
|
||||
int work_hpthread(int argc, char *argv[])
|
||||
{
|
||||
volatile FAR struct work_s *work;
|
||||
worker_t worker;
|
||||
FAR void *arg;
|
||||
uint32_t elapsed;
|
||||
uint32_t remaining;
|
||||
uint32_t next;
|
||||
int usec;
|
||||
irqstate_t flags;
|
||||
|
||||
/* Loop forever */
|
||||
|
||||
usec = CONFIG_SCHED_WORKPERIOD;
|
||||
flags = irqsave();
|
||||
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.
|
||||
/* First, perform garbage collection. This cleans-up memory de-allocations
|
||||
* that were queued because they could not be freed in that execution
|
||||
* context (for example, if the memory was freed from an interrupt handler).
|
||||
* NOTE: If the work thread is disabled, this clean-up is performed by
|
||||
* the IDLE thread (at a very, very lower priority).
|
||||
*/
|
||||
|
||||
usleep(usec);
|
||||
irqrestore(flags);
|
||||
#ifdef CONFIG_SCHED_LPWORK
|
||||
sched_garbagecollection();
|
||||
#endif
|
||||
|
||||
/* Then process queued work. We need to keep interrupts disabled while
|
||||
* we process items in the work list.
|
||||
*/
|
||||
|
||||
work_process(&g_work[HPWORK]);
|
||||
}
|
||||
|
||||
return OK; /* To keep some compilers happy */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_LPWORK
|
||||
int work_lpthread(int argc, char *argv[])
|
||||
{
|
||||
/* Loop forever */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* First, perform garbage collection. This cleans-up memory de-allocations
|
||||
* that were queued because they could not be freed in that execution
|
||||
* context (for example, if the memory was freed from an interrupt handler).
|
||||
@ -141,75 +245,12 @@ int work_thread(int argc, char *argv[])
|
||||
* we process items in the work list.
|
||||
*/
|
||||
|
||||
next = CONFIG_SCHED_WORKPERIOD / USEC_PER_TICK;
|
||||
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. qtime is the time that the work was added
|
||||
* to the work queue. It will always be greater than or equal to
|
||||
* zero. Therefore a delay of zero will always execute immediately.
|
||||
*/
|
||||
|
||||
elapsed = clock_systimer() - work->qtime;
|
||||
if (elapsed >= work->delay)
|
||||
{
|
||||
/* Remove the ready-to-execute work from the list */
|
||||
|
||||
(void)dq_rem((struct dq_entry_s *)work, &g_work);
|
||||
|
||||
/* Extract the work description from the entry (in case the work
|
||||
* instance by the re-used after it has been de-queued).
|
||||
*/
|
||||
|
||||
worker = work->worker;
|
||||
arg = work->arg;
|
||||
|
||||
/* Mark the work as no longer being queued */
|
||||
|
||||
work->worker = NULL;
|
||||
|
||||
/* 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);
|
||||
worker(arg);
|
||||
|
||||
/* Now, unfortunately, since we re-enabled interrupts we don't
|
||||
* know the state of the work list and we will 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.. will it be ready before the next
|
||||
* scheduled wakeup interval?
|
||||
*/
|
||||
|
||||
remaining = elapsed - work->delay;
|
||||
if (remaining < next)
|
||||
{
|
||||
/* Yes.. Then schedule to wake up when the work is ready */
|
||||
|
||||
next = remaining;
|
||||
}
|
||||
|
||||
/* Then try the next in the list. */
|
||||
|
||||
work = (FAR struct work_s *)work->dq.flink;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now calculate the microsecond delay we should wait */
|
||||
|
||||
usec = next * USEC_PER_TICK;
|
||||
work_process(&g_work[LPWORK]);
|
||||
}
|
||||
|
||||
return OK; /* To keep some compilers happy */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SCHED_LPWORK */
|
||||
|
||||
#endif /* CONFIG_SCHED_WORKQUEUE */
|
||||
|
@ -101,17 +101,17 @@ if [ ! -d "${configpath}" ]; then
|
||||
fi
|
||||
|
||||
if [ ! -r "${configpath}/Make.defs" ]; then
|
||||
echo "File ${configpath}/Make.defs does not exist"
|
||||
echo "File \"${configpath}/Make.defs\" does not exist"
|
||||
exit 4
|
||||
fi
|
||||
|
||||
if [ ! -r "${configpath}/setenv.sh" ]; then
|
||||
echo "File ${configpath}/setenv.sh does not exist"
|
||||
echo "File \"${configpath}/setenv.sh\" does not exist"
|
||||
exit 5
|
||||
fi
|
||||
|
||||
if [ ! -r "${configpath}/defconfig" ]; then
|
||||
echo "File ${configpath}/defconfig does not exist"
|
||||
echo "File \"${configpath}/defconfig\" does not exist"
|
||||
exit 6
|
||||
fi
|
||||
|
||||
@ -127,7 +127,7 @@ if [ -z "${appdir}" ]; then
|
||||
appdir=`grep CONFIG_APPS_DIR= "${configpath}/defconfig" | cut -d'=' -f2`
|
||||
fi
|
||||
|
||||
# Check for the apps/ dir in the usual place if appdir was not provided
|
||||
# Check for the apps/ directory in the usual place if appdir was not provided
|
||||
|
||||
if [ -z "${appdir}" ]; then
|
||||
|
||||
@ -152,7 +152,15 @@ if [ -z "${appdir}" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Okay... setup the configuration
|
||||
# If appsdir was provided (or discovered) then make sure that the apps/
|
||||
# directory exists
|
||||
|
||||
if [ ! -z "${appdir}" -a ! -d "${TOPDIR}/${appdir}" ]; then
|
||||
echo "Directory \"${TOPDIR}/${appdir}\" does not exist"
|
||||
exit 7
|
||||
fi
|
||||
|
||||
# Okay... Everything looks good. Setup the configuration
|
||||
|
||||
install -C "${configpath}/Make.defs" "${TOPDIR}/." || \
|
||||
{ echo "Failed to copy ${configpath}/Make.defs" ; exit 7 ; }
|
||||
|
Loading…
Reference in New Issue
Block a user