1 +#if USE_TCACHE 2 +/* We want 64 entries. This is an arbitrary limit, which tunables can reduce. */ 3 +# define TCACHE_MAX_BINS 64 4 +# define MAX_TCACHE_SIZE tidx2usize (TCACHE_MAX_BINS-1) 5 + 6 +/* Only used to pre-fill the tunables. */ 7 +# define tidx2usize(idx) (((size_t) idx) * MALLOC_ALIGNMENT + MINSIZE - SIZE_SZ) 8 + 9 +/* When "x" is from chunksize(). */ 10 +# define csize2tidx(x) (((x) - MINSIZE + MALLOC_ALIGNMENT - 1) / MALLOC_ALIGNMENT) 11 +/* When "x" is a user-provided size. */ 12 +# define usize2tidx(x) csize2tidx (request2size (x)) 13 + 14 +/* With rounding and alignment, the bins are... 15 + idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit) 16 + idx 1 bytes 25..40 or 13..20 17 + idx 2 bytes 41..56 or 21..28 18 + etc. */ 19 + 20 +/* This is another arbitrary limit, which tunables can change. Each 21 + tcache bin will hold at most this number of chunks. */ 22 +# define TCACHE_FILL_COUNT 7 23 +#endif +
+/* We overlay this structure on the user-data portion of a chunk when + the chunk is stored in the per-thread cache. */ +typedefstructtcache_entry +{ + structtcache_entry *next; +} tcache_entry; + +/* There is one of these for each thread, which contains the + per-thread cache (hence "tcache_perthread_struct"). Keeping + overall size low is mildly important. Note that COUNTS and ENTRIES + are redundant (we could have just counted the linked list each + time), this is for performance reasons. */ +typedefstructtcache_perthread_struct +{ + char counts[TCACHE_MAX_BINS]; + tcache_entry *entries[TCACHE_MAX_BINS]; +} tcache_perthread_struct; + +static __thread char tcache_shutting_down = 0; +static __thread tcache_perthread_struct *tcache = NULL;
+static void +tcache_init(void) +{ + mstate ar_ptr; + void *victim = 0; + const size_t bytes = sizeof (tcache_perthread_struct); + + if (tcache_shutting_down) + return; + + arena_get (ar_ptr, bytes); + victim = _int_malloc (ar_ptr, bytes); + if (!victim && ar_ptr != NULL) + { + ar_ptr = arena_get_retry (ar_ptr, bytes); + victim = _int_malloc (ar_ptr, bytes); + } + + + if (ar_ptr != NULL) + __libc_lock_unlock (ar_ptr->mutex); + + /* In a low memory situation, we may not be able to allocate memory + - in which case, we just keep trying later. However, we + typically do this very early, so either there is sufficient + memory, or there isn't enough memory to do non-trivial + allocations anyway. */ + if (victim) + { + tcache = (tcache_perthread_struct *) victim; + memset (tcache, 0, sizeof (tcache_perthread_struct)); + } + +}
可以看到tcache的内存块是由_int_malloc_生成的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
+#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
+#if USE_TCACHE + /* While we're here, if we see other chunks of the same size, + stash them in the tcache. */ + size_t tc_idx = csize2tidx (nb); + if (tcache && tc_idx < mp_.tcache_bins) + { + mchunkptr tc_victim; + + /* While bin not empty and tcache not full, copy chunks over. */ + while (tcache->counts[tc_idx] < mp_.tcache_count + && (pp = *fb) != NULL) + { + REMOVE_FB (fb, tc_victim, pp); + if (tc_victim != 0) + { + tcache_put (tc_victim, tc_idx); + } + } + } +#endif
defadd(size): p.sendlineafter('Your choice?','1') p.sendlineafter('What size do you want?',str(size))
defedit(num,size,buf): p.sendlineafter('Your choice?','3') log.success('[*]choice3') p.sendlineafter('Which one do you want to modify?',str(num)) log.success('[*]str') p.sendlineafter('What size is the point?',str(size)) log.success('[*]256') p.send(buf)
defshow(num): p.sendlineafter('Your choice?','4') p.sendlineafter('Which one do you want to see?',str(num))
defdele(num): p.sendlineafter('Your choice?','2') p.sendlineafter('Which one do you want to delete?',str(num))
try: f = open('pid', 'w') f.write(str(proc.pidof(p)[0])) f.close() except Exception as e: print(e)
def add(size): p.sendlineafter('Your choice?','1') p.sendlineafter('What size do you want?',str(size))
def edit(num,size,buf): p.sendlineafter('Your choice?','3') log.success('[*]choice3') p.sendlineafter('Which one do you want to modify?',str(num)) log.success('[*]str') p.sendlineafter('What size is the point?',str(size)) log.success('[*]256') p.send(buf)
def show(num): p.sendlineafter('Your choice?','4') p.sendlineafter('Which one do you want to see?',str(num))
def dele(num): p.sendlineafter('Your choice?','2') p.sendlineafter('Which one do you want to delete?',str(num))