1
0
Fork 0
forked from nuttx/nuttx-update

An address environment is the property of a task group, not of a thread

This commit is contained in:
Gregory Nutt 2014-08-22 12:32:34 -06:00
parent 150fcfb5b8
commit 1d586e6136
13 changed files with 278 additions and 306 deletions

View file

@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttX Binary Loader</i></font></big></h1>
<p>Last Updated: January 16, 2013</p>
<p>Last Updated: August 22, 2014</p>
</td>
</tr>
</table>
@ -170,7 +170,7 @@ struct binary_s
*/
#ifdef CONFIG_ADDRENV
task_addrenv_t addrenv; /* Task address environment */
group_addrenv_t addrenv; /* Task group address environment */
#endif
size_t mapsize; /* Size of the mapped address region (needed for munmap) */

View file

@ -12,7 +12,7 @@
<h1><big><font color="#3c34ec">
<i>NuttX RTOS Porting Guide</i>
</font></big></h1>
<p>Last Updated: August 21, 2014</p>
<p>Last Updated: August 22, 2014</p>
</td>
</tr>
</table>
@ -107,13 +107,13 @@
<a href="#addrenv">4.4 Address Environments</a>
<ul>
<a href="#up_addrenv_create">4.4.1 <code>up_addrenv_create()</code></a></br>
<a href="#up_addrenv_vaddr">4.4.2 <code>up_addrenv_vaddr()</code></a></br>
<a href="#up_addrenv_select">4.4.3 <code>up_addrenv_select()</code></a></br>
<a href="#up_addrenv_restore">4.4.4 <code>up_addrenv_restore()</code></a></br>
<a href="#up_addrenv_destroy">4.4.5 <code>up_addrenv_destroy()</code></a></br>
<a href="#up_addrenv_destroy">4.4.2 <code>up_addrenv_destroy()</code></a></br>
<a href="#up_addrenv_vaddr">4.4.3 <code>up_addrenv_vaddr()</code></a></br>
<a href="#up_addrenv_select">4.4.4 <code>up_addrenv_select()</code></a></br>
<a href="#up_addrenv_restore">4.4.5 <code>up_addrenv_restore()</code></a></br>
<a href="#up_addrenv_assign">4.4.6 <code>up_addrenv_assign()</code></a></br>
<a href="#up_addrenv_share">4.4.7 <code>up_addrenv_share()</code></a></br>
<a href="#up_addrenv_release">4.4.8 <code>up_addrenv_release()</code></a>
<a href="#up_addrenv_attach">4.4.7 <code>up_addrenv_attach()</code></a></br>
<a href="#up_addrenv_detach">4.4.8 <code>up_addrenv_detach()</code></a>
</ul>
<a href="#exports">4.5 APIs Exported by NuttX to Architecture-Specific Logic</a>
<ul>
@ -2625,7 +2625,7 @@ int up_alarm_cancel(FAR struct timespec *ts);
May be called from interrupt level handling or from the normal tasking level. iterrupts may need to be disabled internally to assure non-reentrancy.
</ul>
<h5><a name="upalarmstart">4.3.4.4.5 <code>up_alarm_start()</code></a></h5>
<h5><a name="upalarmstart">4.3.4.4.4 <code>up_alarm_start()</code></a></h5>
<p><b>Function Prototype</b>:<p>
<ul><pre>
#include &lt;nuttx/arch.h&gt;
@ -2930,8 +2930,7 @@ VxWorks provides the following comparable interface:
<p>
<b>Binary Loader Support</b>.
These are low-level interfaces used in <code>binfmt/</code> to instantiate tasks with address environments.
These interfaces all operate on type <code>task_addrenv_t</code> which is an abstract representation of a asks's address environment and must be defined in arch/arch.h if <code>CONFIG_ADDRENV</code> is defined.
These low-level interfaces include:
These interfaces all operate on type <code>group_addrenv_t</code> which is an abstract representation of a task group's address environment and the type must be defined in<code>arch/arch.h</code> if <code>CONFIG_ADDRENV</code> is defined. These low-level interfaces include:
</p>
<ul>
<li>
@ -2939,24 +2938,24 @@ VxWorks provides the following comparable interface:
Create an address environment.
</li>
<li>
<a href="#up_addrenv_vaddr">4.4.2 <code>up_addrenv_vaddr()</code></a>:
Returns the virtual base address of the address environment.
</li>
<li>
<a href="#up_addrenv_select">4.4.3 <code>up_addrenv_select()</code></a>:
Instantiate an address environment.
</li>
<li>
<a href="#up_addrenv_restore">4.4.4 <code>up_addrenv_restore()</code></a>:
Restore an address environment.
</li>
<li>
<a href="#up_addrenv_destroy">4.4.5 <code>up_addrenv_destroy()</code></a>:
<a href="#up_addrenv_destroy">4.4.2 <code>up_addrenv_destroy()</code></a>:
Destroy an address environment.
</li>
<li>
<a href="#up_addrenv_vaddr">4.4.3 <code>up_addrenv_vaddr()</code></a>:
Returns the virtual base address of the address environment.
</li>
<li>
<a href="#up_addrenv_select">4.4.4 <code>up_addrenv_select()</code></a>:
Instantiate an address environment.
</li>
<li>
<a href="#up_addrenv_restore">4.4.5 <code>up_addrenv_restore()</code></a>:
Restore an address environment.
</li>
<li>
<a href="#up_addrenv_assign">4.4.6 <code>up_addrenv_assign()</code></a>:
Assign an address environment to a TCB.
Assign an address environment to a thread.
</li>
</ul>
</li>
@ -2964,31 +2963,30 @@ VxWorks provides the following comparable interface:
<p>
<b>Tasking Support</b>.
Other interfaces must be provided to support higher-level interfaces used by the NuttX tasking logic.
These interfaces are* used by the functions in <code>sched/</code> and all operate on the TCB which as been assigned an address environment by <code>up_addrenv_assign()</code>.
These interfaces are* used by the functions in <code>sched/</code> and all operate on the task group which as been assigned an address environment by <code>up_addrenv_assign()</code>.
</p>
<ul>
<li>
<a href="#up_addrenv_share">4.4.7 <code>up_addrenv_share()</code></a>:
Clone the address environment assigned to one TCB to another.
<a href="#up_addrenv_attach">4.4.7 <code>up_addrenv_attach()</code></a>:
Clone the group address environment assigned to a new thread.
This operation is done when a pthread is created that share's the same address environment.
</li>
<li>
<a href="#up_addrenv_release">4.4.8 <code>up_addrenv_release()</code></a>:
Release the TCB's reference to an address environment when a task/thread exits.
<a href="#up_addrenv_detach">4.4.8 <code>up_addrenv_detach()</code></a>:
Release the thread's reference to a group address environment when a task/thread exits.
</li>
</ul>
</li>
</ol>
<h3><a name="up_addrenv_create">4.4.1 <code>up_addrenv_create()</code></a></h3>
<p><b>Function Prototype</b>:</p>
<ul>
<code>int up_addrenv_create(size_t envsize, FAR task_addrenv_t *addrenv);</code>
<code>int up_addrenv_create(size_t envsize, FAR group_addrenv_t *addrenv);</code>
</ul>
<p><b>Description</b>:</p>
<ul>
This function is called from the binary loader logic when a new task is created in order to instantiate an address environment for the task.
This function is called when a new task is created in order to instantiate an address environment for the new task group.
<code>up_addrenv_create()</code> is essentially the allocator of the physical memory for the new task.
</ul>
<p><b>Input Parameters</b>:</p>
@ -3001,10 +2999,28 @@ VxWorks provides the following comparable interface:
Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure.
</ul>
<h3><a name="up_addrenv_vaddr">4.4.2 <code>up_addrenv_vaddr()</code></a></h3>
<h3><a name="up_addrenv_destroy">4.4.2 <code>up_addrenv_destroy()</code></a></h3>
<p><b>Function Prototype</b>:<p>
<ul>
<code>int up_addrenv_vaddr(FAR task_addrenv_t addrenv, FAR void **vaddr);</code>
<code>int up_addrenv_destroy(group_addrenv_t addrenv);</code>
</ul>
<p><b>Description</b>:</p>
<ul>
This function is called when a final thread leaves the task group and the task group is destroyed. This function then destroys the defunct address environment, releasing the underlying physical memory allocated by <code>up_addrenv_create()</code>.
</ul>
<p><b>Input Parameters</b>:</p>
<ul>
<li><code>addrenv</code>: The representation of the task address environment previously returned by up_addrenv_create.</li>
</ul>
<p><b>Returned Value</b>:</p>
<ul>
Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure.
</ul>
<h3><a name="up_addrenv_vaddr">4.4.3 <code>up_addrenv_vaddr()</code></a></h3>
<p><b>Function Prototype</b>:<p>
<ul>
<code>int up_addrenv_vaddr(FAR group_addrenv_t addrenv, FAR void **vaddr);</code>
</ul>
<p><b>Description</b>:</p>
<ul>
@ -3021,10 +3037,10 @@ VxWorks provides the following comparable interface:
Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure.
</ul>
<h3><a name="up_addrenv_select">4.4.3 <code>up_addrenv_select()</code></a></h3>
<h3><a name="up_addrenv_select">4.4.4 <code>up_addrenv_select()</code></a></h3>
<p><b>Function Prototype</b>:<p>
<ul>
<code>int up_addrenv_select(task_addrenv_t addrenv, hw_addrenv_t *oldenv);</code>
<code>int up_addrenv_select(group_addrenv_t addrenv, hw_addrenv_t *oldenv);</code>
</ul>
<p><b>Description</b>:</p>
<ul>
@ -3037,7 +3053,7 @@ VxWorks provides the following comparable interface:
<li><code>oldenv</code>:
The address environment that was in place before <code>up_addrenv_select()</code> was called.
This may be used with <code>up_addrenv_restore()</code> to restore the original address environment that was in place before <code>up_addrenv_select()</code> was called.
Note that this may be a task agnostic, hardware representation that is different from <code>task_addrenv_t</code>.
Note that this may be a task agnostic, hardware representation that is different from <code>group_addrenv_t</code>.
</li>
</ul>
<p><b>Returned Value</b>:</p>
@ -3045,7 +3061,7 @@ VxWorks provides the following comparable interface:
Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure.
</ul>
<h3><a name="up_addrenv_restore">4.4.4 <code>up_addrenv_restore()</code></a></h3>
<h3><a name="up_addrenv_restore">4.4.5 <code>up_addrenv_restore()</code></a></h3>
<p><b>Function Prototype</b>:<p>
<ul>
<code>int up_addrenv_restore(hw_addrenv_t oldenv);</code>
@ -3064,76 +3080,63 @@ VxWorks provides the following comparable interface:
Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure.
</ul>
<h3><a name="up_addrenv_destroy">4.4.5 <code>up_addrenv_destroy()</code></a></h3>
<p><b>Function Prototype</b>:<p>
<ul>
<code>int up_addrenv_destroy(task_addrenv_t addrenv);</code>
</ul>
<p><b>Description</b>:</p>
<ul>
Called from the binary loader loader during error handling to destroy the address environment previously created by <code>up_addrenv_create()</code>.
</ul>
<p><b>Input Parameters</b>:</p>
<ul>
<li><code>addrenv</code>: The representation of the task address environment previously returned by up_addrenv_create.</li>
</ul>
<p><b>Returned Value</b>:</p>
<ul>
Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure.
</ul>
<h3><a name="up_addrenv_assign">4.4.6 <code>up_addrenv_assign()</code></a></h3>
<p><b>Function Prototype</b>:<p>
<ul>
<code>int up_addrenv_assign(task_addrenv_t addrenv, FAR struct tcb_s *tcb);</code>
<code>int up_addrenv_assign(group_addrenv_t addrenv, FAR struct task_group_s *group);</code>
</ul>
<p><b>Description</b>:</p>
<ul>
Assign an address environment to a TCB.
Assign an address environment to a new task group.
</ul>
<p><b>Input Parameters</b>:</p>
<ul>
<li><code>addrenv</code>: The representation of the task address environment previously returned by up_addrenv_create.</li>
<li><code>tcb</code>: The TCB of the task to receive the address environment.</li>
<li><code>addrenv</code>: The representation of the group address environment previously returned by <code>up_addrenv_create</code>.</li>
<li><code>group</code>: The new task group to receive the address environment.</li>
</ul>
<p><b>Returned Value</b>:</p>
<ul>
Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure.
</ul>
<h3><a name="up_addrenv_share">4.4.7 <code>up_addrenv_share()</code></a></h3>
<h3><a name="up_addrenv_attach">4.4.7 <code>up_addrenv_attach()</code></a></h3>
<p><b>Function Prototype</b>:<p>
<ul>
<code>int up_addrenv_share(FAR const struct tcb_s *ptcb, FAR struct tcb_s *ctcb);</code>
<code>int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb);</code>
</ul>
<p><b>Description</b>:</p>
<ul>
This function is called from the core scheduler logic when a thread is created that needs to share the address environment of its parent task.
In this case, the parent's address environment needs to be &quot;cloned&quot; for the child thread.
<p>
This function is called from the core scheduler logic when a thread is created that needs to share the address environment of its task group.
In this case, the group's address environment may need to be &quot;cloned&quot; for the child thread.
</p>
<p>
NOTE: In most platforms, nothing will need to be done in this case.
Simply being a member of the group that has the address environment may be sufficient.
</p>
</ul>
<p><b>Input Parameters</b>:</p>
<ul>
<li><code>ptcb</code>: The TCB of the parent task that has the address environment.</li>
<li><code>ctcb</code>: The TCB of the child thread needing the address environment.</li>
<li><code>group</code>: The task group to which the new thread belongs.</li>
<li><code>ctcb</code>: The TCB of the thread needing the address environment.</li>
</ul>
<p><b>Returned Value</b>:</p>
<ul>
Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure.
</ul>
<h3><a name="up_addrenv_release">4.4.8 <code>up_addrenv_release()</code></a></h3>
<h3><a name="up_addrenv_detach">4.4.8 <code>up_addrenv_detach()</code></a></h3>
<p><b>Function Prototype</b>:<p>
<ul>
<code>int up_addrenv_release(FAR struct tcb_s *tcb);</code>
<code>int up_addrenv_detach(FAR struct task_group_s *group, FAR struct task_group_s *tcb);</code>
</ul>
<p><b>Description</b>:</p>
<ul>
This function is called when a task or thread exits in order to release its reference to an address environment.
When there are no further references to an address environment, that address environment should
be destroyed.
This function is called when a task or thread exits in order to release its reference to an address environment. The address environment, however, should persist until up_addrenv_destroy() is called when the task group is itself destroyed. Any resources unique to this thread may be destroyed now.
</ul>
<p><b>Input Parameters</b>:</p>
<ul>
<li><code>group</code>: The group to which the thread belonged.</li>
<li><code>tcb</code>: The TCB of the task or thread whose the address environment will be released.</li>
</ul>
<p><b>Returned Value</b>:</p>

View file

@ -1,6 +1,5 @@
/****************************************************************************
* arch/z80/arch.h
* arch/chip/arch.h
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
@ -73,7 +72,7 @@ typedef uint8_t hw_addrenv_t;
*/
struct z180_cbr_s;
typedef FAR struct z180_cbr_s *task_addrenv_t;
typedef FAR struct z180_cbr_s *group_addrenv_t;
#endif
/****************************************************************************

View file

@ -173,7 +173,7 @@ typedef uint16_t chipreg_t;
struct z180_cbr_s
{
uint8_t cbr; /* The CBR value used by the thread */
uint8_t crefs; /* The number of threads sharing this CBR value */
uint8_t crefs; /* The number of task groups using this CBR value (0 or 1) */
uint8_t pages; /* The number of 4KB pages of physical memory in the allocation */
};
@ -183,10 +183,6 @@ struct z180_cbr_s
struct xcptcontext
{
/* CBR allocation */
FAR struct z180_cbr_s *cbr;
/* Register save area */
chipreg_t regs[XCPTCONTEXT_REGS];

View file

@ -1,7 +1,7 @@
/****************************************************************************
* arch/z80/src/z180/z180_mmu.c
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -180,36 +180,37 @@ return g_physhandle ? OK : -ENOMEM;
* Address Environment Interfaces
*
* Low-level interfaces used in binfmt/ to instantiate tasks with address
* environments. These interfaces all operate on task_addrenv_t which is an
* abstract representation of the address environment and must be provided
* by arch/arch.h is CONFIG_ADDRENV is defined.
* environments. These interfaces all operate on type group_addrenv_t which
* is an abstract representation of a task group's address environment and
* must be defined in arch/arch.h if CONFIG_ADDRENV is defined.
*
* up_addrenv_create - Create an address environment
* up_addrenv_destroy - Destroy an address environment.
* up_addrenv_vaddr - Returns the virtual base address of the address
* environment
* up_addrenv_select - Instantiate an address environment
* up_addrenv_destroy - Destroy an address environment.
* up_addrenv_assign - Assign an address environment to a TCB
* up_addrenv_restore - Restore an address environment
* up_addrenv_assign - Assign an address environment to a group
*
* Higher-level interfaces used by the tasking logic. These interfaces are
* used by the functions in sched/ and all operate on the TCB which as been
* assigned an address environment by up_addrenv_assign().
* used by the functions in sched/ and all operate on the thread which whose
* group been assigned an address environment by up_addrenv_assign().
*
* up_addrenv_share - Clone the address environment assigned to one TCB
* up_addrenv_attach - Clone the address environment assigned to one TCB
* to another. This operation is done when a pthread
* is created that share's the same address
* environment.
* up_addrenv_release - Release the TCBs reference to an address
* environment when a task/thread exists.
* up_addrenv_detach - Release the threads reference to an address
* environment when a task/thread exits.
*
****************************************************************************/
/****************************************************************************
* Name: up_addrenv_create
*
* Description:
* This function is called from the binary loader logic when a new
* task is created in order to instantiate an address environment for the
* task. up_addrenv_create is essentially the allocator of the physical
* This function is called when a new task is created in order to
* instantiate an address environment for the new task group.
* up_addrenv_create() is essentially the allocator of the physical
* memory for the new task.
*
* Input Parameters:
@ -223,7 +224,7 @@ return g_physhandle ? OK : -ENOMEM;
*
****************************************************************************/
int up_addrenv_create(size_t envsize, FAR task_addrenv_t *addrenv)
int up_addrenv_create(size_t envsize, FAR group_addrenv_t *addrenv)
{
FAR struct z180_cbr_s *cbr;
irqstate_t flags;
@ -280,7 +281,7 @@ int up_addrenv_create(size_t envsize, FAR task_addrenv_t *addrenv)
cbr->cbr = (uint8_t)alloc;
cbr->pages = (uint8_t)npages;
*addrenv = (task_addrenv_t)cbr;
*addrenv = (group_addrenv_t)cbr;
irqrestore(flags);
return OK;
@ -293,6 +294,42 @@ errout_with_irq:
return ret;
}
/****************************************************************************
* Name: up_addrenv_destroy
*
* Description:
* This function is called when a final thread leaves the task group and
* the task group is destroyed. This function then destroys the defunct
* address environment, releasing the underlying physical memory.
*
* Input Parameters:
* addrenv - The address environment to be destroyed.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int up_addrenv_destroy(group_addrenv_t addrenv)
{
FAR struct z180_cbr_s *cbr = (FAR struct z180_cbr_s *)addrenv;
DEBUGASSERT(cbr);
/* Free the physical address space backing up the mapping */
#ifdef CONFIG_GRAN_SINGLE
gran_free((FAR void *)cbr->cbr, cbr->pages);
#else
gran_free(g_physhandle, (FAR void *)cbr->cbr, cbr->pages);
#endif
/* And make the CBR structure available for re-use */
z180_mmu_freecbr(cbr);
return OK;
}
/****************************************************************************
* Name: up_addrenv_vaddr
*
@ -311,7 +348,7 @@ errout_with_irq:
*
****************************************************************************/
int up_addrenv_vaddr(FAR task_addrenv_t addrenv, FAR void **vaddr)
int up_addrenv_vaddr(FAR group_addrenv_t addrenv, FAR void **vaddr)
{
return CONFIG_Z180_COMMON1AREA_VIRTBASE;
}
@ -334,14 +371,14 @@ int up_addrenv_vaddr(FAR task_addrenv_t addrenv, FAR void **vaddr)
* This may be used with up_addrenv_restore() to restore the original
* address environment that was in place before up_addrenv_select() was
* called. Note that this may be a task agnostic, hardware
* representation that is different from task_addrenv_t.
* representation that is different from group_addrenv_t.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int up_addrenv_select(task_addrenv_t addrenv, hw_addrenv_t *oldenv)
int up_addrenv_select(group_addrenv_t addrenv, hw_addrenv_t *oldenv)
{
FAR struct z180_cbr_s *cbr = (FAR struct z180_cbr_s *)addrenv;
irqstate_t flags;
@ -383,127 +420,76 @@ int up_addrenv_restore(hw_addrenv_t oldenv)
return OK;
}
/****************************************************************************
* Name: up_addrenv_destroy
*
* Description:
* Called from the binary loader loader during error handling to destroy
* the address environment previously created by up_addrenv_create().
*
* Input Parameters:
* addrenv - The representation of the task address environment previously
* returned by up_addrenv_create.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int up_addrenv_destroy(task_addrenv_t addrenv)
{
FAR struct z180_cbr_s *cbr = (FAR struct z180_cbr_s *)addrenv;
DEBUGASSERT(cbr);
/* Free the physical address space backing up the mapping */
#ifdef CONFIG_GRAN_SINGLE
gran_free((FAR void *)cbr->cbr, cbr->pages);
#else
gran_free(g_physhandle, (FAR void *)cbr->cbr, cbr->pages);
#endif
/* And make the CBR structure available for re-use */
z180_mmu_freecbr(cbr);
return OK;
}
/****************************************************************************
* Name: up_addrenv_assign
*
* Description:
* Assign an address environment to a TCB.
* Assign an address environment to a task group.
*
* Input Parameters:
* addrenv - The representation of the task address environment previously
* returned by up_addrenv_create.
* tcb - The TCB of the task to receive the address environment.
* returned by up_addrenv_create().
* group - The task group to receive the address environment.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int up_addrenv_assign(task_addrenv_t addrenv, FAR struct tcb_s *tcb)
int up_addrenv_assign(group_addrenv_t addrenv, FAR struct task_group_s *group)
{
FAR struct z180_cbr_s *cbr = (FAR struct z180_cbr_s *)addrenv;
/* Make sure that there is no address environment in place on this TCB */
DEBUGASSERT(cbr && tcb->xcp.cbr == NULL);
DEBUGASSERT(addrenv && group->addrenv == NULL);
/* Save the CBR strucure in the TCB. This is an atomic operation so no
/* Save the CBR structure in the group. This is an atomic operation so no
* special precautions should be needed.
*/
tcb->xcp.cbr = cbr;
group->addrenv = addrenv;
return OK;
}
/****************************************************************************
* Name: up_addrenv_share
* Name: up_addrenv_attach
*
* Description:
* This function is called from the core scheduler logic when a thread
* is created that needs to share the address ennvironment of its parent
* task. In this case, the parent's address environment needs to be
* "cloned" for the child.
* is created that needs to share the address environment of its task
* group.
*
* Input Parameters:
* ptcb - The TCB of the parent task that has the address environment.
* ctcb - The TCB of the child thread needing the address environment.
* group - The task group to which the new thread belongs.
* tcb - The tcb of the thread needing the address environment.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int up_addrenv_share(FAR const struct tcb_s *ptcb, FAR struct tcb_s *ctcb)
int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb)
{
irqstate_t flags;
/* There is nothing that needs to be done */
/* Make sure that the child has no address environment. It is okay if
* if the parent does not have one.
*/
DEBUGASSERT(ctcb->xcp.cbr == NULL);
flags = irqsave();
if (ptcb->xcp.cbr)
{
/* Clone the CBR by incrementing the reference counting and saving a
* copy in the child thread's TCB.
*/
ptcb->xcp.cbr->crefs++;
ctcb->xcp.cbr = ptcb->xcp.cbr;
}
irqrestore(flags);
return OK;
}
/****************************************************************************
* Name: up_addrenv_release
* Name: up_addrenv_detach
*
* Description:
* This function is called when a task or thread exits in order to release
* its reference to an address environment. When there are no further
* references to an address environment, that address environment should
* be destroyed.
* its reference to an address environment. The address environment,
* however, should persist until up_addrenv_destroy() is called when the
* task group is itself destroyed. Any resources unique to this thread
* may be destroyed now.
*
* NOTE: In some platforms, nothing will need to be done in this case.
* Simply being a member of the group that has the address environment
* may be sufficient.
*
* Input Parameters:
* group - The group to which the thread belonged.
* tcb - The TCB of the task or thread whose the address environment will
* be released.
*
@ -512,39 +498,10 @@ int up_addrenv_share(FAR const struct tcb_s *ptcb, FAR struct tcb_s *ctcb)
*
****************************************************************************/
int up_addrenv_release(FAR struct tcb_s *tcb)
int up_addrenv_detach(FAR struct task_group_s *group,
FAR struct task_group_s *tcb);
{
FAR struct z180_cbr_s *cbr;
irqstate_t flags;
/* There is nothing that needs to be done */
/* Check if the task has an address environment. */
flags = irqsave();
cbr = tcb->xcp.cbr;
if (cbr)
{
/* Nullify the reference to the CBR structure and decrement the number
* of references on the CBR.
*/
tcb->xcp.cbr = NULL;
/* If the reference count would decrement to zero, then free the CBR
* structure.
*/
if (cbr->crefs <= 1)
{
up_addrenv_destroy(cbr);
}
else
{
/* Otherwise, just decrement the reference count */
cbr->crefs--;
}
}
irqrestore(flags);
return OK;
}

View file

@ -1,7 +1,7 @@
/****************************************************************************
* binfmt/binfmt_execmodule.c
*
* Copyright (C) 2009, 2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2009, 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -205,10 +205,10 @@ int exec_module(FAR const struct binary_s *binp)
up_initial_state(&tcb->cmn);
#endif
/* Assign the address environment to the task */
/* Assign the address environment to the new task group */
#ifdef CONFIG_ADDRENV
ret = up_addrenv_assign(binp->addrenv, &tcb->cmn);
ret = up_addrenv_assign(binp->addrenv, tcb->group);
if (ret < 0)
{
err = -ret;

View file

@ -669,27 +669,27 @@ void up_allocate_kheap(FAR void **heap_start, size_t *heap_size);
* Address Environment Interfaces
*
* Low-level interfaces used in binfmt/ to instantiate tasks with address
* environments. These interfaces all operate on type task_addrenv_t which
* is an abstract representation of a task's address environment and must be
* defined in arch/arch.h if CONFIG_ADDRENV is defined.
* environments. These interfaces all operate on type group_addrenv_t which
* is an abstract representation of a task group's address environment and
* must be defined in arch/arch.h if CONFIG_ADDRENV is defined.
*
* up_addrenv_create - Create an address environment
* up_addrenv_destroy - Destroy an address environment.
* up_addrenv_vaddr - Returns the virtual base address of the address
* environment
* up_addrenv_select - Instantiate an address environment
* up_addrenv_restore - Restore an address environment
* up_addrenv_destroy - Destroy an address environment.
* up_addrenv_assign - Assign an address environment to a TCB
* up_addrenv_assign - Assign an address environment to a group
*
* Higher-level interfaces used by the tasking logic. These interfaces are
* used by the functions in sched/ and all operate on the TCB which as been
* assigned an address environment by up_addrenv_assign().
* used by the functions in sched/ and all operate on the thread which whose
* group been assigned an address environment by up_addrenv_assign().
*
* up_addrenv_share - Clone the address environment assigned to one TCB
* up_addrenv_attach - Clone the address environment assigned to one TCB
* to another. This operation is done when a pthread
* is created that share's the same address
* environment.
* up_addrenv_release - Release the TCBs reference to an address
* up_addrenv_detach - Release the threads reference to an address
* environment when a task/thread exits.
*
****************************************************************************/
@ -697,9 +697,9 @@ void up_allocate_kheap(FAR void **heap_start, size_t *heap_size);
* Name: up_addrenv_create
*
* Description:
* This function is called from the binary loader logic when a new
* task is created in order to instantiate an address environment for the
* task. up_addrenv_create is essentially the allocator of the physical
* This function is called when a new task is created in order to
* instantiate an address environment for the new task group.
* up_addrenv_create() is essentially the allocator of the physical
* memory for the new task.
*
* Input Parameters:
@ -714,7 +714,27 @@ void up_allocate_kheap(FAR void **heap_start, size_t *heap_size);
****************************************************************************/
#ifdef CONFIG_ADDRENV
int up_addrenv_create(size_t envsize, FAR task_addrenv_t *addrenv);
int up_addrenv_create(size_t envsize, FAR group_addrenv_t *addrenv);
#endif
/****************************************************************************
* Name: up_addrenv_destroy
*
* Description:
* This function is called when a final thread leaves the task group and
* the task group is destroyed. This function then destroys the defunct
* address environment, releasing the underlying physical memory.
*
* Input Parameters:
* addrenv - The address environment to be destroyed.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_ADDRENV
int up_addrenv_destroy(group_addrenv_t addrenv);
#endif
/****************************************************************************
@ -736,17 +756,17 @@ int up_addrenv_create(size_t envsize, FAR task_addrenv_t *addrenv);
****************************************************************************/
#ifdef CONFIG_ADDRENV
int up_addrenv_vaddr(FAR task_addrenv_t addrenv, FAR void **vaddr);
int up_addrenv_vaddr(FAR group_addrenv_t addrenv, FAR void **vaddr);
#endif
/****************************************************************************
* Name: up_addrenv_select
*
* Description:
* After an address environment has been established for a task (via
* After an address environment has been established for a task group (via
* up_addrenv_create(). This function may be called to to instantiate
* that address environment in the virtual address space. this might be
* necessary, for example, to load the code for the task from a file or
* necessary, for example, to load the code for the task group from a file or
* to access address environment private data.
*
* Input Parameters:
@ -757,7 +777,7 @@ int up_addrenv_vaddr(FAR task_addrenv_t addrenv, FAR void **vaddr);
* This may be used with up_addrenv_restore() to restore the original
* address environment that was in place before up_addrenv_select() was
* called. Note that this may be a task agnostic, hardware
* representation that is different from task_addrenv_t.
* representation that is different from group_addrenv_t.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
@ -765,15 +785,15 @@ int up_addrenv_vaddr(FAR task_addrenv_t addrenv, FAR void **vaddr);
****************************************************************************/
#ifdef CONFIG_ADDRENV
int up_addrenv_select(task_addrenv_t addrenv, hw_addrenv_t *oldenv);
int up_addrenv_select(group_addrenv_t addrenv, hw_addrenv_t *oldenv);
#endif
/****************************************************************************
* Name: up_addrenv_restore
*
* Description:
* After an address environment has been temporarilty instantiated by
* up_addrenv_select, this function may be called to to restore the
* After an address environment has been temporarily instantiated by
* up_addrenv_select(), this function may be called to to restore the
* original address environment.
*
* Input Parameters:
@ -789,36 +809,16 @@ int up_addrenv_select(task_addrenv_t addrenv, hw_addrenv_t *oldenv);
int up_addrenv_restore(hw_addrenv_t oldenv);
#endif
/****************************************************************************
* Name: up_addrenv_destroy
*
* Description:
* Called from the binary loader loader during error handling to destroy
* the address environment previously created by up_addrenv_create().
*
* Input Parameters:
* addrenv - The representation of the task address environment previously
* returned by up_addrenv_create.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_ADDRENV
int up_addrenv_destroy(task_addrenv_t addrenv);
#endif
/****************************************************************************
* Name: up_addrenv_assign
*
* Description:
* Assign an address environment to a TCB.
* Assign an address environment to a new task group.
*
* Input Parameters:
* addrenv - The representation of the task address environment previously
* returned by up_addrenv_create.
* tcb - The TCB of the task to receive the address environment.
* returned by up_addrenv_create().
* group - The new task group to receive the address environment.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
@ -826,21 +826,24 @@ int up_addrenv_destroy(task_addrenv_t addrenv);
****************************************************************************/
#ifdef CONFIG_ADDRENV
int up_addrenv_assign(task_addrenv_t addrenv, FAR struct tcb_s *tcb);
int up_addrenv_assign(group_addrenv_t addrenv, FAR struct task_group_s *group);
#endif
/****************************************************************************
* Name: up_addrenv_share
* Name: up_addrenv_attach
*
* Description:
* This function is called from the core scheduler logic when a thread
* is created that needs to share the address ennvironment of its parent
* task. In this case, the parent's address environment needs to be
* "cloned" for the child.
* is created that needs to share the address environment of its task
* group.
*
* NOTE: In some platforms, nothing will need to be done in this case.
* Simply being a member of the group that has the address environment
* may be sufficient.
*
* Input Parameters:
* ptcb - The TCB of the parent task that has the address environment.
* ctcb - The TCB of the child thread needing the address environment.
* group - The task group to which the new thread belongs.
* tcb - The TCB of the thread needing the address environment.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
@ -848,19 +851,25 @@ int up_addrenv_assign(task_addrenv_t addrenv, FAR struct tcb_s *tcb);
****************************************************************************/
#ifdef CONFIG_ADDRENV
int up_addrenv_share(FAR const struct tcb_s *ptcb, FAR struct tcb_s *ctcb);
int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb);
#endif
/****************************************************************************
* Name: up_addrenv_release
* Name: up_addrenv_detach
*
* Description:
* This function is called when a task or thread exits in order to release
* its reference to an address environment. When there are no further
* references to an address environment, that address environment should
* be destroyed.
* its reference to an address environment. The address environment,
* however, should persist until up_addrenv_destroy() is called when the
* task group is itself destroyed. Any resources unique to this thread
* may be destroyed now.
*
* NOTE: In some platforms, nothing will need to be done in this case.
* Simply being a member of the group that has the address environment
* may be sufficient.
*
* Input Parameters:
* group - The group to which the thread belonged.
* tcb - The TCB of the task or thread whose the address environment will
* be released.
*
@ -870,7 +879,8 @@ int up_addrenv_share(FAR const struct tcb_s *ptcb, FAR struct tcb_s *ctcb);
****************************************************************************/
#ifdef CONFIG_ADDRENV
int up_addrenv_release(FAR struct tcb_s *tcb);
int up_addrenv_detach(FAR struct task_group_s *group,
FAR struct task_group_s *tcb);
#endif
/****************************************************************************

View file

@ -125,7 +125,7 @@ struct binary_s
*/
#ifdef CONFIG_ADDRENV
task_addrenv_t addrenv; /* Task address environment */
group_addrenv_t addrenv; /* Task group address environment */
#endif
size_t mapsize; /* Size of the mapped address region (needed for munmap) */

View file

@ -131,8 +131,8 @@ struct elf_loadinfo_s
*/
#ifdef CONFIG_ADDRENV
task_addrenv_t addrenv; /* Task address environment */
hw_addrenv_t oldenv; /* Saved hardware address environment */
group_addrenv_t addrenv; /* Task group address environment */
hw_addrenv_t oldenv; /* Saved hardware address environment */
#endif
uint16_t symtabidx; /* Symbol table section index */

View file

@ -103,13 +103,13 @@ struct nxflat_loadinfo_s
*/
#ifdef CONFIG_ADDRENV
task_addrenv_t addrenv; /* Task address environment */
hw_addrenv_t oldenv; /* Saved hardware address environment */
group_addrenv_t addrenv; /* Task group address environment */
hw_addrenv_t oldenv; /* Saved hardware address environment */
#endif
/* File descriptors */
int filfd; /* Descriptor for the file being loaded */
int filfd; /* Descriptor for the file being loaded */
/* This is a copy of the NXFLAT header (still in network order) */

View file

@ -1,7 +1,7 @@
/********************************************************************************
* include/nuttx/sched.h
*
* Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -99,6 +99,8 @@
# define HAVE_TASK_GROUP 1 /* Sockets */
# elif !defined(CONFIG_DISABLE_MQUEUE)
# define HAVE_TASK_GROUP 1 /* Message queues */
# elif defined(CONFIG_ADDRENV)
# define HAVE_TASK_GROUP 1 /* Address environment */
# endif
#endif
@ -264,25 +266,24 @@ struct dspace_s
/* struct task_group_s ***********************************************************/
/* All threads created by pthread_create belong in the same task group (along with
* the thread of the original task). struct task_group_s is a shared, "breakaway"
* structure referenced by each TCB.
* the thread of the original task). struct task_group_s is a shared structure
* referenced by the TCB of each thread that is a member of the task group.
*
* This structure should contain *all* resources shared by tasks and threads that
* belong to the same task group:
*
* Child exit status
* Environment varibles
* Environment variables
* PIC data space and address environments
* File descriptors
* FILE streams
* Sockets
*
* Currenty, however, this implementation only applies to child exit status.
* Address environments.
*
* Each instance of struct task_group_s is reference counted. Each instance is
* created with a reference count of one. The reference incremeneted when each
* created with a reference count of one. The reference incremented when each
* thread joins the group and decremented when each thread exits, leaving the
* group. When the refernce count decrements to zero, the struc task_group_s
* group. When the reference count decrements to zero, the struct task_group_s
* is free.
*/
@ -313,9 +314,9 @@ struct task_group_s
FAR pid_t *tg_members; /* Members of the group */
#endif
/* atexit/on_exit support ****************************************************/
#if defined(CONFIG_SCHED_ATEXIT) && !defined(CONFIG_SCHED_ONEXIT)
/* atexit support ************************************************************/
# if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1
atexitfunc_t tg_atexitfunc[CONFIG_SCHED_ATEXIT_MAX];
# else
@ -324,6 +325,8 @@ struct task_group_s
#endif
#ifdef CONFIG_SCHED_ONEXIT
/* on_exit support ***********************************************************/
# if defined(CONFIG_SCHED_ONEXIT_MAX) && CONFIG_SCHED_ONEXIT_MAX > 1
onexitfunc_t tg_onexitfunc[CONFIG_SCHED_ONEXIT_MAX];
FAR void *tg_onexitarg[CONFIG_SCHED_ONEXIT_MAX];
@ -333,23 +336,22 @@ struct task_group_s
# endif
#endif
#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
/* Child exit status **********************************************************/
#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
FAR struct child_status_s *tg_children; /* Head of a list of child status */
#endif
#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
/* waitpid support ************************************************************/
/* Simple mechanism used only when there is no support for SIGCHLD */
#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
sem_t tg_exitsem; /* Support for waitpid */
int *tg_statloc; /* Location to return exit status */
#endif
/* Pthreads *******************************************************************/
#ifndef CONFIG_DISABLE_PTHREAD
/* Pthreads *******************************************************************/
/* Pthread join Info: */
sem_t tg_joinsem; /* Mutually exclusive access to join data */
FAR struct join_s *tg_joinhead; /* Head of a list of join data */
@ -357,15 +359,15 @@ struct task_group_s
uint8_t tg_nkeys; /* Number pthread keys allocated */
#endif
#ifndef CONFIG_DISABLE_SIGNALS
/* POSIX Signal Control Fields ************************************************/
#ifndef CONFIG_DISABLE_SIGNALS
sq_queue_t sigpendingq; /* List of pending signals */
#endif
#ifndef CONFIG_DISABLE_ENVIRON
/* Environment variables ******************************************************/
#ifndef CONFIG_DISABLE_ENVIRON
size_t tg_envsize; /* Size of environment string allocation */
FAR char *tg_envp; /* Allocated environment strings */
#endif
@ -376,19 +378,19 @@ struct task_group_s
* life of the PIC data is managed.
*/
#if CONFIG_NFILE_DESCRIPTORS > 0
/* File descriptors ***********************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
struct filelist tg_filelist; /* Maps file descriptor to file */
#endif
#if CONFIG_NFILE_STREAMS > 0
/* FILE streams ***************************************************************/
/* In a flat, single-heap build. The stream list is allocated with this
* structure. But kernel mode with a kernel allocator, it must be separately
* allocated using a user-space allocator.
*/
#if CONFIG_NFILE_STREAMS > 0
#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
FAR struct streamlist *tg_streamlist;
#else
@ -396,16 +398,24 @@ struct task_group_s
#endif
#endif
#if CONFIG_NSOCKET_DESCRIPTORS > 0
/* Sockets ********************************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0
struct socketlist tg_socketlist; /* Maps socket descriptor to socket */
#endif
/* POSIX Named Message Queue Fields *******************************************/
#ifndef CONFIG_DISABLE_MQUEUE
/* POSIX Named Message Queue Fields *******************************************/
sq_queue_t tg_msgdesq; /* List of opened message queues */
#endif
#ifdef CONFIG_ADDRENV
/* POSIX Named Message Queue Fields *******************************************/
/* POSIX Named Message Queue Fields *******************************************/
group_addrenv_t addrenv; /* Task group address environment */
#endif
};
#endif
@ -508,7 +518,7 @@ struct tcb_s
int pterrno; /* Current per-thread errno */
/* State save areas ***********************************************************/
/* The form and content of these fields are processor-specific. */
/* The form and content of these fields are platform-specific. */
struct xcptcontext xcp; /* Interrupt register save area */

View file

@ -1,7 +1,7 @@
/****************************************************************************
* sched/pthread/pthread_create.c
*
* Copyright (C) 2007-2009, 2011, 2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011, 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -254,11 +254,11 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
return ENOMEM;
}
#ifdef HAVE_TASK_GROUP
/* Bind the parent's group to the new TCB (we have not yet joined the
* group).
*/
#ifdef HAVE_TASK_GROUP
ret = group_bind(ptcb);
if (ret < 0)
{
@ -267,14 +267,11 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
}
#endif
/* Share the address environment of the parent task. NOTE: Only tasks
* created throught the nuttx/binfmt loaders may have an address
* environment.
*/
#ifdef CONFIG_ADDRENV
ret = up_addrenv_share((FAR const struct tcb_s *)g_readytorun.head,
(FAR struct tcb_s *)ptcb);
/* Share the address environment of the parent task group. */
ret = up_addrenv_attach(ptcb->group,
(FAR const struct tcb_s *)g_readytorun.head);
if (ret < 0)
{
errcode = -ret;
@ -323,9 +320,9 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
priority = SCHED_FIFO;
}
#if CONFIG_RR_INTERVAL > 0
/* Get the scheduler policy for this thread */
#if CONFIG_RR_INTERVAL > 0
policy = sched_getscheduler(0);
if (policy == ERROR)
{
@ -358,9 +355,9 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
pthread_argsetup(ptcb, arg);
#ifdef HAVE_TASK_GROUP
/* Join the parent's task group */
#ifdef HAVE_TASK_GROUP
ret = group_join(ptcb);
if (ret < 0)
{
@ -373,11 +370,11 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
ptcb->joininfo = (FAR void *)pjoin;
#if CONFIG_RR_INTERVAL > 0
/* If round robin scheduling is selected, set the appropriate flag
* in the TCB.
*/
#if CONFIG_RR_INTERVAL > 0
if (policy == SCHED_RR)
{
ptcb->cmn.flags |= TCB_FLAG_ROUND_ROBIN;

View file

@ -193,10 +193,10 @@ int sched_releasetcb(FAR struct tcb_s *tcb, uint8_t ttype)
/* Release this thread's reference to the address environment */
#ifdef CONFIG_ADDRENV
ret = up_addrenv_release(tcb);
ret = up_addrenv_detach(tcp->group, tcb);
#endif
/* Leave the group (if we did not already leady in task_exithook.c) */
/* Leave the group (if we did not already leave in task_exithook.c) */
#ifdef HAVE_TASK_GROUP
group_leave(tcb);