Research note: RTEMS SuperCore¶
Kind: Read-only source analysis, 2026-10-07, on a sparse shallow clone of RTEMS/rtems at commit b3a3b372fa8d (cpukit/score/, cpukit/include/rtems/score/, cpukit/rtems/src/, cpukit/include/rtems/rtems/). Citations are relative to cpukit/; S/ is include/rtems/score/, R/ is include/rtems/rtems/. Line numbers drift; paths and symbols are the durable reference. Synthesized in R-001.
Q1 Scheduler¶
Plugin interface
Scheduler_Operations(S/scheduler.h:62-311): initialize, schedule, yield, block, unblock, update_priority, map and unmap_priority, node_initialize and destroy, release_job and cancel_job (EDF hooks), start_idle, and SMP-only ask_for_help, reconsider_help_request, withdraw_node, make and clean_sticky, pin and unpin, add and remove_processor, set_affinity.Scheduler_Controlis {context, Operations, maximum_priority, name, is_non_preempt_mode_supported} (S/scheduler.h:337-366). Selection is a const table_Scheduler_Table[]and_Scheduler_Countplus_Scheduler_Initial_assignments[]with PROCESSOR_MANDATORY or OPTIONAL (S/scheduler.h:378-449), emitted byconfdefs/scheduler.h(include/rtems/confdefs.h:79).Deterministic Priority:
Scheduler_priority_Contextis a 16x16Priority_bit_map_ControlplusChain_Control Ready[](S/schedulerpriority.h:81-96; S/prioritybitmap.h:58-76); highest is find-first-bit on the major then minor word via__builtin_clzor_CPU_Bitfield_Find_first_bit(S/prioritybitmapimpl.h:75-82, 208-219). The Simple scheduler is one ordered chain (S/schedulersimple.h:83-93).EDF: an RB-tree
Ready; the node holds aPriority_Control(S/scheduleredf.h:83-113). A deadline is just another priority:release_jobdoes_Thread_Priority_changedoraddwithSCHEDULER_PRIORITY_MAP(deadline); non-deadline threads carrySCHEDULER_EDF_PRIO_MSB(bit 63) so they sort as background (score/src/scheduleredfreleasejob.c:45-98; S/scheduleredfimpl.h:55-61). CBS extends EDF with budget-overrun servers (S/schedulercbs.h:109-159).Priority_Controlisuint64_t(S/priority.h:91);SCHEDULER_PRIORITY_MAPshifts left by 1, reserving the LSB as the FIFO or LIFO “append” bit (S/schedulernodeimpl.h:65-70).SMP:
Scheduler_SMP_Contextadds aScheduledchain beside the ready structure; node states BLOCKED, SCHEDULED, READY with Graphviz state diagrams in the header (S/schedulersmp.h:61-121; S/schedulersmpimpl.h:44-120). Priority SMP is G-FP; Priority Affinity SMP admits it “does not honor that affinity” yet (S/schedulerpriorityaffinitysmp.h:about 50-56); EDF SMP keeps per-processor affine RB queues, index 0 is one-to-all (S/scheduleredfsmp.h:59-136); Strong APA (Cerqueira et al.) does BFS backtracking over CPUs in the affinity set (S/schedulerstrongapa.h:58-67, 99-140).Scheduler_Nodeis {owner, user (owner or idle), idle placeholder, sticky_level, Wait.Priority aggregation, request queue} (S/schedulernode.h:94-229). One node per scheduler instance per thread:Thread_Scheduler_control{nodes, Wait_nodes, Scheduler_nodes, helping_nodes, pin_level, Affinity} (S/thread.h:297-420).Helping:
_Scheduler_SMP_Ask_for_helppreempts the lowest scheduled node or parks the node READY (S/schedulersmpimpl.h:1592-1700); requests are appended toPer_CPU_Control::Threads_in_need_for_helpwithdispatch_necessary=true(S/schedulersmpimpl.h:610-640) and drained in_Thread_Preemption_interventionon the next dispatch (score/src/threaddispatch.c:176-213).Dispatch:
Per_CPU_Controlholds isr_nest_level, isr_dispatch_disable, thread_dispatch_disable_level,volatile bool dispatch_necessary, executing, heir (S/percpu.h:406-473)._Thread_Dispatch_enabledispatches only on the 1 to 0 transition whendispatch_necessary(threaddispatch.c:375-400);_Thread_Do_dispatchloops heir to executing, callsCPU_budget.at_context_switch,_Context_Switch, repeats whiledispatch_necessary, then runs post-switch actions with level 0 (threaddispatch.c:278-358). A remote heir change is an atomic message plus IPI (S/threaddispatch.h:270-283).Idle:
_Thread_Idle_bodydefaults to the port_CPU_Thread_Idle_body(score/src/threadidledefault.c:44; score/cpu/no_cpu/include/rtems/score/cpu.h:1050); idle threads also serve as placeholders for sticky and ceiling nodes across scheduler instances (S/schedulernode.h:122-132).Effective priority:
Priority_Aggregationis an RB-treeContributorsplus aNodewhose.prioritymirrors the minimum (S/priority.h:112-198);_Priority_Insert,Extract,ChangedrewriteNode.priorityonly when the minimum changes (S/priorityimpl.h:565-741). A thread’sReal_prioritynode (S/thread.h:about 863) is one contributor into its home scheduler node’sWait.Priority; ceilings, inherited queue minima, and EDF deadlines are further nodes._Thread_Priority_applyseeds one action and_Thread_Priority_do_perform_actionspushes the result into_Scheduler_Node_set_priority(score/src/threadchangepriority.c:53-65, 284-336).
Q2 Context switch and interrupts¶
_Context_Switchcalls the port_CPU_Context_switch; FP is lazily switched (CPU_USE_DEFERRED_FP_SWITCH) with_Thread_Save_fpand_Restore_fparound the switch (S/context.h:137-183; no_cpu cpu.h:207, 1068-1143; threaddispatch.c:about 328-336).Two orthogonal levels: an
ISR_Levelcookie saved in a local by_ISR_Local_disable,enable,flashwrapping_CPU_ISR_Disable(S/isrlevel.h:60-118), and the per-CPUthread_dispatch_disable_level, which is the scheduler lock:_Thread_Dispatch_disable*increments (S/threaddispatch.h:183-222),_Thread_Dispatch_enabledecrements (threaddispatch.c:375-400).ISR_lock_ControlwrapsSMP_lock_Control; on UP it degrades to interrupt disable andISR_LOCK_NEEDS_OBJECTremoves the object entirely (S/isrlock.h:54-106).SMP locks: a ticket lock (
fetch_add next_ticket, spin onnow_serving, release stores +1) (S/smplockticket.h:60-197); an MCS queue lock (exchange tail, spin on ownlocked, CAS on release) (S/smplockmcs.h:60-280); a Boehm-style seqlock (S/smplockseq.h).SMP_lock_Controldefaults to the ticket lock with optional stats (S/smplock.h:86-119).Interrupt exit: the port’s
_ISR_Handler(S/isr.h:163-174) consults_Thread_Dispatch_necessary,_ISR_Nest_level, andisr_dispatch_disable(S/percpu.h:402-437, 903-906) and calls_Thread_Dispatch, which sets the level 0 to 1 and runs_Thread_Do_dispatch(score/src/threadplaindispatch.c:43-57).RTEMS_SCORE_ROBUST_THREAD_DISPATCHfaults withINTERNAL_ERROR_BAD_THREAD_DISPATCH_ENVIRONMENTif interrupts are disabled at dispatch (threaddispatch.c:282-292; S/threaddispatch.h:64).Interrupt stacks: per-CPU
interrupt_stack_lowandhighcarved from the configured_ISR_Stack_area_beginand_ISR_Stack_size(S/percpu.h:395-400; S/isr.h:101-125; score/src/isr.c:58-78).CPU_HAS_SOFTWARE_INTERRUPT_STACKis gone from the template port; every port now gets the per-CPU stack fields.ISR misuse:
_ISR_Is_in_progressvia the nest level or a port hook (S/percpu.h:722-728; cpu.h:555). Blocking sends from an ISR returnSTATUS_MESSAGE_QUEUE_WAIT_IN_ISR(score/src/coremsgsubmit.c:139-142), which maps toRTEMS_CALLED_FROM_ISR = 18(R/status.h:187).
Q3 Time¶
Watchdog_Controlis an RB node, cpu, routine, 64-bitexpire(S/watchdog.h:110-138);Watchdog_Headercachesfirst(leftmost) (S/watchdog.h:91-102)._Watchdog_Insertdescends while tracking whether the new node becomes first (score/src/watchdoginsert.c:41-81);_Watchdog_Removeadvancesfirstvia_Watchdog_Next_first(watchdogremove.c:41-56);_Watchdog_Do_ticklefires allexpire <= nowunder the per-CPU lock (watchdogtick.c:46-74).Per CPU:
Watchdog {Lock, uint64_t ticks, Header[TICKS, REALTIME, MONOTONIC]}(S/percpu.h:345-376, 494-514)._Watchdog_Tick: the boot CPU bumps_Watchdog_Ticks_since_boot, tickles TICKS with++ticks, MONOTONIC with_Timecounter_Getnanouptime, REALTIME with bintime, thenCPU_budget.at_tick(watchdogtick.c:76-156). Clock headers key onseconds<<30 | ns(WATCHDOG_BITS_FOR_1E9_NANOSECONDS, S/watchdogimpl.h:427, 528-586).The timecounter is FreeBSD’s:
_Timecounter_Install,Tick,Bintime,Getnanouptime,Set_NTP_update_second,Discipline(S/timecounter.h:65-320);kern_tc.cis outside this sparse clone. Simple counters use_Timecounter_Tick_simple(S/timecounter.h:242).Strictly tick-driven:
CONFIGURE_MICROSECONDS_PER_TICKgives_Watchdog_Microseconds_per_tick(include/rtems/config.h:527; S/watchdogticks.h:76-108). No tickless support anywhere in score (grep for “tickless” is empty).Thread timeouts:
Thread_Timer_information {Lock, header, Watchdog}(S/thread.h:566-572)._Thread_queue_Add_timeout_ticks,monotonic,realtime,by_clock_idpick the header; an absolute time already past yields immediate_Thread_Continue(STATUS_TIMEOUT), an invalid timespec givesSTATUS_INVALID_NUMBER(score/src/threadqtimeout.c:48-170);_Thread_Timeoutis just_Thread_Continue(STATUS_TIMEOUT)(score/src/threadtimeout.c:101-111).Rate monotonic:
Rate_monotonic_Control {Timer, state, Priority node, owner, Statistics, postponed_jobs, latest_deadline}(R/ratemondata.h:89-153); states INACTIVE, ACTIVE, EXPIRED (R/ratemon.h:96-110).rtems_rate_monotonic_period: non-owner givesRTEMS_NOT_OWNER_OF_RESOURCE;RTEMS_PERIOD_STATUSreturnsRTEMS_TIMEOUTif EXPIRED; ACTIVE blocks (STATES_WAITING_FOR_PERIOD) until the watchdog fires; EXPIRED orpostponed_jobs>0returnsRTEMS_TIMEOUTimmediately and renews (rtems/src/ratemonperiod.c:243-400). The timeout incrementspostponed_jobsand sets EXPIRED when the owner is not blocked (rtems/src/ratemontimeout.c:46-116). Statistics: count, missed_count, min, max, total CPU and wall time (ratemonperiod.c:158-212). Each period release calls_Scheduler_Release_job, so EDF deadlines come from this manager (ratemonperiod.c:108-135).Timer server: the watchdog routine moves the timer onto a
Pendingchain and sends a system event; the server task runs routines in task context (rtems/src/timerserver.c:71-160);rtems_timer_server_fire_afteruses classTIMER_INTERVAL_ON_TASK(rtems/src/timerserverfireafter.c:64).
Q4 Blocking and waiting¶
Thread_queue_Queue {ticket Lock, heads, owner, name}(S/threadq.h:434-468).Thread_queue_Headsis a union: a FIFO chain, or a chain of per-schedulerThread_queue_Priority_queue, each holding aPriority_Aggregation Queue(S/threadq.h:356-432).Thread_queue_Operations {priority_actions, enqueue, extract, surrender, first}(S/threadq.h:561-610) with FIFO, priority, and priority_inherit tables (score/src/threadqops.c:160-218, 369-690, 693-1424). Because the queue itself is an aggregation, its minimum becomes a contributor to the owner (threadqops.c:1041-1067)._Thread_queue_Enqueue(score/src/threadqenqueue.c:411-498): claim wait,Path_acquire,ops->enqueue, setINTEND_TO_BLOCK, disable dispatch, release the queue lock, runenqueue_callout(arms the timeout),_Thread_Set_state, then CASINTEND_TO_BLOCKtoBLOCKED; if the CAS fails a surrender or timeout already set READY, so it removes the timer and unblocks; finally_Thread_Dispatch_direct.Wait flags: READY 0, INTEND_TO_BLOCK 1, BLOCKED 2 plus class bits EVENT, SYSTEM_EVENT, OBJECT, PERIOD (S/threadimpl.h:2259-2307), changed by atomic CAS (S/threadimpl.h:2426-2431). Wakers try
INTEND_TO_BLOCKto READY; if that fails the thread is BLOCKED so they set READY and_Thread_Unblock(threadtimeout.c:45-99; threadqenqueue.c:597-630).Deletion with waiters:
_Thread_queue_Flush_criticalwith a filter that writesSTATUS_OBJECT_WAS_DELETEDorSTATUS_UNAVAILABLEintoWait.return_code(score/src/threadqflush.c:49-90), used by semaphore destroy and barriers (S/coresemimpl.h:123-126; S/corebarrierimpl.h:163-182).Events: a 32-bit
rtems_event_set,RTEMS_ALL_EVENTS(R/event.h:96-436); seize and surrender reuse the wait-flag machine without a thread queue (rtems/src/eventseize.c:87-122; eventsurrender.c:102-140); system events are a separate class.Condition variables: self-contained
_Condition_Wait*on a FIFO queue, releasing the mutex inside the enqueue callout (score/src/condition.c:55, 120-175).
Q5 Synchronization and PI¶
CORE_mutex_Controlis a thread queue; recursive addsnest_level; ceiling adds aPriority_ceilingnode and scheduler (S/coremutex.h:74-118). The slow seize enqueues with a deadlock callout (score/src/coremutexseize.c:47-75); surrender via_Thread_queue_Surrender(S/coremuteximpl.h:285-320); ceiling ownership adds the ceiling node to the owner,STATUS_MUTEX_CEILING_VIOLATEDotherwise (S/coremuteximpl.h:431-461).PI is
_Thread_queue_Operations_priority_inherit(S/coremuteximpl.h:61): enqueue inserts the waiter’s node into the queue aggregation; a new minimum generates an action on the owner’s scheduler node and_Thread_Priority_perform_actions(owner)(threadqops.c:989-1067).Transitive: yes.
_Thread_Priority_perform_actionsloops: apply actions tothe_thread; if actions remain,the_thread = the_thread->Wait.queue->ownerand repeat (score/src/threadchangepriority.c:227-282). Inside,_Thread_Priority_do_perform_actionscallsoperations->priority_actionsof the queue the current thread waits on, so an owner that is itself blocked on a PI mutex regenerates actions for the next owner (threadchangepriority.c:127-225). On SMP the whole owner chain is locked first by_Thread_queue_Path_acquire, which collects oneThread_queue_Linkper hop (threadchangepriority.c:302-313; threadqenqueue.c:273-383).MrsP: a ceiling priority per scheduler instance (S/mrsp.h:77-92), waiters spin-wait “sticky” via
_Thread_queue_Enqueue_stickyand_Thread_Priority_update_and_make_sticky; a preempted owner borrows a waiter’s processor through the helping protocol (S/mrsp.h:about 50-66; S/mrspimpl.h:363-410; threadqenqueue.c:500-575). A recursive seize isSTATUS_DEADLOCK(S/mrspimpl.h:459). OMIP-style migratory inheritance is what the per-instanceWait_nodesandhelping_nodesdeliver for PI mutexes across clusters (S/thread.h:356-420).Semaphore variants derived from attributes: counting, simple binary, binary mutex with no protocol, inherit, ceiling, or MrsP (rtems/src/semcreate.c:95-125; R/semimpl.h:65-72);
STATUS_MAXIMUM_COUNT_EXCEEDEDon counting overflow (S/coresemimpl.h:148-175).Barrier: automatic release at
maximum_countreturnsSTATUS_BARRIER_AUTOMATICALLY_RELEASED(score/src/corebarrierwait.c:76-100); manual release is a flush.
Q6 IPC and memory¶
Message queue: preallocated buffers,
Pending_messages,notify_handler(S/coremsg.h:117-164); a buffer carriessizeandint priority(S/coremsgbuffer.h:64-89). Send appends (INT_MAX), urgent prepends (INT_MIN), priority inserts ordered (S/coremsgimpl.h:67-75; score/src/coremsginsert.c:82-103); a waiting receiver gets a direct copy (coremsgsubmit.c:about 85-150).Partition: fixed-size buffers threaded as a chain by
_Chain_Initialize(R/partdata.h:57-106; rtems/src/partcreate.c:68-76). Region:Heap_Controlplus a FIFO or priority thread queue,STATES_WAITING_FOR_SEGMENT, waiters retried by_Region_Process_queueafter each free (R/regiondata.h:60-67; rtems/src/regiongetsegment.c:100-128; regionprocessqueue.c:46-87).Heap: boundary-tagged blocks
prev_sizeandsize_and_flagwithHEAP_PREV_BLOCK_USED, first-fit over a free list (S/heap.h:60-146, 278-348; score/src/heapallocate.c:217-290; S/heapfirstfitimpl.h). OptionalHEAP_PROTECTIONadds protector words, an owning task tag, and delayed frees (S/heap.h:50, 239-261)._Protected_heap_*wraps with the allocator mutex (score/src/pheapallocate.c:53-55). The workspace_Workspace_Areais a heap, optionally unified with the C heap (S/wkspace.h:59; S/wkspacedata.h:77-98).Objects: a 32-bit id is class (5 bits at 27) | API (3 at 24) | node (8 at 16) | index (16) (S/object.h:101-174);
Objects_Informationwithlocal_table, inactive chain, block extension forOBJECTS_UNLIMITED_OBJECTS(S/objectdata.h:198-312; S/object.h:180)._Objects_Getis a single unsigned “delta” range check, a local interrupt disable stored in the lock context, and a table lookup (score/src/objectgetlocal.c:44-80).Configuration:
confdefs.hincludes topic headers (include/rtems/confdefs.h:61-81) that emit const objects consumed throughrtems_configuration_get_*macros (config.h:392-840). Static by default, dynamic only via the unlimited flag.
Q7 Isolation¶
No MPU or MMU task isolation: no MPU, MMU, or protection-domain references in score headers or the template port; the Memory Handler only distributes BSP-provided areas (S/memory.h:63-93, 308-334). Stack overflow is detected after the fact by the stack checker (include/rtems/stackchk.h:70-94;
RTEMS_FATAL_SOURCE_STACK_CHECKER, S/interr.h:126); heap protection is a debug aid.rtems_task_modeoffers PREEMPT or NO_PREEMPT, TIMESLICE, ASR or NO_ASR, INTERRUPT_LEVEL (R/modes.h:83-256), implemented by togglingis_preemptible,CPU_budget.operations, ASR enable, and_ISR_Set_level; on SMP NO_PREEMPT needs scheduler support and interrupt-level changes areRTEMS_NOT_IMPLEMENTED(rtems/src/taskmode.c:67-155). Timeslicing is a pluggableThread_CPU_budget_operations(S/threadcpubudget.h:86-94).
Q8 Observability¶
Present in the clone: the capture engine (include/rtems/capture.h:53-413; per-thread hook S/thread.h:822-825), record infrastructure (S/percpu.h:638),
rtems_cpu_usage_reportandreset(include/rtems/cpuuse.h:123-169), the stack checker, and user extensions {create, start, restart, delete, switch, begin, exitted, fatal, terminate} (S/userext.h:253-263).Per-thread CPU time:
cpu_time_usedupdated on each heir change as the uptime delta against the per-CPUcpu_usage_timestamp(S/threadimpl.h:1260-1293; S/percpu.h:489).Fatal:
Internal_errors_Source(S/interr.h:63-179) and core codes includingTHREAD_QUEUE_DEADLOCK=28,BAD_THREAD_DISPATCH_DISABLE_LEVEL=30,BAD_THREAD_DISPATCH_ENVIRONMENT=31(S/interr.h:188-237)._Terminatedisables interrupts, runs fatal extensions, marks the system terminated, halts in the idle body (score/src/interr.c:51-81).Deadlock detection:
_Thread_queue_Path_acquirewalks owner toowner->Wait.queueto its owner; reaching the enqueuing thread isTHREAD_QUEUE_DEADLOCK_DETECTED. On SMP each hop registers aThread_queue_Linkin a global RB-tree_Thread_queue_Links;_Thread_queue_Link_addfinding a reverse edge is the cycle test, andThread_queue_Gateordering avoids deadlocking on the SMP locks themselves (score/src/threadqenqueue.c:65-175, 273-383; S/threadq.h:135-139). Enqueue then invokesdeadlock_callout:STATUS_DEADLOCKfor mutexes or fatalINTERNAL_ERROR_THREAD_QUEUE_DEADLOCK(threadqenqueue.c:400-449; coremutexseize.c:57-60).
Q9 Configuration, portability, quality¶
Port contract (score/cpu/no_cpu/include/rtems/score/cpu.h): feature macros
CPU_SIMPLE_VECTORED_INTERRUPTS,CPU_HARDWARE_FP,CPU_USE_DEFERRED_FP_SWITCH,CPU_ENABLE_ROBUST_THREAD_DISPATCH,CPU_STACK_GROWS_UP,CPU_CACHE_LINE_BYTES,CPU_MAXIMUM_PROCESSORS,CPU_STACK_MINIMUM_SIZE, alignments (cpu.h:80-636); functions_CPU_ISR_Disable,Enable,Flash,Set_level,Get_level,_CPU_Context_Initialize,switch,restore,save_fp,restore_fp,_CPU_Thread_Idle_body,_CPU_Bitfield_Find_first_bit,_CPU_Counter_readandfrequency,_CPU_Exception_frame_print,_CPU_Spin_wait(cpu.h:654-1362); cpuimpl.h adds the per-CPU control size, TLS variant,_CPU_Get_current_per_CPU_control, context validate and clobber (cpuimpl.h:58-204). Ten ports under score/cpu.Configuration is
confdefs.hplus per-topic headers (include/rtems/confdefs.h:61-81), compile-time only.Quality discipline: SPDX BSD-2-Clause on every file (S/thread.h:1), dense Doxygen (248 tags in the 1,517-line S/threadqimpl.h),
_clang-formatat the repository root, and 34 files in the clone are “part of the RTEMS quality process and was automatically generated” from specification items (R/tasks.h:38-45, 423spec:/rtems/task/if/create), the ESA pre-qualification toolchain. NoRTEMS_PRE_QUALIFIEDmacro or test-name references appear in the clone.
Q10 Synthesis¶
RTEMS turns every priority influence (base, ceiling, inheritance, EDF deadline, MrsP ceiling) into a Priority_Node in a min-tree, so one algebra serves UP, SMP, and clustered scheduling; its lock-free wait-flag CAS, per-hop path locking, and cycle detection make blocking provably race- and deadlock-aware. The price is heavy abstraction, a large footprint, a tick-only clock, and no memory isolation.
Ideas to borrow¶
Priority aggregation trees as the single effective-priority mechanism (S/priority.h:147-198; S/priorityimpl.h:565-741).
The INTEND_TO_BLOCK, BLOCKED, READY CAS state machine shared by queues, events, and periods (S/threadimpl.h:2259-2431; threadqenqueue.c:458-498).
Deadlock detection in PI chains with a status-or-fatal callout (threadqenqueue.c:273-383, 400-449).
Transitive PI via the owner-chain action loop (threadchangepriority.c:227-282).
Per-CPU watchdog headers with 64-bit expiry and a cached first node, separate tick, monotonic, and realtime trees (S/percpu.h:494-514; watchdoginsert.c:41-81).
The rate monotonic manager with postponed-job counting and CPU and wall statistics (ratemonperiod.c:158-212; ratemontimeout.c:46-66).
A scheduler plugin table selected at configuration time (S/scheduler.h:62-449).
MrsP sticky spin-wait plus helping (S/mrspimpl.h:363-410; threadqenqueue.c:500-575).
Flush filters that encode the wake reason into the waiter (threadqflush.c:49-90).
Spec-generated API headers with constraint blocks (R/tasks.h:38-45).
Weaknesses¶
Complexity: a 1,575-line threadqops.c, a 919-line threadqenqueue.c, a 2,000-plus-line schedulersmpimpl.h; helping, sticky, and pinning interactions are hard to audit (S/thread.h:297-420).
Footprint: 64-bit priorities, per-scheduler nodes per thread, RB-trees everywhere, per-CPU locks and stats (S/percpu.h:384-641; S/schedulernode.h:94-229).
No isolation: no MPU or MMU domains; only after-the-fact stack checking (S/memory.h; include/rtems/stackchk.h).
Tick-only timing, no tickless idle (watchdogtick.c:76-156; config.h:527).
Configuration burden: dozens of
CONFIGURE_*headers, compile-time static tables (include/rtems/confdefs.h:61-81).Incomplete features: the affinity scheduler ignores affinity (S/schedulerpriorityaffinitysmp.h:about 50-56); SMP task modes return
RTEMS_NOT_IMPLEMENTED(taskmode.c:67-81).The global
_Thread_queue_Linksregistry is a shared contention point on SMP (threadqenqueue.c:65-175).