summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2010-08-15 16:50:25 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2010-08-15 16:50:25 +0000
commite29947db6aba1a4797b093b64548e40ad14d12b0 (patch)
treebf022bdca59370edf1dae8d42e3c4a86be392e74 /nuttx
parentaa8fe0d6cf94a297fd0e7c8a6ab1ddb315fda57e (diff)
downloadpx4-nuttx-e29947db6aba1a4797b093b64548e40ad14d12b0.tar.gz
px4-nuttx-e29947db6aba1a4797b093b64548e40ad14d12b0.tar.bz2
px4-nuttx-e29947db6aba1a4797b093b64548e40ad14d12b0.zip
Add logic to drop the priority of the page fill task
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2857 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rwxr-xr-xnuttx/Documentation/NuttXDemandPaging.html24
-rwxr-xr-xnuttx/sched/pg_internal.h10
-rw-r--r--nuttx/sched/pg_miss.c2
-rwxr-xr-xnuttx/sched/pg_worker.c99
4 files changed, 86 insertions, 49 deletions
diff --git a/nuttx/Documentation/NuttXDemandPaging.html b/nuttx/Documentation/NuttXDemandPaging.html
index dc0d5d6ae..3246e070d 100755
--- a/nuttx/Documentation/NuttXDemandPaging.html
+++ b/nuttx/Documentation/NuttXDemandPaging.html
@@ -160,7 +160,7 @@
<dl>
<dt><code>g_waitingforfill</code></dt>
<dd>An OS list that is used to hold the TCBs of tasks that are waiting for a page fill.</dd>
- <dt><code>g_pendingfilltcb</code></dt>
+ <dt><code>g_pftcb</code></dt>
<dd>A variable that holds a reference to the TCB of the thread that is currently be re-filled.</dd>
<dt><code>g_pgworker</code></dt>
<dd>The <i>process</i> ID of of the thread that will perform the page fills.</dd>
@@ -307,8 +307,8 @@
</p>
<p>
- The page fill worker thread will maintain a static variable called <code>_TCB *g_pendingfilltcb</code>.
- If no fill is in progress, <code>g_pendingfilltcb</code> will be NULL.
+ The page fill worker thread will maintain a static variable called <code>_TCB *g_pftcb</code>.
+ If no fill is in progress, <code>g_pftcb</code> will be NULL.
Otherwise, it will point to the TCB of the task which is receiving the fill that is in progess.
</p>
<ul><small>
@@ -319,7 +319,7 @@
</small></ul>
<p>
- When awakened from <code>pg_miss()</code>, no fill will be in progress and <code>g_pendingfilltcb</code> will be NULL.
+ When awakened from <code>pg_miss()</code>, no fill will be in progress and <code>g_pftcb</code> will be NULL.
In this case, the page fill worker thread will call <code>pg_startfill()</code>.
That function will perform the following operations:
<ul>
@@ -387,10 +387,10 @@
In this non-blocking case, the callback <code>pg_callback()</code> will perform the following operations when it is notified that the fill has completed:
<ul>
<li>
- Verify that <code>g_pendingfilltcb</code> is non-NULL.
+ Verify that <code>g_pftcb</code> is non-NULL.
</li>
<li>
- Find the higher priority between the task waiting for the fill to complete in <code>g_pendingfilltcb</code> and the task waiting at the head of the <code>g_waitingforfill</code> list.
+ Find the higher priority between the task waiting for the fill to complete in <code>g_pftcb</code> and the task waiting at the head of the <code>g_waitingforfill</code> list.
That will be the priority of he highest priority task waiting for a fill.
</li>
<li>
@@ -409,20 +409,20 @@
<a name="TaskResumption"><h2>Task Resumption</h2></a>
<p>
- For the non-blocking <code>up_fillpage()</code>, the page fill worker thread will detect that the page fill is complete when it is awakened with <code>g_pendingfilltcb</code> non-NULL and fill completion status from <code>pg_callback</code>.
+ For the non-blocking <code>up_fillpage()</code>, the page fill worker thread will detect that the page fill is complete when it is awakened with <code>g_pftcb</code> non-NULL and fill completion status from <code>pg_callback</code>.
In the non-blocking case, the page fill worker thread will know that the page fill is complete when <code>up_fillpage()</code> returns.
</p>
<p>
In this either, the page fill worker thread will:
<ul>
<li>
- Verify consistency of state information and <code>g_pendingfilltcb</code>.
+ Verify consistency of state information and <code>g_pftcb</code>.
</li>
<li>
Verify that the page fill completed successfully, and if so,
</li>
<li>
- Call <code>up_unblocktask(g_pendingfilltcb)</code> to make the task that just received the fill ready-to-run.
+ Call <code>up_unblocktask(g_pftcb)</code> to make the task that just received the fill ready-to-run.
</li>
<li>
Check if the <code>g_waitingforfill</code> list is empty.
@@ -432,10 +432,10 @@
Remove the highest priority task waiting for a page fill from <code>g_waitingforfill</code>,
</li>
<li>
- Save the task's TCB in <code>g_pendingfilltcb</code>,
+ Save the task's TCB in <code>g_pftcb</code>,
</li>
<li>
- If the priority of the thread in <code>g_pendingfilltcb</code>, is higher in priority than the default priority of the page fill worker thread, then set the priority of the page fill worker thread to that priority.
+ If the priority of the thread in <code>g_pftcb</code>, is higher in priority than the default priority of the page fill worker thread, then set the priority of the page fill worker thread to that priority.
</li>
<li>
Call <code>pg_startfill()</code> which will start the next fill (as described above).
@@ -446,7 +446,7 @@
Otherwise,
<ul>
<li>
- Set <code>g_pendingfilltcb</code> to NULL.
+ Set <code>g_pftcb</code> to NULL.
</li>
<li>
Restore the default priority of the page fill worker thread.
diff --git a/nuttx/sched/pg_internal.h b/nuttx/sched/pg_internal.h
index 15f7bbb18..6ea35eed4 100755
--- a/nuttx/sched/pg_internal.h
+++ b/nuttx/sched/pg_internal.h
@@ -87,10 +87,10 @@
extern pid_t g_pgworker;
-/* The page fill worker thread maintains a static variable called
- * g_pendingfilltcb. If no fill is in progress, g_pendingfilltcb will be NULL.
- * Otherwise, g_pendingfile will point to the TCB of the task which is
- * receiving the fill that is in progess.
+/* The page fill worker thread maintains a static variable called g_pftcb.
+ * If no page fill is in progress, g_pftcb will be NULL. Otherwise, g_pftcb
+ * will point to the TCB of the task which is receiving the fill that is
+ * in progess.
*
* NOTE: I think that this is the only state in which a TCB does not reside
* in some list. Here is it in limbo, outside of the normally queuing while
@@ -98,7 +98,7 @@ extern pid_t g_pgworker;
* TSTATE_TASK_INVALID.
*/
-extern FAR _TCB *g_pendingfilltcb;
+extern FAR _TCB *g_pftcb;
/****************************************************************************
* Public Function Prototypes
diff --git a/nuttx/sched/pg_miss.c b/nuttx/sched/pg_miss.c
index 10680365b..ff57081eb 100644
--- a/nuttx/sched/pg_miss.c
+++ b/nuttx/sched/pg_miss.c
@@ -166,7 +166,7 @@ void pg_miss(void)
* thread to start working on the queued page fill requests.
*/
- if (!g_pendingfilltcb)
+ if (!g_pftcb)
{
kill(g_pgworker, SIGWORK);
}
diff --git a/nuttx/sched/pg_worker.c b/nuttx/sched/pg_worker.c
index 6c20111ac..50469edf9 100755
--- a/nuttx/sched/pg_worker.c
+++ b/nuttx/sched/pg_worker.c
@@ -82,8 +82,8 @@
pid_t g_pgworker;
/* The page fill worker thread maintains a static variable called
- * g_pendingfilltcb. If no fill is in progress, g_pendingfilltcb will be NULL.
- * Otherwise, g_pendingfile will point to the TCB of the task which is
+ * g_pftcb. If no fill is in progress, g_pftcb will be NULL.
+ * Otherwise, g_pftcb will point to the TCB of the task which is
* receiving the fill that is in progess.
*
* NOTE: I think that this is the only state in which a TCB does not reside
@@ -92,7 +92,7 @@ pid_t g_pgworker;
* TSTATE_TASK_INVALID.
*/
-FAR _TCB *g_pendingfilltcb;
+FAR _TCB *g_pftcb;
/****************************************************************************
* Private Variables
@@ -132,9 +132,9 @@ status uint32_t g_starttime;
*
* When pg_callback() is called, it will perform the following operations:
*
- * - Verify that g_pendingfilltcb is non-NULL.
+ * - Verify that g_pftcb is non-NULL.
* - Find the higher priority between the task waiting for the fill to
- * complete in g_pendingfilltcb and the task waiting at the head of the
+ * complete in g_pftcb and the task waiting at the head of the
* g_waitingforfill list. That will be the priority of he highest priority
* task waiting for a fill.
* - If this higher priority is higher than current page fill worker thread,
@@ -158,20 +158,20 @@ status uint32_t g_starttime;
#ifndef CONFIG_PAGING_BLOCKINGFILL
static void pg_callback(FAR _TCB *tcb, int result)
{
- /* Verify that g_pendingfilltcb is non-NULL */
+ /* Verify that g_pftcb is non-NULL */
- if (g_pendingfilltcb)
+ if (g_pftcb)
{
FAR _TCB *htcb = (FAR _TCB *)g_waitingforfill.head;
FAR _TCB *wtcb = sched_gettcb(g_pgworker);
/* Find the higher priority between the task waiting for the fill to
- * complete in g_pendingfilltcb and the task waiting at the head of the
+ * complete in g_pftcb and the task waiting at the head of the
* g_waitingforfill list. That will be the priority of he highest
* priority task waiting for a fill.
*/
- int priority = g_pendingfilltcb->sched_priority;
+ int priority = g_pftcb->sched_priority;
if (htcb && priority < htcb->sched_priority)
{
priority = htcb->sched_priority;
@@ -218,14 +218,14 @@ static void pg_callback(FAR _TCB *tcb, int result)
* g_waitingforfill task list becomes empty.
*
* The result (NULL or a TCB pointer) will be returned in the global
- * variable, g_pendingfilltcb.
+ * variable, g_pftcb.
*
* Input parameters:
* None
*
* Returned Value:
* If there are no further queue page fill operations to be performed,
- * pg_startfill() will return false. Otherwise, it will return
+ * pg_dequeue() will return false. Otherwise, it will return
* true to that the full is in process (any errors will result in
* assertions and this function will not return).
*
@@ -245,8 +245,8 @@ static inline bool pg_dequeue(void)
{
/* Remove the TCB from the head of the list (if any) */
- g_pendingfilltcb = (FAR _TCB *)dq_remfirst((dq_queue_t*)&g_waitingforfill);
- if (g_pendingfilltcb != NULL)
+ g_pftcb = (FAR _TCB *)dq_remfirst((dq_queue_t*)&g_waitingforfill);
+ if (g_pftcb != NULL)
{
/* Call the architecture-specific function up_checkmapping() to see if
* the page fill still needs to be performed. In certain conditions,
@@ -255,10 +255,47 @@ static inline bool pg_dequeue(void)
* simply be restarted.
*/
- if (!up_checkmapping(g_pendingfilltcb))
+ if (!up_checkmapping(g_pftcb))
{
- /* This page needs to be filled. Return with g_pendingfilltcb
- * holding the pointer to the TCB associated with task.
+ /* This page needs to be filled. pg_miss bumps up
+ * the priority of the page fill worker thread as each
+ * TCB is added to the g_waitingforfill list. So we
+ * may need to also drop the priority of the worker
+ * thread as the next TCB comes off of the list.
+ *
+ * If wtcb->sched_priority > CONFIG_PAGING_DEFPRIO,
+ * then the page fill worker thread is executing at
+ * an elevated priority that may be reduced.
+ *
+ * If wtcb->sched_priority > g_pftcb->sched_priority
+ * then the page fill worker thread is executing at
+ * a higher priority than is appropriate for this
+ * fill (this priority can get re-boosted by pg_miss()
+ * if a new higher priority fill is required).
+ */
+
+ FAR _TCB *wtcb = (FAR _TCB *)g_readytorun.head;
+ if (wtcb->sched_priority > CONFIG_PAGING_DEFPRIO &&
+ wtcb->sched_priority > g_pftcb->sched_priority)
+ {
+ /* Don't reduce the priority of the page fill
+ * worker thread lower than the configured
+ * minimum.
+ */
+
+ int priority = g_pftcb->sched_priority;
+ if (priority < CONFIG_PAGING_DEFPRIO)
+ {
+ priority = CONFIG_PAGING_DEFPRIO;
+ }
+
+ /* Reduce the priority of the page fill worker thread */
+
+ sched_setpriority(wtcb, priority);
+ }
+
+ /* Return with g_pftcb holding the pointer to
+ * the TCB associated with task that requires the page fill.
*/
return true;
@@ -268,10 +305,10 @@ static inline bool pg_dequeue(void)
* virtual address space -- just restart it.
*/
- up_unblock_task(g_pendingfilltcb);
+ up_unblock_task(g_pftcb);
}
}
- while (g_pendingfilltcb != NULL);
+ while (g_pftcb != NULL);
return false;
}
@@ -323,7 +360,7 @@ static inline bool pg_startfill(void)
* a page in-use, un-map it, and make it available.
*/
- result = up_allocpage(g_pendingfilltcb, &vpage);
+ result = up_allocpage(g_pftcb, &vpage);
DEBUGASSERT(result == OK);
/* Start the fill. The exact way that the fill is started depends upon
@@ -339,7 +376,7 @@ static inline bool pg_startfill(void)
* status of the fill will be provided by return value from up_fillpage().
*/
- result = up_fillpage(g_pendingfilltcb, vpage);
+ result = up_fillpage(g_pftcb, vpage);
DEBUGASSERT(result == OK);
#else
/* If CONFIG_PAGING_BLOCKINGFILL is defined, then up_fillpage is non-blocking
@@ -351,7 +388,7 @@ static inline bool pg_startfill(void)
* This callback will probably from interrupt level.
*/
- result = up_fillpage(g_pendingfilltcb, vpage, pg_callback);
+ result = up_fillpage(g_pftcb, vpage, pg_callback);
DEBUGASSERT(result == OK);
/* Save the time that the fill was started. These will be used to check for
@@ -387,7 +424,7 @@ static inline bool pg_startfill(void)
*
* This functin will perform the following operations:
*
- * - Set g_pendingfilltcb to NULL.
+ * - Set g_pftcb to NULL.
* - Restore the default priority of the page fill worker thread.
*
* Input parameters:
@@ -405,7 +442,7 @@ static inline bool pg_startfill(void)
static inline void pg_alldone(void)
{
FAR _TCB *wtcb = (FAR _TCB *)g_readytorun.head;
- g_pendingfilltcb = NULL;
+ g_pftcb = NULL;
sched_setpriority(wtcb, CONFIG_PAGING_DEFPRIO);
}
@@ -436,11 +473,11 @@ static inline void pg_alldone(void)
static inline void pg_fillcomplete(void)
{
- /* Call up_unblocktask(g_pendingfilltcb) to make the task that just
+ /* Call up_unblocktask(g_pftcb) to make the task that just
* received the fill ready-to-run.
*/
- up_unblock_task(g_pendingfilltcb);
+ up_unblock_task(g_pftcb);
}
/****************************************************************************
@@ -510,11 +547,11 @@ int pg_worker(int argc, char *argv[])
#ifdef CONFIG_PAGING_BLOCKINGFILL
/* For the non-blocking up_fillpage(), the page fill worker thread will detect
- * that the page fill is complete when it is awakened with g_pendingfilltcb non-NULL
+ * that the page fill is complete when it is awakened with g_pftcb non-NULL
* and fill completion status from pg_callback.
*/
- if (g_pendingfilltcb != NULL)
+ if (g_pftcb != NULL)
{
/* If it is a real page fill completion event, then the result of the page
* fill will be in g_fillresult and will not be equal to -EBUSY.
@@ -530,7 +567,7 @@ int pg_worker(int argc, char *argv[])
* task that was blocked waiting for this page fill.
*/
- up_unblock_task(g_pendingfilltcb);;
+ up_unblock_task(g_pftcb);;
/* Yes .. Start the next asynchronous fill. Check the return
* value to see a fill was actually started (false means that
@@ -563,14 +600,14 @@ int pg_worker(int argc, char *argv[])
/* Otherwise, this might be a page fill initiation event. When
* awakened from pg_miss(), no fill will be in progress and
- * g_pendingfilltcb will be NULL.
+ * g_pftcb will be NULL.
*/
else
{
/* Are there tasks blocked and waiting for a fill? If so,
* pg_startfill() will start the asynchronous fill (and set
- * g_pendingfilltcb).
+ * g_pftcb).
*/
(void)pg_startfill();
@@ -601,7 +638,7 @@ int pg_worker(int argc, char *argv[])
* returns true.
*/
- up_unblock_task(g_pendingfilltcb);;
+ up_unblock_task(g_pftcb);;
}
/* All queued fills have been processed */