tcache相关结构体

tcache_perthread_struct

typedef struct tcache_perthread_struct
{
uint16_t counts[TCACHE_MAX_BINS];//数量统计
tcache_entry *entries[TCACHE_MAX_BINS];//指针数组
} tcache_perthread_struct;

此结构体为每个线程一个的tcache的管理器,管理级别上类似于arena。详情看源码,此结构体会在调用malloc的时候初始化。初始值全0。

tcache_entry

typedef struct tcache_entry
{
struct tcache_entry *next;
/* This field exists to detect double frees. */
uintptr_t key;
} tcache_entry;

此结构体为tcache的chunk,和一般的chunk比不会记录size字段,也许是不安全的隐患。但是会记录key字段,类似于canary(猜的)。entries数组记录了链表中最后一个chunk的地址,也就是说entries就是所谓的bin。

关于PROTECT_PTR(pos, ptr)和REVEAL_PTR(ptr)宏定义

#define PROTECT_PTR(pos, ptr) \
((__typeof (ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr)))
#define REVEAL_PTR(ptr) PROTECT_PTR (&ptr, ptr)

此宏定义会对bin链表中的指针进行混淆操作,具体方式就是低版本的指针的值与指针存储的位置>>12进行异或操作。若要恢复,就用结果值亦或指针存储的位置>>12即可,可得到正常的值。# tcache相关结构体

tcache相关操作

主要涉及到tcache_put和tcache_get,逻辑比较简单,不细说了

/* Caller must ensure that we know tc_idx is valid and there's room
for more chunks. */
static __always_inline void
tcache_put (mchunkptr chunk, size_t tc_idx)
{
tcache_entry *e = (tcache_entry *) chunk2mem (chunk);

/* Mark this chunk as "in the tcache" so the test in _int_free will
detect a double free. */
e->key = tcache_key;

e->next = PROTECT_PTR (&e->next, tcache->entries[tc_idx]);
tcache->entries[tc_idx] = e;
++(tcache->counts[tc_idx]);
}

/* Caller must ensure that we know tc_idx is valid and there's
available chunks to remove. */
static __always_inline void *
tcache_get (size_t tc_idx)
{
tcache_entry *e = tcache->entries[tc_idx];
if (__glibc_unlikely (!aligned_OK (e)))
malloc_printerr ("malloc(): unaligned tcache chunk detected");
tcache->entries[tc_idx] = REVEAL_PTR (e->next);
--(tcache->counts[tc_idx]);
e->key = 0;
return (void *) e;
}