Алгоритмы динамического управления памятью
_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