From 1d586e6136404bd1a46b09a066b07be111d3ab8a Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 22 Aug 2014 12:32:34 -0600 Subject: [PATCH] An address environment is the property of a task group, not of a thread --- Documentation/NuttXBinfmt.html | 4 +- Documentation/NuttxPortingGuide.html | 145 ++++++++++--------- arch/z80/include/z180/arch.h | 3 +- arch/z80/include/z180/irq.h | 6 +- arch/z80/src/z180/z180_mmu.c | 209 +++++++++++---------------- binfmt/binfmt_execmodule.c | 6 +- include/nuttx/arch.h | 122 +++++++++------- include/nuttx/binfmt/binfmt.h | 2 +- include/nuttx/binfmt/elf.h | 4 +- include/nuttx/binfmt/nxflat.h | 6 +- include/nuttx/sched.h | 52 ++++--- sched/pthread/pthread_create.c | 21 ++- sched/sched/sched_releasetcb.c | 4 +- 13 files changed, 278 insertions(+), 306 deletions(-) diff --git a/Documentation/NuttXBinfmt.html b/Documentation/NuttXBinfmt.html index 2f4f6e4252..0df3b6475e 100644 --- a/Documentation/NuttXBinfmt.html +++ b/Documentation/NuttXBinfmt.html @@ -8,7 +8,7 @@

NuttX Binary Loader

-

Last Updated: January 16, 2013

+

Last Updated: August 22, 2014

@@ -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) */ diff --git a/Documentation/NuttxPortingGuide.html b/Documentation/NuttxPortingGuide.html index 011048d2a3..88c7bb2e1c 100644 --- a/Documentation/NuttxPortingGuide.html +++ b/Documentation/NuttxPortingGuide.html @@ -12,7 +12,7 @@

NuttX RTOS Porting Guide

-

Last Updated: August 21, 2014

+

Last Updated: August 22, 2014

@@ -107,13 +107,13 @@ 4.4 Address Environments 4.5 APIs Exported by NuttX to Architecture-Specific Logic -
4.3.4.4.5 up_alarm_start()
+
4.3.4.4.4 up_alarm_start()

Function Prototype:

-

4.4.2 up_addrenv_vaddr()

+

4.4.2 up_addrenv_destroy()

Function Prototype:

+

Description:

+ +

Input Parameters:

+ +

Returned Value:

+ + +

4.4.3 up_addrenv_vaddr()

+

Function Prototype:

+

Description:

-

4.4.3 up_addrenv_select()

+

4.4.4 up_addrenv_select()

Function Prototype:

Description:

Returned Value:

@@ -3045,7 +3061,7 @@ VxWorks provides the following comparable interface: Zero (OK) on success; a negated errno value on failure. -

4.4.4 up_addrenv_restore()

+

4.4.5 up_addrenv_restore()

Function Prototype:

-

4.4.5 up_addrenv_destroy()

-

Function Prototype:

-

-

Description:

- -

Input Parameters:

- -

Returned Value:

- -

4.4.6 up_addrenv_assign()

Function Prototype:

Description:

Input Parameters:

Returned Value:

-

4.4.7 up_addrenv_share()

+

4.4.7 up_addrenv_attach()

Function Prototype:

Description:

Input Parameters:

Returned Value:

-

4.4.8 up_addrenv_release()

+

4.4.8 up_addrenv_detach()

Function Prototype:

Description:

Input Parameters:

Returned Value:

diff --git a/arch/z80/include/z180/arch.h b/arch/z80/include/z180/arch.h index d7cf82a268..72306b9309 100644 --- a/arch/z80/include/z180/arch.h +++ b/arch/z80/include/z180/arch.h @@ -1,6 +1,5 @@ /**************************************************************************** * arch/z80/arch.h - * arch/chip/arch.h * * Copyright (C) 2012 Gregory Nutt. All rights reserved. * Author: Gregory Nutt @@ -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 /**************************************************************************** diff --git a/arch/z80/include/z180/irq.h b/arch/z80/include/z180/irq.h index 1d0c27cb47..ba809bad84 100644 --- a/arch/z80/include/z180/irq.h +++ b/arch/z80/include/z180/irq.h @@ -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]; diff --git a/arch/z80/src/z180/z180_mmu.c b/arch/z80/src/z180/z180_mmu.c index 4306eaf5fd..c54fda1482 100644 --- a/arch/z80/src/z180/z180_mmu.c +++ b/arch/z80/src/z180/z180_mmu.c @@ -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 * * 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; } diff --git a/binfmt/binfmt_execmodule.c b/binfmt/binfmt_execmodule.c index 13c6920188..c765724bd7 100644 --- a/binfmt/binfmt_execmodule.c +++ b/binfmt/binfmt_execmodule.c @@ -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 * * 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; diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 4fb3a193ad..b1e972be54 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -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 /**************************************************************************** diff --git a/include/nuttx/binfmt/binfmt.h b/include/nuttx/binfmt/binfmt.h index 4e5052a7fd..e9bc03a787 100644 --- a/include/nuttx/binfmt/binfmt.h +++ b/include/nuttx/binfmt/binfmt.h @@ -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) */ diff --git a/include/nuttx/binfmt/elf.h b/include/nuttx/binfmt/elf.h index 7bfe0d9a3d..9f058d6e1f 100644 --- a/include/nuttx/binfmt/elf.h +++ b/include/nuttx/binfmt/elf.h @@ -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 */ diff --git a/include/nuttx/binfmt/nxflat.h b/include/nuttx/binfmt/nxflat.h index c87235c684..c3a7ce29d4 100644 --- a/include/nuttx/binfmt/nxflat.h +++ b/include/nuttx/binfmt/nxflat.h @@ -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) */ diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index f0e52de3f4..5ef5337fca 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -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 * * 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 */ diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c index 9ee5cc5d9c..85ec3c5d8c 100644 --- a/sched/pthread/pthread_create.c +++ b/sched/pthread/pthread_create.c @@ -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 * * 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; diff --git a/sched/sched/sched_releasetcb.c b/sched/sched/sched_releasetcb.c index 7c7eeae3a4..3899911f3f 100644 --- a/sched/sched/sched_releasetcb.c +++ b/sched/sched/sched_releasetcb.c @@ -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);