Skip to content

Commit 88870ee

Browse files
committed
examples/fdpicxip, testing/fs/xipfs: A DT_NEEDED library is one instance.
Both the demo and the test asserted that each running instance of a module gets its own copy of a library named in DT_NEEDED: two instances adding their own seed each saw a total of seed*3. That was true of the loader that walked DT_NEEDED itself. The loader now hands the work to dlopen(), which returns the object already in the module registry rather than loading a second copy of it, so there is one library and one set of its globals, shared by every module that names it. The module's own data stays private per instance, because exec() loads the module afresh each time. What an instance can still assert on its own is that every add it made landed in the library, so that is what it checks; the totals interleave and the final one counts both. The test additionally checks the consequences: the library is pinned once rather than once per instance, and its destructor runs once, at the last close, holding what both instances built up. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
1 parent e59fee5 commit 88870ee

11 files changed

Lines changed: 407 additions & 370 deletions

File tree

examples/fdpicxip/cxxuser_bin.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ static const unsigned char g_cxxuser[] =
144144
0x34, 0x4b, 0x03, 0x93, 0x30, 0x46, 0xff, 0xf7, 0x35, 0xff, 0x03, 0x98,
145145
0xa1, 0x46, 0xff, 0xf7, 0x45, 0xff, 0xba, 0xf1, 0x01, 0x0a, 0xa1, 0x46,
146146
0xf4, 0xd1, 0xff, 0xf7, 0x49, 0xff, 0x06, 0xeb, 0x46, 0x0a, 0xa1, 0x46,
147-
0x50, 0x45, 0x18, 0xbf, 0x45, 0xf0, 0x08, 0x05, 0xff, 0xf7, 0x40, 0xff,
147+
0x50, 0x45, 0xb8, 0xbf, 0x45, 0xf0, 0x08, 0x05, 0xff, 0xf7, 0x40, 0xff,
148148
0xa1, 0x46, 0x03, 0x46, 0x00, 0x2d, 0x38, 0xd1, 0x2c, 0x4a, 0x7a, 0x44,
149149
0x2c, 0x49, 0xcd, 0xe9, 0x00, 0xa2, 0x06, 0x20, 0x32, 0x46, 0x79, 0x44,
150150
0xff, 0xf7, 0x5a, 0xff, 0xb8, 0xf1, 0x03, 0x0f, 0xa1, 0x46, 0x1a, 0xdd,
@@ -175,7 +175,7 @@ static const unsigned char g_cxxuser[] =
175175
0x69, 0x72, 0x73, 0x74, 0x3a, 0x20, 0x25, 0x73, 0x0a, 0x00, 0x5b, 0x75,
176176
0x73, 0x65, 0x72, 0x20, 0x25, 0x64, 0x5d, 0x20, 0x6c, 0x69, 0x62, 0x72,
177177
0x61, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x20, 0x3d, 0x20,
178-
0x25, 0x64, 0x20, 0x28, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64,
178+
0x25, 0x64, 0x20, 0x28, 0x61, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x73, 0x74,
179179
0x20, 0x25, 0x64, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x25, 0x73, 0x0a, 0x00,
180180
0x25, 0x64, 0x00, 0x5b, 0x75, 0x73, 0x65, 0x72, 0x5d, 0x20, 0x63, 0x61,
181181
0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x20,

examples/fdpicxip/fdpicxip_main.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,10 @@ static int extent_info_path(FAR const char *path,
111111
*
112112
* Stages a library and a module that needs it, then runs two instances.
113113
* Both share one mapped copy of each object's code, executed in place from
114-
* flash, while each instance gets private copies of both the module's data
115-
* and the library's. If the library's state were shared, the two totals
116-
* would interleave instead of each reaching seed*3.
114+
* flash. Each instance gets its own copy of the module's data, because
115+
* exec() loads the module afresh; the library is opened with dlopen() and
116+
* so there is one of it, data included. The totals therefore interleave,
117+
* and each instance checks only that its own adds all landed.
117118
****************************************************************************/
118119

119120
static int stage_blob(FAR const char *path, FAR const unsigned char *data,

examples/fdpicxip/modules/Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ CPU ?= cortex-m3
4646

4747
FDPICDIR = $(NUTTX_DIR)/tools/fdpic
4848
MODULE_MK = $(FDPICDIR)/nuttx-fdpic.mk
49-
EMBED = $(FDPICDIR)/fdpic-embed
49+
EMBED = $(FDPICDIR)/fdpic-embed.py
5050

5151
# Where each generated header goes, and its path from the repository root --
52-
# fdpic-embed puts that on line 2, which is what nxstyle wants.
52+
# fdpic-embed.py puts that on line 2, which is what nxstyle wants.
5353

5454
DEMODIR = ..
5555
DEMOREL = apps/examples/fdpicxip
@@ -127,7 +127,7 @@ lazymod.fdpic: lazymod.c
127127
$(BUILD) MODULE=lazymod SRCS=lazymod.c BINDNOW=
128128

129129
# missingsym is linked with the bare .fdpic target rather than the default
130-
# 'verify' one, because it is exactly what fdpic-verify is meant to catch.
130+
# 'verify' one, because it is exactly what fdpic-verify.sh is meant to catch.
131131

132132
missingsym.fdpic: missingsym.c
133133
$(BUILD) MODULE=missingsym SRCS=missingsym.c missingsym.fdpic

examples/fdpicxip/modules/cxxuser.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@
2828
* - constructors ran, in both objects. Neither magic can be right by
2929
* accident: an unconstructed global is zero.
3030
* - the library's constructors ran before this module's, which is the
31-
* ordering DT_NEEDED implies and the loader has to honour.
32-
* - the library's data is private per instance. One copy of its code
33-
* sits in flash; the totals do not interleave.
31+
* ordering DT_NEEDED implies and the loader has to honour. They ran
32+
* once, for the one library, not once per instance.
33+
* - the library is one object shared by both instances. DT_NEEDED is
34+
* loaded with dlopen(), which returns what is already in the module
35+
* registry, so the totals interleave rather than each reaching seed*3.
36+
* Each instance can still see every add it made.
3437
*/
3538

3639
#include <fcntl.h>
@@ -87,7 +90,7 @@ static Instance g_self;
8790
#define USER_FAIL_OWN_CTOR 0x01
8891
#define USER_FAIL_LIB_CTOR 0x02
8992
#define USER_FAIL_ORDER 0x04
90-
#define USER_FAIL_PRIVATE 0x08
93+
#define USER_FAIL_SHARED 0x08
9194

9295
/****************************************************************************
9396
* Name: record
@@ -188,12 +191,17 @@ extern "C" int main(int argc, char *argv[])
188191
usleep(100000);
189192
}
190193

191-
if (shape_total() != seed * 3)
194+
/* The other instance is adding to the same library at the same time, so
195+
* the total is not this instance's alone. What must hold is that every
196+
* add this instance made landed in it.
197+
*/
198+
199+
if (shape_total() < seed * 3)
192200
{
193-
fails |= USER_FAIL_PRIVATE;
201+
fails |= USER_FAIL_SHARED;
194202
}
195203

196-
syslog(LOG_INFO, "[user %d] library total = %d (expected %d) -- %s\n",
204+
syslog(LOG_INFO, "[user %d] library total = %d (at least %d) -- %s\n",
197205
seed, shape_total(), seed * 3,
198206
fails == 0 ? "PASS" : "FAIL");
199207

examples/fdpicxip/modules/libcounter.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
/* A shared library with its own state.
2424
*
2525
* g_calls is the interesting part: it lives in the library's writable
26-
* segment, and each task that loads the library gets a private copy. The
27-
* library's code, meanwhile, is mapped once and executed in place.
26+
* segment, and there is one of it. A library named in DT_NEEDED is opened
27+
* with dlopen(), which hands back the instance already in the module
28+
* registry, so every task that names this library counts into the same
29+
* g_calls. The library's code, meanwhile, is mapped once and executed in
30+
* place.
2831
*/
2932

3033
/****************************************************************************

examples/fdpicxip/modules/libshape.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@
3131
* this is here to catch does not announce itself.
3232
*
3333
* m_total is the second half: it lives in the library's writable segment,
34-
* which is copied once per running instance, so two tasks sharing this
35-
* library's flash-resident code still count independently.
34+
* of which there is one. A library named in DT_NEEDED is opened with
35+
* dlopen(), which returns the object already in the module registry, so
36+
* two tasks naming this library share its data as well as its
37+
* flash-resident code, and m_total ends up counting both of them.
3638
*/
3739

3840
#include <fcntl.h>

examples/fdpicxip/modules/user.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@
2020
*
2121
****************************************************************************/
2222

23-
/* Uses libcounter.so. Two instances run concurrently: if the library's
24-
* data were shared between them the totals would interleave.
23+
/* Uses libcounter.so. Two instances run concurrently, and there is one
24+
* library between them: DT_NEEDED is loaded with dlopen(), which returns
25+
* the object already in the registry rather than a second copy of it, so
26+
* the totals interleave and the final one counts both instances' bumps.
27+
* What each instance can assert on its own is that every bump it made
28+
* landed somewhere it can still see.
2529
*
2630
* libcounter is also a *leaf* library -- it calls nothing outside itself,
2731
* so it has no PLT and therefore no DT_PLTGOT. The loader has to fall back
@@ -56,13 +60,13 @@ int main(int argc, char *argv[])
5660
usleep(100000);
5761
}
5862

59-
syslog(LOG_INFO, "[user %d] library total = %d (expected %d) -- %s\n",
63+
syslog(LOG_INFO, "[user %d] library total = %d (at least %d) -- %s\n",
6064
seed, counter_total(), seed * 3,
61-
counter_total() == seed * 3 ? "PASS" : "FAIL");
65+
counter_total() >= seed * 3 ? "PASS" : "FAIL");
6266

6367
/* Reported through the exit status as well as the log, so a test can
6468
* assert on it rather than a human reading the console.
6569
*/
6670

67-
return counter_total() == seed * 3 ? EXIT_SUCCESS : EXIT_FAILURE;
71+
return counter_total() >= seed * 3 ? EXIT_SUCCESS : EXIT_FAILURE;
6872
}

0 commit comments

Comments
 (0)