<feed xmlns='http://www.w3.org/2005/Atom'>
<title>threadx.git/test/tx/cmake/thread_transition, branch dev</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.</subtitle>
<id>http://cgit.235523.xyz/threadx.git/atom/test/tx/cmake/thread_transition?h=dev</id>
<link rel='self' href='http://cgit.235523.xyz/threadx.git/atom/test/tx/cmake/thread_transition?h=dev'/>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/'/>
<updated>2026-09-28T18:03:53Z</updated>
<entry>
<title>Normalized the AI disclosure comment and added a check that keeps it so (#762)</title>
<updated>2026-09-28T18:03:53Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-28T18:03:53Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=83361990cb4d03da8851e30030688ed3abb4d840'/>
<id>urn:sha1:83361990cb4d03da8851e30030688ed3abb4d840</id>
<content type='text'>
* Normalized the AI disclosure line across every tracked file type

The repository-wide pass covered source files only, so build files, CMake
toolchain files, shell scripts and the GDB and manifest files kept the older
per-edit form of the disclosure comment, which names a product and a model
version. The Cortex-R52 module manager port then merged after that pass and
brought the old form back into the sources as well.

Replaced it with the fixed text in all of them, using the comment character
each file already uses.

Comment-only. 143 files, one line each. The repository now holds 601 files
carrying exactly one disclosure line, none carrying the old form, and none
carrying more than one.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;

* Added a check that keeps the AI disclosure comment in its one accepted form

Nothing enforced the disclosure convention, so the drift it exists to prevent
returned twice: once when a port merged after the normalisation pass carrying
the older per-edit form, and once because that pass had covered source files
only, leaving build files and scripts untouched for months.

Added scripts/check_ai_disclosure.sh, which rejects the superseded per-edit
form, a doubled comment marker, more than one disclosure line in a file, and
any spelling of the line that is not exact. It runs from repo_checks.yml, a
workflow with no path filter, because a source-path filter is what hid the
build files the first time.

The check passes on this branch. Each of its four rules was confirmed to fail
on a tree with that defect reintroduced, and to pass once it was removed.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;

* Normalised the disclosure lines that landed after this branch

Thirteen files reached dev after this branch was written, each carrying the
superseded per-edit form. txm_module_manager_dispatch.h reached it with six
stacked copies, naming the same product and the same model every time -- the
accumulation the fixed text exists to prevent.

Each of those files now carries one disclosure line in the accepted form. Where
the accepted line was already present, the superseded ones are deleted rather
than converted, so no file gains a second.

check_ai_disclosure.sh reported eighteen hits across thirteen files before the
pass and passes after it.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;

* Exempted Markdown from the near-miss disclosure check

The near-miss rule flags any line carrying the phrase "AI assistance" that is
not the accepted text, which is right for source but wrong for documentation.
The contribution guide has to quote the accepted line and say when it applies,
so the check reports two paragraphs of prose as drift and fails the build.

Markdown is now exempt from that rule alone. The three rules that matter for a
documentation file -- superseded form, doubled comment marker, duplicate line
-- still scan it, so a stale disclosure in a Markdown file is still caught.

The check passes against a tree carrying the rewritten contribution guide, and
still fails when a near miss is planted in a source file.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;

* Corrected the trailer command named in the disclosure check

The header comment points a reader at git's own trailer parser to find out
which agents have touched a file. That parser reads trailers only from a block
at the very end of a message, so a squash merge -- which concatenates a
branch's messages -- buries every trailer but the last one mid-message, and an
indented trailer is skipped outright. On dev it finds 122 attributions where
163 exist.

The comment now names count_assisted_by.sh, which reads whole bodies.

Assisted-by: Claude Code (Opus 5) &lt;noreply@anthropic.com&gt;</content>
</entry>
<entry>
<title>Completed Windows simulator support and regression coverage (#736)</title>
<updated>2026-09-15T20:47:08Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-15T20:47:08Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=f5e59a1dd3cd2bdbc6214d408253a089af75a967'/>
<id>urn:sha1:f5e59a1dd3cd2bdbc6214d408253a089af75a967</id>
<content type='text'>
Completed and stabilized the Win32 and Win64 MSVC simulator ports.

- Replaced high-latency host synchronization with bounded scheduler handoffs and
  critical sections.
- Added a high-resolution timer, tick batching, idle fast-forward, shutdown
  coordination and Win64 extension-pointer support.
- Brought the Windows regression tooling and the new thread-transition tests up
  on CMake, Ninja and the Visual Studio Build Tools.
- Extended the SMP teardown diagnostics and corrected 64-bit trace-test handling.

This supersedes the historical `win64`, `win32-perf`, `windows-sim-ports` and
`windows-sim-ports-completion` branches; no unmerged change from them is missing
here. The original Win64 port landed in #529.

1,610 of 1,610 tests pass, across five configurations each: Win32 515, Win64 515,
Win64 SMP 580. No external dependency was added, and the existing MSVC warnings
in the trace configuration are unchanged. Hardware validation does not apply to
host simulator ports.

Assisted-by: Codex (gpt-5.6-sol) &lt;codex@openai.com&gt;</content>
</entry>
<entry>
<title>Refused thread delete and reset while an exit transition is in progress (#724)</title>
<updated>2026-09-10T16:04:40Z</updated>
<author>
<name>Frédéric Desbiens</name>
<email>frederic.desbiens@eclipse-foundation.org</email>
</author>
<published>2026-09-10T16:04:40Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/threadx.git/commit/?id=70741198e9f6831acf52257913d1bb9c7a5a2720'/>
<id>urn:sha1:70741198e9f6831acf52257913d1bb9c7a5a2720</id>
<content type='text'>
_tx_thread_shell_entry and _tx_thread_terminate both publish a thread's
terminal state -- TX_COMPLETED or TX_TERMINATED -- and then call that
thread's exit notification callback, before the thread has been detached
from the ready list and before either service has finished with the pointer
it holds to the control block. That terminal state is exactly the state
_tx_thread_delete and _tx_thread_reset accept as authorization to
invalidate or rebuild the control block, and neither service tested whether
the transition producing it had finished.

A callback could therefore delete the thread it was called for -- and then
lawfully recreate it over the same memory, since delete exists to permit
that -- while the scheduler was still linked to the old incarnation.
tx_thread_create zeroes the whole control block and can auto-start the new
one, so the old priority list is left heading at a block whose own priority
field names a different list, with the old priority's map bit set behind
nothing. Alternatively a callback could reset a terminated thread, which
moves it out of the terminal state, and then resume it: the interrupted-
suspension logic in _tx_thread_system_resume refuses to void a suspension
only while the state is still terminal, so with the reset allowed first the
resume clears the suspending flag and restores TX_READY, the outer service
then finds the flag clear and skips the removal, and tx_thread_terminate
returns TX_SUCCESS for a thread that is runnable again.

Interrupt masking does not close the window, because the kernel restores
the prior posture before invoking the callback deliberately. On SMP
TX_RESTORE also releases the global protection, so the target can be
executing on another core while its callback runs -- and a reset there
memsets the stack a live core is running on. On the Linux, Win32 and Win64
host simulation ports the consequence is more immediate than corruption:
TX_THREAD_DELETE_PORT_COMPLETION cancels and joins the host thread backing
the deleted thread, so a callback-side delete of the completing thread
destroys the host thread the callback is running on.

The fix marks the transition and has the two services refuse a marked
target, returning the errors they already document, TX_DELETE_ERROR and
TX_NOT_DONE. The refusal is transient and the same call succeeds once the
transition has completed, so no documented lifecycle is lost; and it is in
the core services rather than the _txe_ wrappers, so disabling error
checking cannot disable it. Refusing the reset is also what closes the
resume path, without touching _tx_thread_system_resume: its existing
terminal-state test is sufficient once nothing can turn the terminal state
into TX_SUSPENDED from inside the window.

tx_thread_suspending is the marker, rather than a new control-block field.
It already means "a suspension is in progress" and is already true across
the callback in the two interruptable paths, so no field is added, the
public structure is unchanged, and sizeof(TX_THREAD) is unchanged --
which matters, because the Module Manager's object handling depends on the
sizes of the control blocks. Widening its lifetime was checked against
every reader rather than assumed. There are four: two in
_tx_thread_system_suspend and two in _tx_thread_system_resume. In every
window this change widens, the state is TX_COMPLETED or TX_TERMINATED, and
both resume readers already refuse to void a suspension for exactly those
two states, so their behaviour is unchanged; and no suspension routine is
called on the target in those windows, so the suspend readers never see
them. No suspension-initiating service can set the marker again inside a
window either: every one of them acts on a thread that is ready or
suspended.

Three sites needed changing beyond the two refusals, and the shape of each
was decided by where the marker can safely be cleared:

  - The non-ready branch of _tx_thread_terminate cleared the marker before
    the terminated extension and the callback, which is what left them free
    to act on a control block the service still had mutex-release
    processing to do against. The clear moves to the common tail, after the
    last dereference of the target, and becomes the single clear site for
    the whole service. In the interruptable ready branch the flag is
    already false there, because _tx_thread_system_suspend cleared it when
    it detached the thread, so the tail store is a second store of a value
    the flag already holds -- cheaper than testing for it, and it keeps one
    clear site.

  - Under TX_NOT_INTERRUPTABLE neither path set the marker at all, because
    that configuration does not use the interruptable suspension path that
    sets it. Both now set it before the callback. Interrupts being disabled
    there does not help: the callback is reached by a direct call.

  - In the TX_NOT_INTERRUPTABLE completion path the marker is cleared
    before _tx_thread_system_ni_suspend rather than after it. That call
    returns to the scheduler for a thread that is the current thread, which
    a completing thread is, and does not come back; clearing afterwards
    would leave a normally completed thread marked for ever and therefore
    permanently undeletable. Nothing is lost by clearing early there,
    because everything from that point to the detachment runs with
    interrupts disabled and calls no application code.

The change is the same change twice. All four files are byte-for-byte
identical between common and common_smp at this commit and stay so after
it, so common_smp was written by copying rather than by repeating the
edits. tx_thread_system_suspend.c and tx_thread_system_resume.c, which do
differ between the kernels, are deliberately untouched.

Tests. The in-tree regression test goes to both trees and is byte-for-byte
identical between them. It drives seven scenarios: terminating a ready
non-current target with two peers ready at the same priority, with the
callback attempting the delete and recreating the block if it succeeded;
the same with the callback attempting the reset and then the resume;
terminating a target suspended on a semaphore while owning a mutex, which
is the non-ready branch; natural completion alone at its priority,
including the safe post-completion reset, terminate, delete and recreate at
another priority; self termination; a benign callback, whose notification
count and ordering are unchanged; and the state and boundary cases, where
the new refusal must not fire.

It measures rather than describes. The callback records the published
state, the marker, and the status of every lifecycle service it can reach,
calling the core service as well as the wrapper wherever a refusal is
expected. A snapshot taken under interrupt lockout -- which is the global
SMP protection on an SMP port -- checks that every ready list agrees with
the control blocks it heads, that the priority map agrees with the lists,
and that each execute pointer is a member of the list its own priority
field names. Every walk is bounded, so a corrupted ring costs an assertion
and not a hang, and no test in the suite can hang. Expectations are counted
inside a scenario and gated between scenarios, so a failing kernel reports
how much it failed by without being driven further into its own
corruption.

The consequences are demonstrated from the terminator's context rather than
the completing thread's, which is what makes the pre-fix behaviour an
assertion instead of a wedged simulator. Compiled against the unfixed
sources the test fails 9 of the 24 expectations it reaches in the
uniprocessor tree and 10 of 24 in the SMP tree, and the failures are the
finding: the callback-side delete succeeds, the recreate succeeds, the
consistency snapshot disagrees, the target is neither terminal nor detached
when the service returns, and a peer has left the ready ring the recreated
block hijacked.

The SMP tree gets a second test for the case that needs concurrency. The
victim is excluded to core 1 and spins there without relinquishing while
the controller, excluded to core 0, terminates it, so the callback runs on
one core while the target executes on another. The callback-side reset and
delete must both be refused, and a sentinel written into the unused low end
of the victim's stack must survive -- a reset would have memset the whole
stack before rebuilding the frame. Every wait is bounded, and if the remote
precondition cannot be established the test says so and drops only the
assertions that depend on it rather than reporting a pass it did not earn;
measured over twenty consecutive runs it established the precondition every
time.

TX_NOT_INTERRUPTABLE and TX_DISABLE_ERROR_CHECKING are not among the five
build configurations either tree compiles, and each tree builds the whole
library once per configuration, so neither can be reached from inside the
suites. The lines this change adds under TX_NOT_INTERRUPTABLE are therefore
in no configuration the trees build, and they are where the permanent-
undeletability failure mode lives, so they get their own harness rather
than a compile check: the four sources plus the two error wrappers are
compiled directly into a test executable, once per combination, with
recorders standing behind the scheduler services they call. That is what
makes the marker's value at the moment of detachment directly observable.
It runs 66 expectations under TX_NOT_INTERRUPTABLE, 66 under that with
error checking disabled, 45 under that with notification disabled, and 63
under error checking disabled alone; against the unfixed sources those fail
25, 22, 6 and 20 respectively. The harness lives in the uniprocessor tree
only, because the four sources are identical between the kernels and the
shim replaces the very primitive the SMP port differs in, so a second copy
would compile the same text under the same macros. It is deliberately left
out of the coverage instrumentation, since the same source under different
feature macros has a different line set and merging those would confuse the
union rather than add to it.

Results. Both suites pass in all five configurations with GCC 14: 103 of
103 in the uniprocessor tree, up from 98, and 116 of 116 in the SMP tree,
up from 114. Merged line coverage is 100% in the uniprocessor tree and
5172 of 5183 in the SMP tree, whose eleven uncovered lines are the same
eleven that were uncovered before this change and are in tx_byte_pool_search
and tx_thread_smp_utilities; all four changed files are at 100% line
coverage in both trees, and SMP branch coverage rises from 2819 of 3548 to
2831 of 3556. Cross-compiled with arm-none-eabi-gcc at -Wall -Wextra for
Cortex-M4 against common and for Cortex-A7 SMP against common_smp, all four
files produce no diagnostics at all and an identical warning set to before
the change, under -std=gnu99 and -std=c99 alike -- unlike the module ports,
-std=c99 does not fail on these base ports, and even -Wconversion is clean.

No MISRA deviation is required: explicit comparisons to TX_TRUE, existing
ThreadX types, single-entry and single-exit control flow, no goto, and two
added constant-time tests that change no real-time complexity.

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