Skip to content
RED SAGSkills

RTOS interview questions and answers

RTOS questions cover how real-time systems schedule tasks and share resources safely.

Below are 60 RTOS questions with the correct answer and a short explanation, grouped from fresher to experienced level. Try each one before you open the answer.

What RTOS interviews usually check

  • ✓Tasks and priorities
  • ✓Scheduling and preemption
  • ✓Mutexes, semaphores and queues
  • ✓Priority inversion
  • ✓Timing and deadlines

RTOS interview questions for freshers easy

1. Delaying inside an RTOS task

Inside a FreeRTOS task you need to wait 100 ms. Why use vTaskDelay instead of a busy loop?

  1. A.vTaskDelay is more accurate than any hardware timer
  2. B.vTaskDelay blocks the task so other tasks can run and the CPU can idle
  3. C.A busy loop is not allowed by the C standard
  4. D.vTaskDelay disables all interrupts while waiting
Show answer

Answer: B. vTaskDelay blocks the task so other tasks can run and the CPU can idle

vTaskDelay moves the task to the Blocked state, so the scheduler runs other ready tasks or the idle task, which can enter low power. A busy loop burns CPU time and starves lower-priority tasks. Busy waits are only for very short, precise delays in drivers.

2. Mutex compared with semaphore

In most RTOSes, what is a key difference between a mutex and a binary semaphore?

  1. A.A mutex has an owner and supports priority inheritance
  2. B.A semaphore can only be used before the scheduler starts
  3. C.A mutex can be given from an ISR, a semaphore cannot
  4. D.A semaphore always blocks forever when taken
Show answer

Answer: A. A mutex has an owner and supports priority inheritance

A mutex is taken and released by the same task, and the kernel uses that ownership to raise the owner's priority when a higher-priority task waits. Binary semaphores have no owner, which makes them good for signalling, for example from an ISR to a task.

3. FreeRTOS task waiting on a queue

A FreeRTOS task calls xQueueReceive with a 100 ms timeout on an empty queue. Which state is it in while it waits?

  1. A.Ready
  2. B.Running
  3. C.Blocked
  4. D.Deleted
Show answer

Answer: C. Blocked

A task waiting for an event or timeout is Blocked and uses no CPU time. When data arrives or the timeout ends, it moves to Ready, and runs when it is the highest-priority ready task. Suspended is a separate state entered only through vTaskSuspend.

4. Which task the scheduler runs

With FreeRTOS preemptive scheduling, three tasks are Ready with priorities 1, 3 and 2. Which one runs?

  1. A.The priority 1 task
  2. B.The task created first
  3. C.All three take turns equally
  4. D.The priority 3 task
Show answer

Answer: D. The priority 3 task

A preemptive priority scheduler always runs the highest-priority task that is ready. In FreeRTOS a higher number means higher priority, so priority 3 runs. Lower-priority tasks only run when the higher ones block or are suspended.

5. Guarding a pool of 4 buffers

A system has 4 identical DMA buffers that tasks borrow and return. Which primitive suits tracking how many are free?

  1. A.A binary semaphore shared by all tasks
  2. B.A recursive mutex taken once per buffer
  3. C.A counting semaphore with a maximum of 4
  4. D.A periodic software timer set to 4 ticks
Show answer

Answer: C. A counting semaphore with a maximum of 4

A counting semaphore starts at 4. Each take lowers the count when a buffer is borrowed, and each give raises it on return. When the count is 0, tasks block until a buffer is returned. You still need a way to pick which buffer is free.

6. Waiting for three conditions at once

A task must wait until Wi-Fi is connected, time is synced and the sensor is ready. Which FreeRTOS feature handles this in one call?

  1. A.An event group, waiting for all three bits
  2. B.Three mutexes, taken one inside another
  3. C.One binary semaphore given by all three
  4. D.A stream buffer with a trigger level of 3
Show answer

Answer: A. An event group, waiting for all three bits

An event group holds a set of flag bits. xEventGroupWaitBits can wait for all chosen bits (or any of them) with one call and a timeout. Each part of the system sets its own bit when its condition is met.

7. Sending to a full queue

A task calls xQueueSend(q, &item, 0) on a full queue. What happens?

  1. A.It blocks until a slot in the queue is free
  2. B.It overwrites the oldest item in the queue
  3. C.It triggers an assert and halts the system
  4. D.It returns errQUEUE_FULL at once, without waiting
Show answer

Answer: D. It returns errQUEUE_FULL at once, without waiting

A timeout of 0 means do not wait. If there is no space, the call returns errQUEUE_FULL straight away and the item is not sent. Use a timeout to wait, or xQueueOverwrite on a length-1 queue when you want the newest value only.

8. Meaning of portMAX_DELAY

With INCLUDE_vTaskSuspend set to 1, what does passing portMAX_DELAY as a timeout to xSemaphoreTake do?

  1. A.Waits forever until the semaphore is available
  2. B.Waits about 49 days and then fails
  3. C.Returns at once if the semaphore is taken
  4. D.Waits for one tick only
Show answer

Answer: A. Waits forever until the semaphore is available

With INCLUDE_vTaskSuspend enabled, portMAX_DELAY means block with no timeout. The task stays blocked until it gets the semaphore. Without that setting, it is just the largest tick count, a very long but finite wait.

9. Units of the stack size argument

On a 32-bit Cortex-M port, you call xTaskCreate(fn, "net", 512, NULL, 2, NULL). How big is the stack?

  1. A.512 bytes
  2. B.512 KB
  3. C.128 words, which is 512 bytes
  4. D.512 words, which is 2048 bytes
Show answer

Answer: D. 512 words, which is 2048 bytes

FreeRTOS xTaskCreate takes the stack depth in words of StackType_t, which is 4 bytes on Cortex-M. So 512 means 2048 bytes. Zephyr and ESP-IDF variants use bytes, so always check the API before copying numbers between them.

10. Sleeping a Zephyr thread

Which Zephyr call puts the current thread to sleep for 100 ms and lets other threads run?

  1. A.k_busy_wait(100)
  2. B.k_sleep(K_MSEC(100))
  3. C.k_yield(100)
  4. D.sleep(100000)
Show answer

Answer: B. k_sleep(K_MSEC(100))

k_sleep takes a k_timeout_t, built with helpers such as K_MSEC. It blocks the thread so others can run. k_busy_wait spins in microseconds without giving up the CPU, and k_yield takes no argument.

11. Creating a Zephyr thread at build time

Which Zephyr macro defines and starts a thread at boot, with its stack allocated statically?

  1. A.K_SEM_DEFINE
  2. B.DEVICE_DT_GET
  3. C.K_THREAD_DEFINE
  4. D.LOG_MODULE_REGISTER
Show answer

Answer: C. K_THREAD_DEFINE

K_THREAD_DEFINE declares the thread, its stack, entry function, priority and start delay, and the kernel starts it automatically. k_thread_create is the runtime alternative. The other macros define semaphores, get devices and set up logging.

12. Choosing a FreeRTOS heap scheme

Your app creates and deletes tasks and queues at run time. Which FreeRTOS heap file merges adjacent free blocks to limit fragmentation in one RAM region?

  1. A.heap_1.c
  2. B.heap_2.c
  3. C.heap_3.c
  4. D.heap_4.c
Show answer

Answer: D. heap_4.c

The heap_4 scheme is a first-fit allocator that merges neighbouring free blocks. By contrast heap_1 never frees, heap_2 frees without merging, and heap_3 wraps the C library malloc. heap_5 is like heap_4 but can span several RAM regions.

13. Tasks with no heap at all

A safety project forbids dynamic memory. How can you still create FreeRTOS tasks?

  1. A.Use xTaskCreate with a stack size of 0
  2. B.Call malloc once before the scheduler starts
  3. C.Use xTaskCreateStatic with buffers you provide
  4. D.Create tasks inside an ISR
Show answer

Answer: C. Use xTaskCreateStatic with buffers you provide

With configSUPPORT_STATIC_ALLOCATION set to 1, xTaskCreateStatic takes a stack array and a StaticTask_t control block that you allocate. Queues, semaphores and timers have Static versions too. Memory use is then fixed at link time.

14. Checking how much stack a task used

Which FreeRTOS function tells you the minimum free stack space a task has had since it started?

  1. A.xPortGetMinimumEverFreeHeapSize()
  2. B.uxTaskGetNumberOfTasks()
  3. C.xTaskGetTickCountFromISR()
  4. D.uxTaskGetStackHighWaterMark()
Show answer

Answer: D. uxTaskGetStackHighWaterMark()

The stack is filled with a known pattern at creation, and the high water mark counts how much of it is still untouched. A value near zero means the stack is nearly full. Free heap size is a separate measure for the heap.

15. Turning on configASSERT

Why define configASSERT in FreeRTOSConfig.h during development?

  1. A.It makes the scheduler pick the next task more quickly
  2. B.It turns on the tick interrupt when the scheduler starts
  3. C.The kernel then checks for misuse, like bad ISR priorities
  4. D.It is required before any task can be created at all
Show answer

Answer: C. The kernel then checks for misuse, like bad ISR priorities

FreeRTOS has many asserts on parameters and calling context, but they only work if configASSERT is defined. They catch bugs like calling a non-ISR API from an interrupt or wrong NVIC priorities early. Many teams keep a light version in release builds.

16. Code after vTaskStartScheduler

In a FreeRTOS main(), when does code after vTaskStartScheduler() run?

  1. A.Right after the first task has blocked on something
  2. B.Each time the idle task gets a chance to run
  3. C.After every task in the system has been deleted
  4. D.Only if the scheduler could not start, usually for lack of heap
Show answer

Answer: D. Only if the scheduler could not start, usually for lack of heap

vTaskStartScheduler normally never returns, since tasks take over the CPU. It returns only if it could not create the idle or timer task, usually because the heap is too small. Put an error loop or assert after it.

17. FreeRTOS kernel licence

Under which licence is the FreeRTOS kernel released?

  1. A.GPL v3
  2. B.MIT
  3. C.Proprietary only
  4. D.Apache 2.0
Show answer

Answer: B. MIT

The FreeRTOS kernel has used the MIT licence since Amazon took over the project in 2017. It allows commercial use without opening your source. Zephyr uses Apache 2.0, which is also permissive.

18. What jitter means for a periodic task

A 1 ms control task actually starts at 1.00, 2.03, 2.98 and 4.05 ms. What is the variation in start times called?

  1. A.Throughput
  2. B.Utilisation
  3. C.Jitter
  4. D.Deadlock
Show answer

Answer: C. Jitter

Jitter is the variation of an event from its ideal timing. Here the start times wander by tens of microseconds around the 1 ms grid. Control loops and audio are sensitive to jitter even when average timing is right.

19. Checking Zephyr thread stack use

Which Zephyr option prints stack usage and CPU use for each thread?

  1. A.CONFIG_THREAD_ANALYZER
  2. B.CONFIG_GPIO
  3. C.CONFIG_MAIN_STACK_SIZE
  4. D.CONFIG_SERIAL
Show answer

Answer: A. CONFIG_THREAD_ANALYZER

The thread analyzer walks all threads and reports stack usage, and CPU use when runtime stats are on. It can print periodically or on demand. CONFIG_MAIN_STACK_SIZE only sets the size of the main thread stack.

20. Always keeping the latest value

A sensor task publishes the latest temperature. Readers only want the newest value. Which FreeRTOS pattern fits?

  1. A.A length-100 queue written with xQueueSend by the sensor
  2. B.A counting semaphore given once per new reading
  3. C.A length-1 queue, xQueueOverwrite to write, xQueuePeek to read
  4. D.A recursive mutex taken by each reader in turn
Show answer

Answer: C. A length-1 queue, xQueueOverwrite to write, xQueuePeek to read

xQueueOverwrite always replaces the single item, even if the queue is full, so it never blocks. Readers use xQueuePeek to read without removing it, so many readers can see the same value. This is the mailbox pattern.

RTOS intermediate interview questions medium

21. Priority inversion

A low-priority task holds a mutex needed by a high-priority task, while a medium-priority task keeps running and blocks the low one. What RTOS feature solves this?

  1. A.Making all tasks the same priority
  2. B.Using a binary semaphore instead of a mutex
  3. C.Priority inheritance, where the low task temporarily gets the high task's priority while it holds the mutex
  4. D.Increasing the tick rate
Show answer

Answer: C. Priority inheritance, where the low task temporarily gets the high task's priority while it holds the mutex

Priority inversion lets a medium task delay a high task indefinitely. Mutexes with priority inheritance (as in FreeRTOS mutexes) raise the holder's priority so it finishes and releases the lock. This issue famously affected the Mars Pathfinder mission.

22. Lighter than a semaphore

One ISR needs to signal exactly one FreeRTOS task, and RAM and speed matter. What is the lightest built-in mechanism?

  1. A.A direct-to-task notification such as vTaskNotifyGiveFromISR
  2. B.A queue with a length of 100
  3. C.An event group with 24 bits
  4. D.A mutex given from the ISR
Show answer

Answer: A. A direct-to-task notification such as vTaskNotifyGiveFromISR

Task notifications use a value already stored in each task's control block, so no extra kernel object is created and they are faster than semaphores. They work well when there is a single known receiving task. Mutexes must never be given from an ISR.

23. How long vTaskDelay(1) waits

With a 1 kHz tick, a task calls vTaskDelay(1). How long can it actually be blocked?

  1. A.Exactly 1 ms, every single time it is called
  2. B.Anywhere from just over 0 up to about 1 ms
  3. C.At least 2 ms, every single time it is called
  4. D.Exactly 1 µs, the length of one CPU cycle
Show answer

Answer: B. Anywhere from just over 0 up to about 1 ms

The delay ends at the next tick boundary, and the call can happen at any point between ticks. If it is called just before a tick, it unblocks almost at once. For a guaranteed minimum of N ms, delay N + 1 ticks or use a hardware timer.

24. Why portYIELD_FROM_ISR is needed

An ISR calls xSemaphoreGiveFromISR(sem, &woken) and then portYIELD_FROM_ISR(woken). What does the yield do?

  1. A.It gives the semaphore a second time so that the task cannot miss the event
  2. B.It ends the ISR at once and skips any code that comes after it in the handler
  3. C.It lowers the priority of the woken task so that the ISR can finish first
  4. D.On ISR exit, it switches to the woken task if that task outranks the one interrupted
Show answer

Answer: D. On ISR exit, it switches to the woken task if that task outranks the one interrupted

If giving the semaphore unblocks a task with higher priority than the one that was interrupted, woken is set to pdTRUE. portYIELD_FROM_ISR then pends a context switch, so that task runs right after the ISR. Without it, the task may wait until the next tick or until another switch.

25. Lost interrupts with a binary semaphore

An ISR gives a binary semaphore for every received packet. A handler task takes it and processes one packet. Under burst load, packets are left unprocessed. Why?

  1. A.Two gives before one take still leave the count at 1
  2. B.Binary semaphores cannot be given from an ISR
  3. C.The task priority is too high
  4. D.The semaphore resets itself every tick
Show answer

Answer: A. Two gives before one take still leave the count at 1

A binary semaphore can only be 0 or 1, so several gives before the task runs are collapsed into one. Either process everything available on each wake (loop until the FIFO is empty), or use a counting semaphore or a queue that records each event.

26. Mutex held during a long wait

A task takes the SPI bus mutex, sends a command, calls vTaskDelay(100) to wait for the device, then reads and releases the mutex. What is the main issue?

  1. A.vTaskDelay cannot be used while holding a mutex
  2. B.The mutex expires automatically after one tick
  3. C.Every other SPI user is blocked for at least 100 ms
  4. D.Priority inheritance stops working after 10 ms
Show answer

Answer: C. Every other SPI user is blocked for at least 100 ms

Holding a lock while sleeping turns that sleep into blocking time for every other user of the resource. Release the mutex before waiting and take it again for the read, if the device allows. Keep locked sections as short as possible.

27. Three tasks meeting at a point

Three tasks must each finish their setup step and then all continue together. Which FreeRTOS call is designed for this rendezvous?

  1. A.xEventGroupClearBits()
  2. B.xQueuePeek()
  3. C.vTaskSuspendAll()
  4. D.xEventGroupSync()
Show answer

Answer: D. xEventGroupSync()

xEventGroupSync sets the calling task bit and waits for all the bits in the set, atomically. When the last task arrives, all are released together and the bits are cleared. Doing set and wait in two calls can miss the moment the bits are cleared.

28. Queueing pointers to large buffers

To avoid copying 1 KB frames, a producer queues pointers to buffers. What new rule must the design follow?

  1. A.The queue must be created with a length of exactly one item
  2. B.The consumer must delete the queue after it reads each item
  3. C.The producer must not reuse a buffer until the consumer is done
  4. D.The pointers may only point at const data stored in flash
Show answer

Answer: C. The producer must not reuse a buffer until the consumer is done

Now only the address is copied, so both tasks see the same memory. If the producer overwrites the buffer before the consumer finishes, data is corrupted. A common design is a pool of buffers with a free list, passing ownership with each pointer.

29. Waiting on two queues and a semaphore

One FreeRTOS task must block until data arrives on either of two queues or a semaphore is given. Which feature allows a single blocking call?

  1. A.A recursive mutex
  2. B.A queue set with xQueueSelectFromSet
  3. C.vTaskSuspendAll with polling
  4. D.A length-0 queue
Show answer

Answer: B. A queue set with xQueueSelectFromSet

A queue set groups queues and semaphores. xQueueSelectFromSet blocks until one member has data and returns its handle, and then you read from that member. Event groups or one combined queue of tagged messages are simpler alternatives.

30. Heap across two RAM banks

An MCU has 128 KB of main SRAM and 64 KB of separate SRAM2. You want the FreeRTOS heap to use free space in both. Which option fits?

  1. A.heap_5 with vPortDefineHeapRegions
  2. B.heap_1 with a bigger array
  3. C.heap_3 with linker changes only
  4. D.heap_4 twice
Show answer

Answer: A. heap_5 with vPortDefineHeapRegions

heap_5 uses the same merging algorithm as heap_4 but across several non-adjacent regions. You must call vPortDefineHeapRegions with the region list before creating any kernel object. Regions go in address order.

31. errno shared between tasks

Two tasks use newlib functions that set errno, and each sometimes reads the other task error code. What does FreeRTOS provide for this?

  1. A.configUSE_MUTEXES, which wraps errno in a mutex
  2. B.configUSE_TIME_SLICING, which saves errno on each tick
  3. C.Nothing, since errno can never be kept per task
  4. D.configUSE_NEWLIB_REENTRANT, giving each task its own state
Show answer

Answer: D. configUSE_NEWLIB_REENTRANT, giving each task its own state

newlib keeps errno and other state in a _reent struct. With configUSE_NEWLIB_REENTRANT set to 1, FreeRTOS gives each task its own struct and swaps the pointer on context switch. It costs RAM per task.

32. Running a job 500 ms later in Zephyr

A Zephyr driver must run a handler in thread context 500 ms after a button press, and restart that wait if pressed again. What fits best?

  1. A.A k_sem given from the ISR after a 500 ms delay
  2. B.A busy loop of k_busy_wait(500000) in the ISR
  3. C.A k_work_delayable, restarted with k_work_reschedule
  4. D.A new thread created on each button press
Show answer

Answer: C. A k_work_delayable, restarted with k_work_reschedule

Delayable work runs its handler on a workqueue after a delay, in thread context. k_work_reschedule cancels any pending delay and starts a fresh one, which gives a natural debounce. Creating a thread per press wastes memory and time.

33. k_sched_lock compared with irq_lock

In Zephyr, what does k_sched_lock() prevent that irq_lock() also prevents, and what does it allow?

  1. A.It stops ISRs but still lets threads preempt
  2. B.It stops other threads preempting but still lets ISRs run
  3. C.It stops both ISRs and threads
  4. D.It stops neither, it only raises priority by one
Show answer

Answer: B. It stops other threads preempting but still lets ISRs run

k_sched_lock makes the current thread act as cooperative until k_sched_unlock, so other threads cannot preempt it. Interrupts are still served. irq_lock masks interrupts too, so it must stay much shorter.

34. Moving a sensor to another I2C bus

In a Zephyr app, you need the sensor on i2c1 instead of i2c0 for one board only, without editing Zephyr sources. What do you add?

  1. A.A #define for the bus name at the top of main.c
  2. B.A new Kconfig symbol for the bus in prj.conf
  3. C.A board-specific devicetree overlay in the app
  4. D.A patch to the board DTS inside the Zephyr tree
Show answer

Answer: C. A board-specific devicetree overlay in the app

Devicetree overlays are merged on top of the board DTS at build time. Placing one under the application boards directory, named for the board, applies it only for that build target. The Zephyr tree stays untouched.

35. Running Zephyr tests across boards

Which Zephyr tool builds and runs ztest suites on many boards and emulators and reports results?

  1. A.Menuconfig
  2. B.MCUboot
  3. C.Devicetree compiler
  4. D.Twister
Show answer

Answer: D. Twister

Ztest is the test framework you write tests with, and Twister finds the test apps, builds them for each platform and runs them on emulators such as native_sim or QEMU, or on real hardware. It is used in Zephyr CI and works for your own projects too.

36. Pinning a task to one core

On FreeRTOS SMP (configNUMBER_OF_CORES = 2), you want the audio task to run only on core 1. Which feature does that?

  1. A.vTaskPrioritySet with priority 1
  2. B.configUSE_TIME_SLICING = 0
  3. C.Creating the task inside an ISR on core 1
  4. D.vTaskCoreAffinitySet with configUSE_CORE_AFFINITY = 1
Show answer

Answer: D. vTaskCoreAffinitySet with configUSE_CORE_AFFINITY = 1

Core affinity masks limit which cores may run a task. Pinning audio to one core can keep caches warm and its timing steady. ESP-IDF FreeRTOS offers xTaskCreatePinnedToCore for the same idea.

37. Isolating an untrusted task

You want a third-party parser task to be unable to write outside its own buffers on a Cortex-M with an MPU. Which FreeRTOS feature supports this?

  1. A.heap_5 with two regions
  2. B.configUSE_RECURSIVE_MUTEXES
  3. C.vTaskSuspendAll during parsing
  4. D.FreeRTOS-MPU with xTaskCreateRestricted
Show answer

Answer: D. FreeRTOS-MPU with xTaskCreateRestricted

The MPU port can run tasks unprivileged with access only to regions you list. A bad write then raises a MemManage fault instead of corrupting kernel data. Zephyr has a similar user mode with memory domains.

38. Limiting a Zephyr thread to its own memory

In Zephyr with CONFIG_USERSPACE, how does a user-mode thread get access to a shared buffer partition?

  1. A.Declare the shared buffer as volatile in the code
  2. B.Give the user thread a higher priority than others
  3. C.Add the partition to a memory domain that holds the thread
  4. D.Call k_sched_lock before every access to the buffer
Show answer

Answer: C. Add the partition to a memory domain that holds the thread

User threads can only touch their own stack plus partitions in their memory domain, enforced by the MPU or MMU. Kernel objects must also be granted with k_object_access_grant. Anything else faults, which contains bugs.

39. Avoiding malloc after start-up

Why do many real-time projects allocate all RTOS objects at start-up and forbid malloc afterwards?

  1. A.malloc is slower than any call to vTaskDelay
  2. B.Allocation at run time can fail or take varying time
  3. C.The RTOS has no way to free memory once used
  4. D.Static objects always use more RAM than heap ones
Show answer

Answer: B. Allocation at run time can fail or take varying time

Heap allocation time can vary and long-running systems can fragment until an allocation fails at a bad moment. Allocating everything up front makes memory use known at build time. Standards like MISRA and many safety guidelines push this approach.

40. Long critical section and interrupt latency

A task copies a 2 KB struct inside taskENTER_CRITICAL. A UART at 921600 baud starts losing bytes. Why?

  1. A.Critical sections slow down the clock that drives the UART
  2. B.The copy is moved into a separate task by the kernel
  3. C.taskENTER_CRITICAL resets the UART peripheral each time
  4. D.Interrupts up to the syscall priority are masked during the copy
Show answer

Answer: D. Interrupts up to the syscall priority are masked during the copy

A critical section masks kernel-aware interrupts for its whole length. At 921600 baud a byte arrives about every 11 µs, so a copy that takes longer can cause an overrun. Keep critical sections tiny, use a mutex for longer work, or let DMA receive.

RTOS interview questions for experienced candidates hard

41. Memory for a million sockets

A chat service must hold 1 million idle WebSocket connections. Each connection uses about 30 KB of server memory. Each server has 16 GB usable for connections. How many servers are needed at minimum?

  1. A.1
  2. B.4
  3. C.2
  4. D.30
Show answer

Answer: C. 2

1,000,000 x 30 KB = 30,000,000 KB, about 30 GB. With 16 GB per server, one is not enough and two give 32 GB. In practice add headroom for spikes and failover, for example an extra server, and tune buffers to lower per-connection memory.

42. Taking a mutex in an ISR

Why must an ISR never try to take an RTOS mutex that a task might hold?

  1. A.An ISR cannot block, and a mutex is owned by a task with priority inheritance, which has no meaning for an interrupt
  2. B.Mutexes are slower than semaphores
  3. C.ISRs cannot read global variables
  4. D.Mutexes are only for tasks with the same priority
Show answer

Answer: A. An ISR cannot block, and a mutex is owned by a task with priority inheritance, which has no meaning for an interrupt

If the mutex is held, a task would block until it is free, but an ISR cannot be suspended, so it would either fail or deadlock the system. Priority inheritance raises the holder's priority to the waiter's, and an interrupt is not a task. Defer the work to a task, or protect the data with a short critical section.

43. Is this task set schedulable

Three periodic tasks run under rate-monotonic priorities with execution time C and period T of (1 ms, 4 ms), (2 ms, 8 ms) and (3 ms, 12 ms). What does the Liu and Layland bound say?

  1. A.Total use is 75%, over the 69% bound, so it may fail
  2. B.Total use is 100%, so it cannot be scheduled
  3. C.Total use is 75%, under the 78% bound, so it is schedulable
  4. D.Total use is 50%, so priorities do not matter
Show answer

Answer: C. Total use is 75%, under the 78% bound, so it is schedulable

Utilisation is 1/4 + 2/8 + 3/12 = 0.75. The rate-monotonic bound for n tasks is n(2^(1/n) − 1), which for n = 3 is about 0.780. Since 0.75 ≤ 0.78, all deadlines are met. The 69% figure is the limit as n grows very large; passing it is enough, not necessary.

44. Parameter from a function that returns

What is wrong with this code?

void start_sensor(int id) {
    sensor_cfg_t cfg = { .id = id, .rate = 100 };
    xTaskCreate(sensor_task, "s", 256, &cfg, 3, NULL);
}
  1. A.xTaskCreate copies the full struct, so the code is fine
  2. B.The task name must be at least 8 characters long
  3. C.A task priority of 3 is not allowed by the kernel
  4. D.cfg is on this function's stack and is gone once it returns
Show answer

Answer: D. cfg is on this function's stack and is gone once it returns

xTaskCreate only stores the pointer. If the new task runs after start_sensor returns, cfg has been overwritten by later calls. Use static storage, allocate the config for the task, or have the task copy it first and signal back before the function returns.

45. Two stack pointers in an RTOS on Cortex-M

In a FreeRTOS Cortex-M port, which stack pointer do tasks and ISRs use?

  1. A.Tasks and ISRs all share the MSP stack pointer
  2. B.ISRs use the PSP, and tasks use the MSP
  3. C.Tasks use PSP and own stacks; ISRs share the MSP
  4. D.Each ISR gets its own separate PSP stack
Show answer

Answer: C. Tasks use PSP and own stacks; ISRs share the MSP

Thread mode runs on the process stack pointer, which the kernel switches per task. Exceptions always use the main stack pointer. So ISR stack needs are paid once on the MSP, not added to every task stack, apart from the hardware frame pushed onto the task stack.

46. The Mars Pathfinder resets

The 1997 Mars Pathfinder lander kept resetting from watchdog timeouts. What was the root cause and fix?

  1. A.A stack overflow in one task; the stack was made bigger
  2. B.Radiation flipped memory bits; ECC memory was then added
  3. C.Clock drift in the timer; a spare crystal was switched in
  4. D.Priority inversion on a bus mutex; enabling inheritance fixed it
Show answer

Answer: D. Priority inversion on a bus mutex; enabling inheritance fixed it

A low-priority task held a mutex needed by a high-priority bus task, and medium-priority tasks kept the low one from running. The watchdog saw the high task miss its deadline and reset the system. Engineers enabled priority inheritance in VxWorks remotely.

47. Critical sections on FreeRTOS SMP

On FreeRTOS SMP, what does taskENTER_CRITICAL() do that a single-core build does not?

  1. A.It also takes kernel spinlocks, so the other core is kept out
  2. B.It disables interrupts directly on both cores at once
  3. C.It stops the clock of the other core until it exits
  4. D.Nothing extra; it only masks the local interrupts
Show answer

Answer: A. It also takes kernel spinlocks, so the other core is kept out

Masking interrupts only affects the local core. The SMP kernel adds spinlocks so that a critical section on one core excludes kernel critical sections on the other. The other core spins while waiting, so sections must be even shorter than on single core.

48. Inversion with a semaphore used as a lock

A team guards a shared flash driver with a binary semaphore instead of a mutex. Under load the high-priority task misses deadlines while a medium task runs. Why?

  1. A.Binary semaphores are much slower to take than mutexes are
  2. B.Binary semaphores have no inheritance, so the low holder is not boosted
  3. C.The flash driver disables all interrupts while it writes
  4. D.The medium task keeps stealing the semaphore from the high task
Show answer

Answer: B. Binary semaphores have no inheritance, so the low holder is not boosted

With no owner, the kernel cannot raise the priority of whoever took the semaphore. A medium-priority task can then preempt the low holder for a long time while the high task waits. Use a mutex for mutual exclusion.

49. Burst of runs after a long stall

A 10 ms task using vTaskDelayUntil was blocked for 100 ms by a higher-priority task. What does it do when it gets the CPU back?

  1. A.It skips the missed periods and waits 10 ms
  2. B.It runs several passes back to back to catch up
  3. C.It is deleted by the kernel for missing deadlines
  4. D.It waits 100 ms before running its next pass
Show answer

Answer: B. It runs several passes back to back to catch up

The wake time advances by 10 ms each call. If it is already in the past, the call returns at once, so the task loops quickly until its wake time is ahead of the tick count again. If catching up is harmful, check the return value and reset the wake time to now.

50. Seeing queue contents in a debugger

Your debugger plugin shows queues only as addresses. How can you make them show by name in the RTOS view?

  1. A.Name each queue variable with a q_ prefix
  2. B.Create all queues from inside the idle task
  3. C.Create queues only with xQueueCreateStatic
  4. D.Register each queue with vQueueAddToRegistry
Show answer

Answer: D. Register each queue with vQueueAddToRegistry

The queue registry is a small table that kernel-aware debuggers read to label queues and semaphores. It is only for debugging and costs a little RAM. It has no effect on behaviour.

51. Float use in tasks on Cortex-M4F

On a Cortex-M4F FreeRTOS port, several tasks use floats. What must be true for this to work safely?

  1. A.Only one task may ever use the FPU on this core
  2. B.Floats may only be used inside critical sections
  3. C.The FPU must be turned off inside every ISR
  4. D.The port saves FPU registers per task; stacks need room
Show answer

Answer: D. The port saves FPU registers per task; stacks need room

The CM4F port saves the high FPU registers in its context switch when a task has used the FPU, using the EXC_RETURN bits to decide. That adds up to about 136 bytes per task frame (72 stacked by hardware plus 64 by the port). Undersized stacks in float-heavy tasks overflow more easily.

52. Lowest-latency interrupts in Zephyr

A Zephyr app needs the lowest possible latency for one interrupt and the handler does not call kernel APIs. What does Zephyr offer?

  1. A.A cooperative thread at priority -16
  2. B.A k_work item submitted with K_NO_WAIT
  3. C.A k_timer running with a 1 µs period
  4. D.A direct ISR, or a zero-latency IRQ flag
Show answer

Answer: D. A direct ISR, or a zero-latency IRQ flag

Direct ISRs skip the common interrupt wrapper, and with CONFIG_ZERO_LATENCY_IRQS an IRQ can sit above the kernel lock level so irq_lock does not delay it. Like FreeRTOS high-priority ISRs, such handlers must not call kernel services that assume normal ISR context.

53. Limit on Zephyr mutex priority boost

In Zephyr, a cooperative thread waits on a k_mutex held by a preemptible thread. What limits how far the holder can be boosted?

  1. A.Zephyr mutexes never boost the priority of the holder
  2. B.The holder is always boosted to priority -16 at once
  3. C.CONFIG_PRIORITY_CEILING caps how far inheritance can raise it
  4. D.Only the idle thread is ever boosted by a mutex
Show answer

Answer: C. CONFIG_PRIORITY_CEILING caps how far inheritance can raise it

Zephyr k_mutex supports priority inheritance, but the raised priority is capped by CONFIG_PRIORITY_CEILING. Setting it to 0, for example, stops a preemptible holder from being boosted into the cooperative range. Check this value when mixing cooperative and preemptive threads.

54. Using a Zephyr condition variable

Which pattern is correct for waiting on a Zephyr k_condvar?

k_mutex_lock(&m, K_FOREVER);
while (!ready) {
    k_condvar_wait(&cv, &m, K_FOREVER);
}
use_data();
k_mutex_unlock(&m);
  1. A.Call k_condvar_wait without holding the mutex
  2. B.Test the condition once with if instead of while
  3. C.This: test the condition in a loop with the mutex held
  4. D.Signal the condvar first, then lock the mutex
Show answer

Answer: C. This: test the condition in a loop with the mutex held

k_condvar_wait releases the mutex while waiting and takes it back before returning. Another thread may change the condition before this one runs, so the condition must be checked again in a loop. The signalling side should change ready while holding the same mutex.

55. Catching thread stack overflow in Zephyr

Which Zephyr option uses the MPU to fault the moment a thread overflows its stack?

  1. A.CONFIG_THREAD_NAME
  2. B.CONFIG_HW_STACK_PROTECTION
  3. C.CONFIG_LOG_MODE_DEFERRED
  4. D.CONFIG_TIMESLICING
Show answer

Answer: B. CONFIG_HW_STACK_PROTECTION

Hardware stack protection places an MPU guard at the end of each thread stack, or uses stack limit registers on Armv8-M. An overflow triggers a fault at the bad access, and the fatal handler reports which thread. CONFIG_STACK_SENTINEL is a cheaper software check.

56. Time slicing in Zephyr

With CONFIG_TIMESLICING=y and CONFIG_TIMESLICE_SIZE=10, two preemptible Zephyr threads at priority 5 never sleep. What happens?

  1. A.The first thread keeps the CPU until it blocks
  2. B.Both are raised to priority 4
  3. C.Time slicing applies only to cooperative threads
  4. D.They alternate about every 10 ms
Show answer

Answer: D. They alternate about every 10 ms

Time slicing lets equal-priority preemptible threads share the CPU in slices of the set size in milliseconds. Without it, a thread runs until it blocks or yields. Cooperative threads are never sliced, and CONFIG_TIMESLICE_PRIORITY limits which priorities slicing applies to.

57. Aborting a thread that holds a mutex

A Zephyr supervisor calls k_thread_abort on a worker that currently holds a k_mutex. What problem follows?

  1. A.Zephyr releases the mutex for the thread automatically
  2. B.The mutex is never released, so its waiters block forever
  3. C.The supervisor thread is aborted along with the worker
  4. D.The mutex turns into a semaphore that anyone can give
Show answer

Answer: B. The mutex is never released, so its waiters block forever

Aborting a thread stops it at once without running cleanup, so locks, buffers and peripheral states it owned stay as they were. Waiters on that mutex hang. Prefer asking threads to exit through a flag or event, and let them release resources first.

58. Setting configMAX_PRIORITIES to 64

A developer sets configMAX_PRIORITIES to 64 "just in case", but uses only 6 levels. What is the cost on a typical port?

  1. A.Tasks above priority 32 can never be scheduled
  2. B.The tick rate drops by half to cover the levels
  3. C.There is no cost of any kind on any port
  4. D.More ready lists in RAM, and a slower priority search
Show answer

Answer: D. More ready lists in RAM, and a slower priority search

The kernel keeps one ready list per priority, so more levels use more RAM. Without configUSE_PORT_OPTIMISED_TASK_SELECTION, finding the top ready task scans from the highest level down. The optimised Cortex-M selection uses CLZ but limits you to 32 priorities.

59. Debugger shows only one call stack

The board halts in a HardFault, and the debugger shows only the fault handler and current task stack. How do you see what every task was doing?

  1. A.Turn on RTOS-aware debugging so it reads each task context
  2. B.Single-step through each task one at a time to see them
  3. C.Make every task stack bigger and run the test again
  4. D.Turn off the scheduler before halting the processor
Show answer

Answer: A. Turn on RTOS-aware debugging so it reads each task context

An RTOS plugin in tools like Ozone, Cube IDE or OpenOCD with GDB reads the kernel task lists and saved stack pointers. It rebuilds each task call stack and state. That often shows the task that corrupted memory before the fault.

60. Active object design in an RTOS

In the active object pattern, each task owns its data, waits on its own event queue and handles one event at a time. What is the main benefit?

  1. A.Tasks no longer need any stack memory at all
  2. B.Every event handler runs inside an ISR instead
  3. C.Little shared data and few locks remain, so races are rarer
  4. D.The scheduler is no longer needed by the system
Show answer

Answer: C. Little shared data and few locks remain, so races are rarer

Each object owns its state and others only send it events, so there is little shared memory to protect. Run-to-completion handling makes behaviour easier to reason about. The cost is queue RAM and thinking in events, which frameworks like QP help with.

Ready to test yourself?

Take a 15-question RTOS MCQ test with a score at the end, or practise the full RTOS question bank and earn points on the leaderboard.