From 71f174d00dcd678fa9da5acea8e1454f2417810c Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sat, 2 Apr 2016 16:47:14 +0000 Subject: [PATCH] Fixed stack limit conditions in RT4. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9224 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- demos/various/RT-Win32-Simulator/main.c | 8 ++++++-- os/common/ports/ARM/chcore.h | 4 ++-- os/common/ports/ARMCMx/chcore_v6m.h | 2 +- os/common/ports/ARMCMx/chcore_v7m.h | 4 ++-- os/common/ports/e200/chcore.h | 2 +- os/common/ports/templates/chcore.h | 2 +- os/nil/include/ch.h | 2 +- os/nil/src/ch.c | 4 ++-- os/rt/include/chschd.h | 10 +++++++--- os/rt/include/chthreads.h | 11 +++++++---- os/rt/src/chregistry.c | 9 ++++++--- os/rt/src/chsys.c | 13 ++++++++++--- os/rt/src/chthreads.c | 12 ++++++++---- os/various/shell/shell_cmd.c | 7 ++++++- 14 files changed, 60 insertions(+), 30 deletions(-) diff --git a/demos/various/RT-Win32-Simulator/main.c b/demos/various/RT-Win32-Simulator/main.c index d4a3da302..02d700e73 100644 --- a/demos/various/RT-Win32-Simulator/main.c +++ b/demos/various/RT-Win32-Simulator/main.c @@ -104,7 +104,9 @@ static void sd1_handler(eventid_t id) { flags = chEvtGetAndClearFlags(&sd1fel); if ((flags & CHN_CONNECTED) && (shelltp1 == NULL)) { cputs("Init: connection on SD1"); - shelltp1 = shellCreate(&shell_cfg1, SHELL_WA_SIZE, NORMALPRIO + 1); + shelltp1 = chThdCreateFromHeap(NULL, SHELL_WA_SIZE, + "shell1", NORMALPRIO + 10, + shellThread, (void *)&shell_cfg1); } if (flags & CHN_DISCONNECTED) { cputs("Init: disconnection on SD1"); @@ -127,7 +129,9 @@ static void sd2_handler(eventid_t id) { flags = chEvtGetAndClearFlags(&sd2fel); if ((flags & CHN_CONNECTED) && (shelltp2 == NULL)) { cputs("Init: connection on SD2"); - shelltp2 = shellCreate(&shell_cfg2, SHELL_WA_SIZE, NORMALPRIO + 10); + shelltp2 = chThdCreateFromHeap(NULL, SHELL_WA_SIZE, + "shell2", NORMALPRIO + 10, + shellThread, (void *)&shell_cfg2); } if (flags & CHN_DISCONNECTED) { cputs("Init: disconnection on SD2"); diff --git a/os/common/ports/ARM/chcore.h b/os/common/ports/ARM/chcore.h index 532fb0d11..3aa31eedc 100644 --- a/os/common/ports/ARM/chcore.h +++ b/os/common/ports/ARM/chcore.h @@ -337,7 +337,7 @@ struct port_context { #if CH_DBG_ENABLE_STACK_CHECK == TRUE #define port_switch(ntp, otp) { \ register struct port_intctx *r13 asm ("r13"); \ - if ((stkalign_t *)(r13 - 1) < otp->p_stklimit) \ + if ((stkalign_t *)(r13 - 1) < otp->wabase) \ chSysHalt("stack overflow"); \ _port_switch_thumb(ntp, otp); \ } @@ -350,7 +350,7 @@ struct port_context { #if CH_DBG_ENABLE_STACK_CHECK == TRUE #define port_switch(ntp, otp) { \ register struct port_intctx *r13 asm ("r13"); \ - if ((stkalign_t *)(r13 - 1) < otp->stklimit) \ + if ((stkalign_t *)(r13 - 1) < otp->wabase) \ chSysHalt("stack overflow"); \ _port_switch_arm(ntp, otp); \ } diff --git a/os/common/ports/ARMCMx/chcore_v6m.h b/os/common/ports/ARMCMx/chcore_v6m.h index 0afeeabe9..06039ecc6 100644 --- a/os/common/ports/ARMCMx/chcore_v6m.h +++ b/os/common/ports/ARMCMx/chcore_v6m.h @@ -285,7 +285,7 @@ struct port_intctx { #else #define port_switch(ntp, otp) { \ struct port_intctx *r13 = (struct port_intctx *)__get_PSP(); \ - if ((stkalign_t *)(r13 - 1) < (otp)->stklimit) { \ + if ((stkalign_t *)(r13 - 1) < (otp)->wabase) { \ chSysHalt("stack overflow"); \ } \ _port_switch(ntp, otp); \ diff --git a/os/common/ports/ARMCMx/chcore_v7m.h b/os/common/ports/ARMCMx/chcore_v7m.h index 5dbbed8bd..bf6a998f3 100644 --- a/os/common/ports/ARMCMx/chcore_v7m.h +++ b/os/common/ports/ARMCMx/chcore_v7m.h @@ -440,7 +440,7 @@ struct port_intctx { #if PORT_ENABLE_GUARD_PAGES == FALSE #define port_switch(ntp, otp) { \ struct port_intctx *r13 = (struct port_intctx *)__get_PSP(); \ - if ((stkalign_t *)(r13 - 1) < (otp)->stklimit) { \ + if ((stkalign_t *)(r13 - 1) < (otp)->wabase) { \ chSysHalt("stack overflow"); \ } \ _port_switch(ntp, otp); \ @@ -451,7 +451,7 @@ struct port_intctx { \ /* Setting up the guard page for the switched-in thread.*/ \ mpuConfigureRegion(MPU_REGION_0, \ - chThdGetSelfX()->stklimit, \ + chThdGetSelfX()->wabase, \ MPU_RASR_ATTR_AP_NA_NA | \ MPU_RASR_ATTR_NON_CACHEABLE | \ MPU_RASR_SIZE_32 | \ diff --git a/os/common/ports/e200/chcore.h b/os/common/ports/e200/chcore.h index d031f1c28..453f955bb 100644 --- a/os/common/ports/e200/chcore.h +++ b/os/common/ports/e200/chcore.h @@ -392,7 +392,7 @@ struct port_context { #else #define port_switch(ntp, otp) { \ register struct port_intctx *sp asm ("%r1"); \ - if ((stkalign_t *)(sp - 1) < otp->stklimit) \ + if ((stkalign_t *)(sp - 1) < otp->wabase) \ chSysHalt("stack overflow"); \ _port_switch(ntp, otp); \ } diff --git a/os/common/ports/templates/chcore.h b/os/common/ports/templates/chcore.h index 4b92a3a23..8faf4ec35 100644 --- a/os/common/ports/templates/chcore.h +++ b/os/common/ports/templates/chcore.h @@ -272,7 +272,7 @@ struct port_context { #else #define port_switch(ntp, otp) { \ register struct port_intctx *sp asm ("%r1"); \ - if ((stkalign_t *)(sp - 1) < otp->stklimit) \ + if ((stkalign_t *)(sp - 1) < otp->wabase) \ chSysHalt("stack overflow"); \ _port_switch(ntp, otp); \ } diff --git a/os/nil/include/ch.h b/os/nil/include/ch.h index dd548ab20..e517b9551 100644 --- a/os/nil/include/ch.h +++ b/os/nil/include/ch.h @@ -492,7 +492,7 @@ struct nil_thread { eventmask_t epmask; /**< @brief Pending events mask. */ #endif #if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__) - stkalign_t *stklimit; /**< @brief Thread stack boundary. */ + stkalign_t *wabase; /**< @brief Thread stack boundary. */ #endif /* Optional extra fields.*/ CH_CFG_THREAD_EXT_FIELDS diff --git a/os/nil/src/ch.c b/os/nil/src/ch.c index d527fc60f..3a5a3b8e0 100644 --- a/os/nil/src/ch.c +++ b/os/nil/src/ch.c @@ -234,7 +234,7 @@ void chSysInit(void) { tcp = nil_thd_configs; while (tp < &nil.threads[CH_CFG_NUM_THREADS]) { #if CH_DBG_ENABLE_STACK_CHECK - tp->stklimit = (stkalign_t *)tcp->wbase; + tp->wabase = (stkalign_t *)tcp->wbase; #endif /* Port dependent thread initialization.*/ @@ -250,7 +250,7 @@ void chSysInit(void) { #if CH_DBG_ENABLE_STACK_CHECK /* The idle thread is a special case because its stack is set up by the runtime environment.*/ - tp->stklimit = THD_IDLE_BASE; + tp->wabase = THD_IDLE_BASE; #endif /* Interrupts partially enabled. It is equivalent to entering the diff --git a/os/rt/include/chschd.h b/os/rt/include/chschd.h index aa49adcff..a00b2fa5a 100644 --- a/os/rt/include/chschd.h +++ b/os/rt/include/chschd.h @@ -169,11 +169,15 @@ struct ch_thread { */ const char *name; #endif +#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \ + defined(__DOXYGEN__) /** - * @brief Thread stack boundary. - * @note This pointer matches with the working area base address. + * @brief Working area base address. + * @note This pointer is used for stack overflow checks and for + * dynamic threading. */ - stkalign_t *stklimit; + stkalign_t *wabase; +#endif /** * @brief Current thread state. */ diff --git a/os/rt/include/chthreads.h b/os/rt/include/chthreads.h index 47d7c2672..1b29260ed 100644 --- a/os/rt/include/chthreads.h +++ b/os/rt/include/chthreads.h @@ -307,18 +307,21 @@ static inline systime_t chThdGetTicksX(thread_t *tp) { } #endif +#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \ + defined(__DOXYGEN__) /** - * @brief Returns the stack limit of the specified thread. + * @brief Returns the working area base of the specified thread. * * @param[in] tp pointer to the thread - * @return The stack limit pointer. + * @return The working area base pointer. * * @xclass */ -static inline stkalign_t *chthdGetStackLimitX(thread_t *tp) { +static inline stkalign_t *chThdGetWorkingAreaX(thread_t *tp) { - return tp->stklimit; + return tp->wabase; } +#endif /* CH_DBG_ENABLE_STACK_CHECK == TRUE */ /** * @brief Verifies if the specified thread is in the @p CH_STATE_FINAL state. diff --git a/os/rt/src/chregistry.c b/os/rt/src/chregistry.c index c20909cd0..7be0939c8 100644 --- a/os/rt/src/chregistry.c +++ b/os/rt/src/chregistry.c @@ -95,8 +95,8 @@ ROMCONST chdebug_t ch_debug = { (uint8_t)_offsetof(thread_t, newer), (uint8_t)_offsetof(thread_t, older), (uint8_t)_offsetof(thread_t, name), -#if CH_DBG_ENABLE_STACK_CHECK == TRUE - (uint8_t)_offsetof(thread_t, stklimit), +#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) + (uint8_t)_offsetof(thread_t, wabase), #else (uint8_t)0, #endif @@ -233,6 +233,8 @@ thread_t *chRegFindThreadByPointer(thread_t *tp) { return NULL; } +#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \ + defined(__DOXYGEN__) /** * @brief Confirms that a working area is being used by some active thread. * @note The reference counter of the found thread is increased by one so @@ -251,7 +253,7 @@ thread_t *chRegFindThreadByWorkingArea(stkalign_t *wa) { /* Scanning registry.*/ ctp = chRegFirstThread(); do { - if (ctp->stklimit == wa) { + if (chThdGetWorkingAreaX(ctp) == wa) { return ctp; } ctp = chRegNextThread(ctp); @@ -259,6 +261,7 @@ thread_t *chRegFindThreadByWorkingArea(stkalign_t *wa) { return NULL; } +#endif #endif /* CH_CFG_USE_REGISTRY == TRUE */ diff --git a/os/rt/src/chsys.c b/os/rt/src/chsys.c index 82a9e78d6..f4dbbb4e2 100644 --- a/os/rt/src/chsys.c +++ b/os/rt/src/chsys.c @@ -98,7 +98,6 @@ static void _idle_thread(void *p) { * @special */ void chSysInit(void) { - extern stkalign_t __main_thread_stack_base__; _scheduler_init(); _vt_init(); @@ -135,8 +134,16 @@ void chSysInit(void) { currp = _thread_init(&ch.mainthread, "idle", IDLEPRIO); #endif - /* Setting up the base address of the static main thread stack.*/ - currp->stklimit = &__main_thread_stack_base__; +#if CH_DBG_ENABLE_STACK_CHECK == TRUE + { + /* Setting up the base address of the static main thread stack, the + symbol must be provided externally.*/ + extern stkalign_t __main_thread_stack_base__; + currp->wabase = &__main_thread_stack_base__; + } +#elif CH_CFG_USE_DYNAMIC == TRUE + currp->wabase = NULL; +#endif /* Setting up the caller as current thread.*/ currp->state = CH_STATE_CURRENT; diff --git a/os/rt/src/chthreads.c b/os/rt/src/chthreads.c index 8566aaa11..74c41fa7b 100644 --- a/os/rt/src/chthreads.c +++ b/os/rt/src/chthreads.c @@ -182,8 +182,10 @@ thread_t *chThdCreateSuspendedI(const thread_descriptor_t *tdp) { tp = (thread_t *)((uint8_t *)tdp->wend - MEM_ALIGN_NEXT(sizeof (thread_t), PORT_STACK_ALIGN)); +#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) /* Stack boundary.*/ - tp->stklimit = tdp->wbase; + tp->wabase = tdp->wbase; +#endif /* Setting up the port-dependent part of the working area.*/ PORT_SETUP_CONTEXT(tp, tdp->wbase, tp, tdp->funcp, tdp->arg); @@ -348,8 +350,10 @@ thread_t *chThdCreateStatic(void *wsp, size_t size, tp = (thread_t *)((uint8_t *)wsp + size - MEM_ALIGN_NEXT(sizeof (thread_t), PORT_STACK_ALIGN)); +#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) /* Stack boundary.*/ - tp->stklimit = (stkalign_t *)wsp; + tp->wabase = (stkalign_t *)wsp; +#endif /* Setting up the port-dependent part of the working area.*/ PORT_SETUP_CONTEXT(tp, wsp, tp, pf, arg); @@ -436,12 +440,12 @@ void chThdRelease(thread_t *tp) { switch (tp->flags & CH_FLAG_MODE_MASK) { #if CH_CFG_USE_HEAP == TRUE case CH_FLAG_MODE_HEAP: - chHeapFree(chthdGetStackLimitX(tp)); + chHeapFree(chThdGetWorkingAreaX(tp)); break; #endif #if CH_CFG_USE_MEMPOOLS == TRUE case CH_FLAG_MODE_MPOOL: - chPoolFree(tp->mpool, chthdGetStackLimitX(tp)); + chPoolFree(tp->mpool, chThdGetWorkingAreaX(tp)); break; #endif default: diff --git a/os/various/shell/shell_cmd.c b/os/various/shell/shell_cmd.c index 359207da0..7f31dc87f 100644 --- a/os/various/shell/shell_cmd.c +++ b/os/various/shell/shell_cmd.c @@ -161,8 +161,13 @@ static void cmd_threads(BaseSequentialStream *chp, int argc, char *argv[]) { chprintf(chp, "stklimit stack addr refs prio state name\r\n"); tp = chRegFirstThread(); do { +#if CH_DBG_ENABLE_STACK_CHECK == TRUE + uint32_t stklimit = (uint32_t)tp->stklimit; +#else + uint32_t stklimit = 0U; +#endif chprintf(chp, "%08lx %08lx %08lx %4lu %4lu %9s %12s\r\n", - (uint32_t)tp->stklimit, (uint32_t)tp->ctx.sp, (uint32_t)tp, + stklimit, (uint32_t)tp->ctx.sp, (uint32_t)tp, (uint32_t)tp->refs - 1, (uint32_t)tp->prio, states[tp->state], tp->name == NULL ? "" : tp->name); tp = chRegNextThread(tp);