This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new 72018699a examples/fdpicxip, testing/fs/xipfs: Each task group has its 
own library.
72018699a is described below

commit 72018699a3fe59df30eb6952fce175df23aee553
Author: Marco Casaroli <[email protected]>
AuthorDate: Wed Oct 7 19:17:30 2026 +0200

    examples/fdpicxip, testing/fs/xipfs: Each task group has its own library.
    
    The NuttX change "libs/libc/elf: Keep a module registry per task group"
    gives each task group its own list of loaded ELF objects.  A library that
    a module names in DT_NEEDED is now loaded once per task group, not once
    for the system.  Two instances of a module thus have two copies of the
    library data.  The library text in xipfs is still shared, and is pinned
    once per instance.
    
    Change the C++ test to check this:
    
    * The library is pinned twice while both instances run.
    * The library destructor runs once per instance.
    * Each destructor sees only the adds of its own instance.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 examples/fdpicxip/fdpicxip_main.c                 |  6 ++--
 examples/fdpicxip/modules/cxxuser/cxxuser.cpp     | 15 ++++------
 examples/fdpicxip/modules/libcounter/libcounter.c |  8 ++----
 examples/fdpicxip/modules/libshape/libshape.cpp   |  8 ++----
 examples/fdpicxip/modules/user/user.c             |  9 ++----
 testing/fs/xipfs/xipfs_main.c                     | 34 +++++++++++------------
 6 files changed, 33 insertions(+), 47 deletions(-)

diff --git a/examples/fdpicxip/fdpicxip_main.c 
b/examples/fdpicxip/fdpicxip_main.c
index 9041fe534..b945fb388 100644
--- a/examples/fdpicxip/fdpicxip_main.c
+++ b/examples/fdpicxip/fdpicxip_main.c
@@ -123,10 +123,8 @@ static int extent_info_path(FAR const char *path,
  *
  * Stages a library and a module that needs it, then runs two instances.
  * Both share one mapped copy of each object's code, executed in place from
- * flash.  Each instance gets its own copy of the module's data, because
- * exec() loads the module afresh; the library is opened with dlopen() and
- * so there is one of it, data included.  The totals therefore interleave,
- * and each instance checks only that its own adds all landed.
+ * flash.  Each instance is a task group with its own copy of the data of
+ * the module and of the library, so each total holds its own adds only.
  ****************************************************************************/
 
 static int stage_blob(FAR const char *path, FAR const unsigned char *data,
diff --git a/examples/fdpicxip/modules/cxxuser/cxxuser.cpp 
b/examples/fdpicxip/modules/cxxuser/cxxuser.cpp
index f788e1174..e8a524787 100644
--- a/examples/fdpicxip/modules/cxxuser/cxxuser.cpp
+++ b/examples/fdpicxip/modules/cxxuser/cxxuser.cpp
@@ -28,12 +28,10 @@
  *   - constructors ran, in both objects.  Neither magic can be right by
  *     accident: an unconstructed global is zero.
  *   - the library's constructors ran before this module's, which is the
- *     ordering DT_NEEDED implies and the loader has to honour.  They ran
- *     once, for the one library, not once per instance.
- *   - the library is one object shared by both instances.  DT_NEEDED is
- *     loaded with dlopen(), which returns what is already in the module
- *     registry, so the totals interleave rather than each reaching seed*3.
- *     Each instance can still see every add it made.
+ *     ordering DT_NEEDED implies and the loader has to honour.
+ *   - each instance has its own library data.  A DT_NEEDED library belongs
+ *     to the task group that loads it, so each total reaches seed*3.  Only
+ *     the library text is shared.
  */
 
 #include <fcntl.h>
@@ -191,10 +189,7 @@ extern "C" int main(int argc, char *argv[])
       usleep(100000);
     }
 
-  /* The other instance is adding to the same library at the same time, so
-   * the total is not this instance's alone.  What must hold is that every
-   * add this instance made landed in it.
-   */
+  /* Every add this instance made must be in the total */
 
   if (shape_total() < seed * 3)
     {
diff --git a/examples/fdpicxip/modules/libcounter/libcounter.c 
b/examples/fdpicxip/modules/libcounter/libcounter.c
index ccf2a9cde..e44bb69b1 100644
--- a/examples/fdpicxip/modules/libcounter/libcounter.c
+++ b/examples/fdpicxip/modules/libcounter/libcounter.c
@@ -23,11 +23,9 @@
 /* A shared library with its own state.
  *
  * g_calls is the interesting part: it lives in the library's writable
- * segment, and there is one of it.  A library named in DT_NEEDED is opened
- * with dlopen(), which hands back the instance already in the module
- * registry, so every task that names this library counts into the same
- * g_calls.  The library's code, meanwhile, is mapped once and executed in
- * place.
+ * segment.  Each task group that names this library in DT_NEEDED loads its
+ * own instance, so each has its own g_calls.  The library's code is mapped
+ * once and executed in place.
  */
 
 /****************************************************************************
diff --git a/examples/fdpicxip/modules/libshape/libshape.cpp 
b/examples/fdpicxip/modules/libshape/libshape.cpp
index a40df451e..63adb15f6 100644
--- a/examples/fdpicxip/modules/libshape/libshape.cpp
+++ b/examples/fdpicxip/modules/libshape/libshape.cpp
@@ -30,11 +30,9 @@
  * demo checks for a magic rather than just printing a total: the failure
  * this is here to catch does not announce itself.
  *
- * m_total is the second half: it lives in the library's writable segment,
- * of which there is one.  A library named in DT_NEEDED is opened with
- * dlopen(), which returns the object already in the module registry, so
- * two tasks naming this library share its data as well as its
- * flash-resident code, and m_total ends up counting both of them.
+ * m_total is the second half: it lives in the library's writable segment.
+ * Each task group that names this library loads its own instance, so each
+ * has its own m_total.  Only the flash-resident code is shared.
  */
 
 #include <nuttx/compiler.h>
diff --git a/examples/fdpicxip/modules/user/user.c 
b/examples/fdpicxip/modules/user/user.c
index 7f8faf7b1..2a26df1e9 100644
--- a/examples/fdpicxip/modules/user/user.c
+++ b/examples/fdpicxip/modules/user/user.c
@@ -20,12 +20,9 @@
  *
  ****************************************************************************/
 
-/* Uses libcounter.so.  Two instances run concurrently, and there is one
- * library between them: DT_NEEDED is loaded with dlopen(), which returns
- * the object already in the registry rather than a second copy of it, so
- * the totals interleave and the final one counts both instances' bumps.
- * What each instance can assert on its own is that every bump it made
- * landed somewhere it can still see.
+/* Uses libcounter.so.  Two instances run concurrently.  Each instance is a
+ * task group with its own copy of the library data, so its total counts
+ * its own bumps.  The library text is shared.
  *
  * libcounter is also a *leaf* library -- it calls nothing outside itself,
  * so it has no PLT and therefore no DT_PLTGOT.  The loader has to fall back
diff --git a/testing/fs/xipfs/xipfs_main.c b/testing/fs/xipfs/xipfs_main.c
index 3e98bc075..904cf3dad 100644
--- a/testing/fs/xipfs/xipfs_main.c
+++ b/testing/fs/xipfs/xipfs_main.c
@@ -2371,14 +2371,13 @@ static void test_fdpic(void)
 
   usleep(150000);
 
-  /* One library, so one pin.  Both instances name it in DT_NEEDED, the
-   * loader opens it with dlopen(), and the second open takes a reference to
-   * what the first loaded rather than loading it again.
+  /* Each instance is a task group with its own registry, so each loads
+   * the library: one pin per instance on the one flash copy.
    */
 
   ret = extent_info(PATH("libshape.so"), &info);
-  CHECK("one flash copy of the library, pinned once for both instances",
-        ret == 0 && info.pincount == 1, "wrong pin count");
+  CHECK("one flash copy of the library, pinned once per instance",
+        ret == 0 && info.pincount == 2, "wrong pin count");
 
   /* Wait for both, but do not read the exit status from waitpid().
    *
@@ -2426,23 +2425,20 @@ static void test_fdpic(void)
         (fails & USER_FAIL_LIB_CTOR) == 0, "global left as .bss");
   CHECK("the library was constructed before the module needing it",
         (fails & USER_FAIL_ORDER) == 0, "wrong DT_NEEDED order");
-  CHECK("every add an instance makes lands in the one shared library",
+  CHECK("every add an instance makes lands in its library",
         (fails & USER_FAIL_SHARED) == 0, "an instance lost its own adds");
 
   /* Destructors run on unload, which happens as each task is reaped --
    * after waitpid() has already returned.
    *
-   * The library is one object, so its destructor runs once, when the last
-   * instance holding it goes.  Both instances handed it a marker path and
-   * the second one to do so won, which is why this looks for exactly one
-   * file rather than for a particular one.  What it holds is the total of
-   * both instances' adds: three each of one and two.
+   * Each instance has its own copy of the library data, so each destructor
+   * writes its own marker with only its own adds: three of its seed.
    */
 
   usleep(200000);
 
   found = 0;
-  total = -1;
+  total = 0;
 
   for (i = 0; i < 2; i++)
     {
@@ -2450,14 +2446,18 @@ static void test_fdpic(void)
       if (ret >= 0)
         {
           found++;
-          total = ret;
+        }
+
+      if (ret == 3 * (i + 1))
+        {
+          total++;
         }
     }
 
-  CHECK("the library's destructor ran once, at the last close",
-        found == 1, "marker missing or written twice");
-  CHECK("it ran with the state both instances had built up",
-        total == 3 * (1 + 2), "wrong total");
+  CHECK("the library's destructor ran once per instance",
+        found == 2, "marker missing");
+  CHECK("each ran with the state of its own instance only",
+        total == 2, "wrong total");
 
   ret = extent_info(PATH("libshape.so"), &info);
   CHECK("the library's pins return to zero once both instances are gone",

Reply via email to