69,382
社区成员
发帖
与我相关
我的任务
分享
#include <cruntime.h>
#include <assert.h>
#include <heap.h>
#include <malloc.h>
#include <os2dll.h>
#include <stddef.h>
#ifndef _POSIX_
#include <new.h>
_PNH _pnhHeap = NULL; /* pointer to new() handler */
#endif
#ifdef MTHREAD
void * _CALLTYPE1 malloc (
size_t size
)
{
void *pret;
#ifndef _POSIX_
for (;;)
{
#endif
/* lock the heap
*/
_mlock(_HEAP_LOCK);
/* do the allocation
*/
pret = _malloc_lk(size);
/* unlock the heap
*/
_munlock(_HEAP_LOCK);
#ifndef _POSIX_
if (pret || _pnhHeap == NULL || (*_pnhHeap)(size) == 0)
#endif
return(pret);
#ifndef _POSIX_
}
#endif /* ndef _POSIX_ */
}
void * _CALLTYPE1 _malloc_lk (
size_t size
)
#else /* ndef MTHREAD */
void * _CALLTYPE1 malloc (
size_t size
)
#endif /* MTHREAD */
#ifdef _CRUISER_
{
char *pblck;
_PBLKDESC pdesc;
size_t dist;
/* round size up to the nearest whole number of dwords
*/
size = _ROUND2(size, 4);
/* first try allocating a block of size bytes
*/
if ( ((pblck = _flat_malloc(size)) == NULL) || (size > _SEGSIZE_) ||
(_DISTTOBNDRY(pblck) >= size) )
/* all done!
*/
goto done;
else
/* doesn't meet requirements, free the allocation back to the
* heap
*/
_free_lk(pblck);
/* now, try allocating a block of 2*size bytes. if successful, the
* allocated block is guaranteed to contain a region of size bytes
* which does not cross a 64 K boundary.
*/
if ( (pblck = _flat_malloc(2*size)) == NULL )
/* allocation failed, return NULL to the caller
*/
goto done;
/* set pdesc to point to the descriptor for the allocation block
*/
pdesc = _BACKPTR(pblck);
/* find a subregion of at least size bytes which does not cross a
* 64 Kb boundary and build a heap block around it. set pblck to
* point to to allocation area of the block and pdesc to point to
* its descriptor
*/
if ( (dist = _DISTTOBNDRY(pblck)) < size ) {
/* the subregion from pblck to (pblck + size) crosses a 64 Kb
* boundary, but the subregion from (pblck + dist) to (pblck +
* dist + size) cannot (it starts on one). therefore, split
* the block into two heap blocks, with the later block
* starting at (pblck + dist - _HDRSIZE), and free the first
* block.
*/
_heap_split_block(pdesc, dist - _HDRSIZE);
_free_lk(pblck);
pdesc = pdesc->pnextdesc;
_SET_INUSE(pdesc);
pblck += dist;
}
/* pblck and pdesc are now bound to allocation block whose first size
* bytes do not cross any 64 Kb boundary. only detail is the block
* may be too large so...
*/
#ifdef _OLDROVER_
_heap_split_block(pdesc, size);
_SET_FREE(pdesc->pnextdesc);
_heap_advance_rover();
#else /* ndef _OLDROVER_ */
if ( _BLKSIZE(pdesc) > size ) {
_heap_split_block(pdesc, size);
_SET_FREE(pdesc->pnextdesc);
_heap_desc.proverdesc = pdesc->pnextdesc;
}
#endif /* _OLDROVER_ */
done:
return(pblck);
}
void * _CALLTYPE1 _flat_malloc (
size_t size
)
#endif /* _CRUISER_ */
{
_PBLKDESC pdesc;
/* validate size
*/
/***** COMMENTED OUT UNTIL _HEAP_MAXREQ IS DEFINED
if ( size > _HEAP_MAXREQ )
return(NULL);
*****/
/* round requested size
*/
size = _ROUND2(size, 4);
#if !defined(_POSIX_) && !defined(MTHREAD)
for (;;)
{
#endif /* !_POSIX && !MTHREAD */
/* try to find a big enough free block
*/
if ( (pdesc = _heap_search(size)) == NULL )
if ( _heap_grow(size) != -1 ) {
/* try finding a big enough free block again. the
* success of the call to _heap_grow should guarantee
* it, but...
*/
if ( (pdesc = _heap_search(size)) == NULL )
/* something unexpected, and very bad, has
* happened. abort!
*/
_heap_abort();
}
#if !defined(_POSIX_) && !defined(MTHREAD)
else if (!_pnhHeap || (*_pnhHeap)(size) == 0)
return(NULL);
else
continue;
else
break; /* success! */
}
#else /* _POSIX || MTHREAD */
else
return(NULL);
#endif /* !_POSIX && !MTHREAD */
/* carve the block into two pieces (if necessary). the first piece
* shall be of the exact requested size, marked inuse and returned to
* the caller. the leftover piece is to be marked free.
*/
if ( _BLKSIZE(pdesc) != size ) {
/* split up the block and free the leftover piece back to
* the heap
*/
_heap_split_block(pdesc, size);
_SET_FREE(pdesc->pnextdesc);
}
/* mark pdesc inuse
*/
_SET_INUSE(pdesc);
/* check proverdesc and reset, if necessary
*/
#ifdef _OLDROVER_
_heap_advance_rover();
#else /* ndef _OLDROVER_ */
_heap_desc.proverdesc = pdesc->pnextdesc;
#endif /* _OLDROVER_ */
return( (void *)((char *)_ADDRESS(pdesc) + _HDRSIZE) );
}
void _CALLTYPE1 _heap_split_block (
REG1 _PBLKDESC pdesc,
size_t newsize
)
{
REG2 _PBLKDESC pdesc2;
assert(("_heap_split_block: bad pdesc arg", _CHECK_PDESC(pdesc)));
assert(("_heap_split_block: bad newsize arg", _ROUND2(newsize,4) == newsize));
/* carve the block into two pieces (if possible). the first piece
* is to be exactly newsize bytes.
*/
if ( _BLKSIZE(pdesc) > newsize ) {
/* get an empty decriptor
*/
_GETEMPTY(pdesc2)
/* set it up to manage the second piece and link it in to
* the list
*/
pdesc2->pblock = (void *)((char *)_ADDRESS(pdesc) + newsize +
_HDRSIZE);
*(void **)(pdesc2->pblock) = pdesc2;
pdesc2->pnextdesc = pdesc->pnextdesc;
pdesc->pnextdesc = pdesc2;
}
}
#ifdef _OLDROVER_
void _CALLTYPE1 _heap_advance_rover(void)
{
REG1 _PBLKDESC pdesc;
/* check proverdesc and advance it, if necessary
*/
#ifdef _CRUISER_ /* CRUISER TARGET */
if ( !_IS_FREE(_heap_desc.proverdesc) && (_heap_desc.proverdesc !=
&_heap_desc.sentinel) ) {
#else /* ndef _CRUISER_ */
#ifdef _WIN32_
if ( _heap_desc.proverdesc != &_heap_desc.sentinel &&
(!_IS_FREE(_heap_desc.proverdesc) ||
_BLKSIZE(_heap_desc.proverdesc) <= 8)) {
#else /* ndef _WIN32_ */
#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
#endif /* _WIN32_ */
#endif /* _CRUISER_ */
/* set pdesc to point to the descriptor for the next free
* block, if any, or &sentinel, otherwise.
*/
for ( pdesc = (_heap_desc.proverdesc)->pnextdesc ;
#ifdef _CRUISER_ /* CRUISER TARGET */
!(_IS_FREE(pdesc)) && (pdesc != &_heap_desc.sentinel) ;
#else /* ndef _CRUISER_ */
#ifdef _WIN32_
pdesc != &_heap_desc.sentinel &&
(!(_IS_FREE(pdesc)) || _BLKSIZE(pdesc) <= 8) ;
#else /* ndef _WIN32_ */
#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
#endif /* _WIN32_ */
#endif /* _CRUISER_ */
pdesc = pdesc->pnextdesc )
;
/* update proverdesc with pdesc
*/
_heap_desc.proverdesc = pdesc;
}
}
#endif /* _OLDROVER_ */