Алгоритмы динамического управления памятью
_bytes_used -= heapinfo [block].busy .info .size * BLOCKSIZE;
bytes_free += heapinfo [block].busy .info .size * BLOCKSIZE;
/* Найти свободный кластер, предшествующий этому в списке свободных.
Начать поиск с последнего блока, к которому было обращение.
Это может быть преимуществом для программ, в которых выделение локальное.
*/ i = _heapindex; if (i > block)
while (i > block)
i = _heapinfo[i) .free.prev; else { do
i = __heapinfo[i] .free .next; while (i > 0 && i < block); i = _heapinfo [i] .free.prev; 1
/* Определить, как включить этот блок в список свободных. */
if (block == i + _heapinfo[i] .free .size) {
/* Слить этот блок с его предшественником.
*/ _heapinfo[i].free .size += _heapinfo [block].busy .info .size/block = i;
else
/* Действительно включить этот блок в список свободных. */
_heapinf о [block] .free .size = _heapinfo [block].busy .info .size;
_heapinf о [block].free .next = _heapinfo[i] .free .next;
_heapinf о [block] .free.prev = i;
_heapinfo[i].free .next = block;
_heapinf о [_heapinfo [block].free .next].free.prev = block;
++chunksfree;
/* Теперь, поскольку блок включен, проверить, не можем ли мы
слить его с его последователем (исключая его последователя из списка и складывая размеры). */
if (block + _heapinf о [block] .free .size == heapinfo [block].free .next)
{ _heapinfo [block].free .size
+= _heapinfo [_heapinfo [block].free .next] .free .size; _heapinfo [block].free .next
= _heapinfo[_heapinfo[block].free .next] .free .next;
_heapinf о [_heapinfo[block].free .next].free .prev = block; -chunksf ree;
/* Проверить, не можем ли мы вернуть память системе. */
blocks = _heapinf о [block].free .size;
if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
&& (*_morecore) (0) == ADDRESS (block +.blocks)) {
register size_t bytes = blocks * BLOCKSIZE; _heaplimit -= blocks;
(*__morecore) (-bytes); _heapinf о [_heapinf о [block].free .prev].free .next
= _heapinf о [block] .free .next; _heapinfo[_heapinfo[block].free .next].free .prev
= _heapinf о [block] .free .prev; block = _heapinf о [block] .free .prev;
-_chunks_f ree; _bytes_free -= bytes;
/* Установить следующий поиск, стартовать с этого блока. */
_heapindex = block; break;
default:
/* Собрать некоторую статистику. */
-_chunks_used; _bytes_used -= 1 << type; ++_chunks_free; bytes_free += 1 << type;
/* Получить адрес первого свободного фрагмента в этом блоке.
*/ prev = (struct list *) ((char *) ADDRESS (block) +
(_heapinfo[block].busy.info.frag.first " type));
#if 1 /* Adapted from Mike */
if (_heapinfо[block].busy.info.frag.nfree == (BLOCKSIZE >> type) -1
&& _fragblocks[type] > 1) #else
if (_heapinfо[block].busy.info.frag.nfree == (BLOCKSIZE >> type) -1)
#endif
lif 1 #endii
/* Если все фрагменты этого блока свободны, удалить их из списка фрагментов
и освободить полный блок. */ /* Adapted from Mike */
-_f ragblocks [type];
next = prev;
for (i = 1; i < (size_t) (BLOCKSIZE " type)
next = next › next; prev › prev › next = next; if (next!= NULL)
next › prev = prev › prev; _heapinf о [block].busy .type = 0;
_heapinf о [block].busy .info .size = 1;
/* Следим за точностью статистики.
*/ ++_chunks_used; _bytes_used += BLOCKSIZE;
_chunks_free -= BLOCKSIZE >> type; _bytes_free -= BLOCKSIZE;
libc free (ADDRESS (block));
I
else if (heapinfо[block].busy.info.frag.nfree!= 0)
/* Если некоторые фрагменты этого блока свободны,
включить этот фрагмент в список фрагментов после первого свободного фрагмента этого блока. */
next = (struct list *) ptr;
next › next = prev › next;
next › prev = prev;
prev › next = next;
if (next › next!= NULL) next › next › prev = next;
++_heapinfо[block].busy.info.frag.nfree;
else
/* В этом блоке нет свободных фрагментов, поэтому включить этот фрагмент
в список фрагментов и анонсировать, что это первый свободный фрагмент в этом блоке. */
prev = (struct list *) ptr;
_heapinfo [block].busy .info .frag .nfree = 1;
_heapinfo [block].busy .info .frag .first = (unsigned long int)
((unsigned long int) ((char *) ptr -(char *) NULL) % BLOCKSIZE >> type);
prev › next = _fraghead[type].next; prev › prev = &_fraghead[type];
prev › prev › next = prev; if (prev › next!= NULL)
prev › next › prev = prev;
break;
/* Вернуть память в кучу. */ void
_ libc_free (ptr) _ ptr_t ptr; {
register struct alignlist *1;
if (ptr == NULL) return;
for (1 = _aligned_blocks; 1!= NULL; 1 = l › next) if (l › aligned == ptr)
{
1 › aligned = NULL;
/* Пометить элемент списка как свободный. */
ptr = l › exact;
break;
if (_ free_hook!= NULL) (* _ free_hook) (ptr);
else
_free_internal (ptr);
#include <gnu-stabs .h>
#ifdef elf_alias
elf_alias (free, cfree);
#endif