mem.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 344 行 · 第 1/2 页
C
344 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Heart of the heap manager. Do not break
* unless you have a death wish.
*
****************************************************************************/
#include "variety.h"
#include <limits.h>
#include <malloc.h>
#include "heap.h"
#if defined(M_I86)
extern unsigned setup_ds( unsigned );
#pragma aux setup_ds = \
"push ax" \
"mov ax,ds" \
"pop ds" \
parm [ax] value [ax];
#define setup_segment( _x ) _x = setup_ds( _x );
#else
#define setup_segment( _x ) (void)(_x = _x);
#endif
//
// input:
// size - #bytes to allocate
// segment - 16bit Intel data selector containing heap
// offset - address of heap control block
// if 16bit Intel -> offset within segment
// else -> absolute pointer value
//
// output:
// result - address of allocated storage or zero on failure
// if 16bit Intel -> offset within segment
// else -> absolute pointer value
//
unsigned __MemAllocator( unsigned size, unsigned segment, unsigned offset )
{
frlptr result;
result = 0; // assume the worst
setup_segment( segment ); // setup DS for 16bit Intel
if( size != 0 ) { // quit if size is zero
unsigned new_size;
new_size = size + TAG_SIZE + ROUND_SIZE;// round up size
if( new_size >= size ) { // quit if overflowed
struct heapblkp _WCI86NEAR *heap;
unsigned largest;
heap = (struct heapblkp _WCI86NEAR *)offset;
size = new_size & ~ROUND_SIZE; // make size even
largest = heap->largest_blk;
if( size < FRL_SIZE ) {
size = FRL_SIZE;
}
if( size <= largest ) { // quit if size too big
frlptr pcur;
unsigned len;
pcur = heap->rover; // start at rover
largest = heap->b4rover;
if( size <= largest ) { // check size with rover
pcur = heap->freehead.next; // start at beginning
largest = 0; // reset largest block size
}
for(;;) { // search free list
len = pcur->len;
if( size <= len ) { // found one
break;
}
if( len > largest ) { // update largest block size
largest = len;
}
pcur = pcur->next; // advance to next entry
if( pcur == // if back at start
(frlptr)&(heap->freehead)) {
heap->largest_blk = largest; // update largest
setup_segment( segment ); // 16bit Intel restore
return( (unsigned)result ); // return 0
}
}
heap->b4rover = largest; // update rover size
heap->numalloc++; // udpate allocation count
len -= size; // compute leftover size
if( len >= FRL_SIZE ) { // if leftover big enough
// split into two chunks
frlptr pprev; // before current
frlptr pnext; // after current
frlptr pnew; // start of new piece
pnew = (frlptr)((PTR)pcur + size);
heap->rover = pnew; // update rover
pnew->len = len; // set new size
pcur->len = size; // reset current size
pprev = pcur->prev; // update next/prev links
pnew->prev = pprev;
pnext = pcur->next;
pnew->next = pnext;
pprev->next = pnew;
pnext->prev = pnew;
} else { // just use this chunk
frlptr pprev; // before current
frlptr pnext; // after current
heap->numfree--; // 1 fewer entries in free list
pprev = pcur->prev;
heap->rover = pprev; // update rover
pnext = pcur->next; // update next/prev links
pprev->next = pnext;
pnext->prev = pprev;
}
pcur->len |= 1; // mark as allocated
// get pointer to user area
result = (frlptr)((PTR)pcur + TAG_SIZE);
}
}
}
setup_segment( segment ); // 16bit Intel restore
return( (unsigned)result );
}
//
// input:
// pointer - address of block to free
// if 16bit Intel -> offset within segment
// else -> absolute pointer value
// segment - 16bit Intel data selector containing heap
// offset - address of heap control block
// if 16bit Intel -> offset within segment
// else -> absolute pointer value
//
// output:
// none
//
void __MemFree( unsigned pointer, unsigned segment, unsigned offset )
{
setup_segment( segment ); // setup DS for 16bit Intel
if( pointer != 0 ) { // quit if pointer is zero
frlptr pfree;
pfree = (frlptr)(pointer - TAG_SIZE);
if( pfree->len & 1 ) { // quit if storage is free
struct heapblkp _WCI86NEAR *heap;
frlptr pnext;
frlptr pprev;
frlptr ptr;
unsigned len;
heap = (struct heapblkp _WCI86NEAR *)offset;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?