diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2010-08-15 16:50:25 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2010-08-15 16:50:25 +0000 |
commit | e29947db6aba1a4797b093b64548e40ad14d12b0 (patch) | |
tree | bf022bdca59370edf1dae8d42e3c4a86be392e74 /nuttx | |
parent | aa8fe0d6cf94a297fd0e7c8a6ab1ddb315fda57e (diff) | |
download | px4-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-x | nuttx/Documentation/NuttXDemandPaging.html | 24 | ||||
-rwxr-xr-x | nuttx/sched/pg_internal.h | 10 | ||||
-rw-r--r-- | nuttx/sched/pg_miss.c | 2 | ||||
-rwxr-xr-x | nuttx/sched/pg_worker.c | 99 |
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 */ |