This function will call <code>up_block_task()</code> to block the task at the head of the ready-to-run list.
This should cause an interrupt level context switch to the next highest priority task.
The blocked task will be marked with state <code>TSTATE_WAIT_PAGEFILL</code> and will be retained in the <code>g_waitingforfill</code> prioritized task list.
</li>
<li>
<b>Boost the page fill worker thread priority</b>.
Check the priority of the task at the head of the <code>g_waitingforfill</code> list.
If the priority of that task is higher than the current priority of the page fill worker thread, then boost the priority of the page fill worker thread to that priority.
</li>
<li>
<b>Signal the page fill worker thread</b>.
Is there a page already being filled?
If not then signal the page fill worker thread to start working on the queued page fill requests.
</li>
</ol>
</p>
<p>
When signaled from <code>pg_miss()</code>, the page fill worker thread will be awakenend and will initiate the fill operation.
</p>
<p>
<b>Input Parameters.</b>
None -- The head of the ready-to-run list is assumed to be that task that caused the exception.
The current task context should already be saved in the TCB of that task.
No additional inputs are required.
</p>
<p>
<b>Assumptions</b>.
<ul>
<li>
It is assumed that this function is called from the level of an exception handler and that all interrupts are disabled.
Interrupt handling logic must always be available and "<ahref="#MemoryOrg">locked</a>" into memory so that page faults never come from interrupt handling.
The chip-specific page fault exception handling has already verified that the exception did not occur from interrupt/exception handling logic.
</li>
<li>
As mentioned above, the task causing the page fault must not be the page fill worker thread because that is the only way to complete the page fill.
</li>
</ul>
</p>
<p>
<b>Locking code in Memory</b>.
One way to accomplish this would be a two phase link:
<ul>
<li>
In the first phase, create a partially linked objected containing all interrupt/exception handling logic, the page fill worker thread plus all parts of the IDLE thread (which must always be available for execution).
</li>
<li>
All of the <code>.text</code> and <code>.rodata</code> sections of this partial link should be collected into a single section.
</li>
<li>
The second link would link the partially linked object along with the remaining object to produce the final binary.
The linker script should position the "special" section so that it lies in a reserved, "non-swappable" region.
While the fill is in progress, other tasks may execute.
If another page fault occurs during this time, the faulting task will be blocked and its TCB will be added (in priority order) to <code>g_waitingforfill</code>.
But no action will be taken until the current page fill completes.
When the page fill worker thread is awakened and <code>g_pendingfill</code> is non-NULL (and other state variables are in concurrence),
the page fill thread will know that is was awakened because of a page fill completion event.
In this case, the page fill worker thread will:
<ul>
<li>
Verify consistency of state information and <code>g_pendingfill</code>.
</li>
<li>
Verify that the page fill completed successfully, and if so,
</li>
<li>
Call <code>up_unblocktask(g_pendingfill)</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.
If not:
<ul>
<li>
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_pendingfill</code>,
</li>
<li>
If the priority of the thread in <code>g_pendingfill</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).
</li>
</ul>
</li>
<li>
Otherwise,
<ul>
<li>
Set <code>g_pendingfill</code> to NULL.
</li>
<li>
Restore the default priority of the page fill worker thread.
</li>
<li>
Wait for the next fill related event (a new page fault).
The currently executing task at the head of the ready to run list must be stopped.
Save its context and move it to the inactive list specified by task_state.
This function is called by the on-demand paging logic in order to block the task that requires the
page fill, and to
</dd>
<dt>
<code>void up_unblock_task(FAR _TCB *tcb);</code>
</dt>
<dd>
A task is currently in an inactive task list but has been prepped to execute.
Move the TCB to the ready-to-run list, restore its context, and start execution.
This function will be called
</dd>
</dl></ul>
<p>
New, additional functions that must be implemented just for on-demand paging support:
</p>
<ul><dl>
<dt>
<code>int up_checkmapping(FAR _TCB *tcb);</code>
</dt>
<dd>
The function <code>up_checkmapping()</code> returns an indication that checks if the page fill still needs to performed or not.
In certain conditions, the page fault may occur on several threads and be queued multiple times.
This function will prevent the same page from be filled multiple times.
</dd>
<dt>
<code>int up_allocpage(FAR _TCB *tcb, FAR void *vpage);</code>
</dt>
<dd>
This chip-specific function will set aside page in memory and map to its correct virtual address.
Architecture-specific context information saved within the TCB will provide the function with the information need to identify the virtual miss address.
This function will return the allocated physical page address in <code>paddr</code>.
The size of a physical page is determined by the configuration setting <code>CONFIG_PAGING_PAGESIZE</code>.
NOTE: This function must <i>always</i> return a page allocation.
If all pages available pages are in-use (the typical case), then this function will select a page in-use, un-map it, and make it available.
</dd>
<dt><code>int up_fillpage(FAR _TCB *tcb, FAR const void *vpage, void (*pg_callback)(FAR _TCB *tcb, int result));</code>
</dt>
The actual filling of the page with data from the non-volatile, be performed by a separate call to the architecture-specific function, <code>up_fillpage()</code>.
This will start asynchronous page fill.
The common logic will provide a callback function, <code>pg_callback</code>, that will be called when the page fill is finished (or an error occurs).
This callback is assumed to occur from an interrupt level when the device driver completes the fill operation.