Dynamic thread creation when using PORT_ENABLE_GUARD_PAGES may fail Topic is solved

Report here problems in any of ChibiOS components. This forum is NOT for support.
Post Reply
User avatar
craig.sacco
Posts: 5
Joined: Mon Jul 17, 2017 2:22 am
Has thanked: 2 times
Been thanked: 2 times

Dynamic thread creation when using PORT_ENABLE_GUARD_PAGES may fail

Post by craig.sacco »

Given the following:
  • Micro is an STM32F407
  • CH_DBG_ENABLE_CHECKS is TRUE
  • CH_DBG_ENABLE_ASSERTS is TRUE
  • CH_DBG_ENABLE_STACK_CHECK is TRUE
  • PORT_ENABLE_GUARD_PAGES is TRUE

When trying to use the dynamic thread creation (chThdCreateFromHeap) in ChibiOS 17.6.x, the pointer returned by chHeapAllocAligned may not be aligned to a 32-byte boundary (which is the minimum memory guard size when using the MPU), even if the requested alignment is 32 bytes, it will alway return a pointer aligned to the size of stkalign_t (see macro H_BLOCK).

When the check API is enabled the following check fails in chThdCreateSuspendedI:

chDbgCheck(MEM_IS_ALIGNED(tdp->wbase, PORT_WORKING_AREA_ALIGN) &&
MEM_IS_ALIGNED(tdp->wend, PORT_STACK_ALIGN) &&
(tdp->wend > tdp->wbase) &&
(((size_t)tdp->wend - (size_t)tdp->wbase) >= THD_WORKING_AREA_SIZE(0)));

As tdp->wbase is not aligned to 32 bytes.

Now I am not using chThdCreateFromHeap since I don't want the thread to be started immediately. I have a custom function that realigns pointer returned by chHeapAllocAligned to a 32-byte boundary - only problem is that it may waste up to 32 bytes of RAM in the process:

void* wsp = chHeapAllocAligned(NULL, size + PORT_WORKING_AREA_ALIGN, PORT_WORKING_AREA_ALIGN);
ASSERT(wsp != NULL);

uint8_t* tmp = (uint8_t*)wsp;
tmp = (uint8_t*)(((uint32_t)tmp) & ~((uint32_t)PORT_WORKING_AREA_ALIGN - 1));
if (tmp != wsp) {
tmp += PORT_WORKING_AREA_ALIGN; // move to next 32-byte alignment
} else {
size += PORT_WORKING_AREA_ALIGN; // size of working area can be safely increased by 32 bytes
}
wsp = (void*)tmp;

I don't believe this affects any other release branch in ChibiOS since MPU guards were only implemented in 17.6.x release.
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Dynamic thread creation when using PORT_ENABLE_GUARD_PAGES may fail

Post by Giovanni »

Hi,

It is a bug in the heap allocator at lines 263...273, it requests to the "provider" an aligned block but then it is returned not aligned because the size of the header is not considered.

A workaround could be (not tested yet):
1) Allocate from the heap the total amount of memory you will need.
2) Release the allocated block, now it is in the free list.
3) Use the allocator normally, the problematic code is never triggered again.

Alternatively:
1) Create an heap without "provider" using a static area.

A full fix does not look straightforward but I hope to make a 17.6.2 release today.

Giovanni
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Dynamic thread creation when using PORT_ENABLE_GUARD_PAGES may fail

Post by Giovanni »

Hi,

I committed a tentative fix (bug #888) in both trunk and branch stable 17.6.x, it required changes in some API, could you verify that everything is fine in your application?

I will release it as 17.6.2 afterward.

Giovanni
User avatar
craig.sacco
Posts: 5
Joined: Mon Jul 17, 2017 2:22 am
Has thanked: 2 times
Been thanked: 2 times

Re: Dynamic thread creation when using PORT_ENABLE_GUARD_PAGES may fail

Post by craig.sacco »

I can try the fix later this afternoon (Melbourne time)
User avatar
craig.sacco
Posts: 5
Joined: Mon Jul 17, 2017 2:22 am
Has thanked: 2 times
Been thanked: 2 times

Re: Dynamic thread creation when using PORT_ENABLE_GUARD_PAGES may fail

Post by craig.sacco »

The fix looks good - memory allocated from the heap to be used for threads are now aligned to 32 bytes.
Post Reply