summaryrefslogtreecommitdiff
path: root/utility
AgeCommit message (Collapse)Author
2026-09-28Made ThreadX object names const-qualifiable behind an option (#761)Frédéric Desbiens
Fixes #61 Object names are exposed as writable pointers throughout the kernel API, which rejects string literals in C++ and lets a caller modify a name an object still holds. Information services return those names through writable double pointers. Create services, control blocks, information services, the module manager and trace registration now preserve const qualification, behind TX_ENABLE_CONST_NAMES. The option defaults to off, so a build that says nothing gets exactly the types it got before. It is opt-in rather than opt-out because it changes the type of a public struct field: application code that copies a name into a writable CHAR * stops compiling, which is a reasonable thing to ask of a minor release and not of a patch one. Issue #780 tracks making it the default in 6.6. Two things the option reaches that its own call sites do not. TX_CHAR_TO_UCHAR_POINTER_CONVERT has exactly two users, both of them reading an object name in _tx_trace_object_register, and every form of that macro but the MISRA one casts the qualifier away without saying so; the conversion is now const in and const out, so nothing launders const to make the build pass. The FreeRTOS adapter holds the name pcTaskGetName retrieves in a TX_NAME_CONST pointer so that it tracks whichever declaration tx_thread_info_get has, and keeps its writable return type through an explicit MISRA C:2012 Rule 11.8 cast, because that signature is part of the FreeRTOS API. Default build: all seven host configurations and all five SMP configurations build with zero warnings and pass -- 113/113 on five host configurations, 100/100 on the two MISRA builds, 118/118 on SMP, 3/3 FreeRTOS. With TX_ENABLE_CONST_NAMES set, the host default and both MISRA configurations, the SMP trace configuration and the FreeRTOS adapter build with zero warnings and pass. Co-authored-by: Tilen Majerle <[email protected]> Assisted-by: Codex (gpt-6-astra) <[email protected]> Assisted-by: Claude Code (Opus 5) <[email protected]>
2026-09-15Normalized the AI disclosure comment to one fixed line per file (#740)Frédéric Desbiens
The per-edit disclosure named the product and model, so every agent and every model version appended another line. 74 files carried two to four of them, and the same five products had accumulated 13 spellings -- Copilot against GitHub Copilot, Claude Sonnet 4.6 against claude-sonnet-4.6, four spellings of Codex. Twenty assembly lines carried a doubled comment marker, `; //` or `@ //`. Every file now carries exactly one line, fixed text naming no product: Portions of this file were generated with AI assistance. It is written with the comment character that file already uses, so the `;` and `@` assembly files keep theirs and the doubled markers are gone. Precise attribution stays on the commit, where the Assisted-by trailer is per-change, dated and attached to the diff it describes. A header line cannot hold that record honestly, because the code it names gets rewritten and the line stays. A file-level flag answers whether; the history answers who. Comment-only. 455 files, 455 insertions and 574 deletions: every removed line was a disclosure line, every added line is the fixed text, and no file is left with zero or with more than one. `scripts/check_ports.sh` passes, including the reproducibility check that would catch a ports_arch master and its generated copies drifting apart. Recompiled against dev, every file that builds without a vendor toolchain gives a byte-identical object: 19 of 19 C files under common, 100 of 100 GNU assembly files, and all 16 assemblable files whose comment marker changed. The 10 remaining marker changes are ac5 and IAR sources where `;` already started the comment and only the redundant `//` was removed. Assisted-by: Claude Code (Opus 5) <[email protected]>
2026-09-09Marked every published ThreadX include directory as SYSTEM so applications ↵Frédéric Desbiens
no longer get warnings from ThreadX headers (#713) * Marked every published ThreadX include directory as SYSTEM so applications no longer get warnings from ThreadX headers Commit 8c3c08f added the SYSTEM keyword to the target_include_directories call in common/CMakeLists.txt, but the same call in every port, in the SMP common directory's consumers, in the POSIX and FreeRTOS compatibility layers, and for the generated tx_user.h directory was left unchanged. A consumer building with a strict warning set therefore still saw diagnostics coming from tx_port.h and from the compatibility layer headers, which is exactly what the original change set out to avoid. Added the SYSTEM keyword to all of those calls so CMake emits -isystem rather than -I for every directory holding a ThreadX public header. The ARMv7-M, ARMv8-M, ARMv7-A and ARMv8-A architecture sources under ports_arch were updated alongside the ports they generate, keeping the two in step. Directories that are PRIVATE to an example or test build were left as they are, since nothing is published from them. Fixes #290 Assisted-by: Copilot (Opus 5) <[email protected]> * Stopped apt-get update being a gate it was never meant to be apt-get update fails if any configured repository serves a bad index, including ones this project never reads. The GitHub runner image carries Google's and Microsoft's apt repositories, and a Hash Sum mismatch from Google's, their CDN caught mid-publish with the index and the Release file eight hours apart, failed all three attempts and turned a run red over a browser nobody was installing. Made a failed update warn and carry on, leaving apt-get install as the gate. Nothing is weakened by that: the install still exits on a package it cannot find, so an unreachable archive still stops the script, one step later and naming the package it could not get, which is a better diagnostic than a hash mismatch in a repository nobody asked for. Disabling third-party sources before updating would keep the update strict, but this script also runs on a contributor's own machine, and rewriting someone's apt configuration to suit CI would be worse than tolerating a stale index for an archive we do not read. Assisted-by: Copilot (Opus 5) <[email protected]>
2026-09-03Fixed the garbled comment in the POSIX condition variable sources (#694)Frédéric Desbiens
The comment above the internal semaphore lookup in the POSIX condition variable implementation was garbled: it contained a capitalisation typo ("COndition") and an incomplete sentence ("into a semaphore a cast"). The four affected sources now share a single, correct wording. This is a comment-only change; there is no functional impact. Fixes #419 Assisted-by: Copilot (Opus 5) <[email protected]>
2026-08-16Stopped pthread_self() faulting when the caller is not a pthread (#627)Frédéric Desbiens
Nothing prevents an application mixing tx_thread_create() with the POSIX layer, and a thread created that way has no POSIX control block. posix_thread2tcb() returns NULL for it, which posix_thread2tid() then read through: p_tcb = posix_thread2tcb(thread_ptr); thread_ID = p_tcb->pthreadID; pthread_self() went on to compound it, reading the signal fields of a POSIX_TCB out of a thread that is only a TX_THREAD: if (((POSIX_TCB *) thread_ptr) -> signals.signal_handler) The first is a null dereference and the second runs off the end of the control block into whatever the linker put there. Under qemu-system-riscv32 the first one lands first: mcause=0x5, a load access fault, with mtval=0xb4 for the offset of pthreadID. Have posix_thread2tid() report zero for a thread with no control block, which is what px_pth_join.c already does for the same call, and have pthread_self() skip the signal check unless the ID says the caller really is a pthread. Zero cannot collide with a real ID because px_pth_create.c uses the address of the control block as the ID. This also covers the case where there is no current thread at all, from an ISR or before the scheduler starts: tx_thread_identify() returns NULL, and the same zero comes back instead of a fault. Add posix_pthread_self_test, which asks both kinds of thread for their ID: a pthread, which has to report what pthread_create() returned, and a plain ThreadX thread, which has to report zero. Reverting either half of the fix turns the test into the load access fault above. Verified with riscv64-unknown-elf and qemu-system-riscv32: 4 tests across the default build, 4 of 4 passing. Assisted-by: Claude Code (Opus 5) <[email protected]>
2026-08-16Added the POSIX compatibility layer to the CMake build, with regression ↵Frédéric Desbiens
tests (#626) * Added the POSIX compatibility layer to the CMake build Nothing in the repository built the POSIX layer. The FreeRTOS layer next to it has had a target since the CMake build was introduced, so the POSIX one was the odd one out, and 106 source files went unbuilt by any target, on any architecture. Add a posix-threadx target, following the FreeRTOS layer's shape: a static library, EXCLUDE_FROM_ALL so the default build is unchanged, linking threadx and publishing its own directory as a PUBLIC include path. The sources live in their own CMakeLists.txt rather than the top-level file, as common/ does, because there are 106 of them. The seven posix_*.c files in the same directory are a demo and standalone signal tests, each with its own entry point, so they stay out of the library. The layer does not suit every configuration, and the target is only offered where it can work: - Hosted simulation ports (linux, win32, win64) build against a C library that already provides errno.h, pthread.h and the rest. The layer replaces those. Its pthread.h even uses _PTHREAD_H, the same include guard as glibc's, so its declarations are skipped wholesale and the build fails on missing types. Neutralising that guard only exposes the real problem: 69 conflicting definitions in a single translation unit, for time_t, struct timespec, sigset_t, pthread_t, pthread_mutex_t, sem_t and more. Both the layer and the C library implement POSIX, and only one of them can define those names. The linux port also emulates threads by calling the C library's pthread_create and sem_wait, which the layer exports itself, so linking the two would divert the port into the layer that sits on top of it. - SMP builds. px_int.h declares _tx_thread_current_ptr as a plain pointer, which is a per-core array under SMP, and the layer tracks no current core. Building the layer for the first time exposed one portability defect worth fixing rather than working around. tx_posix.h defined ssize_t as INT, with a comment conceding it should come from <sys/types.h>. That is correct only where the C library agrees: on AArch64 newlib makes ssize_t 64 bits, and every translation unit that reached a library header failed to compile. Defer to the library when it has declared the type, keyed on the _*_DECLARED guards newlib uses, and do the same for mode_t, which had the same problem waiting. Where no library declaration exists the previous definitions still apply, so the 32-bit targets that did build are unaffected. Verified by building posix-threadx for arm9, arm11, cortex_m0, cortex_m3, cortex_m4, cortex_m7, cortex_m33, cortex_m55, cortex_m85, cortex_a7, cortex_a9, cortex_r4, cortex_r5, cortex_a34, cortex_a53 and cortex_a55 with arm-gnu-toolchain-14.3.rel1, and for risc-v32 and risc-v64 with riscv64-unknown-elf: 18 of 18, 106 objects each. cortex_a78 has no non-SMP port and fails to configure with or without this change. Linking the result against libthreadx.a leaves only tx_application_define, _tx_initialize_low_level, the optional execution profile hooks, and memset and strlen unresolved, all of which the application or its C library supplies. The default build still produces libthreadx.a and no POSIX library. Compiling is not the same as working, and on the 64-bit targets in that list it is not enough. The layer carries a message by putting the address of a private buffer into the queue, and ULONG is 32 bits on every port, so that address only fits when TX_64_BIT is defined. Without it px_mq_send.c truncates the pointer and px_mq_receive.c casts the truncated value back, which GCC reports as nothing worse than a -Wpointer-to-int-cast warning. Defining TX_64_BIT is not a remedy either: tx_api.h then reaches for the extension pointer macros, which need tx_thread_extension_ptr in the thread control block, and outside ports_smp and ports/linux no port declares it. So the target builds everywhere, but the message queues are only sound on the 32-bit ports. That is pre-existing, it is not made worse here, and it is left for a change of its own. Assisted-by: Claude Code (Opus 5) <[email protected]> * Added regression tests for the POSIX compatibility layer The POSIX layer had no tests. The seven posix_*.c programs shipped beside it are demos: they print nothing, report no result and end in infinite loops, so they tell a person watching a debugger something and an automated run nothing. Add a suite under test/posix, laid out like the FreeRTOS one and driven the same way, with scripts/build_posix.sh and scripts/test_posix.sh over a run.sh that takes the same arguments as its RISC-V counterpart. The tests run on emulated hardware because they have nowhere else to go. The layer replaces the C library's POSIX headers and exports the same symbols the linux port calls to emulate threads, so a host build is not available to it. The RISC-V QEMU harness that the ThreadX suite already uses is, and this suite reuses its BSP and testcontrol.c rather than growing copies of them. Three tests to start: - posix_mq_basic_test sends a message through a queue and checks the contents and priority survive the round trip. - posix_mq_send_abort_test covers the leak fixed in #624, by filling a queue, blocking a sender on it, aborting the wait and watching the queue's byte pool. Reverting the fix makes it fail on the pool check, so it measures what it claims to. - posix_pthread_basic_test covers pthread creation, a mutex, a semaphore handoff, pthread_self and collecting an exit value through pthread_join. The queue's pool is sized (mq_maxmsg + 1) * (mq_msgsize + 11), which leaves room for about one message beyond a full queue, so the abort test uses small messages and a shallow queue. With a larger message the first leaked buffer exhausts the pool, tx_byte_allocate fails, and the sender disappears into the endless loop in posix_internal_error() instead of reporting anything. Sizing it this way keeps the failure legible as a pool measurement rather than a timeout. riscv32 only, and the reason is the layer rather than the harness. The layer puts the address of a message buffer into the queue, ULONG is 32 bits on every port, and a 64-bit address only fits there when TX_64_BIT is defined. Defining it makes tx_api.h use the extension pointer macros, which need tx_thread_extension_ptr in the thread control block, and no port outside ports_smp and ports/linux declares it. Configuring for risc-v64 stops with that explanation rather than building something that would corrupt a pointer at runtime. Verified with riscv64-unknown-elf and qemu-system-riscv32: 3 tests across default_build, disable_notify_callbacks_build, stack_checking_build and trace_build, 12 of 12 passing. Assisted-by: Claude Code (Opus 5) <[email protected]>
2026-08-16Stopped two POSIX call sites falling through their error handler (#625)Frédéric Desbiens
posix_internal_error() never comes back for a non-zero code: its body is "while (error_code) { ; }". Most callers in the layer still follow it with an explicit error return. Two do not, and both fall through into a pointer dereference, so they are only correct because the handler happens to hang. That is a fragile thing to rely on. The C standard permits an implementation to assume a loop with no side effects terminates (C11 6.8.5p6), so the guarantee is a property of the toolchain rather than of the language. Both toolchains the project supports do preserve the loop today - checked with GCC 14.3 at -O0, -O1, -O2 and -Os, and with Clang 22 at -O0 and -O2 - so nothing is broken right now. Neither call site should depend on that. mq_send() falls through with bp indeterminate, having just been told the allocation failed, and would copy msg_len bytes through it. Report ENOMEM and return ERROR instead. posix_thread2tid() falls through with thread_ptr NULL. posix_thread2tcb() returns NULL for that input, and the next line reads p_tcb->pthreadID. Return zero, which is never a valid pthread ID because px_pth_create.c assigns the address of the TCB as the ID. No behaviour changes while the handler keeps hanging; both additions are unreachable today. Assisted-by: Claude Code (Opus 5) <[email protected]>
2026-08-16Stopped POSIX mq_send() leaking the message buffer when the send fails (#624)Frédéric Desbiens
mq_send() allocates a private buffer from the queue's own byte pool, copies the caller's message into it, and passes the buffer's address through the queue. The receiver takes ownership: px_mq_receive.c releases the buffer once it has copied the message out. If tx_queue_send() fails, the message never reaches the queue, so no receiver will ever release that buffer. mq_send() returned ERROR while still holding the only pointer to it, leaking it from the pool. The failure is reachable. With TX_WAIT_FOREVER the send suspends, and tx_queue_send() then returns the thread's suspend status. tx_thread_wait_abort() sets TX_WAIT_ABORTED on a suspended sender, and the queue survives that, so the pool keeps shrinking with every aborted send. Queue deletion also reaches the branch, via TX_DELETED, but vq_message_area is a TX_BYTE_POOL embedded in the queue structure and destroyed with it, so nothing outlives the failure there. Exhausting the pool does not merely make later calls fail. tx_byte_allocate() failure runs into posix_internal_error(9999), which busy-loops forever on a non-zero code, so a caller hangs rather than getting an error back. Release the buffer before returning. The EINTR reporting is unchanged, since TX_WAIT_ABORTED maps onto it reasonably. Reported-by: K-ANOY <https://github.com/eclipse-threadx/threadx/issues/568> Assisted-by: Claude Code (Opus 5) <[email protected]>
2026-08-14Made the basic processing counter visible to the reporting thread (#616)Frédéric Desbiens
The thread-metric basic processing test reports 0 for every period when built with optimisation, and additionally claims "Basic processing thread died!" because the counter never differs from the previous reading. tm_basic_processing_counter is written by the processing thread and read by the reporting thread, but it was a plain global. The processing loop calls nothing, so nothing forces the compiler to write the counter back to memory, and in an infinite loop there is no exit path where it must. At -O2 with arm-none-eabi-gcc 13.2.1 the counter is loaded once before the loop, incremented in a register, and never stored: 28: ldr ip, [r3] counter loaded once ... inner loop over the volatile array 50: add ip, ip, #1 increment stays in the register 54: b 2c and around again The reporting thread reads the memory location, which stays 0 for the life of the program. This is not specific to the Armv8-R target it was reported on: the same shape appears for Cortex-M4 in Thumb state, and at -O1, -O2, -O3 and -Os. Only -O0 happens to work. Declare the counter volatile so the increment becomes a real store. Read it into a local once per pass and use the local inside the 1024-iteration loop, rather than letting every iteration re-read the volatile: that would add a memory access to each iteration and change the amount of work the test performs. This test is the baseline the rest of the suite is scaled against, per the readme, so its throughput has to stay comparable with previously published figures and with other RTOSes. The array was already volatile, which is why the arithmetic itself survives optimisation; only the counter was missing. Verified by disassembly rather than by inspection. After the change the inner loop is instruction-for-instruction identical to what dev generates today, ldr/ldr/add/eor/str/add/cmp/bne, with one volatile read hoisted above the loop and one store below it: 30: ldr ip, [lr] one read per pass, outside the loop 34: ... inner loop unchanged, back edge targets 34 54: add ip, ip, #1 58: str ip, [lr] the counter is now published 5c: b 2c Confirmed for cortex-r52 in Arm state and cortex-m4 in Thumb state. Reported by @hotislandn in #480, which identified the cause correctly. Assisted-by: Claude Code (Opus 5) <[email protected]>
2026-08-09Fixed the kernel object leaks on the static creation error paths (#584)Frédéric Desbiens
xQueueCreateStatic() and xTaskCreateStatic() take their storage from the caller, so neither leaks memory, but both create ThreadX objects and both return NULL when a later step fails. The caller is left without a handle and cannot call the matching delete function, so any object already created stays registered in the kernel, pointing into a caller buffer that the application is now free to reuse or discard. Three paths were affected. xQueueCreateStatic() abandoned the read semaphore when the write semaphore could not be created. xTaskCreateStatic() abandoned the notification semaphore when the thread could not be created, and abandoned both the semaphore and the thread when the thread could not be resumed. Delete what was already created before returning on each of them. The resume path terminates the thread before deleting it, since a thread created with TX_DONT_START is suspended rather than terminated, which is the same order the idle task uses when it reaps a deleted task. Extend the regression suite to cover all three paths, and add thread resume to the set of entry points the harness can force to fail. Each static failure case now uses its own control block, so a future regression on one path cannot carry damage into the next case and report misleading counts there. Verified against the layer as it stands on dev, where the three new checks fail with the objects left behind, and against the fixed layer, where the suite passes. Assisted-by: Claude Code (Opus 5) <[email protected]>
2026-08-09Fixed the resource leaks on the xQueueCreate error paths (#582)Frédéric Desbiens
xQueueCreate() allocated the queue descriptor and its backing memory, then created two ThreadX semaphores, and returned NULL on either semaphore failure without releasing anything. Since no handle reached the caller, vQueueDelete() could not be used to recover, so both allocations were lost. A failure on the second semaphore additionally abandoned the read semaphore it had already created, leaving a live ThreadX control block inside freed memory. Release the backing memory and the descriptor on both paths, and delete the read semaphore before returning when the write semaphore cannot be created. This is the teardown order vQueueDelete() already uses, and it matches the cleanup xTaskCreate() performs on its own error paths. Verified with a fault injection harness that intercepts the ThreadX byte pool and semaphore entry points to force tx_semaphore_create() to fail on a chosen call. On a read semaphore failure the layer previously performed 2 allocations and 0 releases, and on a write semaphore failure 2 allocations, 0 releases and 0 semaphore deletions. It now performs 2 releases in both cases and deletes the read semaphore in the second, with the byte pool restored to its prior state. Fixes https://github.com/eclipse-threadx/threadx/issues/570 Assisted-by: Claude Code (Opus 5) <[email protected]>
2026-06-22Fixed SMP execution profile total getters (#553)Frédéric Desbiens
Updated the SMP execution profile aggregate getters to copy each core's total into the matching output array element. Added a focused regression test for thread, ISR, and idle total getters. Co-authored-by: Codex <[email protected]>
2026-06-06Added copyright headers to files missing themFrédéric Desbiens
Applied the standard MIT license header to all project-owned C, header, assembly, shell, and Python files that were missing a copyright notice. Third-party, toolchain startup, and auto-generated files were excluded. Co-authored-by: Copilot <[email protected]>
2026-05-19Updated Xtensa support (#525)Ian Thompson
* Add LX8 support for > 32 interrupts Also fix inconsistent SWPRI define in interrupt handler * ThreadX: Fix context switch logic - Disable interrupts prior to allocating a large exception frame; only reenable them after deallocating the extra memory. - Any user tasks with stacks based on TX_MINIMUM_STACK do not have sufficient space for both a context switch frame and an ISR frame; ill-timed interrupts were causing stack overruns. * ThreadX: Interrupt fixes for TX_ENABLE_EXECUTION_CHANGE_NOTIFY - Must reload register trashed by notify hook function call - Must ensure PS.WOE is set before using call8 - Remove unused XT_USE_INT_WRAPPER define and associated changes, which had a bug in XEA2 usage - Fix another case where enabling the thread notify hooks for call0 ABI corrupted a register * ThreadX: Support for __DYNAMIC_REENT__ - ThreadX change to handle dynamic reent for both newlib and xclib - Adapt ThreadX xclib interface code to handle dynamic reent pointers * ThreadX: Xtensa execution profiling support - Update upstream execution profiling for Xtensa port * ThreadX: Update xtensa port readme * ThreadX: Add Xtensa example to EPK - tx_execution_profile.h now defines an Xtensa example in addition to the existing Cortex example * ThreadX: Add xtensa.cmake * ThreadX: Update XSHAL_CLIB ifdefs in __getreent() - Prevent a fall-through with no return value when neither xclib nor newlib are used.
2026-03-05Updated copyright headers and version number constants (#509)Frédéric Desbiens
* Updated version number constants * Removed revision history from all files * Added Eclipse ThreadX contributors' copyright header
2025-11-18Fix: Return 0u when no counters availablenopnopnop-lavine
2024-02-23Update the copyright for all assembly files.bo chen
2024-01-30Update version id string.Bo Chen (from Dev Box)
2024-01-29Update copyright.Bo Chen (from Dev Box)
2023-12-28Add check for overflow in queue size calculation in RTOS compatibility ↵Xiuwen Cai
layer. (#339) * Add check for overflow in queue size calculation. * Update release data and version.
2022-10-26Release 6.2.0v6.2.0_relTiejun Zhou
2022-07-26Release 6.1.12v6.1.12_relYuxin Zhou
2022-04-20Release 6.1.11Yuxin Zhou
2022-01-29Release 6.1.10Yuxin Zhou
2021-10-14Release 6.1.9Yuxin Zhou
2021-07-28Release 6.1.8v6.1.8_relYuxin Zhou
2021-06-07FreeRTOS readmeLiya Du
2021-06-02Release 6.1.7Bo Chen
2021-04-03Release 6.1.6v6.1.6_relYuxin Zhou
2021-03-05Release 6.1.5v6.1.5_relYuxin Zhou
2020-10-01add utilities and update TraceX install linkv6.1_relScott Larson