Menu

#186 QXK: Extended thread context switch causes assertion in PendSV_Handler

QPCPP
closed
None
1
2024-08-01
2017-10-12
No

The following scenario causes assertion in PendSV_Handler in the QXK kernel (QP/C/C++ 5.9.9):

  1. An extended thread priority = 18 calls QXSemaphore_wait() with count = 0 (i.e. thread 18 should block).
  2. QXSemaphore_wait() calls QXK_sched_() inside a critical region
  3. QXK_sched_() finds extended thread or Active Object with priority = 17 ready, sets the next pointer to it, and triggers a context switch (i.e. PendSV is set)
  4. An interrupt fires while still inside the critical region of QXSemaphore_wait().
  5. Once QXSemaphore_wait() re-enables interrupts, this ISR will immediately executes (since it is higher priority than PendSV) and suppose it makes the same extended thread with priority=18 ready again; NOTE: QXSemaphore_signal() does not context switch since we are inside ISR.
  6. Before exiting, this ISR calls QXK_ISR_EXIT(), this in turn calls QXK_sched_().
  7. This time, QXK_sched_() sees that the curr active thread #18 is the same as the next active thread #18 and sets QXK_attr_.next pointer to 0.
  8. As soon as the ISR returns, it tail-chains directly into PendSV which is still pending from the first call to QXK_sched_(). However this time the next pointer is 0 and PendSV will trigger an assert failure (at label PendSV_error).

--MMS

Discussion

  • Quantum Leaps

    Quantum Leaps - 2017-10-12
    • status: open --> accepted
     
  • Quantum Leaps

    Quantum Leaps - 2017-10-12

    This bug will be fixed in the upcoming QP/C/C++ 6.0.0 by modifying QXK_sched_() as follows:

    old code:

            else {
                QXK_attr_.next = (QActive *)0;
                p = (uint_fast8_t)0; /* no activation needed */
            }
    

    new code:

            else {
                /* the current QXK thread must be the same as 'next' */
                Q_ASSERT_ID(620, QXK_attr_.curr == next);
    
                QXK_attr_.next = next;
                p = (uint_fast8_t)0; /* no activation needed */
            }
    

    This will ensure that the QXK_attr_.next pointer has the non-NULL value, so the PendSV_Handler will no longer assert. In this corner-case the current thread and the next thread will be the same, so PendSV_Handler will end up switching the context back and forth to the same extended thread. This has been tested to be safe.

    --MMS

     
  • Quantum Leaps

    Quantum Leaps - 2017-11-11
    • status: accepted --> closed
     
  • Quantum Leaps

    Quantum Leaps - 2017-11-11

    Fixed in QP/C/C++6.0.0.
    --MMS

     

Anonymous
Anonymous

Add attachments
Cancel