| Age | Commit message (Collapse) | Author |
|
The byte allocate saves the time stamp of its own trace entry and comes back to
fill in the address it allocated, unless a later event overwrote the entry
meanwhile. Interrupts are off across all of the service but the pool search, and
nothing in the kernel writes a trace event in that gap, so the other arm never
ran.
The Linux port already calls out to the harness inside that gap:
TX_BYTE_ALLOCATE_EXTENSION exists for coverage work and sits between the restore
and the disable that bracket the search. It gains a second clause, under its own
flag, calling a routine the harness declares weakly. 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 has the hook write a user event, which
lands on exactly that entry. Neither half reaches the arm alone.
One configuration cannot take it at all, and that is a property of the port
rather than of the test: under TX_MISRA_ENABLE the trace time stamp comes from a
function whose body returns zero, so every entry reads zero and the comparison
is 0 == 0 whatever overwrites it. The test drives the overwrite there too and
asserts the consequence only where the time source is real.
805/805 in each of the seven configurations. Union coverage is 4383/4383 lines
and 3150/3170 branches against 3147/3168; the denominator gains the new clause's
two outcomes and both are covered. Gate raised to 99.30.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
Under TX_MISRA_ENABLE three kernel loops test a value produced by a function
whose whole body returns a constant, so the arm that goes round again cannot
execute; the six configurations without the macro compile a plain call, with no
loop and no branch at all. Two of the three are the mutex put's prioritize loops
and the third is the timer thread's own body.
Two new tests define those shim functions themselves. The kernel is built shared
and every internal call to either goes through the procedure linkage table, so
the executable's definition is the one the kernel reaches and no build file
changes. A shim that withholds success on alternate calls sends each mutex loop
round exactly twice; the prioritize processing runs unaltered and is idempotent,
so the release still leaves the mutex unowned, the suspension list empty and the
inherited priority given back, which the test asserts. The timer thread's loop is
that thread's whole body, so leaving it ends the thread: that test proves the
timer is doing its work first, arms the shim last, and depends on no tick
afterwards. Both files record which symbol they replace, why replacing it
preserves what surrounds it, and where the replaced function's own coverage comes
from -- the other tests, which call both shims through these same constructs.
798/798 in each of the seven configurations. Union coverage is 4383/4383 lines
and 3147/3168 branches against 3144 before, the three being one loop exit each;
no other outcome moved. Gate raised to 99.25.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
Four scheduler services check the stack of the thread they are about to hand the
processor to, and reach that check through a test of whether it differs from the
thread that is running. An idle system satisfies that test with no thread to
execute at all, and the kernel counts the case explicitly, but no ordinary
sequence produces it: the one path that leaves no thread to execute returns to
the scheduler from inside the suspend, without reaching any of the four.
A new test clears the thread to execute and enters one of the four services
inside a single interrupt lockout, so the tick cannot put a thread back between
the clear and the test the service makes of it. The ready list, the priority map
and the highest ready priority are left correct, so the first scheduler operation
afterwards recomputes the pointer; a periodic one-tick timer runs throughout, so
each idle period ends at the next tick rather than at a retry. The test asserts
that the thread was rescheduled and is the thread to execute again, so a service
that returned without going through the scheduler fails it rather than covering
nothing.
784/784 in each of the seven configurations. Union coverage is 4383/4383 lines
and 3144/3168 branches against 3140 before, the four being the null arm at each
of the four sites; no other outcome moved. Gate raised to 99.15.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
The trace object registry carried three decisions ordinary use never reaches.
The name copy stops at the string's terminator, so it never left the loop by its
own count; it had no caller that passed no name at all, so the check that
recognises one was never true and the line behind it never ran; and the search
that reuses an old entry prefers a later free entry to an earlier one unless the
earlier one has never held a valid object, which nothing the kernel registers
produces.
A new regression test creates one object whose name is longer than a registry
entry keeps room for and one with no name at all, and asserts the entry each
leaves behind. It then fills the registry, registering one entry with the object
type the registry treats as not valid, frees that entry last so the search starts
there, and registers again - so the search meets a free entry that has never held
a valid object and keeps it rather than moving on. The test asserts the new
object landed in that entry.
The registry is now at 65/65 lines and 42/42 branches, and common/src is at
4339/4339 lines - every line of the certified source is reached in at least one
of the six build configurations. Branches are at 4599/4627, up 3 outcomes and the
last uncovered line, with the gates raised to 99.95 and 99.30 to hold them.
111/111 tests pass in each of the six.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
Five in-line trace inserts sit in the trace component itself rather than in a
service that uses it: two in the enable, one in the interrupt control, one in
each of the two inserts a port's interrupt shim makes around an ISR, and one in
the user event insert. Between them they scored four to seven of the twelve
branch outcomes the macro carries.
A new regression test walks the four ordinary ones once per condition the macro
distinguishes: tracing off altogether, thread context with every event enabled,
their three event classes filtered out, interrupt context through the test ISR
dispatch, initialization context, the state an interrupt presents, and a
positioned buffer wrap with and without a buffer-full notification registered.
None of these services has an error checking shell in front of it and none
refuses a caller on the strength of the system state, so the published entry
points reach every insert in every state. The interrupt control is driven as the
kernel's own lockout macros drive it, a disable whose returned posture is handed
straight back, so the pair is balanced whatever posture it is called in. The
buffer is positioned and the service called under one lockout, because the tick's
own ISR inserts would otherwise take the boundary.
A second test drives the two inserts the enable writes itself. They run a few
lines after the buffer pointer and the event enable bits are both set, so the
only things left free are the system state, whether the buffer holds a single
entry, and what a notification called from inside the first insert does before
the second runs. The enable is given a buffer sized from the kernel's own
structures to hold exactly one event, with three notifications: one that counts,
one that filters the running event's class, and one that turns tracing off - the
shape an application capturing a single bufferful of history uses.
Four of the five inserts now score twelve of twelve. The user event insert
reaches eleven: its own guard on the buffer pointer, a few lines above and inside
the same lockout, makes the insert's null arm unreachable. The enable's first
insert reaches ten for the same kind of reason - the buffer pointer and the
enable bits are assigned above it. Merged over the six build configurations:
4338/4339 lines and 4596/4627 branches, up 36 outcomes, with the branch gate
raised to 99.20 to hold them. 110/110 tests pass in each of the six.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
A MISRA build routes the kernel's pointer conversions, its user timer derivation
and its thread stack check through functions in the compliance shim. Four of
them had no caller in any build configuration: the stack check and the user
timer derivation are only reached from code the shim's own configuration
compiles out, and two of the conversions are only used by the trace sources,
which a MISRA build does not compile either. The shim carried 24 uncovered lines
and 14 uncovered branch outcomes, all of it certified source.
A new regression test drives each of them through the macro the kernel itself
uses, so the shim and the in-line form the other five configurations compile are
asserted to agree. The stack check is the one with logic in it, and it is driven
the way the in-line form is: a scratch thread is created on a buffer of the
test's own with a fence on each side, given one fault at a time, and checked with
the fault in place. The faults reach the stack going deeper than recorded, each
of the two fences overwritten, the lowest recorded pointer dropped below the
stack, the word under that pointer used, a control block that is no longer a
thread, and no thread at all. Nothing is written outside the scratch thread's
control block and its own fenced stack, and the thread is never started, so no
faulted state is ever visible to the scheduler.
The compliance shim is now at 81/81 lines and 18/18 branches. Merged over the
six build configurations: 4338/4339 lines and 4560/4627 branches, up 24 lines
and 14 outcomes, with the gates raised to 99.90 and 98.40 to hold them. 108/108
tests pass in each of the six.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
The six in-line trace inserts in the memory byte pool services were reached in
one system state only, so each scored one or five of the twelve branch outcomes
the macro carries.
A new regression test walks the six services once per condition the macro
distinguishes: thread context with every event enabled, the byte pool trace
event class filtered out, interrupt context through the test ISR dispatch,
initialization context, the state an interrupt presents, and a positioned buffer
wrap with and without a buffer-full notification registered. Only the prioritize
and information services are driven from the ISR: the shell rejects a byte
allocate and a byte release from an interrupt outright, where the block pool
permits an allocate that does not ask to suspend. The forced-state passes drive
the internal entry points, and no byte pool service reads the system state
itself, so the internal entry point reaches every insert in every state. The
byte pool search restores interrupts to their previous posture rather than
enabling them outright, so the lockout the forced-state pass holds survives the
allocate.
A second test drives the allocate service's trace update in place, the same way
its block pool counterpart is driven: the path that finds memory immediately,
the path that suspends until a release hands it some, and then the suspending
path again with the trace buffer written all the way round while the thread is
suspended, so the service correctly declines to update an entry that now belongs
to a different event.
Every byte pool insert now scores twelve of twelve, and the subsystem is at
413/413 lines and 381/382 branches. The one outcome left is the same one the
block pool leaves: the arm that needs an event written over the same slot
between the insert and the check on the immediate path. Merged over the six
build configurations: 4314/4339 lines and 4546/4627 branches, up 5 lines and 64
outcomes, with the gates raised to 99.30 and 98.00 to hold them.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
The six in-line trace inserts in the memory block pool services were reached in
one system state only, so each scored one or five of the twelve branch outcomes
the macro carries.
A new regression test walks the six services once per condition the macro
distinguishes: thread context with every event enabled, the block pool trace
event class filtered out, interrupt context through the test ISR dispatch,
initialization context, the state an interrupt presents, and a positioned buffer
wrap with and without a buffer-full notification registered. The forced-state
passes drive the internal entry points, because the error checking shell rejects
a create from an interrupt and a delete from any caller that is not a thread, so
the inserts behind those two cannot be reached through the published ones. No
block pool service reads the system state itself, so the internal entry point
reaches every insert in every state.
A second test drives the allocate service's trace update in place. The service
records its event, remembers the entry and its time stamp, and comes back to
write the address of the block it handed out into that same entry, but only if
the time stamp says no later event has taken the slot. Neither of the two
regions had ever run with tracing enabled over the service, so both the update
and the lines behind it were dead in the report. The test walks the path that
finds a block immediately and the path that suspends until a release hands one
over, and then drives the suspending path again with the trace buffer written
all the way round while the thread is suspended, so the service correctly
declines to update an entry that now belongs to a different event.
Every block pool insert now scores twelve of twelve, and the subsystem is at
278/278 lines and 251/252 branches. The one outcome left is the arm that needs
an event written over the same slot between the insert and the check on the
immediate path, where the whole window is interrupt-locked and contains no other
insert. Merged over the six build configurations: 4309/4339 lines and 4482/4627
branches, up 5 lines and 64 outcomes, with the gates raised to 99.20 and 96.50
to hold them.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
The six in-line trace inserts in the event flags services were reached in one
system state only, so each scored one or five of the twelve branch outcomes the
macro carries.
A new regression test walks the six services once per condition the macro
distinguishes: thread context with every event enabled, the event flags trace
event class filtered out, interrupt context through the test ISR dispatch,
initialization context, the state an interrupt presents, and a positioned buffer
wrap with and without a buffer-full notification registered. The forced-state
passes drive the internal entry points, because the error checking shell rejects
a create from an interrupt and a delete from any caller that is not a thread, so
the inserts behind those two cannot be reached through the published ones.
A second test covers the remaining arm of the get service's suspension check. A
request for no flags at all cannot be satisfied under any option, so a thread
that suspended on it would never be resumed and the service refuses the
suspension instead. The companion arm, a suspension requested while preemption
is disabled, is already driven by the test control preempt-disable safeguard.
Every event flags insert now scores twelve of twelve, and the subsystem is at
396/396 lines and 421/421 branches. Merged over the six build configurations:
4304/4339 lines and 4418/4627 branches, up 60 outcomes, with the branch gate
raised to 95.00 to hold them.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
The six in-line trace inserts in the mutex services were reached in one system
state only, so each scored one or five of the twelve branch outcomes the macro
carries.
A new regression test walks the six services once per condition the macro
distinguishes: thread context with every event enabled, the mutex trace event
class filtered out, interrupt context through the test ISR dispatch,
initialization context, the state an interrupt presents, and a positioned buffer
wrap with and without a buffer-full notification registered. The forced-state
passes drive the internal entry points, because the error checking shell rejects
a create, a get and a put from an interrupt and a delete from any caller that is
not a thread, so the inserts behind those four cannot be reached through the
published ones. The resident mutex carries no priority inheritance, so a release
with nothing suspended on it takes the simple path and the pass leaves the
calling thread's priority alone.
Every mutex insert now scores twelve of twelve, and the subsystem is at 517/517
lines and 513/517 branches. The four outcomes left are the exit arms of the four
TX_MISRA_ENABLE release loops, whose condition is produced unconditionally.
Merged over the six build configurations: 4304/4339 lines and 4358/4627
branches, up 58 outcomes, with the branch gate raised to 94.00 to hold them.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
The eight in-line trace inserts in the counting semaphore services were reached
in one system state only, so each scored one or five of the twelve branch
outcomes the macro carries.
A new regression test walks the eight services once per condition the macro
distinguishes: thread context with every event enabled, the semaphore trace
event class filtered out, interrupt context through the test ISR dispatch,
initialization context, the state an interrupt presents, and a positioned buffer
wrap with and without a buffer-full notification registered. The forced-state
passes drive the internal entry points, because the error checking shell rejects
a create from an interrupt and a delete from any caller that is not a thread, so
the inserts behind those two cannot be reached through the published ones.
Every semaphore insert now scores twelve of twelve, and the subsystem is at
356/356 lines and 340/340 branches. Merged over the six build configurations:
4304/4339 lines and 4300/4627 branches, up 80 outcomes, with the branch gate
raised to 92.50 to hold them.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
The eight in-line trace inserts in the application timer and system time
services were reached in one system state only, so each scored one or five
of the twelve branch outcomes the macro carries.
A new regression test walks the eight services once per condition the macro
distinguishes: thread context with every event enabled, both of the services'
trace event classes filtered out, interrupt context through the test ISR
dispatch, initialization context, the state an interrupt presents, and a
positioned buffer wrap with and without a buffer-full notification registered.
The forced-state passes drive the internal entry points, because the error
checking shell rejects a create from an interrupt, a delete from any caller
that is not a thread, and a change from initialization, so the inserts behind
those three cannot be reached through the published ones.
All eight sites now score twelve of twelve. Merged over the six build
configurations: 4304/4339 lines and 4220/4627 branches, up 80 outcomes, with
the branch gate raised to 91.00 to hold them.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
TX_THREAD_STACK_CHECK sits on ten sites across the scheduler and scores seven
conditions at each of them. Ordinary use only ever takes the clean arm of five:
the stack pointer never goes below the lowest recorded, neither fence word is
overwritten, the lowest recorded pointer stays inside the stack, the word under
it is still fill, and the control block is always a thread. The ten sites sat
between eight and eleven of fourteen for that reason, 47 outcomes in all.
The new test gives a thread a fault, drives a site, and takes the fault out
again. Five faults, each written into the thread's own control block or into the
fence words around its stack: the lowest recorded stack pointer put above the
thread's stack pointer, the fence above the stack overwritten, the lowest
recorded pointer dropped below the stack, the word under it made used, and the
fence below the stack overwritten. A sixth pass clears the thread identifier,
which is the arm that makes the check skip the block entirely.
Three things about it need stating.
The fault is applied and removed around each step rather than around a pass. The
first site to see a thread whose recorded stack pointer is wrong repairs that
pointer on its way through, so a pass driven with one application of the fault
covers the first site and nothing after it.
Two sites look at the thread that is going to run rather than the one being
operated on, and reaching them needs the two to differ. A time slice rotation
leaves the peer as the thread to execute while the test thread is still the one
running, which is the only arrangement that separates them; preemption is held
off across the rotation and the service that follows it, because a tick in
between would act on the rotation and the peer repairs itself on its way back.
The threads that run while a thread identifier is cleared use the internal entry
points. The error checking shell rejects such a block before the service behind
it is reached, so a peer that relinquishes through the published entry point
would stop relinquishing for as long as the fault is in place.
The file also closes the two parts of the stack machinery no fault reaches: a
create handed an odd stack address, which rounds it up and takes another word
off the size, and the error handler's MISRA build, where there is no application
handler to call and the function exists only to keep its argument referenced.
The ten sites reach thirteen of fourteen, tx_thread_create.c and
tx_thread_stack_error_handler.c reach 100%, and every tx_thread_* file is at
100% line. What is left in the batch is eighteen branch outcomes, all of them
arms that need something the test side cannot produce: a null thread pointer at
nine of the sites, which every caller of the scheduler makes impossible; the
second check in _tx_thread_system_resume seeing a stack pointer the first one has
already recorded; the sleep service's trace insert, which its own system state
test puts out of reach at anything but thread level; and the trace update's
"a later event overwrote this one", which needs an event inserted inside a
window the kernel holds interrupts off across.
Merged coverage over the six build configurations rises from 4097/4627 branches
to 4140/4627 and from 4300/4339 lines to 4304/4339, identical across three clean
runs. The gates go to 99.10 and 89.00.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
Every thread service carries one TX_TRACE_IN_LINE_INSERT, and gcov scores twelve
branch outcomes for the macro. Seventeen of those inserts sat between one and
nine of twelve, because exactly one test in the suite ever turns tracing on and
it does not drive the thread API. The code runs -- the sites are hit hundreds of
thousands of times -- but tracing is never enabled when it does.
The new test follows the shape the queue subsystem established. It enables
tracing and walks all sixteen services once per condition the macro
distinguishes: in thread context, in interrupt context from the test ISR
dispatch, with the system state forced to TX_INITIALIZE_IN_PROGRESS and again to
the value an interrupt presents, with the thread and internal event classes
filtered out, and across a buffer wrap with and without a buffer-full
notification registered.
Three things are specific to this subsystem rather than inherited from the queue
test.
The scheduler's inserts sit behind the published ones. A resume writes an API
event and then _tx_thread_system_resume writes an internal event of its own, so
positioning the buffer one entry short of its end puts the API insert on the
boundary and never the scheduler's. The wrap pass therefore drives the resume
and the suspend twice, positioned one entry short and then two.
The scheduler also updates the entry it wrote, once it knows which thread runs
next, and only if the timestamp says nothing overwrote it in between. That
update is unreachable unless a resume actually preempts while tracing is on, so
the test ends with a pass that resumes a higher-priority thread and takes the
processor back from it four times. The three regions of
_tx_thread_system_suspend and the two of _tx_thread_system_resume are reached
this way; what is left uncovered in them is the arm where the timestamp differs,
which needs a second event inserted inside a window the kernel holds interrupts
off across.
The sleep service tests the system state itself, ahead of its own insert, and
refuses every caller that is not a thread. Its insert is therefore only ever
reached at system state zero and stops at nine of twelve. Neither the published
entry point nor the internal one can reach the other three.
A thread's lifecycle does not close on itself the way a queue's does: a reset is
only legal from the terminated state, which a reset does not leave the thread
in. So the reset is driven against a second scratch thread that the service
terminates again on its way out, after its own insert has run, and the first
scratch thread is created and deleted once per pass as the queue was.
Merged coverage over the six build configurations rises from 3927/4627 branches
to 4097/4627, with lines at 4300/4339. Every thread trace insert but the sleep
is now at twelve of twelve. The gates go to 99.00 and 88.00, below the measured
figures by the margin the resume-from-ISR variance needs: two clean runs agree
exactly on lines and differ by one branch outcome.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
Each queue service carries one TX_TRACE_IN_LINE_INSERT, and gcov scores twelve
branch outcomes for the macro. Nine of those inserts sat at one or five of
twelve, 91 uncovered outcomes in all, because exactly one test in the suite ever
turns tracing on and it does not drive the queue API. The code runs -- the sites
are hit hundreds of times -- but tracing is never enabled when it does.
The new test enables tracing and walks all nine services once per condition the
macro distinguishes: in thread context, in interrupt context from the test ISR
dispatch, with the system state forced to TX_INITIALIZE_IN_PROGRESS, with the
queue event class filtered out, and across a buffer wrap with and without a
buffer-full notification registered. That is every arm of the macro, so all nine
sites reach twelve of twelve and the whole queue subsystem -- 22 files, 596
lines, 394 branches -- is at 100% line and branch in the trace configuration and
in the merged report.
Two techniques need stating, because both reach into the kernel from the test
rather than through the API.
The system state is written directly, with interrupts held off across the pass.
The initialization arm of the macro is otherwise unreachable: the only caller
that runs at that state is tx_application_define, and under the ctest harness
that entry point belongs to the test control code, not to the test. Interrupts
are disabled for the pass so the timer thread cannot observe the forced value,
and the same variable's interrupt nesting count is restored before anything else
reads it.
Create and delete are driven through _tx_queue_create and _tx_queue_delete in
the forced-state passes. The error checking shell rejects both from any caller
that is not a thread, so the inserts behind it cannot be reached any other way.
The shell itself is already at 100% from its own tests; what these passes cover
is the insert behind it.
The trace buffer is positioned one entry short of its end before each service in
the wrap passes. Filling the buffer instead wraps it on whichever service
happens to write the last entry, which covers one site and leaves the other
eight; positioning puts each service's own insert on the boundary in turn. The
buffer is also small enough that ordinary use wraps it many times over, and the
test fails unless the notification is called once per service.
This is the test shape the remaining subsystems will follow, worked end to end on
one of them first.
Merged coverage over the five build configurations rises from 3329/4108 branches
to 3421/4108, with lines unchanged at 4204/4220. The branch gate goes to 82.50,
below the measured figure by the same margin the line gate carries, because the
resume-from-ISR sites still move between runs.
Assisted-by: Claude Code (Opus 5) <[email protected]>
|
|
|