본문 바로가기

Heap analysis/glibc 2.26

(glibc 2.26) malloc

전체 코드는 아래 더보기

더보기
void *
__libc_malloc (size_t bytes)
{
  mstate ar_ptr;
  void *victim;

  void *(*hook) (size_t, const void *)
    = atomic_forced_read (__malloc_hook);
  if (__builtin_expect (hook != NULL, 0))
    return (*hook)(bytes, RETURN_ADDRESS (0));
#if USE_TCACHE
  /* int_free also calls request2size, be careful to not pad twice.  */
  size_t tbytes = request2size (bytes);
  size_t tc_idx = csize2tidx (tbytes);

  MAYBE_INIT_TCACHE ();

  DIAG_PUSH_NEEDS_COMMENT;
  if (tc_idx < mp_.tcache_bins
      /*&& tc_idx < TCACHE_MAX_BINS*/ /* to appease gcc */
      && tcache
      && tcache->entries[tc_idx] != NULL)
    {
      return tcache_get (tc_idx);
    }
  DIAG_POP_NEEDS_COMMENT;
#endif

  arena_get (ar_ptr, bytes);

  victim = _int_malloc (ar_ptr, bytes);
  /* Retry with another arena only if we were able to find a usable arena
     before.  */
  if (!victim && ar_ptr != NULL)
    {
      LIBC_PROBE (memory_malloc_retry, 1, bytes);
      ar_ptr = arena_get_retry (ar_ptr, bytes);
      victim = _int_malloc (ar_ptr, bytes);
    }

  if (ar_ptr != NULL)
    __libc_lock_unlock (ar_ptr->mutex);

  assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
          ar_ptr == arena_for_chunk (mem2chunk (victim)));
  return victim;
}
libc_hidden_def (__libc_malloc)

 

glibc 2.23에서는 없었던 tcache에 관련한 코드만을 주로 정리한다 (malloc 할당 과정은 (glibc 2.23) _int_malloc 글 참고)

tcache와 관련된 코드를 제외하곤 glibc 2.23과 동일하다

 

#if USE_TCACHE
  /* int_free also calls request2size, be careful to not pad twice.  */
  size_t tbytes = request2size (bytes);
  size_t tc_idx = csize2tidx (tbytes);

  MAYBE_INIT_TCACHE ();

  DIAG_PUSH_NEEDS_COMMENT;
  if (tc_idx < mp_.tcache_bins
      /*&& tc_idx < TCACHE_MAX_BINS*/ /* to appease gcc */
      && tcache
      && tcache->entries[tc_idx] != NULL)
    {
      return tcache_get (tc_idx);
    }
  DIAG_POP_NEEDS_COMMENT;
#endif

glibc 2.23에서는 없어던 tcache관련 처리 코드가 hook과 arena_get함수 사이에 추가되었다

tcache로 재할당이 가능하면 재할당해주는 코드이다

 

변수 선언


tcache_init을 호출하기 전에 변수 초기화해준다 (초기화 되는 변수를 아래와 같음)

  • tbytes :  request2size(bytes)의 반환 값을 저장 (가공된 할당 받을 크기 )
  • tc_idx : tbytes의 인덱스를 구해 저장

tcache_init


#define MAYBE_INIT_TCACHE() \
  if (__glibc_unlikely (tcache == NULL)) \
    tcache_init();

변수 초기화 이후에 tcache가 NULL이면 tcache_init을 호출한다

tcache_init에서는 tcache_perthread_struct 크기의 힙을 할당 받는다

tcache_init 링크 글

tcache_get


  DIAG_PUSH_NEEDS_COMMENT;
  if (tc_idx < mp_.tcache_bins
      /*&& tc_idx < TCACHE_MAX_BINS*/ /* to appease gcc */
      && tcache
      && tcache->entries[tc_idx] != NULL)
    {
      return tcache_get (tc_idx);
    }
  DIAG_POP_NEEDS_COMMENT;
  • 할당 받을 크기가 tcache 범위내에 존재하는지
  • tcache_perthread_struct가 할당되어있는지
  • 할당 받을 크기의 freed chunk가 cache에 있는지

위의 검사를 한 뒤 tcache_get함수를 호출한다

tcache_get함수에서는 tcache에서 재할당알 청크를 반환한다 (tcache_get 링크글)

 

 

 

 

 

이후에 glibc 2.23과 동일하다

'Heap analysis > glibc 2.26' 카테고리의 다른 글

(glibc 2.26) _int_free  (0) 2022.05.02
(glibc 2.26) _int_malloc  (0) 2022.05.01
(glibc 2.26) tcache_put  (0) 2022.05.01
(glibc 2.26) tcache_get  (0) 2022.05.01
(glibc 2.26) tcache_init  (0) 2022.05.01