diff --git a/miosix/arch/cpu/common/cortexMx_interrupts.cpp b/miosix/arch/cpu/common/cortexMx_interrupts.cpp index 113a8a5af9dec6f7d4f84f550c1b8486317563ac..a2514b9e26c7cf42aee548699599732cf7cb4273 100644 --- a/miosix/arch/cpu/common/cortexMx_interrupts.cpp +++ b/miosix/arch/cpu/common/cortexMx_interrupts.cpp @@ -618,7 +618,11 @@ void __attribute__((noinline)) svcImpl() return; } } - Thread::IRQstackOverflowCheck(); + // NOTE: Do not process the syscall if a stack overflow was detected, since + // the process will segfault anyway. Moreover, the stack overflow check code + // switches the thread context to the kernelspace one and attempting to + // extract the syscall number from ctxsave will return garbage! + if(Thread::IRQstackOverflowCheck()) return; //Miosix on ARM uses r3 for the syscall number. //Note that it is required to use ctxsave and not cur->ctxsave because diff --git a/miosix/kernel/kernel.cpp b/miosix/kernel/kernel.cpp index 39df313f5e15e22d1002d34ad77c096884971a8d..0b80bd189183597d2256afa7e66c1dab9452d2ed 100755 --- a/miosix/kernel/kernel.cpp +++ b/miosix/kernel/kernel.cpp @@ -617,29 +617,29 @@ int Thread::getStackSize() return getCurrentThread()->stacksize; } -void Thread::IRQstackOverflowCheck() +bool Thread::IRQstackOverflowCheck() { const unsigned int watermarkSize=WATERMARK_LEN/sizeof(unsigned int); #ifdef WITH_PROCESSES if(const_cast<Thread*>(runningThread)->flags.isInUserspace()) { bool overflow=false; - for(unsigned int i=0;i<watermarkSize;i++) - if(runningThread->userWatermark[i]!=WATERMARK_FILL) overflow=true; if(runningThread->userCtxsave[stackPtrOffsetInCtxsave] < reinterpret_cast<unsigned int>(runningThread->userWatermark+watermarkSize)) overflow=true; + if(overflow==false) + for(unsigned int i=0;i<watermarkSize;i++) + if(runningThread->userWatermark[i]!=WATERMARK_FILL) overflow=true; if(overflow) IRQreportFault(FaultData(fault::STACKOVERFLOW,0)); - } else { + return overflow; + } #endif //WITH_PROCESSES - for(unsigned int i=0;i<watermarkSize;i++) - if(runningThread->watermark[i]!=WATERMARK_FILL) errorHandler(STACK_OVERFLOW); if(runningThread->ctxsave[stackPtrOffsetInCtxsave] < reinterpret_cast<unsigned int>(runningThread->watermark+watermarkSize)) errorHandler(STACK_OVERFLOW); - #ifdef WITH_PROCESSES - } - #endif //WITH_PROCESSES + for(unsigned int i=0;i<watermarkSize;i++) + if(runningThread->watermark[i]!=WATERMARK_FILL) errorHandler(STACK_OVERFLOW); + return false; } #ifdef WITH_PROCESSES diff --git a/miosix/kernel/kernel.h b/miosix/kernel/kernel.h index 829519bbf233a6061f2b2b99e34af80ed20d1633..5033e5d5f04334155b132c337a2efdd00917bf4e 100755 --- a/miosix/kernel/kernel.h +++ b/miosix/kernel/kernel.h @@ -888,10 +888,19 @@ public: /** * \internal - * Used before every context switch to check if the stack of the thread - * being preempted has overflowed + * To be used in interrupts where a context switch can occur to check if the + * stack of the thread being preempted has overflowed. + * Note that since Miosix 3 all peripheral interrupts no longer perform a + * full context save/restore thus you cannot call this functions from such + * interrupts. + * \return On a platform without processes this function returns false if no + * stack overflow was detected or causes a reboot if a stack overflow was + * detected. Basically, it never returns true. On a platform with processes + * return true if the stack overflow check failed for a thread running in + * userspace. If the overflow check failed for a kernel thread or a thread + * running in kernelspace this function causes a reboot. */ - static void IRQstackOverflowCheck(); + static bool IRQstackOverflowCheck(); #ifdef WITH_PROCESSES