<feed xmlns='http://www.w3.org/2005/Atom'>
<title>threadx.git/test/smp/cmake/regression, branch v6.4.1_cert</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.</subtitle>
<id>http://cgit.235523.xyz/threadx.git/atom/test/smp/cmake/regression?h=v6.4.1_cert</id>
<link rel='self' href='http://cgit.235523.xyz/threadx.git/atom/test/smp/cmake/regression?h=v6.4.1_cert'/>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/'/>
<updated>2026-09-21T04:01:02Z</updated>
<entry>
<title>Covered the user event insert's own test of a disabled trace buffer</title>
<updated>2026-09-21T04:01:02Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-21T04:01:02Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=ac514bcc246e4b57c05f5e1bf071d2bcf23be1da'/>
<id>urn:sha1:ac514bcc246e4b57c05f5e1bf071d2bcf23be1da</id>
<content type='text'>
_tx_trace_user_event_insert tests the trace buffer pointer and returns
TX_NOT_DONE if it is null; the insert sits in the else, and the macro reads the
same variable and tests it again a few instructions later, inside one
protection with nothing between. The second test's false arm had no route on one
core and was carried as unreachable.

It is an ordinary state of the running kernel on SMP, and no fault has to be
invented for it. _tx_trace_disable clears that pointer and takes no lock of any
kind, so a thread disabling tracing on one core while another is inside the
insert clears it under that core. A new test drives 300,000 inserts against a
second thread on a core of its own writing the same store the disable service
writes. No kernel symbol is replaced and both services run their own code from
end to end; the test asserts that the two threads held different cores and that
the writer's stores reached the service, and says in the file that the arm
itself is evidenced by the coverage report because nothing outside the macro can
observe it.

The pass count is sized from measurement on the slower of two machines. The arm
is taken 49 to 132 times per run on this workstation over three runs and 521 to
1298 times per run on a CI runner over seven.

136/136 in each of eight configurations, twice from clean, 3588/3612 branch
outcomes on the union basis against 3587/3612 before. Fifty standalone repeats
in each of the eight, no failures.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Covered the byte allocate's overwritten trace entry</title>
<updated>2026-09-21T00:08:56Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-21T00:08:56Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=194d128bec585d6535ff9ac37bd0ac35b8f9cafc'/>
<id>urn:sha1:194d128bec585d6535ff9ac37bd0ac35b8f9cafc</id>
<content type='text'>
The byte allocate records a trace event on the way in, saves the entry's time
stamp, and comes back to write the address it returned into that same entry --
but only if the time stamp says nothing overwrote the entry meanwhile. Nothing
in the kernel writes a trace event inside the window, so the other arm had no
agent and no test.

The Linux SMP port's TX_BYTE_ALLOCATE_EXTENSION gains a second clause, guarded
by its own flag and calling a routine the harness declares weakly, in the shape
TX_BYTE_RELEASE_EXTENSION already uses. The hook runs between the restore and
the disable that bracket the pool search, which on SMP is a real release of the
protection rather than an interrupt gap. A new test filters the byte pool event
class so the allocate's own insert writes nothing and leaves the buffer parked
on the saved entry, then lets the hook write a user event onto it; neither lever
reaches the arm without the other. No kernel symbol is replaced and the allocate
runs its own code end to end. The macro expands inside tx_byte_allocate.c, so
the new clause's if is certified-source branch: the union branch denominator
moves from 3610 to 3612 and both new outcomes are covered.

The arm closes in trace_build alone. Under TX_MISRA_ENABLE the port's trace time
source returns a constant, so the comparison reads 0 == 0 whatever the hook
writes, and the test asserts the consequence only where the time source is real.

135/135 in each of eight configurations, 3586/3612 branch outcomes on the union
basis against 3583/3610 before. Fifty standalone repeats in each of the eight,
no failures.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Covered the enable's inserts with their own event class filtered</title>
<updated>2026-09-20T22:16:05Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-20T22:16:05Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=ed6c279090c3ece241a82725389c32ecfb224f08'/>
<id>urn:sha1:ed6c279090c3ece241a82725389c32ecfb224f08</id>
<content type='text'>
The two inserts the trace enable writes read an event class the same call sets
to all ones a few hundred lines above them, so from inside the enabling thread
neither can find it disabled. A buffer-full notification reaches the second one,
because it is called from inside the first; the first has no lever of that kind
and sat at 10 of 12.

SMP has one the monoprocessor does not, and it is an arrangement rather than a
race because the enable blocks. tx_trace_event_filter is an unprotected
read-modify-write of the enable bits, while the enable takes the SMP protection
after setting them and long before either insert, so a thread already holding
the protection on another core parks the enable there for as long as it likes. A
new test takes the protection from a core of its own, waits for the bits, clears
every class and releases; the enable runs on and both inserts find the class
gone. It asserts the consequence rather than the timing - neither insert wrote
an entry, so the buffer is where the enable left it.

A first version that waited for the window instead of holding it open was
measured and discarded: it failed 11 runs of 400, and widening the window
eightfold only took that to 3 of 100. tx_trace_enable.c:391 goes to 11 of 12 and
:392 stays at 12. 133/133 in each of the eight configurations, and 50 standalone
repeats of the new test green in every one of them.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Covered the three registry decisions ordinary use never reaches</title>
<updated>2026-09-20T21:55:38Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-20T21:55:38Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=2f09a736f94d44623eae10b87cb7fefb9c3027b7'/>
<id>urn:sha1:2f09a736f94d44623eae10b87cb7fefb9c3027b7</id>
<content type='text'>
The trace object registry carried one uncovered line and three uncovered branch
outcomes. The name copy stops at the string's terminator, so it never left the
loop by its own count and never met a caller passing no name at all. The search
that reuses an entry prefers a later free one unless the earlier one has never
held a valid object, and nothing the kernel registers produces an entry that is
both in use and of no valid type.

A new test registers an object whose name is longer than a registry entry keeps
room for, one with no name, and one of the type the registry treats as not
valid. It then fills the registry, frees the not-valid entry last so the search
starts there, registers again, and asserts the new object landed in the entry
the search kept rather than in the later free one. The registry is rearranged
under one SMP protection, because every service that creates an object writes
it.

tx_trace_object_register.c goes to 66/66 lines and 42/42 branch outcomes on the
union of the eight configurations, from 65/66 and 39/42. 133/133 in each of the
eight, and 50 standalone repeats of the new test green in every one of them.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Covered both trace inserts the enable service writes itself</title>
<updated>2026-09-20T21:55:38Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-20T21:55:38Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=90707029524ff145397035ae4d9d78eec0674260'/>
<id>urn:sha1:90707029524ff145397035ae4d9d78eec0674260</id>
<content type='text'>
The enable records two running events so that a buffer handed to an analysis
tool is never empty, and those two inserts are the only ones in the kernel that
run inside the service that turns tracing on. The buffer pointer and the event
enable bits are both set a few lines above, so neither can be found in any other
state on the way in, and both inserts sat at 4 of 12.

A new test enables with a buffer sized from the kernel's own structures to hold
exactly one event, which puts both inserts on the wrap boundary, and with three
notifications: one that counts, one that filters the running event's own class,
and one that turns tracing off. The last two are what reach the second insert's
filtered and no-buffer arms, and both are ordinary application behaviour rather
than a contrivance - a notification that stops tracing is what an application
capturing a single bufferful of history does. The forced-state passes hold one
SMP protection across the write, the enable and the restore.

tx_trace_enable.c:392 goes to 12 of 12 and :391 to 10 of 12 on the union of the
eight configurations, from 4 each. The two arms left are the first insert's own
copies of the filtered and no-buffer tests, which nothing can reach between the
assignments above it and the insert. 133/133 in each of the eight, and 50
standalone repeats of the new test green in every one of them.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Covered the four trace services that carry an insert of their own</title>
<updated>2026-09-20T21:55:38Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-20T21:55:38Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=3f56bfe4826367ba5f5fad802130ce2af4650f9f'/>
<id>urn:sha1:3f56bfe4826367ba5f5fad802130ce2af4650f9f</id>
<content type='text'>
The interrupt control, the two ISR inserts and the user event insert are part of
the tracing machinery rather than users of it, and nothing drove their inserts
beyond the conditions testcontrol.c and threadx_trace_basic_test.c happen to
present. The two ISR inserts were the whole of this suite's unstable set: their
buffer-wrap arms were reached when the buffer happened to wrap under an insert,
which is why they moved between runs.

A new test walks the services once per condition the insert distinguishes, and
positions the buffer one entry short of its end rather than waiting for it to
wrap, under one SMP protection and asserting the wrap per service. The interrupt
control is driven at the outermost level only, and is left out of the pass that
runs from interrupt context: _tx_thread_interrupt_control takes the Linux
critical section on every call and hands it back in full only on an enable, so a
pair completed where the section is already held leaves it two levels deeper and
locks the process. Its disable half runs inside the protection, where the insert
is, and its enable half once the protection is released. Its own forced-state
passes reach the two arms the interrupt pass would have covered.

All four sites go to 12 of 12 on the union of the eight configurations, from
7, 5, 5 and 6. 133/133 in each of the eight, and 50 standalone repeats of the
new test green in every one of them.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Covered the MISRA shim's stack check and its two conversions</title>
<updated>2026-09-20T21:55:38Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-20T21:55:38Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=32def98fc0e277f1fa782646f15112938d74f15b'/>
<id>urn:sha1:32def98fc0e277f1fa782646f15112938d74f15b</id>
<content type='text'>
Three regions of tx_misra.c had no caller in any of the eight build
configurations. The thread stack check is reached through TX_THREAD_STACK_CHECK,
whose call sites sit inside TX_ENABLE_STACK_CHECKING and which is redirected to
the shim only under TX_MISRA_ENABLE, and no configuration defines both. The user
timer derivation's six call sites are behind TX_TIMER_ENABLE_PERFORMANCE_INFO,
three of them behind TX_TIMER_PROCESS_IN_ISR as well. The trace entry conversion
has no caller in common_smp/src at all.

A new test drives all three through the macro the kernel itself uses, so the
shim and the in-line form the other builds compile are asserted to agree. The
stack check is the one with logic in it, and is given a scratch thread one fault
at a time: a cleared identifier, either stack fence overwritten, the recorded
high-water mark moved above the stack pointer and below the stack. That thread
is created with TX_DONT_START on a fenced buffer of the test's own and never
runs, so no faulted state is ever visible to the scheduler.

tx_misra.c goes from 138/163 lines and 16/30 branch outcomes to 163/163 and
30/30 on the union of the eight configurations. 133/133 in each of the eight,
and 50 standalone repeats of the new test green in every one of them.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Covered the byte pool search retry when the pool changes owner</title>
<updated>2026-09-20T17:10:47Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-20T17:10:47Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=7e6960210fec350a3c5f0857e88665a9ac6ec69b'/>
<id>urn:sha1:7e6960210fec350a3c5f0857e88665a9ac6ec69b</id>
<content type='text'>
Where the SMP byte pool search gives the protection up, it checks on taking it
back whether the pool is still its own, and if not it delays, resets the walk and
claims the pool again. Three branch outcomes and eight lines of that were never
executed. The pool owner is written in six places, all of them kernel services,
and none can run on the searching thread's own core while that thread is inside
the walk, so the construct needs a second core in use. The existing contention
test does not reach it because its pool is too small to open the window at all:
the protection is only given up once per multiple block search limit.

A new test keeps the test thread on its own core and puts one claim thread on
each of the others, each making the same unsatisfiable request and so walking the
same pool. A claim thread is then usually already holding the protection when the
test thread reaches a window, which is the state the construct is written
against. The test waits for every claim thread to be mapped and claiming before
it starts searching, rather than sleeping a fixed number of ticks, because how
long the rebalance takes varies by configuration. It asserts the arrangement
rather than the retry, which restores the owner the walk had already set and
leaves nothing a test can read.

Three outcomes and eight lines, measured at 48,971 changes of owner in a run of
2.6 seconds. This is the second test in the suite that needs more than one core.
129/129 in each of eight configurations with retries disabled, and sixty
standalone repeats clean in the three configurations that schedule it slowest.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Covered the byte pool search past its multiple block limit</title>
<updated>2026-09-20T17:10:47Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-20T17:10:47Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=440e80c6961d1cd70dc4918ee6aafc520645089f'/>
<id>urn:sha1:440e80c6961d1cd70dc4918ee6aafc520645089f</id>
<content type='text'>
The SMP byte pool search walks the pool holding the protection and gives it up
every TX_BYTE_POOL_MULTIPLE_BLOCK_SEARCH blocks, so that a long walk does not
lock the other cores out for its whole duration. No test fragmented a pool past
that limit, so the release and the reacquire behind it were never executed and
the branch that guards them stood at one of two. The region has no monoprocessor
counterpart: that search gives the protection up on every block and has no
counter.

A new test fills a pool with small fragments until it refuses another, checks it
broke into at least twice the limit, and then asks for one more. Every block is
then in use or too small, so the search examines all of them and crosses the
limit several times. The walk length is the pool's fragment count plus one and
nothing else runs, so there is no timing in it. The limit is not a feature gate:
tx_api.h defines it to 20 unless the application overrides it, so the region is
compiled in every configuration.

One outcome and three lines, in all eight configurations. 129/129 in each with
retries disabled.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Covered the byte allocate trace update on both of its paths</title>
<updated>2026-09-20T17:10:46Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-20T17:10:46Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=a19782d1cf8f436b2c23013bedd844daa143b51c'/>
<id>urn:sha1:a19782d1cf8f436b2c23013bedd844daa143b51c</id>
<content type='text'>
The byte allocate keeps the same trace update in place the block allocate does,
in the same two regions, and it was uncovered for the same reason: no test had
run the service with tracing enabled, so the entry pointer checks stood at one of
two and the time stamp comparisons at zero of two.

A new test drives it with the three passes the block pool test uses. One
configuration reaches less of it than the others and that is a property of the
port rather than of the test: under TX_MISRA_ENABLE the trace time source is a
routine whose body returns a constant, so every entry carries the same time stamp
and the comparison reads equal whatever has been written over the entry. The
overwritten round drives the same arm as the intact one there, and the arm that
declines to update is reached in the plain trace configuration alone.

Seven of the eight outcomes and all seven lines. The remaining one is the false
arm of the immediate path's comparison. 129/129 in each of eight configurations
with retries disabled.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
