A task woken from a semaphore, a signal wait, a message queue or an event
wait gets its timeout watchdog cancelled, but most waiters set none, and
wd_cancel() then only takes the critical section to find that out.
Check WDOG_ISACTIVE() first at these call sites. Each already holds the
critical section, so wd_expiration() cannot be running the watchdog on
another CPU and the check is exact on SMP too. wd_cancel() itself keeps
its locked check.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Add the blank line nxstyle wants after three declarations. No code
change.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
nxsig_abnormal_termination() popped the thread's pthread cleanup
handlers in the kernel, so in the protected and kernel builds a process
could get its own code called with kernel privilege by raising a fatal
signal. POSIX runs cleanup handlers on pthread_exit() and on acting upon
a cancellation; termination by a signal is as if by _exit(), which runs
none.
Signed-off-by: Royyan Zahir <royzah@gmail.com>
Add the blank line required by nxstyle between the local declaration and the following statement in task_restart().
Signed-off-by: yushuailong <yyyusl@qq.com>
Kernel threads use the statically allocated g_kthread_group. If initialization of the first kernel thread fails, the common error path currently passes that static object to kmm_free(), corrupting the kernel heap.
Only free dynamically allocated task groups and detach the failed group from the TCB before returning.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
group_kill_children() marks the task group as exiting, but task restart reuses that same group. Leaving the flag set causes later group shutdown to skip child termination and changes cancellation behavior for threads created after the restart.
Clear GROUP_FLAG_EXITING after the old child threads have been removed so the reused group starts in its normal state.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Use Floyd cycle detection on the mutex wait-for chain so only threads that actually participate in a cycle are reported. This avoids omitting the last cycle member and incorrectly including threads that merely lead into a deadlock.
Also handle empty output buffers and document truncation semantics.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
clock_get_sched_ticks() stored the value of read_seqbegin(), a
uint32_t, in an unsigned int and passed it back to read_seqretry().
Where int is 16 bits the copy is truncated, so once the 32-bit
sequence number passes 65535 read_seqretry() always reports a change
and the loop never ends. The sequence advances once per tick, so after
65536 ticks (11 minutes at 100 Hz) the next caller, the timer interrupt
itself, spins forever with interrupts disabled and the system stops.
Seen on the CDP1802 (16-bit int): NSH stopped answering after 55
minutes at 20 Hz. AVR has the same problem. hrtimer's readers of the
same lock already use uint32_t. Don't assume int is 32-bit :-D
Signed-off-by: Alan Carvalho de Assis <acassis@gmail.com>
Assisted-by: Claude Opus 5.5 (claude-opus-5-5)
Add the blank line required by nxstyle after the SMP-local declaration in
the profiling timer handler.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Round the usable profiling buffer size down to complete unsigned short
counters before deriving highpc. Without this, an odd-sized buffer can
allow the timer handler to increment a counter that extends one byte past
the buffer.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
When waitpid(-1) finds an exited child in the retained status list, honor
WNOWAIT instead of unconditionally removing and freeing the child entry.
This makes the any-child path consistent with the specific-PID and SIGCHLD
paths.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
The base firmware and an FDPIC module disagree about what a function
pointer is. Firmware is not built FDPIC, so to it a pointer is a code
address and it branches there. A module passes the address of a two word
descriptor instead, because its code and data are placed independently and
a bare code address would leave the callee unable to find its own data. A
firmware routine that takes a callback therefore branches into the
module's data segment and faults.
So the ten entry points that can be handed a callback by a module resolve
the descriptor before storing or branching to it: qsort, bsearch,
pthread_create, signal, sigaction, task_create and task_create_with_stack,
task_spawn, pthread_once, scandir, and mq_notify and timer_create with
SIGEV_THREAD.
Which one resolves matters as much as that one does. Resolving twice would
take an already resolved code address for a descriptor and read two words
from the instruction stream, so each pointer is resolved exactly once, at
the outermost point that sees it. signal() passes its argument through
untouched because sigaction() and then nxsig_action() will resolve it,
which covers a module calling sigaction() directly as well. qsort() is
split so that the public entry resolves and the recursive implementation
does not. scandir() resolves its filter but not its comparison function,
which it hands to qsort().
Whether a caller is a module at all is asked of the PIC base register,
which up_initial_state() sets only for a task that has a D-Space. A plain
kernel task therefore reads zero and is left alone.
SIGEV_THREAD is the case the register cannot answer, because the callback
runs later on a work queue worker that carries no module's base at all.
The base is captured instead when the notification is registered, in the
module's own context, and installed around the call.
All of it is behind CONFIG_FDPIC, which defaults off. Built for
mps3-an547:picostest both ways; with it off the entry points compile to
what they were.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
nxsem_init(), nxsem_destroy(), nxmutex_init(), nxmutex_destroy(),
nxrmutex_init() and nxrmutex_destroy() cannot fail, so promising a
negated errno value on failure documents an error that is never returned.
The coding standard asks the returned value description to identify all
error values of a function, and there are none, so state that OK is
always returned.
Follows "sched/semaphore: Remove the return value check of
nxsem_init/nxmutex_init", which removed the last checks of these values.
Assisted-by: DeepSeek Harness:deepseek-flash
Signed-off-by: rongbaichuan <rongbaichuan1027@163.com>
nxsem_init(), nxsem_destroy(), nxmutex_init() and nxmutex_destroy()
always return OK, so checking the result only leaves dead code: the
compiler cannot remove it, because these are cross-translation-unit calls
and the nxrmutex_destroy() test is duplicated into every inlined call
site.
Apply the convention already established in commit a47a36bc5b (PR #7473)
to the two definitions which still test the value and to the 54 remaining
call sites. No signature or prototype is changed.
Testing: stm32f103-minimum:nsh builds with -Os without new warnings.
Assisted-by: DeepSeek Harness:deepseek-flash
Signed-off-by: rongbaichuan <rongbaichuan1027@163.com>
Increase MOD_LINELEN from 64 to 256 so complete /proc/modules lines fit the formatting buffer on 64-bit targets.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Add the required blank line between the intcount declaration and the
following statement.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
irq_callback() passed snprintf()'s would-have-written length to
procfs_memcpy(). If an IRQ line exceeded IRQ_LINELEN, the copy could read
beyond the formatting buffer.
Use procfs_snprintf() so the copy is limited to the bytes actually written.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
modprocfs_callback() formatted each line into line[64] with snprintf()
and passed snprintf()'s return value, the length the line would have
had, to procfs_memcpy() as the source length. A module name longer
than a few characters therefore made the copy read past the end of
the line buffer and hand kernel heap memory to the reader, and grew
totalsize by the difference.
Use procfs_snprintf(), which returns the length actually written, as
the other procfs entries already do.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Implements the pthread_sigqueue Linux extension to pthreads. Follows a
similar implementation to sigqueue, except targeting a specific thread
through nxsig_dispatch.
Signed-off-by: Matteo Golin <matteo.golin@gmail.com>
Allocate the new handler node independently of the initial chain
conversion so handlers beyond the second are appended instead of silently
dropped. Delay vector conversion until both required nodes are available
to avoid leaving a partially constructed chain on allocation failure.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Store the jail as an absolute path on the task group, copy it to
children, and free it when the last member leaves.
Signed-off-by: Abhishek Mishra <mishra.abhishek2808@gmail.com>
1. nxsched_process_timer: call clock_update_wall_time() under
CONFIG_CLOCK_TIMEKEEPING so that wall time is updated on timer
events during tickless operation.
2. clock_timekeeping_get_wall_time: call clock_update_wall_time()
before sampling the base and counter.
3. clock_timekeeping: allow overriding NTP_MAX_ADJUST with
CONFIG_CLOCK_ADJTIME_SLEWLIMIT_PPM if configured.
4. Use clock_t consistently for counter values in clock_timekeeping.c.
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Convert failures from CLOCK_FD lookup and PTP_CLOCK_GETRES into the public
clock_getres() convention of returning ERROR and setting errno. This keeps
dynamic PTP clocks consistent with the other clock_getres() error paths.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Move the critical-monitor update after PID hash entry validation and keep
the scheduler critical section held so the TCB remains stable. Invalid or
stale PIDs now return -ESRCH instead of passing a NULL TCB to
nxsched_update_critmon().
Also add the declaration spacing required by nxstyle in the modified file.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Move RTC synchronization outside the non-timekeeping branch so setting
CLOCK_REALTIME also updates the RTC when CONFIG_CLOCK_TIMEKEEPING is
enabled. This prevents corrected wall time from reverting to an older RTC
value after restart.
Preserve the existing low-priority work queue path for RTC drivers that may
block while updating hardware.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Remove pending IRQ work before clearing its callback state, and guard the
worker callback against a concurrent detach. This prevents detached worked
IRQs from invoking a NULL function pointer.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Only call kthread_delete for a valid positive PID and always clear the IRQ
thread slot afterward. This makes detach on an unused IRQ, including a
repeated detach, a safe no-op instead of deleting the calling task.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Return ENOMEM and leave the IRQ detached when no custom work queue can be
created or all queue slots are occupied. Also release the queue mutex on
the full-table path and avoid caching a failed queue creation.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Store the thread PID only after kthread_create succeeds. This prevents a
negative error value from making subsequent attachment attempts fail with
EINVAL after a transient thread creation failure.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
strlcpy() was given sizeof(tcb->name), i.e. CONFIG_TASK_NAME_SIZE + 1,
but the documented caller contract is a buffer of CONFIG_TASK_NAME_SIZE
bytes (include/sys/prctl.h). When a task name is exactly
CONFIG_TASK_NAME_SIZE chars (the normal result of nxtask_setup_name()
truncation), the terminating NUL lands one byte past the caller buffer.
Pass CONFIG_TASK_NAME_SIZE to strlcpy() so the copy is truncated
in-bounds, and drop the stale forced-NUL line left over from the strncpy
era (it ran after the overflow had already happened).
Before:
```
guard byte placed right after a CONFIG_TASK_NAME_SIZE caller buffer
reads 0x00 (expected 0xAA) after the call: strlcpy writes its
terminating NUL one byte past the buffer when the task name is exactly
CONFIG_TASK_NAME_SIZE chars.
```
After:
```
strlcpy(name, tcb->name, CONFIG_TASK_NAME_SIZE) writes at most
CONFIG_TASK_NAME_SIZE bytes; the caller buffer stays intact.
```
Testing:
Simulated (sim:nsh, CONFIG_TASK_NAME_SIZE=31).
Build and run:
```
cmake -B build -DBOARD_CONFIG=sim:nsh -GNinja
cmake --build build -j$(nproc)
echo hello | ./build/nuttx
```
then run "hello" at the NSH prompt.
The test was carried by apps/examples/hello/hello_main.c (scratch only,
not part of this commit); its diff:
```
--- a/examples/hello/hello_main.c
+++ b/examples/hello/hello_main.c
@@ -24,6 +24,8 @@
#include <nuttx/config.h>
#include <stdio.h>
+#include <string.h>
+#include <sys/prctl.h>
/****************************************************************************
* Public Functions
@@ -35,6 +37,55 @@
int main(int argc, FAR char *argv[])
{
+ /* Longest-legal task name: exactly CONFIG_TASK_NAME_SIZE chars, the
+ * normal result of nxtask_setup_name() truncation.
+ */
+
+ static const char longname[] =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+ /* Caller buffer per the documented prctl(PR_GET_NAME) contract, with a
+ * guard byte immediately after it to detect the 1-byte overflow.
+ */
+
+ struct
+ {
+ char buf[CONFIG_TASK_NAME_SIZE];
+ volatile unsigned char guard;
+ } s;
+
+ _Static_assert(sizeof(longname) - 1 > CONFIG_TASK_NAME_SIZE,
+ "test name must exceed CONFIG_TASK_NAME_SIZE");
+
printf("Hello, World!!\n");
+ printf("prctl test: CONFIG_TASK_NAME_SIZE=%d\n", CONFIG_TASK_NAME_SIZE);
+
+ s.guard = 0xaa;
+ s.buf[0] = '\0';
+
+ if (prctl(PR_SET_NAME, (unsigned long)longname) != 0)
+ {
+ printf("prctl test: PR_SET_NAME failed\n");
+ return 1;
+ }
+
+ if (prctl(PR_GET_NAME, (unsigned long)s.buf) != 0)
+ {
+ printf("prctl test: PR_GET_NAME failed\n");
+ return 1;
+ }
+
+ printf("prctl test: guard=0x%02x (expected 0xaa), name len=%zu, "
+ "last char=0x%02x\n",
s.guard, strlen(s.buf), (unsigned char)s.buf[strlen(s.buf)]);
+
+ if (s.guard != 0xaa)
+ {
+ printf("prctl test: FAIL - terminating NUL written 1 byte past "
+ "the caller buffer\n");
+ return 1;
+ }
+
+ printf("prctl test: PASS - caller buffer intact\n");
return 0;
}
```
Before the fix:
```
prctl test: guard=0x00 (expected 0xaa), name len=30, last char=0x00
prctl test: FAIL - terminating NUL written 1 byte past the caller buffer
```
After the fix:
```
prctl test: guard=0xaa (expected 0xaa), name len=30, last char=0x00
prctl test: PASS - caller buffer intact
```
Assisted-by: Claude Code (GLM-5.3) <claude@anthropic.com>
Signed-off-by: Junbo Zheng <zhengjunbo1@xiaomi.com>
work_cancel() used to return -ENOENT when the work structure was not
in the queue, and callers depend on that: aio_cancel() tears down the
AIO container (file_put() + aioc_free()) only when work_cancel()
reports success, because a work item that is not queued may already be
executing on a worker thread (see the comment in fs/aio/aio_cancel.c).
Since commit 6f72f5481d ("sched/wqueue: Refactor delayed and periodical
workqueue") work_cancel() returns OK unconditionally, and commit
d2e01b9055 ("sched/wqueue: harden custom queue lifecycle") kept that
behaviour and dropped -ENOENT from the function documentation. Under
SMP the LTP aio_cancel tests then free the aio container and its file
while the lpwork thread is still executing aio_write_worker() on it,
which ends in a page fault in file_write() (f_inode == NULL) and a
panic.
Return -ENOENT again when the work is not queued, and document it.
For the synchronous variant "not queued" alone does not tell whether
the callback is running: the worker scan does, so report OK when a
running callback was found and waited for, and -ENOENT only when the
work was neither queued nor running.
Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
Clamp each wall-clock adjustment in both positive and negative directions, then subtract the applied amount from the remaining adjustment. This makes adjtime converge to zero and prevents large negative adjustments from slewing the clock in the wrong direction.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
CLOCK_TIMEKEEPING already provides a software-based adjtime implementation. Exclude the generic adjtime state and entry point when timekeeping is enabled, while retaining clock_adjtime support for PTP clocks.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
spawn_execattrs() discards the return value from nxsched_set_scheduler(). As a result, an invalid scheduling policy or parameter is silently ignored and the spawn operation continues with the original scheduling configuration.
Store and return the result from nxsched_set_scheduler() so that the caller can tear down the child task when applying the requested scheduler attributes fails. Update the function comments to describe the existing error return behavior.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Sporadic scheduling parameters are processed independently by sched_setparam(), sched_setscheduler(), and pthread_create(). The three paths currently validate different subsets of the parameters.
In particular, pthread_create() does not validate sched_ss_max_repl and only requires the replenishment period to be greater than the budget, while the scheduler interfaces enforce the implementation's 50 percent duty-cycle limit.
Add nxsched_validate_sporadic() to validate the common parameters and convert the replenishment period and budget to ticks. Use it from all paths that directly initialize or update sporadic scheduler state.
Express the duty-cycle check using division to avoid overflow when doubling a clock_t value.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
nxsched_set_param() applied the sporadic parameters and restarted the
replenishment timer in set_sporadic_param() before nxsched_reprioritize()
rejected an out-of-range priority with EINVAL, leaving stale sporadic
state (e.g. a truncated hi_priority) behind on failure.
Validate sched_priority up front so the error path is atomic.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Commit 2ec7d90eba refactored sched_setparam() into set_sporadic_param()
but moved the apply logic into the former reject branch without
inverting the condition. As a result sched_setparam() rejects valid
sporadic parameters (repl >= 2 * budget) with EINVAL and accepts
invalid ones, tripping the DEBUGASSERT in sched_sporadic.c or wrapping
the replenishment calculation.
Invert the condition to match process_sporadic() in sched_setscheduler.c.
Fixes: 2ec7d90eba ("sched_setparam.c: coverity HIS_metric_violation: RETURN")
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
waitid() documents WNOWAIT support but exited_child() unconditionally
removed and freed the child status entry, so a second wait on the same
child failed with ECHILD. Debug builds were also inconsistent: the
options mask rejected WNOWAIT entirely with ENOSYS.
Pass options down to exited_child() and skip the discard when WNOWAIT
is set, matching waitpid(), and add WNOWAIT to the debug options mask.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Replace a literal 100000 with the USEC_PER_SEC macro in the oneshot
timer restart calculation. This bug causes incorrect timeout values
when CONFIG_SCHED_CPULOAD_TICKSPERSEC=1, though defaults are not
affected. Present since 2016 (commit 300361539a).
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Add a NULL check for the param argument before dereferencing
param->sched_priority. The sibling functions sched_setparam and
sched_getparam already have this check; sched_setscheduler was
the only one missing it, allowing a NULL pointer dereference
via sched_setscheduler(0, SCHED_FIFO, NULL).
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Compare ctcb->group->tg_ppid against rtcb->group->tg_pid (the group
leader PID) instead of rtcb->pid in waitid() and in the
!CONFIG_SCHED_CHILD_STATUS path of waitpid(). Commit ece224a7e3
("handle waitpid waitting tcb->group is NULL") rewrote the
comparisons this way when adding the ctcb->group NULL guard,
regressing what 90be95bb89 had correct: a non-group-leader thread
calling waitid(P_PID) or waitpid() on a child always gets ECHILD.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Protect the environment release in clearenv() with the task group mutex.
This prevents concurrent environment operations from racing with cleanup.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
Remove the per-arch testset implementation from the spinlock layer.
The testset abstraction predates the unified spinlock.h API and is no
longer used now that all arches provide spin_lock_irqsave()/
spin_unlock_irqrestore() directly. Drop the per-arch *_testset.{c,S}
implementations and spinlock.h files for arm, sim, sparc, tricore,
x86_64, and xtensa, along with the CXD56_TESTSET,
CXD56_TESTSET_WITH_HWSEM, and CXD56_ATOMIC_WITH_HWSEM Kconfig options
in arch/arm/src/cxd56xx, and simplify the CXD56 semaphore pool loop
in cxd56_sph.c to a single unconditional range.
Signed-off-by: zhangyu117 <zhangyu117@xiaomi.com>
Fix checkpatch "Missing blank line after declarations" errors in
drivers/timers/arch_timer.c and sched/sched/sched_processtickless.c.
These are pre-existing issues, not introduced by the recent tickless
RR series.
Assisted-by: Zhipu GLM-5.3
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
In tickless mode, the scheduler timer is stopped whenever the currently
running task requires no time slicing (CLOCK_MAX). When a SCHED_RR task
was later switched in, nothing re-armed the timer, so the task could run
indefinitely without round-robin rotation.
Also, when a SCHED_RR task was preempted, its timeslice counter was not
decremented for the time already consumed, effectively giving the task
"bonus" CPU time when resumed.
Solve both by performing RR accounting on context switches:
- nxsched_suspend_roundrobin() charges the elapsed execution time
against the timeslice of the RR task being switched out
- nxsched_resume_roundrobin() restarts the scheduler timer for the
remaining timeslice of the RR task being switched in, so the timer
is always armed while an RR task is running
This also removes the previous workaround in nxsched_process_timer
that triggered the scheduler on every timer tick.
Assisted-by: Zhipu GLM-5.3
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
In tickless mode, the scheduler timer is stopped whenever the currently
running task requires no time slicing (CLOCK_MAX). When a SCHED_RR task
was later switched in, nothing re-armed the timer, so the task could run
indefinitely without round-robin rotation.
Reassess the scheduler timer in nxsched_switch_context() before the
context switch when the task being switched in uses round-robin
scheduling, so that the timer is always armed while an RR task is
running. Hooking into nxsched_switch_context() covers all context
switch paths (task context switch, interrupt exit, syscall and task
exit) since every architecture calls it on every switch.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
In hrtimer_start_absolute, when a pending hrtimer is removed (was the
head) and reinserted with a later expiration time, the reprogram flag
remains true but the hrtimer is no longer the earliest timer in the
queue. The old code passed hrtimer->expired to hrtimer_reprogram, which
was incorrect. Use hrtimer_get_first()->expired to ensure the hardware
timer is reprogrammed with the actual earliest timer's expiration time.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
The context-switch merge assigned the current timestamp to run_time instead of run_start. This overwrote the accumulated runtime and left the next elapsed-time calculation with a stale start value when critical-monitor CPU load accounting was disabled.
Store the timestamp in run_start under the thread runtime monitor configuration, matching the former resume path.
Fixes: b2a69ba781 ("sched: merge nxsched_suspend/resume_critmon")
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
The premp_start member was renamed to preemp_start, but the old name was reintroduced when the critical monitor switch paths were merged.
Use the current struct tcb_s field name so configurations with preemption monitoring enabled build successfully.
Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>