📄 wip_mem.c
字号:
current_stats.bytes_requested += current_stats.last_req;
current_stats.currently_allocated += current_stats.last_alloc;
if (current_stats.currently_allocated > current_stats.max_allocated)
current_stats.max_allocated = current_stats.currently_allocated;
current_stats.num_alloc++;
current_stats.traverse_count += tmp_traverse_count;
current_stats.maxfreelistlength = MAX (current_stats.maxfreelistlength,
tmp_traverse_count);
check_allocated_chunk (p);
#endif
return chunk2mem (p);
}
/*
* Allocate and return a pointer to a memory area of at least
* the indicated size. The allocated block of memory will be aligned
* on a 4-byte boundary.
* Memory blocks allocated with this routine can be freed in one
* batch operation by calling wip_gc.
* Returns 0 if allocation fails.
*/
void *
wip_gcmalloc (UINT32 size)
{
chunkptr p = 0, ptmp;
UINT32 nb;
UINT32 sz = 250000;
UINT32 remsize;
INT16 i;
#ifdef DEBUG_WIP_MALLOC
int tmp_traverse_count = 0;
#endif
/* We add space for our overhead (4 bytes) plus round to nearest
* larger multiple of 4, plus never allocate a chunk less than 8 bytes. */
nb = request2size (size);
/* Check all relevant free lists, until a non-empty one is found. */
for (i = list_idx (nb); i < NUM_FREE_LISTS; i++) {
chunkptr freelist = freelists[i];
/* Search the entire list, select chunk with closest fit */
for (ptmp = forward (freelist); ptmp != freelist;
ptmp = forward (ptmp)) {
UINT32 tmpsz = chunksize (ptmp);
#ifdef DEBUG_WIP_MALLOC
tmp_traverse_count++;
#endif
if (tmpsz == nb) { /* Exact fit: no need to search any further. */
p = ptmp;
sz = tmpsz;
goto found;
}
else if (tmpsz > nb) { /* Chunk is large enough */
if (tmpsz < sz) {
/* This is the best so far. */
p = ptmp;
sz = tmpsz;
}
}
}
if (p != 0) {
goto found;
}
}
/* Searched all lists, but found no large enough chunk */
return 0;
found:
/* We have found a large enough chunk, namely "p" of size "sz". */
remove_from_list (p);
remsize = sz - nb;
if (remsize >= MINCHUNKSIZE) {
/* The remainder is large enough to become a separate chunk */
chunkptr q, next;
chunkptr l;
sz = nb;
/* "q" will be the new chunk */
q = (chunkptr)((BYTE *)p + sz);
set_hd2 (q, remsize >> 1);
set_hd1 (q, nb >> 1);
next = nextchunk (q);
set_prevsize (next, remsize);
l = freelists[list_idx (remsize)];
add_to_list (l, q);
}
set_hd2 (p, (sz >> 1) | 0x01);
set_gcbit (p);
#ifdef DEBUG_WIP_MALLOC
current_stats.last_alloc = sz;
current_stats.bytes_allocated += current_stats.last_alloc;
current_stats.last_req = size;
current_stats.bytes_requested += current_stats.last_req;
current_stats.currently_allocated += current_stats.last_alloc;
if (current_stats.currently_allocated > current_stats.max_allocated)
current_stats.max_allocated = current_stats.currently_allocated;
current_stats.num_alloc++;
current_stats.traverse_count += tmp_traverse_count;
current_stats.maxfreelistlength = MAX (current_stats.maxfreelistlength,
tmp_traverse_count);
check_allocated_chunk (p);
#endif
return chunk2mem (p);
}
/*
* Free a memory area previously allocated with wip_malloc or wip_gcmalloc.
* Calling this routine with 'mem' equal to 0 has no effect.
*/
void
wip_free (void* mem)
{
chunkptr p; /* chunk corresponding to mem */
UINT32 sz; /* its size */
chunkptr next; /* next adjacent chunk */
chunkptr prev; /* previous adjacent chunk */
chunkptr l;
if (mem == 0) {
return;
}
p = mem2chunk (mem);
#ifdef DEBUG_WIP_MALLOC
check_allocated_chunk (p);
#endif
if (chunk_isfree (p)) {
return;
}
sz = chunksize (p);
prev = prevchunk (p);
next = nextchunk (p);
#ifdef DEBUG_WIP_MALLOC
current_stats.last_alloc = -(INT32)sz;
current_stats.last_req = current_stats.last_alloc;
current_stats.currently_allocated -= sz;
current_stats.num_free++;
#endif
if (chunk_isfree (prev)) { /* Join with previous chunk */
sz += chunksize (prev);
p = prev;
remove_from_list (prev);
}
if (chunk_isfree (next)) { /* Join with next chunk */
sz += chunksize (next);
remove_from_list (next);
}
set_hd2 (p, sz >> 1);
clear_gcbit (p);
next = nextchunk (p);
set_prevsize (next, sz);
l = freelists [list_idx (sz)];
add_to_list (l, p);
}
/*
* Free all memory areas allocated with wip_gcmalloc.
* Memory blocks allocated with wip_malloc are left undisturbed.
*/
void
wip_gc (void)
{
chunkptr p;
chunkptr l;
for (p = firstchunk; p != lastchunk; p = nextchunk (p)) {
if (chunk_inuse (p) && chunk_has_gcbit (p)) {
UINT32 sz; /* its size */
chunkptr next; /* next contiguous chunk */
chunkptr prev; /* previous contiguous chunk */
sz = chunksize (p);
prev = prevchunk (p);
next = nextchunk (p);
#ifdef DEBUG_WIP_MALLOC
check_allocated_chunk (p);
current_stats.last_alloc = -(INT32)sz;
current_stats.last_req = current_stats.last_alloc;
current_stats.currently_allocated -= sz;
current_stats.num_free++;
#endif
if (chunk_isfree (prev)) { /* Join with previous chunk */
sz += chunksize (prev);
remove_from_list (prev);
p = prev;
}
if (chunk_isfree (next)) { /* Join with next chunk */
sz += chunksize (next);
remove_from_list (next);
}
set_hd2 (p, sz >> 1);
clear_gcbit (p);
next = nextchunk (p);
set_prevsize (next, sz);
l = freelists [list_idx (sz)];
add_to_list (l, p);
}
}
}
/*
* Return the size of an allocated memory area.
* The reported size includes the overhead used by the memory allocation
* system.
*/
UINT32
wip_memsize (void *mem)
{
chunkptr p; /* chunk corresponding to mem */
p = mem2chunk (mem);
return chunksize (p);
}
/*
* Routines for debugging and statistics.
*/
#ifdef DEBUG_WIP_MALLOC
/*
* Print all currently allocated chunks.
*/
void
wip_printalloc (FILE *logfile)
{
chunkptr p;
for (p = firstchunk; p != lastchunk; p = nextchunk (p)) {
if (!chunk_isfree (p)) {
fprintf (logfile, "id: %d\tsize: %d\n", 0, chunksize (p));
}
}
}
/*
* Prints a list of all the current chunks.
*/
void
wip_printchunks (FILE *logfile)
{
chunkptr p = firstchunk;
fprintf (logfile, "\n***************\n");
for (;;) {
fprintf (logfile, "-------------------\n");
fprintf (logfile, "address: 0x%x\n", p);
fprintf (logfile, "prev size: %d\n", prevsize (p));
fprintf (logfile, "size: %d\n", chunksize (p));
fprintf (logfile, "gc: %d, inuse: %d\n", chunk_has_gcbit (p),
chunk_inuse (p));
if (chunk_isfree (p) || (p == (chunkptr)baseptr)) {
fprintf (logfile, "fwd: 0x%x\n", forward (p));
fprintf (logfile, "bck: 0x%x\n", back (p));
}
if (p == lastchunk) {
break;
}
p = nextchunk (p);
}
fprintf (logfile, "***************\n\n");
}
/*
* Prints a sequence of numbers representing the sizes of
* the chunks on the free list.
*/
void
wip_printfreelist (FILE *logfile)
{
chunkptr p;
UINT32 sz;
INT16 i;
fprintf (logfile, "\t");
for (i = 0; i < NUM_FREE_LISTS; i++) {
for (p = forward (freelists[i]); p != freelists[i]; p = forward (p)) {
sz = chunksize (p);
fprintf (logfile, " %d", sz);
}
}
}
/*
* Print brief statistics:
* the number of bytes requested in the last allocation/free made
* the number of bytes allocated in the last allocation/free made
* the total number of bytes currently allocated
* the number of chunks checked in the last allocation
* the current length of the free list
* the current number of chunks that the memory is divided into
*/
void
wip_printbriefstats (FILE *logfile)
{
INT16 i;
chunkptr p;
UINT32 listcount = 0;
UINT32 chunkcount = 0;
for (i = 0; i < NUM_FREE_LISTS; i++) {
for (p = forward (freelists[i]); p != freelists[i]; p = forward (p)) {
listcount++;
}
}
for (p = firstchunk; p != lastchunk; p = nextchunk (p)) {
chunkcount++;
}
if (current_stats.last_req < 0) {
current_stats.last_req = 0;
}
fprintf (logfile, "%6d%6d%6d%6d%6d%6d", current_stats.last_req,
current_stats.last_alloc, current_stats.currently_allocated,
current_stats.traverse_count, listcount, chunkcount);
}
/*
* Prints accumulated statistics.
*/
wip_malloc_stats
wip_getstats (void)
{
return current_stats;
}
INT16
wip_getfragmentation (void)
{
chunkptr p;
UINT32 largestsize = 0;
UINT32 totalfreesize = 0;
UINT32 sz;
for (p = firstchunk; p != lastchunk; p = nextchunk (p)) {
if (chunk_isfree (p)) {
sz = chunksize (p);
totalfreesize += sz;
largestsize = MAX (largestsize, sz);
}
}
if (totalfreesize == 0)
return 100;
return (INT16)((largestsize * 100) / totalfreesize);
}
void
wip_fragmentationstats (FILE *logfile)
{
chunkptr p;
UINT32 largestsize = 0;
UINT32 totalfreesize = 0;
UINT32 sz;
for (p = firstchunk; p != lastchunk; p = nextchunk (p)) {
if (chunk_isfree (p)) {
sz = chunksize (p);
totalfreesize += sz;
largestsize = MAX (largestsize, sz);
}
}
fprintf (logfile, "Total free size: %d\nLargest chunk: %d (%d%%)\n",
totalfreesize, largestsize, (largestsize * 100) / totalfreesize);
}
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -