nuttx/Documentation/os/memory/addrenv.rst
Vinicius May f6ecf80ebb Documentation: brand new layout for NuttX documentation.
The documentation grew one page at a time, so the tree follows the
history of who wrote what and not the shape of NuttX. Scheduling is
spread over three places, a driver page can sit above the subsystem
that owns it, and the front page lists everything at the same level.
That is a lot to face when all you want to know is where the scheduler
lives.

This change files every page under the code it describes. It is a move,
not a rewrite: outside the ten pages named below, every page keeps the
text that is already in master, and no page's text is deleted.

What it does:

* Groups the table of contents into nine chapters.
* Moves the OS subsystems under os/: scheduling, memory, drivers,
  filesystem, networking, IPC, interrupts, libs, time.
* Renames the platform pages to the names the source tree uses, and
  derives their tags from the tree instead of by hand.
* Splits guides/ by subject.
* Adds Documentation/redirects.py, with a rule for every page that left
  its old path, so old URLs keep working. The redirect page also carries
  a link's #anchor across to the new page.

Ten pages have text that is new or rewritten. Nine of them are the
landing page of a chapter, which has to exist for the new structure:

    index                  the front page
    os/index               OS Design
    os/scheduling/index    Scheduling
    os/interrupts/index    Interrupts
    os/ipc/index           IPC
    os/time/index          Time and timers
    about/index            About
    developing/index       Developing NuttX
    ReleaseNotes/index     Release notes

The tenth is os/libs/libbuiltin, the only page here with technical
content: libs/libbuiltin/ had no page at all. Five SVG diagrams come
with these pages, hand-written XML with no editor metadata.

Nothing outside Documentation/ is touched.

How it was checked:

* Sphinx builds with -W: no warnings, and no document left outside a
  toctree.
* A script, offered in the PR, proves the narrow claim this rests on.
  For every page outside the ten named above it erases what a move
  touches -- link target, path, tag line, toctree block, table border --
  from the whole old text and the whole new text, and requires the two
  to be byte for byte identical. It also requires every sentence of a
  deleted page to turn up somewhere, and every page that left its old
  path to have a redirect, from a URL that existed, to where its content
  went. It exits non-zero and names the page if any of that is not true,
  and it tests added pages too, so forgetting to declare one cannot make
  it pass.
* An independent audit checked 133 factual claims on these ten pages
  against the tree, one shell command per claim: 130 confirmed, 1
  refuted and fixed here, 2 not checkable.
* tools/checkpatch.sh is clean over the range.

The diff is large because moving a page changes every link that points
to it. Most of it is pure renames, and board pages that gained one tag
line.

Assisted-by: Claude:claude-opus-5
2026-10-08 01:40:54 +08:00

286 lines
13 KiB
ReStructuredText

====================
Address Environments
====================
CPUs that support memory management units (MMUs) may provide
*address environments* within which tasks and their child threads
execute. The configuration indicates the CPUs ability to support
address environments by setting the configuration variable
``CONFIG_ARCH_HAVE_ADDRENV=y``. That will enable the selection of
the actual address environment support which is indicated by the
selection of the configuration variable ``CONFIG_ARCH_ADDRENV=y``.
These address environments are created only when tasks are created
via ``exec()`` or ``exec_module()`` (see
``include/nuttx/binfmt/binfmt.h``).
When ``CONFIG_ARCH_ADDRENV=y`` is set in the board configuration,
the CPU-specific logic must provide a set of interfaces as defined
in the header file ``include/nuttx/arch.h``. These interfaces are
listed below and described in detail in the following paragraphs.
The CPU-specific logic must provide two categories in interfaces:
#. **Binary Loader Support**. These are low-level interfaces used
in ``binfmt/`` to instantiate tasks with address environments.
These interfaces all operate on type ``arch_addrenv_t`` which
is an abstract representation of a task group's address
environment and the type must be defined in\ ``arch/arch.h`` if
``CONFIG_ARCH_ADDRENV`` is defined. These low-level interfaces
include:
- :c:func:`up_addrenv_create()`: Create an address environment.
- :c:func:`up_addrenv_destroy()`: Destroy an address environment.
- :c:func:`up_addrenv_vtext()`: Returns the virtual base address of the ``.text`` address environment.
- :c:func:`up_addrenv_vdata()`: Returns the virtual base address of the ``.bss``/``.data`` address environment.
- :c:func:`up_addrenv_heapsize()`: Return the initial heap size.
- :c:func:`up_addrenv_select()`: Instantiate an address environment.
- :c:func:`up_addrenv_clone()`: Copy an address environment from one location to another.
#. **Tasking Support**. Other interfaces must be provided to
support higher-level interfaces used by the NuttX tasking
logic. These interfaces are used by the functions in ``sched/``
and all operate on the task group which as been assigned an
address environment by ``up_addrenv_clone()``.
- :c:func:`up_addrenv_attach()`: 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.
- :c:func:`up_addrenv_detach()`: Release the thread's reference to a group address
environment when a task/thread exits.
#. **Dynamic Stack Support**. ``CONFIG_ARCH_STACK_DYNAMIC=y``
indicates that the user process stack resides in its own
address space. This option is also *required* if
``CONFIG_BUILD_KERNEL`` and ``CONFIG_LIBC_EXECFUNCS`` are
selected. Why? Because the caller's stack must be preserved in
its own address space when we instantiate the environment of
the new process in order to initialize it.
**NOTE:** The naming of the ``CONFIG_ARCH_STACK_DYNAMIC``
selection implies that dynamic stack allocation is supported.
Certainly this option must be set if dynamic stack allocation
is supported by a platform. But the more general meaning of
this configuration environment is simply that the stack has its
own address space.
If ``CONFIG_ARCH_STACK_DYNAMIC=y`` is selected then the
platform specific code must export these additional interfaces:
- :c:func:`up_addrenv_ustackalloc()`: Create a stack address environment
- :c:func:`up_addrenv_ustackfree()`: Destroy a stack address environment.
- :c:func:`up_addrenv_vustack()`: Returns the virtual base address of the stack
- :c:func:`up_addrenv_ustackselect()`: Instantiate a stack address environment
#. If ``CONFIG_ARCH_KERNEL_STACK`` is selected, then each user
process will have two stacks: (1) a large (and possibly
dynamic) user stack and (2) a smaller kernel stack. However,
this option is *required* if both ``CONFIG_BUILD_KERNEL`` and
``CONFIG_LIBC_EXECFUNCS`` are selected. Why? Because when we
instantiate and initialize the address environment of the new
user process, we will temporarily lose the address environment
of the old user process, including its stack contents. The
kernel C logic will crash immediately with no valid stack in
place.
If ``CONFIG_ARCH_KERNEL_STACK=y`` is selected then the platform
specific code must export these additional interfaces:
- :c:func:`up_addrenv_kstackalloc`: Allocate the process kernel stack.
.. c:function:: int up_addrenv_create(size_t textsize, size_t datasize, \
size_t heapsize, FAR arch_addrenv_t *addrenv);
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.
:param textsize: The size (in bytes) of the ``.text`` address
environment needed by the task. This region may be read/execute
only.
:param datasize: The size (in bytes) of the ``.bss/.data`` address
environment needed by the task. This region may be read/write
only.
:param heapsize: The initial size (in bytes) of the heap address
environment needed by the task. This region may be read/write
only.
:param addrenv: The location to return the representation of the
task address environment.
:return: Zero (OK) on success; a negated errno value on failure.
.. c:function:: int up_addrenv_destroy(arch_addrenv_t *addrenv)
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 up_addrenv_create().
:param addrenv: The representation of the task address environment
previously returned by ``up_addrenv_create()``.
:return: Zero (OK) on success; a negated errno value on failure.
.. c:function:: int up_addrenv_vtext(FAR arch_addrenv_t addrenv, FAR void **vtext)
Return the virtual .text address associated with the newly create
address environment. This function is used by the binary loaders
in order get an address that can be used to initialize the new task.
:param addrenv: The representation of the task address environment
previously returned by ``up_addrenv_create()``.
:param vtext: The location to return the virtual address.
:return: Zero (OK) on success; a negated errno value on failure.
.. c:function:: int up_addrenv_vdata(FAR arch_addrenv_t *addrenv, size_t textsize, FAR void **vdata)
Return the virtual .text address associated with the newly create
address environment. This function is used by the binary loaders
in order get an address that can be used to initialize the new task.
:param addrenv: The representation of the task address environment
previously returned by ``up_addrenv_create()``.
:param textsize: For some implementations, the text and data will
be saved in the same memory region (read/write/execute) and, in
this case, the virtual address of the data just lies at this
offset into the common region.
:param vdata: The location to return the virtual address.
:return: Zero (OK) on success; a negated errno value on failure.
.. c:function:: ssize_t up_addrenv_heapsize(FAR const arch_addrenv_t *addrenv)
Return the initial heap allocation size. That is the amount of
memory allocated by up_addrenv_create() when the heap memory
region was first created. This may or may not differ from the
heapsize parameter that was passed to up_addrenv_create().
:param addrenv: The representation of the task address environment
previously returned by ``up_addrenv_create()``.
:return: The initial heap size allocated is returned on success;
a negated errno value on failure.
.. c:function:: int up_addrenv_select(arch_addrenv_t *addrenv)
After an address environment has been established for a task
(via up_addrenv_create()), this function may be called 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
to access address environment private data.
:param addrenv: The representation of the task address environment
previously returned by ``up_addrenv_create()``.
:return: Zero (OK) on success; a negated errno value on failure.
.. c:function:: int up_addrenv_clone(FAR const task_group_s *src, FAR struct task_group_s *dest)
Duplicate an address environment. This does not copy the underlying
memory, only the representation that can be used to instantiate
that memory as an address environment.
:param src: The address environment to be copied.
:param dest: The location to receive the copied address
environment.
:return: Zero (OK) on success; a negated errno value on failure.
.. c:function:: int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb)
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 "cloned" for the child thread.
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.
:param group: The task group to which the new thread belongs.
:param ctcb: The TCB of the thread needing the address
environment.
:return: Zero (OK) on success; a negated errno value on failure.
.. c:function:: int up_addrenv_detach(FAR struct task_group_s *group, FAR struct task_group_s *tcb)
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.
:param group: The group to which the thread belonged.
:param tcb: The TCB of the task or thread whose the address
environment will be released.
:return: Zero (OK) on success; a negated errno value on failure.
.. c:function:: int up_addrenv_ustackalloc(FAR struct tcb_s *tcb, size_t stacksize)
This function is called when a new thread is created in order
to instantiate an address environment for the new thread's stack.
up_addrenv_ustackalloc() is essentially the allocator of the
physical memory for the new task's stack.
:param tcb: The TCB of the thread that requires the stack address
environment.
:param stacksize: The size (in bytes) of the initial stack address
environment needed by the task. This region may be read/write
only.
:return: Zero (OK) on success; a negated errno value on failure.
.. c:function:: int up_addrenv_ustackfree(FAR struct tcb_s *tcb)
This function is called when any thread exits. This function then
destroys the defunct address environment for the thread's stack,
releasing the underlying physical memory.
:param tcb: The TCB of the thread that no longer requires the
stack address environment.
:return: Zero (OK) on success; a negated errno value on failure
.. c:function:: int up_addrenv_vustack(FAR const struct tcb_s *tcb, FAR void **vstack)
Return the virtual address associated with the newly create stack address environment.
:param tcb: The TCB of the thread with the stack address environment of interest.
:param vstack: The location to return the stack virtual base address.
:return: Zero (OK) on success; a negated errno value on failure.
.. c:function:: int up_addrenv_ustackselect(FAR const struct tcb_s *tcb)
After an address environment has been established for a task's
stack (via up_addrenv_ustackalloc(). This function may be called to
instantiate that address environment in the virtual address space.
This is a necessary step before each context switch to the newly
created thread (including the initial thread startup).
:param tcb: The TCB of the thread with the stack address
environment to be instantiated.
:return: Zero (OK) on success; a negated errno value on failure.
.. c:function:: int up_addrenv_kstackalloc(FAR struct tcb_s *tcb)
This function is called when a new thread is created to allocate the
new thread's kernel stack. This function may be called for certain
terminating threads which have no kernel stack. It must be
tolerant of that case.
:param tcb: The TCB of the thread that requires the kernel stack.
:return: Zero (OK) on success; a negated errno value on failure.
.. c:function:: int up_addrenv_kstackfree(FAR struct tcb_s *tcb);
This function is called when any thread exits. This function frees the kernel stack.
:param tcb: The TCB of the thread that no longer requires the
kernel stack.
:return: Zero (OK) on success; a negated errno value on failure.