diff --git a/os/kernel/include/heap.h b/os/kernel/include/heap.h index c044f47c7..0ebe1d7b5 100644 --- a/os/kernel/include/heap.h +++ b/os/kernel/include/heap.h @@ -46,12 +46,15 @@ typedef struct memory_heap MemoryHeap; /** * @brief Memory heap block header. */ -struct heap_header { - union { - struct heap_header *next; /**< @brief Next block in free list. */ - MemoryHeap *heap; /**< @brief Block owner heap. */ - } h_u; /**< @brief Overlapped fields. */ - size_t h_size; /**< @brief Size of the memory block. */ +union heap_header { + stkalign_t align; + struct { + union { + union heap_header *next; /**< @brief Next block in free list. */ + MemoryHeap *heap; /**< @brief Block owner heap. */ + } u; /**< @brief Overlapped fields. */ + size_t size; /**< @brief Size of the memory block. */ + } h; }; /** @@ -60,7 +63,7 @@ struct heap_header { struct memory_heap { memgetfunc_t h_provider; /**< @brief Memory blocks provider for this heap. */ - struct heap_header h_free; /**< @brief Free blocks list header. */ + union heap_header h_free; /**< @brief Free blocks list header. */ #if CH_USE_MUTEXES Mutex h_mtx; /**< @brief Heap access mutex. */ #else diff --git a/os/kernel/include/memcore.h b/os/kernel/include/memcore.h index 9fc8d7a44..c0aa9c9a2 100644 --- a/os/kernel/include/memcore.h +++ b/os/kernel/include/memcore.h @@ -28,11 +28,6 @@ #ifndef _MEMCORE_H_ #define _MEMCORE_H_ -/** - * @brief Memory alignment type. - */ -typedef void *align_t; - /** * @brief Memory get function. * @note This type must be assignment compatible with the @p chMemAlloc() @@ -43,7 +38,7 @@ typedef void *(*memgetfunc_t)(size_t size); /** * @brief Alignment mask constant. */ -#define MEM_ALIGN_MASK (sizeof(align_t) - 1) +#define MEM_ALIGN_MASK (sizeof(stkalign_t) - 1) /** * @brief Alignment helper macro. diff --git a/os/kernel/src/chheap.c b/os/kernel/src/chheap.c index 45431d5f4..91b7d01bc 100644 --- a/os/kernel/src/chheap.c +++ b/os/kernel/src/chheap.c @@ -53,8 +53,8 @@ static MemoryHeap default_heap; */ void heap_init(void) { default_heap.h_provider = chCoreAlloc; - default_heap.h_free.h_u.next = (struct heap_header *)NULL; - default_heap.h_free.h_size = 0; + default_heap.h_free.h.u.next = (union heap_header *)NULL; + default_heap.h_free.h.size = 0; #if CH_USE_MUTEXES chMtxInit(&default_heap.h_mtx); #else @@ -72,15 +72,15 @@ void heap_init(void) { * @param[in] size heap size */ void chHeapInit(MemoryHeap *heapp, void *buf, size_t size) { - struct heap_header *hp; + union heap_header *hp; chDbgCheck(MEM_IS_ALIGNED(buf) && MEM_IS_ALIGNED(size), "chHeapInit"); heapp->h_provider = (memgetfunc_t)NULL; - heapp->h_free.h_u.next = hp = buf; - heapp->h_free.h_size = 0; - hp->h_u.next = NULL; - hp->h_size = size - sizeof(struct heap_header); + heapp->h_free.h.u.next = hp = buf; + heapp->h_free.h.size = 0; + hp->h.u.next = NULL; + hp->h.size = size - sizeof(union heap_header); #if CH_USE_MUTEXES chMtxInit(&heapp->h_mtx); #else @@ -103,7 +103,7 @@ void chHeapInit(MemoryHeap *heapp, void *buf, size_t size) { * @retval NULL if the block cannot be allocated. */ void *chHeapAlloc(MemoryHeap *heapp, size_t size) { - struct heap_header *qp, *hp, *fp; + union heap_header *qp, *hp, *fp; if (heapp == NULL) heapp = &default_heap; @@ -112,24 +112,24 @@ void *chHeapAlloc(MemoryHeap *heapp, size_t size) { qp = &heapp->h_free; H_LOCK(heapp); - while (qp->h_u.next != NULL) { - hp = qp->h_u.next; - if (hp->h_size >= size) { - if (hp->h_size < size + sizeof(struct heap_header)) { + while (qp->h.u.next != NULL) { + hp = qp->h.u.next; + if (hp->h.size >= size) { + if (hp->h.size < size + sizeof(union heap_header)) { /* Gets the whole block even if it is slightly bigger than the requested size because the fragment would be too small to be useful.*/ - qp->h_u.next = hp->h_u.next; + qp->h.u.next = hp->h.u.next; } else { /* Block bigger enough, must split it.*/ - fp = (void *)((uint8_t *)(hp) + sizeof(struct heap_header) + size); - fp->h_u.next = hp->h_u.next; - fp->h_size = hp->h_size - sizeof(struct heap_header) - size; - qp->h_u.next = fp; - hp->h_size = size; + fp = (void *)((uint8_t *)(hp) + sizeof(union heap_header) + size); + fp->h.u.next = hp->h.u.next; + fp->h.size = hp->h.size - sizeof(union heap_header) - size; + qp->h.u.next = fp; + hp->h.size = size; } - hp->h_u.heap = heapp; + hp->h.u.heap = heapp; H_UNLOCK(heapp); return (void *)(hp + 1); @@ -142,10 +142,10 @@ void *chHeapAlloc(MemoryHeap *heapp, size_t size) { /* More memory is required, tries to get it from the associated provider else fails.*/ if (heapp->h_provider) { - hp = heapp->h_provider(size + sizeof(struct heap_header)); + hp = heapp->h_provider(size + sizeof(union heap_header)); if (hp != NULL) { - hp->h_u.heap = heapp; - hp->h_size = size; + hp->h.u.heap = heapp; + hp->h.size = size; hp++; return (void *)hp; } @@ -153,9 +153,9 @@ void *chHeapAlloc(MemoryHeap *heapp, size_t size) { return NULL; } -#define LIMIT(p) (struct heap_header *)((uint8_t *)(p) + \ - sizeof(struct heap_header) + \ - (p)->h_size) +#define LIMIT(p) (union heap_header *)((uint8_t *)(p) + \ + sizeof(union heap_header) + \ + (p)->h.size) /** * @brief Frees a previously allocated memory block. @@ -163,13 +163,13 @@ void *chHeapAlloc(MemoryHeap *heapp, size_t size) { * @param[in] p pointer to the memory block to be freed */ void chHeapFree(void *p) { - struct heap_header *qp, *hp; + union heap_header *qp, *hp; MemoryHeap *heapp; chDbgCheck(p != NULL, "chHeapFree"); - hp = (struct heap_header *)p - 1; - heapp = hp->h_u.heap; + hp = (union heap_header *)p - 1; + heapp = hp->h.u.heap; qp = &heapp->h_free; H_LOCK(heapp); @@ -179,24 +179,24 @@ void chHeapFree(void *p) { "within free block"); if (((qp == &heapp->h_free) || (hp > qp)) && - ((qp->h_u.next == NULL) || (hp < qp->h_u.next))) { + ((qp->h.u.next == NULL) || (hp < qp->h.u.next))) { /* Insertion after qp.*/ - hp->h_u.next = qp->h_u.next; - qp->h_u.next = hp; + hp->h.u.next = qp->h.u.next; + qp->h.u.next = hp; /* Verifies if the newly inserted block should be merged.*/ - if (LIMIT(hp) == hp->h_u.next) { + if (LIMIT(hp) == hp->h.u.next) { /* Merge with the next block.*/ - hp->h_size += hp->h_u.next->h_size + sizeof(struct heap_header); - hp->h_u.next = hp->h_u.next->h_u.next; + hp->h.size += hp->h.u.next->h.size + sizeof(union heap_header); + hp->h.u.next = hp->h.u.next->h.u.next; } if ((LIMIT(qp) == hp)) { /* Merge with the previous block.*/ - qp->h_size += hp->h_size + sizeof(struct heap_header); - qp->h_u.next = hp->h_u.next; + qp->h.size += hp->h.size + sizeof(union heap_header); + qp->h.u.next = hp->h.u.next; } break; } - qp = qp->h_u.next; + qp = qp->h.u.next; } H_UNLOCK(heapp); @@ -217,7 +217,7 @@ void chHeapFree(void *p) { * @return The number of fragments in the heap. */ size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep) { - struct heap_header *qp; + union heap_header *qp; size_t n, sz; if (heapp == NULL) @@ -226,8 +226,8 @@ size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep) { H_LOCK(heapp); sz = 0; - for (n = 0, qp = &heapp->h_free; qp->h_u.next; n++, qp = qp->h_u.next) - sz += qp->h_u.next->h_size; + for (n = 0, qp = &heapp->h_free; qp->h.u.next; n++, qp = qp->h.u.next) + sz += qp->h.u.next->h.size; if (sizep) *sizep = sz; diff --git a/os/kernel/src/chmemcore.c b/os/kernel/src/chmemcore.c index 8269deb48..d5adbef48 100644 --- a/os/kernel/src/chmemcore.c +++ b/os/kernel/src/chmemcore.c @@ -43,17 +43,19 @@ void core_init(void) { nextmem = &__heap_base__; endmem = &__heap_end__; #else - static align_t buffer[MEM_ALIGN_SIZE(CH_MEMCORE_SIZE) / sizeof(align_t)]; + static stkalign_t buffer[MEM_ALIGN_SIZE(CH_MEMCORE_SIZE) / + sizeof(stkalign_t)]; nextmem = (uint8_t *)&buffer[0]; - endmem = (uint8_t *)&buffer[MEM_ALIGN_SIZE(CH_MEMCORE_SIZE) / sizeof(align_t)]; + endmem = (uint8_t *)&buffer[MEM_ALIGN_SIZE(CH_MEMCORE_SIZE) / + sizeof(stkalign_t)]; #endif } /** * @brief Allocates a memory block. * @details The size of the returned block is aligned to the alignment - * type @p align_t so it is not possible to allocate less than - * sizeof(align_t). + * type @p stkalign_t so it is not possible to allocate less + * than sizeof(stkalign_t). * * * @param[in] size the size of the block to be allocated diff --git a/os/ports/GCC/SIMIA32/chcore.h b/os/ports/GCC/SIMIA32/chcore.h index a0e26bf29..114e9ef43 100644 --- a/os/ports/GCC/SIMIA32/chcore.h +++ b/os/ports/GCC/SIMIA32/chcore.h @@ -36,9 +36,11 @@ #define CH_ARCHITECTURE_NAME "x86 Simulator" /** - * 32 bit stack alignment. + * 16 bytes stack alignment. */ -typedef uint32_t stkalign_t; +typedef struct { + uint8_t a[16]; +} stkalign_t __attribute__((aligned(16))); /** * Generic x86 register. diff --git a/readme.txt b/readme.txt index 0c705159d..e207ac1aa 100644 --- a/readme.txt +++ b/readme.txt @@ -52,6 +52,8 @@ ***************************************************************************** *** 1.5.2 *** +- FIX: Impossible to enforce alignment greater of a pointer size for heap/core + objects (bug 2952961)(backported in 1.4.1). - FIX: Wrong prototype in template file chcore.c (bug 2951529)(backported in 1.4.1). - NEW: Added BOARD_NAME macro to the various board.h files.