710 lines
24 KiB
C
710 lines
24 KiB
C
/* memPartLibP.h - private memory management library header file */
|
|
|
|
/*
|
|
* Copyright (c) 1992, 1996, 2001, 2003-2010, 2013, 2018
|
|
* Wind River Systems, Inc.
|
|
*
|
|
* The right to copy, distribute, modify or otherwise make use
|
|
* of this software may be licensed only pursuant to the terms
|
|
* of an applicable Wind River license agreement.
|
|
*/
|
|
|
|
|
|
/*
|
|
modification history
|
|
--------------------
|
|
12apr18,dlk added memSysPartCouldBeOwner() (VXW6-86724)
|
|
08jul13,pcs Fix macro GET_ALLOC_STATE.
|
|
08jul13,pcs Code review changes.
|
|
23may13,pcs Fix macro CLEAR_ALLOC_STATE.
|
|
03may13,pcs Add support for SMP-optimized memory allocator.
|
|
11nov10,pcs Make headGuard configurable for LP64.
|
|
01nov10,pcs Fix typo in previous checkin.
|
|
26oct10,jpb Fixed type-casting in macro MAX_ALLOWED_ALLOC_SIZE
|
|
21oct10,pcs add a macro MAX_ALLOWED_ALLOC_SIZE to represent the maximum
|
|
allowed/possible single allocation in LP64.
|
|
30sep10,pcs Change the typecase of the return value of macro
|
|
BLOCK_END_GUARD from (ULONG *) to (UINT *)
|
|
27jul10,pcs Fix issue with macro BLOCK_END_GUARD.
|
|
17feb10,pch small footprint
|
|
13may10,cww 64-bit SMP update
|
|
19apr10,jpb Added function pointers.
|
|
31mar10,pcs typecast the return value of macro BYTE_SIZE_TO_SIZE to
|
|
UINT32.
|
|
30mar10,pad Moved declaration of extern C block for C++ after the
|
|
inclusion of header files.
|
|
04nov09,pcs Updated to reflect the name changes to the 64bit heaps.
|
|
24sep09,pcs Add support for heap growth in 64bit vxWorks.
|
|
08sep09,pcs Updated to add support for multiple heaps for 64bit vxWorks.
|
|
31may09,dlk Fix GET_SIZE and GET_SIZE_IN_BYTES for LP64 case.
|
|
06may09,pcs Updated macro NEXT_CHUNK_HDR to properly use paranthesis.
|
|
30apr09,pcs Update macros to use paranthesis around parameters.
|
|
24mar09,pcs Updated to add support for the LP64 data model.
|
|
14apr09,zl partial 64-bit updates.
|
|
13aug09,gls revamped refCnt (WIND00166706)
|
|
27aug08,jpb Renamed VSB header file
|
|
18jun08,jpb Added include path for kernel configurations options set in
|
|
vsb.
|
|
08may08,jpb Modifications for source build. Renamed INCLUDE_MEM_ALLOT
|
|
to _WRS_CONFIG_MEM_ALLOT, _WRS_VX_SMP to _WRS_CONFIG_SMP.
|
|
05feb07,pcs Add refCnt support for SMP.
|
|
08jan07,jmg Added _func_memRealloc (Req WIND0008666).
|
|
16jun06,zl added memPartFreeListWalk()
|
|
27sep05,zl added ED&R option bits to MEM_OPTIONS_MASK.
|
|
09aug05,zl use semMTake() and semMGive() in the lock/unlock macros.
|
|
26jul05,mil Added prototype for memAllotLibInit.
|
|
12jul05,mil Added memAllot support to minimal kernel.
|
|
14apr05,zl changed CHUNK_MIN_SIZE to larger minimum block
|
|
16feb05,aeg added memBlockSizeGet() function prototype (SPR #106381).
|
|
03may04,zl made cumWordsAllocated 64-bit, removed minBlockWords.
|
|
03feb04,zl added allocated block guard signature support.
|
|
03nov03,zl added create, delete, alloc, free, realloc hooks.
|
|
20oct03,zl updated for new avlLib API.
|
|
27jun03,tam merge with latest VxWorks AE version
|
|
14mar03,pch runtime sizing of BLOCK_HDR for PPC32
|
|
23oct01,tam re-organized FREE_BLOCK
|
|
19oct01,tam added definition for KMEM_XXX macros
|
|
25sep01,tam added definition of the KHEAP_XXX macros
|
|
19aug96,dbt removed memPartAlignedAlloc prototype (fixed SPR #6898).
|
|
05aug96,kkk made padding in BLOCK_HDR generic to all arch with alignment
|
|
at 16.
|
|
22sep92,rrr added support for c++
|
|
28jul92,jcf added external declaration for memPartOptionsDefault.
|
|
19jul92,pme added external declarations for sm partition functions.
|
|
01jul92,jcf extracted from memLib v3r.
|
|
*/
|
|
|
|
#ifndef __INCmemPartLibPh
|
|
#define __INCmemPartLibPh
|
|
|
|
#include <vxWorks.h>
|
|
#include <vsbConfig.h>
|
|
#include <vwModNum.h>
|
|
#include <memLib.h>
|
|
#include <sllLib.h>
|
|
#include <avlUintLib.h>
|
|
#include <private/semLibP.h>
|
|
#include <classLib.h>
|
|
#include <private/objLibP.h>
|
|
#include <private/kernelLibP.h>
|
|
#include <vxAtomicLib.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
|
|
/*
|
|
* Kernel memory allocation macros (KHEAP and KMEM macros)
|
|
*
|
|
* NOTE: They should not be used by any application code.
|
|
* It is also needed by code being back-ported from VxWorks AE 1.x. to VxWorks
|
|
* 5.5.x.
|
|
*/
|
|
|
|
/*
|
|
* KHEAP macros:
|
|
*
|
|
* *******************************************************
|
|
* *******************************************************
|
|
* *** The KHEAP macros are deprecated in VxWorks 6.x. ***
|
|
* *** Use the KMEM macros instead. ***
|
|
* *******************************************************
|
|
* *******************************************************
|
|
*
|
|
* These macros are defined simply for cosmetic reasons, to make it more
|
|
* obvious that buffers are allocated or freed from the kernel heap, also
|
|
* called the system memory partition.
|
|
* No guaranty is given that the buffer allocated from the Kernel
|
|
* Heap via KHEAP_ALLOC has a known and constant virtual to physical mapping
|
|
* (1 to 1 mapping for instance) if virtual memory support is included (i.e.
|
|
* INCLUDE_MMU_BASIC or INCLUDE_MMU_FULL components).
|
|
*
|
|
* NOTE: with the exception of KHEAP_REALLOC(), the definitions are based
|
|
* on API from memPartLib.c, to prevent any requirements on
|
|
* INCLUDE_MEM_MGR_FULL (memLib.c).
|
|
*/
|
|
|
|
#define KHEAP_ALLOC(nBytes) \
|
|
memPartAlloc(memSysPartId, (nBytes))
|
|
#define KHEAP_FREE(pChar) \
|
|
memPartFree(memSysPartId, (char *)(pChar))
|
|
#define KHEAP_ALIGNED_ALLOC(nBytes, alignment) \
|
|
memPartAlignedAlloc(memSysPartId, (nBytes), (alignment))
|
|
#define KHEAP_REALLOC(pChar, newSize) \
|
|
memPartRealloc(memSysPartId, (pChar), (newSize))
|
|
|
|
/*
|
|
* KMEM macros:
|
|
* If a known and constant virtual to physical mapping is required for
|
|
* buffer allocated, KMEM macros should be used instead of KHEAP macros.
|
|
* For instance memory block dynamically allocated that may be accessed when
|
|
* the processor MMU is turned off or on should always be allocated using
|
|
* KMEM_ALLOC() or KMEM_ALIGNED_ALLOC(). Good examples are memory blocks used
|
|
* to store MMU translation information on some processors, or memory blocks
|
|
* accessed by DMA devices.
|
|
*
|
|
* NOTE: With VxWorks 5.5.x, there's no differences between KHEAP_XXX and
|
|
* KMEM_XXX macros. However this will change in future releases.
|
|
*/
|
|
|
|
#ifdef _WRS_CONFIG_MEM_ALLOT
|
|
|
|
/* minimal kernel definitions, KMEM_FREE is not available */
|
|
|
|
#define KMEM_ALLOC(nBytes) \
|
|
memAllot((nBytes), 0)
|
|
#define KMEM_ALIGNED_ALLOC(nBytes, alignment) \
|
|
memAllot((nBytes), (alignment))
|
|
|
|
extern void * memAllot (unsigned size, unsigned alignment);
|
|
extern STATUS memAllotLibInit (char * pPool, unsigned poolSize);
|
|
|
|
#else /* _WRS_CONFIG_MEM_ALLOT */
|
|
|
|
#define KMEM_ALLOC(nBytes) \
|
|
memPartAlloc(memSysPartId, (nBytes))
|
|
#define KMEM_FREE(pChar) \
|
|
memPartFree(memSysPartId, (pChar))
|
|
#define KMEM_ALIGNED_ALLOC(nBytes, alignment) \
|
|
memPartAlignedAlloc(memSysPartId, (nBytes), (alignment))
|
|
#endif /* _WRS_CONFIG_MEM_ALLOT */
|
|
|
|
|
|
/*
|
|
* For PowerPC, _ALLOC_ALIGN_SIZE is a variable whose runtime value is not
|
|
* known when compiling generic code (i.e. with CPU=PPC32), so the conditional
|
|
* padding in the ALLOC_CHUNK_HDR and MEM_SECTION_HDR definitions does not work.
|
|
* The folowing definitions are based on the size of ALLOC_CHUNK_HDR being 16,
|
|
* and the size of MEM_SECTION_HDR being 8.
|
|
* NOTE: The assembly code will be slightly longer for PowerPC CPUs than
|
|
* for architectures for which _ALLOC_ALIGN_SIZE value can be resolved by the
|
|
* processor.
|
|
*/
|
|
|
|
extern UINT allocChunkEndGuardSize;
|
|
#ifdef _WRS_CONFIG_LP64
|
|
extern UINT allocChunkHeadGuardSize;
|
|
#define ALLOC_CHUNK_HDR_SIZE (sizeof(ALLOC_CHUNK_HDR) + \
|
|
allocChunkHeadGuardSize)
|
|
#else
|
|
#define ALLOC_CHUNK_HDR_SIZE sizeof(ALLOC_CHUNK_HDR)
|
|
#endif
|
|
#define MEM_SECTION_HDR_SIZE max(_ALLOC_ALIGN_SIZE, sizeof(MEM_SECTION_HDR))
|
|
|
|
|
|
#define PREV_CHUNK_IS_FREE 1U
|
|
#define CHUNK_SIZE_MASK (~(PREV_CHUNK_IS_FREE))
|
|
|
|
#define ALLOC_STATE_HEAP_ALLOC 0
|
|
#define ALLOC_STATE_MEM_CACHE_ALLOC 1
|
|
#define ALLOC_STATE_MEM_CACHE_FREE 2
|
|
#define ALLOC_STATE_MASK (3)
|
|
|
|
#define GET_ALLOC_STATE(blkHdr) ((ULONG)((blkHdr)->memPartId) & \
|
|
(ALLOC_STATE_MASK))
|
|
#define IS_ALLOC_STATE_MEM_CACHE_ALLOC(blkHdr) \
|
|
(((ULONG)((ALLOC_CHUNK_HDR *)blkHdr)->memPartId == \
|
|
((ULONG)ALLOC_STATE_MEM_CACHE_ALLOC | (ULONG)memSysPartId)) ? TRUE : FALSE)
|
|
|
|
#define IS_ALLOC_STATE_MEM_CACHE_FREE(blkHdr) \
|
|
(((ULONG)((ALLOC_CHUNK_HDR *)blkHdr)->memPartId == \
|
|
((ULONG)ALLOC_STATE_MEM_CACHE_FREE | (ULONG)memSysPartId)) ? TRUE : FALSE)
|
|
|
|
#define SET_ALLOC_STATE_MEM_CACHE_ALLOC(blkHdr) \
|
|
((((ALLOC_CHUNK_HDR *)blkHdr)->memPartId) = \
|
|
((PART_ID)(((ULONG)(((ALLOC_CHUNK_HDR *)blkHdr)->memPartId) & \
|
|
~ALLOC_STATE_MASK) | ALLOC_STATE_MEM_CACHE_ALLOC)))
|
|
|
|
#define SET_ALLOC_STATE_MEM_CACHE_FREE(blkHdr) \
|
|
((((ALLOC_CHUNK_HDR *)blkHdr)->memPartId) = \
|
|
((PART_ID)(((ULONG)(((ALLOC_CHUNK_HDR *)blkHdr)->memPartId) & \
|
|
~ALLOC_STATE_MASK) | ALLOC_STATE_MEM_CACHE_FREE)))
|
|
|
|
#define CLEAR_ALLOC_STATE(blkHdr) \
|
|
((((ALLOC_CHUNK_HDR *)blkHdr)->memPartId) = \
|
|
((PART_ID)(((ULONG)(blkHdr)->memPartId) & ~ALLOC_STATE_MASK)))
|
|
|
|
#define GET_MEM_PART_ID(blkHdr) \
|
|
((PART_ID)((ULONG)(((ALLOC_CHUNK_HDR *)blkHdr)->memPartId) & \
|
|
(~ALLOC_STATE_MASK)))
|
|
|
|
|
|
#ifndef _WRS_CONFIG_LP64
|
|
#define BYTE_SIZE_TO_SIZE(blkSize) (blkSize)
|
|
#define SIZE_TO_BYTE_SIZE(blkSize) (blkSize)
|
|
#else /* _WRS_CONFIG_LP64 */
|
|
#define SIZE_SHIFT 2
|
|
#define BYTE_SIZE_TO_SIZE(blkSize) ((UINT32)((ULONG)(blkSize) >> SIZE_SHIFT))
|
|
#define SIZE_TO_BYTE_SIZE(blkSize) ((ULONG)((ULONG)(blkSize) << SIZE_SHIFT))
|
|
#define MAX_ALLOWED_ALLOC_SIZE (((size_t)(-1U) << SIZE_SHIFT))
|
|
#endif /* _WRS_CONFIG_LP64 */
|
|
|
|
#define GET_SIZE(blkHdr) ((blkHdr)->size & CHUNK_SIZE_MASK)
|
|
#define GET_SIZE_IN_BYTES(blkHdr) \
|
|
(SIZE_TO_BYTE_SIZE((blkHdr)->size & CHUNK_SIZE_MASK))
|
|
#define IS_PREV_CHUNK_FREE(blkHdr) \
|
|
(((blkHdr)->size & PREV_CHUNK_IS_FREE) ? TRUE : FALSE)
|
|
|
|
|
|
/* macros for getting to next and previous blocks */
|
|
|
|
#define NEXT_CHUNK_HDR(pHdr) ((FREE_CHUNK_HDR *) (((ULONG) (pHdr)) + \
|
|
(SIZE_TO_BYTE_SIZE((pHdr)->size & \
|
|
CHUNK_SIZE_MASK))))
|
|
#define PREV_CHUNK_HDR(pHdr) ((FREE_CHUNK_HDR *) (((ULONG) (pHdr)) - \
|
|
(SIZE_TO_BYTE_SIZE((pHdr)->prevSize))))
|
|
|
|
|
|
/*
|
|
* macros for converting between the "block" that caller knows
|
|
* (actual available data area) and the chunk header in front of it
|
|
* The memory chunck is the header plus the data block.
|
|
*/
|
|
|
|
#define BLOCK_TO_CHUNK_HDR(pBlock) ((ALLOC_CHUNK_HDR *) (((ULONG) (pBlock)) - \
|
|
ALLOC_CHUNK_HDR_SIZE))
|
|
#define CHUNK_HDR_TO_BLOCK(pHdr) ((char *) (((ULONG) (pHdr)) + \
|
|
ALLOC_CHUNK_HDR_SIZE))
|
|
|
|
|
|
/* macro to get to head guard */
|
|
|
|
#ifdef _WRS_CONFIG_LP64
|
|
#define BLOCK_HEAD_GUARD(pHdr) ((ULONG *) (((ULONG) (pHdr)) + \
|
|
sizeof(ALLOC_CHUNK_HDR)))
|
|
#else
|
|
#define BLOCK_HEAD_GUARD(pHdr) ((&pHdr->headGuard))
|
|
#endif
|
|
|
|
|
|
/* macro to get to end guard */
|
|
|
|
#define BLOCK_END_GUARD(pHdr) ((ULONG *) (((ULONG) (pHdr)) + \
|
|
(SIZE_TO_BYTE_SIZE((pHdr)->size \
|
|
& CHUNK_SIZE_MASK)) - \
|
|
allocChunkEndGuardSize))
|
|
|
|
/*
|
|
* optimized version of NEXT_CHUNK_HDR for cases where we know that
|
|
* the current block is free (so the previous one can not be free !)
|
|
*/
|
|
|
|
#define NEXT_CHUNK_HDR_FREE(pHdr) ((CHUNK_HDR *) (((ULONG) (pHdr)) + \
|
|
(SIZE_TO_BYTE_SIZE((pHdr)->size))))
|
|
|
|
|
|
/* overhead of allocated, free chunks and region */
|
|
|
|
#define CHUNK_ALLOC_OVERHEAD (ALLOC_CHUNK_HDR_SIZE + allocChunkEndGuardSize)
|
|
#define CHUNK_FREE_OVERHEAD (sizeof(FREE_CHUNK_HDR))
|
|
#define MEM_SECTION_OVERHEAD (MEM_SECTION_HDR_SIZE)
|
|
#define MIN_BLOCK_WORDS ((CHUNK_FREE_OVERHEAD) >> 1)
|
|
|
|
/*
|
|
* minimum meaningful size for a chunk. This is due to the fact that:
|
|
* - any allocted chunk must be convertible into a free chunk eventually.
|
|
* - a free chunk should accomodate allocation of at least 16 bytes to
|
|
* avoid creation of very small free blocks that could cause
|
|
* fragmentation.
|
|
*/
|
|
|
|
#define CHUNK_MIN_SIZE (max (CHUNK_FREE_OVERHEAD, \
|
|
CHUNK_ALLOC_OVERHEAD + MEM_ROUND_UP(16)))
|
|
|
|
/*
|
|
* minimum size of a memory region added via memPartAddToPool. This is due to
|
|
* the fact that any region has to host at least 3 allocated blocks of size 0
|
|
* plus a free block of size 0 plus a region header. Assume worst case with
|
|
* end guards enabled.
|
|
*/
|
|
|
|
#define REGION_START_OVERHEAD (MEM_SECTION_OVERHEAD + ALLOC_CHUNK_HDR_SIZE + \
|
|
END_GUARD_WORDS * sizeof (ULONG) + \
|
|
CHUNK_FREE_OVERHEAD)
|
|
#define REGION_END_OVERHEAD (2 * (ALLOC_CHUNK_HDR_SIZE + \
|
|
END_GUARD_WORDS * sizeof (ULONG)))
|
|
|
|
#define REGION_MIN_SIZE (REGION_START_OVERHEAD + REGION_END_OVERHEAD)
|
|
|
|
/*
|
|
* actual size of the data block within an allocated chunck, retrieved from
|
|
* the chunk header address (BLOCK_SIZE) or the buffer address (MEM_BLOCK_SIZE)
|
|
*/
|
|
|
|
#define BLOCK_SIZE(pHdr) ((SIZE_TO_BYTE_SIZE((pHdr)->size & CHUNK_SIZE_MASK))- \
|
|
CHUNK_ALLOC_OVERHEAD)
|
|
#define MEM_BLOCK_SIZE(pBlock) memBlockSizeGet((void *)(pBlock))
|
|
|
|
#define MEM_PART_SHOW_LOG_LVL_1 1 /* memPartShow: display numbers of free */
|
|
/* blocks of a given size */
|
|
#define MEM_PART_SHOW_LOG_LVL_2 2 /* memPartShow: display numbers of free */
|
|
/* blocks of a given size plus the address */
|
|
/* of each free block */
|
|
|
|
#define SIZE_NODE_MIN_NB 4 /* minimum number of available bin */
|
|
/* size nodes at any time */
|
|
#define SIZE_NODE_INIT_NB 8 /* number of available bin at the */
|
|
/* creation of the partition should */
|
|
/* NOT be LESS than */
|
|
/* SIZE_NODE_MIN_NB */
|
|
#define SIZE_NODE_DEFAULT_NB 8 /* number of bin size nodes */
|
|
/* allocated at a time by default */
|
|
|
|
/* partition option mask */
|
|
|
|
#define MEM_OPTIONS_MASK (MEM_BLOCK_CHECK | \
|
|
MEM_ALLOC_ERROR_EDR_FATAL_FLAG | \
|
|
MEM_ALLOC_ERROR_EDR_WARN_FLAG | \
|
|
MEM_ALLOC_ERROR_LOG_FLAG | \
|
|
MEM_ALLOC_ERROR_SUSPEND_FLAG | \
|
|
MEM_BLOCK_ERROR_EDR_FATAL_FLAG | \
|
|
MEM_BLOCK_ERROR_EDR_WARN_FLAG | \
|
|
MEM_BLOCK_ERROR_LOG_FLAG | \
|
|
MEM_BLOCK_ERROR_SUSPEND_FLAG | \
|
|
MEM_ALLOC_ERROR_MASK | \
|
|
MEM_BLOCK_ERROR_MASK)
|
|
|
|
|
|
/* pattern to fill guard zones */
|
|
|
|
#ifdef _WRS_CONFIG_LP64
|
|
#define GUARD_PATTERN 0xa110cb1ca110cb1c
|
|
#else
|
|
#define GUARD_PATTERN 0xa110cb1c
|
|
#endif
|
|
#define END_GUARD_WORDS 4
|
|
#ifdef _WRS_CONFIG_LP64
|
|
#define HEAD_GUARD_WORDS 2
|
|
#endif
|
|
/* for memPartFreeListWalk() */
|
|
|
|
#define MEM_WALK_UP 0
|
|
#define MEM_WALK_DOWN 1
|
|
|
|
|
|
#ifndef _ASMLANGUAGE
|
|
|
|
#ifdef _WRS_CONFIG_SMP
|
|
#define TYPE_1_SPIN_LOCK
|
|
|
|
/*
|
|
* FIXME: one of the type designations in this comment is wrong.
|
|
* Because of the bug in the intExit path where the workQ is drained,
|
|
* we are using a type-1 spinlock.
|
|
* Once the bug, is rectified, we will have to switch back to using
|
|
* a type-1 spinlock.
|
|
*/
|
|
|
|
#ifdef TYPE_1_SPIN_LOCK
|
|
|
|
extern spinlockIsr_t memPartClassLock;
|
|
#define MEM_PART_SPIN_LOCK_TAKE(lock) \
|
|
SPIN_LOCK_ISR_TAKE (lock)
|
|
|
|
#define MEM_PART_SPIN_LOCK_GIVE(lock) \
|
|
SPIN_LOCK_ISR_GIVE (lock)
|
|
|
|
#else /* TYPE_1_SPIN_LOCK */
|
|
|
|
extern spinlockTask_t memPartClassLock;
|
|
#define MEM_PART_SPIN_LOCK_TAKE(lock) \
|
|
SPIN_LOCK_TASK_TAKE (lock)
|
|
|
|
#define MEM_PART_SPIN_LOCK_GIVE(lock) \
|
|
SPIN_LOCK_TASK_GIVE (lock)
|
|
|
|
#endif /* TYPE_1_SPIN_LOCK */
|
|
|
|
#endif /* _WRS_CONFIG_SMP */
|
|
|
|
#ifdef _WRS_CONFIG_SMP
|
|
/* Note: REF_CNT_INC needs to be called with the spinlock taken. */
|
|
#define REF_CNT_INC(partId) \
|
|
vxAtomic32Inc (&partId->refCnt)
|
|
#else /* _WRS_CONFIG_SMP */
|
|
#define REF_CNT_INC(partId)
|
|
#endif /* _WRS_CONFIG_SMP */
|
|
|
|
|
|
#ifdef _WRS_CONFIG_SMP
|
|
/*
|
|
* Reference counting mechanism is not implemented for
|
|
* system memory partition (kernel heap), since the system
|
|
* memory partion cannot be deleted.
|
|
*/
|
|
|
|
#define REF_CNT_DEC(partId) \
|
|
vxAtomic32Dec (&partId->refCnt)
|
|
#else /* _WRS_CONFIG_SMP */
|
|
#define REF_CNT_DEC(partId)
|
|
#endif /* _WRS_CONFIG_SMP */
|
|
|
|
|
|
#define MEM_PART_ID_VERIFY(partId) \
|
|
(((partId) == NULL) ? ERROR : \
|
|
OBJ_VERIFY ((partId), memPartClassId))
|
|
#define MEM_PART_INVALIDATE(partId) \
|
|
objCoreInvalidate (&(partId)->objCore)
|
|
|
|
#define MEM_PART_LOCK(partId) \
|
|
semMTake (&(partId)->sem, WAIT_FOREVER)
|
|
#define MEM_PART_VERIFIED_LOCK(partId) \
|
|
memPartVerifiedLock(partId)
|
|
#define MEM_PART_UNLOCK(partId) \
|
|
semMGive (&(partId)->sem)
|
|
|
|
/* typedefs */
|
|
|
|
typedef void * (*FUNC_ALLOC) (PART_ID partId, size_t nBytes,
|
|
size_t alignment);
|
|
typedef STATUS (*FUNC_FREE) (PART_ID partId, char * pBlk);
|
|
typedef void * (*FUNC_REALLOC) (PART_ID partId, char * pBlk,
|
|
size_t nBytes);
|
|
typedef STATUS (*FUNC_CREATE_HOOK) (PART_ID partId, FUNC_ALLOC allocFunc,
|
|
FUNC_FREE freeFunc,
|
|
FUNC_REALLOC reallocFunc,
|
|
size_t defAlign);
|
|
typedef void * (*FUNC_ALLOC_HOOK) (PART_ID partId, void * arg,
|
|
size_t nBytes, size_t alignment);
|
|
typedef STATUS (*FUNC_FREE_HOOK) (PART_ID partId, void * arg,
|
|
char * ptr);
|
|
typedef void * (*FUNC_REALLOC_HOOK) (PART_ID partId, void * arg, char * ptr,
|
|
size_t nBytes);
|
|
typedef STATUS (*FUNC_DELETE_HOOK) (PART_ID partId, void * arg);
|
|
typedef STATUS (*FUNC_FREE_WALK_CB) (void * pMemBlock, size_t size,
|
|
void * cbArg, BOOL * pCont);
|
|
typedef void * (*FUNC_MEM_PART_REALLOC) (PART_ID partId, char * pBlock,
|
|
size_t nBytes);
|
|
typedef void * (*FUNC_PART_GROW) (size_t reqSize, size_t * pActualSize);
|
|
|
|
|
|
/*
|
|
* Data structure for a memory section (i.e. piece of memory added to a
|
|
* a partition via memPartAddToPool
|
|
*/
|
|
|
|
typedef struct mem_section_hdr
|
|
{
|
|
/* pointer to the next section part of the memory partition */
|
|
|
|
SL_NODE sectionNode;
|
|
|
|
/* size of this section */
|
|
|
|
size_t size;
|
|
|
|
/* padding is done through MEM_SECTION_HDR_SIZE */
|
|
|
|
} MEM_SECTION_HDR;
|
|
|
|
/* data structure for a free chunk */
|
|
|
|
typedef struct free_chunk_hdr
|
|
{
|
|
/*
|
|
* size of previous chunk.
|
|
* For ILP32, the size = number of bytes.
|
|
* For LP64, the size = (number of bytes) >> 2.
|
|
* This allows for supporting upto 16GBytes.
|
|
*/
|
|
|
|
UINT prevSize;
|
|
|
|
/*
|
|
* size of current chunk + flag indicating if previous chunk is free.
|
|
* For ILP32, the size = number of bytes.
|
|
* For LP64, the size = (number of bytes) >> 2.
|
|
* This allows for supporting upto 16GBytes.
|
|
*/
|
|
|
|
UINT size;
|
|
|
|
/*
|
|
* pointers to previous and next free chunks of the same size
|
|
*/
|
|
|
|
struct free_chunk_hdr * next;
|
|
struct free_chunk_hdr * prev;
|
|
|
|
} FREE_CHUNK_HDR;
|
|
|
|
/* the order of the fields in MEM_PART_SIZE_NODE is important */
|
|
|
|
typedef struct
|
|
{
|
|
AVLU_NODE avlSize; /* AVL tree sorted by the size key */
|
|
FREE_CHUNK_HDR * next; /* pointer to the first free chunck */
|
|
FREE_CHUNK_HDR * prev; /* pointer to the last free chunck */
|
|
|
|
} MEM_PART_SIZE_NODE;
|
|
|
|
/* memory partition data structure */
|
|
|
|
typedef struct mem_part
|
|
{
|
|
OBJ_CORE objCore; /* object management */
|
|
|
|
AVLU_TREE avlSize; /* root of the size node AVL tree */
|
|
MEM_PART_SIZE_NODE * freeSizeNode; /* pointer to first free size node */
|
|
UINT sizeNodeNb; /* number of used avl size node */
|
|
|
|
UINT freeSizeNodeNb; /* number of remaining free size node */
|
|
|
|
SEMAPHORE sem; /* partition semaphore */
|
|
size_t totalWords; /* total number of words in partition */
|
|
unsigned options; /* options */
|
|
#ifdef _WRS_CONFIG_LP64
|
|
unsigned pad; /* explicit padding */
|
|
#endif /* _WRS_CONFIG_LP64 */
|
|
SL_LIST sectionHdrLst; /* list of sections in partition */
|
|
|
|
/* alloc hooks */
|
|
|
|
FUNC_ALLOC_HOOK allocHook; /* hook for memPartAlignedAlloc */
|
|
FUNC_FREE_HOOK freeHook; /* hook for memPartFree */
|
|
FUNC_REALLOC_HOOK reallocHook; /* hook for memPartRealloc */
|
|
FUNC_DELETE_HOOK deleteHook; /* hook for memPartDelete */
|
|
void * hookArg; /* argument for hooks */
|
|
|
|
/* allocation statistics */
|
|
|
|
size_t curBlocksFreed; /* current # of blocks freed */
|
|
size_t curWordsFreed; /* current # of words freed */
|
|
size_t curBlocksAllocated; /* current # of blocks allocated */
|
|
size_t curWordsAllocated; /* current # of words allocated */
|
|
UINT64 cumBlocksAllocated; /* cumulative # of blocks allocated */
|
|
UINT64 cumWordsAllocated; /* cumulative # of words allocated */
|
|
size_t maxWordsAllocated; /* peak # of words allocated */
|
|
size_t curBlocksAllocatedInternal; /* current # of blocks allocated */
|
|
/* for internal use */
|
|
size_t curWordsAllocatedInternal; /* current # of words allocated */
|
|
/* for internal use */
|
|
#ifdef _WRS_CONFIG_LP64
|
|
/* automatic growth support fields */
|
|
|
|
FUNC_PART_GROW memPartGrowFuncPtr;
|
|
#endif /* _WRS_CONFIG_LP64 */
|
|
|
|
#ifdef ENABLE_LOCALITY_PRESERVATION
|
|
/* locality preservation support */
|
|
|
|
FREE_CHUNK_HDR * lastSplittedChunkHdr;
|
|
size_t lastSplittedChunkSize;
|
|
#endif /* ENABLE_LOCALITY_PRESERVATION */
|
|
|
|
#ifdef _WRS_CONFIG_SMP
|
|
Q_HEAD deleterPendQ; /* deleter pend queue */
|
|
atomic32_t refCnt; /* reference count for SMP */
|
|
#endif /* _WRS_CONFIG_SMP */
|
|
|
|
} PARTITION;
|
|
|
|
|
|
/* data structure for an allocated chunk */
|
|
|
|
typedef struct alloc_chunk_hdr
|
|
{
|
|
/*
|
|
* size of previous chunk.
|
|
* For ILP32, the size = number of bytes.
|
|
* For LP64, the size = (number of bytes) >> 2.
|
|
* This allows for supporting upto 16GBytes.
|
|
*/
|
|
|
|
UINT prevSize;
|
|
|
|
/*
|
|
* size of current chunk + flag indicating if previous chunk is free.
|
|
* For ILP32, the size = number of bytes.
|
|
* For LP64, the size = (number of bytes) >> 2.
|
|
* This allows for supporting upto 16GBytes.
|
|
*/
|
|
|
|
UINT size;
|
|
|
|
/* partition ID */
|
|
|
|
PART_ID memPartId;
|
|
|
|
#ifndef _WRS_CONFIG_LP64
|
|
/* head guard */
|
|
|
|
ULONG headGuard;
|
|
#endif
|
|
|
|
} ALLOC_CHUNK_HDR;
|
|
|
|
|
|
/* definitions for backward compatibility */
|
|
|
|
#define BLOCK_HDR ALLOC_CHUNK_HDR
|
|
#define FREE_BLOCK FREE_CHUNK_HDR
|
|
#define BLOCK_TO_HDR(pBuf) BLOCK_TO_CHUNK_HDR(pBuf)
|
|
|
|
|
|
/* variable declarations */
|
|
|
|
extern CLASS_ID memPartClassId; /* memory partition class id */
|
|
extern FUNCPTR memPartBlockErrorRtn; /* block error method */
|
|
extern FUNCPTR memPartAllocErrorRtn; /* alloc error method */
|
|
extern unsigned memPartOptionsDefault; /* default partition options */
|
|
extern size_t memDefaultAlignment; /* default alignment */
|
|
extern PART_ID kProxHeapPartId; /* Kernel Proximity Heap part Id. */
|
|
|
|
/* shared memory manager function pointers */
|
|
|
|
extern FUNCPTR smMemPartAddToPoolRtn;
|
|
extern FUNCPTR smMemPartFreeRtn;
|
|
extern FUNCPTR smMemPartAllocRtn;
|
|
|
|
|
|
/* function declarations */
|
|
|
|
extern BOOL memPartBlockIsValid (PART_ID partId, FREE_CHUNK_HDR *pHdr,
|
|
BOOL isFree);
|
|
extern STATUS memPartBlockValidate (PART_ID partId, char * pBlock);
|
|
extern STATUS memPartCreateHookSet (FUNC_CREATE_HOOK createHook,
|
|
BOOL guardEnable);
|
|
extern STATUS memPartHooksInstall (PART_ID partId, void * hookArg,
|
|
FUNC_ALLOC_HOOK allocHook,
|
|
FUNC_FREE_HOOK freeHook,
|
|
FUNC_REALLOC_HOOK reallocHook,
|
|
FUNC_DELETE_HOOK deleteHook);
|
|
extern STATUS memPartVerifiedLock (PART_ID partId);
|
|
extern size_t memBlockSizeGet (void * pBlock);
|
|
extern STATUS memInfoInit (void);
|
|
extern STATUS memInit (char *pPool, size_t poolSize,
|
|
unsigned options);
|
|
extern STATUS kProxHeapInit (char *pPool, size_t heapSize);
|
|
extern STATUS kCommonHeapInit (size_t heapInitialSize,
|
|
size_t heapIncrSize);
|
|
extern STATUS memPartLibInit (char *pPool, size_t poolSize);
|
|
extern STATUS memPartFreeListWalk (PART_ID partId, int order,
|
|
FUNC_FREE_WALK_CB cbRtn, void * cbArg);
|
|
extern STATUS memPartGrowRtnSet (PART_ID partId,
|
|
FUNC_PART_GROW memPartGrowFunc);
|
|
extern STATUS memPartAllocN (PART_ID partId, size_t size,
|
|
void ** pPtrArray, UINT count);
|
|
extern STATUS memPartFreeN (PART_ID partId, void ** pPtrArray,
|
|
UINT count);
|
|
|
|
extern int memSysPartCouldBeOwner (TASK_ID taskId);
|
|
|
|
/* function pointers */
|
|
|
|
extern void * (*_func_valloc)(size_t size);
|
|
extern void * (*_func_memalign)(size_t alignment, size_t size);
|
|
extern void * (*_func_memPartCacheAlloc)(PART_ID partId, size_t nBytes,
|
|
size_t alignment);
|
|
extern STATUS (*_func_memPartCacheFree)(PART_ID partId, void * pBlock);
|
|
extern STATUS (*_func_memPartCacheInfoGet)(MEM_PART_STATS * pPartStats);
|
|
|
|
#endif /* _ASMLANGUAGE */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
|
|
#endif /* __INCmemPartLibPh */
|