From c089adf2b790a3d44f3075eb4c386d6cada6fa62 Mon Sep 17 00:00:00 2001 From: Vincent Wei Date: Sun, 28 Mar 2021 19:36:05 +0800 Subject: [PATCH] Optimized the implementation of BlockHeap --- include/gdi.h | 40 +++--------- src/include/blockheap.h | 31 +++++---- src/kernel/blockheap.c | 135 +++++++++++++++++++++++++--------------- 3 files changed, 112 insertions(+), 94 deletions(-) diff --git a/include/gdi.h b/include/gdi.h index 617130f6..199bcce6 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -581,35 +581,14 @@ enum { * @{ */ +struct _BLOCKHEAP; + /** * MiniGUI's private block data heap. * * \sa InitBlockDataHeap, DestroyBlockDataHeap */ -typedef struct _BLOCKHEAP -{ -#ifdef _MGRM_THREADS - pthread_mutex_t lock; -#endif - /** - * Size of one block element. - */ - size_t bd_size; - /** - * Size of the heap in blocks. - */ - size_t heap_size; - /** - * The first free element in the heap. - */ - size_t free; - /** - * Pointer to the pre-allocated heap. - */ - void* heap; - - size_t nr_alloc; -} BLOCKHEAP; +typedef struct _BLOCKHEAP BLOCKHEAP; /** * \var typedef BLOCKHEAP* PBLOCKHEAP @@ -620,7 +599,7 @@ typedef struct _BLOCKHEAP typedef BLOCKHEAP* PBLOCKHEAP; /** - * \fn void InitBlockDataHeap (PBLOCKHEAP heap, \ + * \fn BOOL InitBlockDataHeap (PBLOCKHEAP heap, size_t bd_size, size_t heap_size) * \brief Initializes a private block data heap. * @@ -633,15 +612,14 @@ typedef BLOCKHEAP* PBLOCKHEAP; * \param bd_size The size of one block in bytes. * \param heap_size The size of the heap in blocks. * - * \return \a heap->heap will contains a valid pointer on success, - * NULL on error. + * \return TRUE on success, FALSE on error. * * \note This function does not return anything. You should check the \a heap * field of the \a heap structure. * * \sa BLOCKHEAP */ -MG_EXPORT extern void InitBlockDataHeap (PBLOCKHEAP heap, +MG_EXPORT BOOL InitBlockDataHeap (PBLOCKHEAP heap, size_t bd_size, size_t heap_size); /** @@ -659,7 +637,7 @@ MG_EXPORT extern void InitBlockDataHeap (PBLOCKHEAP heap, * \sa InitBlockDataHeap, BlockDataFree */ -MG_EXPORT extern void* BlockDataAlloc (PBLOCKHEAP heap); +MG_EXPORT void* BlockDataAlloc (PBLOCKHEAP heap); /** * \fn void BlockDataFree (PBLOCKHEAP heap, void* data) @@ -674,7 +652,7 @@ MG_EXPORT extern void* BlockDataAlloc (PBLOCKHEAP heap); * * \sa InitBlockDataHeap, BlockDataAlloc */ -MG_EXPORT extern void BlockDataFree (PBLOCKHEAP heap, void* data); +MG_EXPORT void BlockDataFree (PBLOCKHEAP heap, void* data); /** * \fn void DestroyBlockDataHeap (PBLOCKHEAP heap) @@ -684,7 +662,7 @@ MG_EXPORT extern void BlockDataFree (PBLOCKHEAP heap, void* data); * * \sa InitBlockDataHeap, BLOCKHEAP */ -MG_EXPORT extern void DestroyBlockDataHeap (PBLOCKHEAP heap); +MG_EXPORT void DestroyBlockDataHeap (PBLOCKHEAP heap); /** @} end of block_heap_fns */ diff --git a/src/include/blockheap.h b/src/include/blockheap.h index 5d2dd861..46668ec1 100644 --- a/src/include/blockheap.h +++ b/src/include/blockheap.h @@ -52,21 +52,28 @@ #ifndef GUI_BLOCKHEAP_H #define GUI_BLOCKHEAP_H -#define BDS_FREE 0x0000 -#define BDS_SPECIAL 0x0001 -#define BDS_USED 0x0002 - -#ifndef _MGUI_GDI_H /* included in include/gdi.h */ - -typedef struct tagBLOCKHEAP { +struct _BLOCKHEAP { #ifdef _MGRM_THREADS pthread_mutex_t lock; #endif - size_t bd_size; - size_t heap_size; - int free; - void* heap; -} BLOCKHEAP; + /* Size of one block element. */ + size_t sz_block; + /* Size of the heap in blocks. */ + size_t sz_heap; + /* The first free element in the heap. */ + size_t sz_usage_bmp; + /* The number of blocks extra allocated. */ + size_t nr_alloc; + + /* Pointer to the pre-allocated heap. */ + unsigned char* heap; + /* Pointer to the usage bitmap. */ + unsigned char* usage_bmp; +}; + +#ifndef _MGUI_GDI_H /* included in include/gdi.h */ + +typedef struct _BLOCKHEAP BLOCKHEAP; typedef BLOCKHEAP* PBLOCKHEAP; #ifdef __cplusplus diff --git a/src/kernel/blockheap.c b/src/kernel/blockheap.c index 7d532d5e..ee2b5411 100644 --- a/src/kernel/blockheap.c +++ b/src/kernel/blockheap.c @@ -59,96 +59,93 @@ #include "common.h" #include "minigui.h" #include "gdi.h" +#include "constants.h" #include "blockheap.h" +#include "misc.h" -void InitBlockDataHeap (PBLOCKHEAP heap, size_t bd_size, size_t heap_size) +BOOL InitBlockDataHeap (PBLOCKHEAP heap, size_t sz_block, size_t sz_heap) { #ifdef _MGRM_THREADS pthread_mutex_init (&heap->lock, NULL); #endif - heap->heap = NULL; - heap->bd_size = bd_size + sizeof (DWORD); - heap->heap_size = heap_size; - heap->free = 0; + heap->sz_usage_bmp = (sz_heap + 7) >> 3; + heap->sz_block = ROUND_TO_MULTIPLE (sz_block, SIZEOF_PTR); + heap->sz_heap = heap->sz_usage_bmp << 3; + + if (heap->sz_heap == 0 || heap->sz_block == 0) + return FALSE; + + if ((heap->heap = calloc (heap->sz_heap, heap->sz_block)) == NULL) + return FALSE; + + if ((heap->usage_bmp = calloc (heap->sz_usage_bmp, sizeof (char))) == NULL) { + free (heap->heap); + return FALSE; + } + heap->nr_alloc = 0; + memset (heap->usage_bmp, 0xFF, heap->sz_usage_bmp); + return TRUE; } +extern BLOCKHEAP __mg_FreeClipRectList; + void* BlockDataAlloc (PBLOCKHEAP heap) { - size_t i; - char* block_data = NULL; + int free_slot; + unsigned char* block_data = NULL; #ifdef _MGRM_THREADS pthread_mutex_lock (&heap->lock); #endif - if (heap->heap == NULL) { - if (!(heap->heap = calloc (heap->heap_size, heap->bd_size))) - goto ret; - heap->free = 0; - } + free_slot = __mg_lookfor_unused_slot (heap->usage_bmp, heap->sz_usage_bmp, 1); + if (free_slot >= 0) { + block_data = heap->heap + heap->sz_block * free_slot; + _DBG_PRINTF ("Allocated one block in the block heap: %p (%d)\n", + heap, free_slot); - block_data = (char*) heap->heap + heap->bd_size*heap->free; - for (i = heap->free; i < heap->heap_size; i++) { - - if (*((DWORD*)block_data) == BDS_FREE) { - - heap->free = i + 1; - *((DWORD*)block_data) = BDS_USED; - goto ret; - } - - block_data += heap->bd_size; - } - -#if 1 - if (!(block_data = calloc (1, heap->bd_size))) - goto ret; -#else - if (!(block_data = mg_slice_alloc0 (heap->bd_size))) - goto ret; +#if 0 + if (!mgIsServer && heap == &__mg_FreeClipRectList && free_slot == 5) + assert (0); #endif + goto ret; + } + + if ((block_data = calloc (1, heap->sz_block)) == NULL) + goto ret; heap->nr_alloc++; - *((DWORD*)block_data) = BDS_SPECIAL; - ret: - #ifdef _MGRM_THREADS pthread_mutex_unlock (&heap->lock); #endif - if (block_data) - return block_data + sizeof (DWORD); - return NULL; + return block_data; } void BlockDataFree (PBLOCKHEAP heap, void* data) { - size_t i; - char* block_data; + unsigned char* block_data = data; #ifdef _MGRM_THREADS pthread_mutex_lock (&heap->lock); #endif - block_data = (char*) data - sizeof (DWORD); - if (*((DWORD*)block_data) == BDS_SPECIAL) { -#if 1 + if (block_data < heap->heap || + block_data > (heap->heap + heap->sz_block * heap->sz_heap)) { free (block_data); -#else - mg_slice_free (heap->bd_size, block_data); heap->nr_alloc--; -#endif } - else if (*((DWORD*)block_data) == BDS_USED) { - *((DWORD*)block_data) = BDS_FREE; + else { + int slot; + slot = (block_data - heap->heap) / heap->sz_block; + __mg_slot_clear_use (heap->usage_bmp, slot); - i = (block_data - (char*)heap->heap)/heap->bd_size; - if (heap->free > i) - heap->free = i; + _DBG_PRINTF ("Freed one block in the block heap: %p (%d)\n", + heap, slot); } #ifdef _MGRM_THREADS @@ -158,9 +155,45 @@ void BlockDataFree (PBLOCKHEAP heap, void* data) void DestroyBlockDataHeap (PBLOCKHEAP heap) { + int nr_free_slots; + + if (heap->nr_alloc > 0) { + _WRN_PRINTF ("There are still not freed extra blocks in the block heap: %p (%zu)\n", + heap, heap->nr_alloc); + } + + nr_free_slots = __mg_get_nr_idle_slots (heap->usage_bmp, heap->sz_usage_bmp); + if (nr_free_slots != heap->sz_heap) { + _WRN_PRINTF ("There are still not freed blocks in the block heap: %p (%zu)\n", + heap, heap->sz_heap - nr_free_slots); + +#ifdef _DEBUG + { + unsigned char* bitmap = heap->usage_bmp; + int slot = 0; + int i, j; + + for (i = 0; i < heap->sz_usage_bmp; i++) { + for (j = 0; j < 8; j++) { + if (!(*bitmap & (0x80 >> j))) { + _WRN_PRINTF ("Still used slot in the block heap: %p (%d)\n", + heap, slot); + } + slot++; + } + bitmap++; + } + } + + assert (0); +#endif + } + + free (heap->heap); + free (heap->usage_bmp); + #ifdef _MGRM_THREADS pthread_mutex_destroy (&heap->lock); #endif - free (heap->heap); }