Home | History | Annotate | Line # | Download | only in internal
sec.h revision 1.1
      1  1.1  christos #ifndef JEMALLOC_INTERNAL_SEC_H
      2  1.1  christos #define JEMALLOC_INTERNAL_SEC_H
      3  1.1  christos 
      4  1.1  christos #include "jemalloc/internal/atomic.h"
      5  1.1  christos #include "jemalloc/internal/pai.h"
      6  1.1  christos 
      7  1.1  christos /*
      8  1.1  christos  * Small extent cache.
      9  1.1  christos  *
     10  1.1  christos  * This includes some utilities to cache small extents.  We have a per-pszind
     11  1.1  christos  * bin with its own list of extents of that size.  We don't try to do any
     12  1.1  christos  * coalescing of extents (since it would in general require cross-shard locks or
     13  1.1  christos  * knowledge of the underlying PAI implementation).
     14  1.1  christos  */
     15  1.1  christos 
     16  1.1  christos /*
     17  1.1  christos  * For now, this is just one field; eventually, we'll probably want to get more
     18  1.1  christos  * fine-grained data out (like per-size class statistics).
     19  1.1  christos  */
     20  1.1  christos typedef struct sec_stats_s sec_stats_t;
     21  1.1  christos struct sec_stats_s {
     22  1.1  christos 	/* Sum of bytes_cur across all shards. */
     23  1.1  christos 	size_t bytes;
     24  1.1  christos };
     25  1.1  christos 
     26  1.1  christos static inline void
     27  1.1  christos sec_stats_accum(sec_stats_t *dst, sec_stats_t *src) {
     28  1.1  christos 	dst->bytes += src->bytes;
     29  1.1  christos }
     30  1.1  christos 
     31  1.1  christos /* A collections of free extents, all of the same size. */
     32  1.1  christos typedef struct sec_bin_s sec_bin_t;
     33  1.1  christos struct sec_bin_s {
     34  1.1  christos 	/*
     35  1.1  christos 	 * When we fail to fulfill an allocation, we do a batch-alloc on the
     36  1.1  christos 	 * underlying allocator to fill extra items, as well.  We drop the SEC
     37  1.1  christos 	 * lock while doing so, to allow operations on other bins to succeed.
     38  1.1  christos 	 * That introduces the possibility of other threads also trying to
     39  1.1  christos 	 * allocate out of this bin, failing, and also going to the backing
     40  1.1  christos 	 * allocator.  To avoid a thundering herd problem in which lots of
     41  1.1  christos 	 * threads do batch allocs and overfill this bin as a result, we only
     42  1.1  christos 	 * allow one batch allocation at a time for a bin.  This bool tracks
     43  1.1  christos 	 * whether or not some thread is already batch allocating.
     44  1.1  christos 	 *
     45  1.1  christos 	 * Eventually, the right answer may be a smarter sharding policy for the
     46  1.1  christos 	 * bins (e.g. a mutex per bin, which would also be more scalable
     47  1.1  christos 	 * generally; the batch-allocating thread could hold it while
     48  1.1  christos 	 * batch-allocating).
     49  1.1  christos 	 */
     50  1.1  christos 	bool being_batch_filled;
     51  1.1  christos 
     52  1.1  christos 	/*
     53  1.1  christos 	 * Number of bytes in this particular bin (as opposed to the
     54  1.1  christos 	 * sec_shard_t's bytes_cur.  This isn't user visible or reported in
     55  1.1  christos 	 * stats; rather, it allows us to quickly determine the change in the
     56  1.1  christos 	 * centralized counter when flushing.
     57  1.1  christos 	 */
     58  1.1  christos 	size_t bytes_cur;
     59  1.1  christos 	edata_list_active_t freelist;
     60  1.1  christos };
     61  1.1  christos 
     62  1.1  christos typedef struct sec_shard_s sec_shard_t;
     63  1.1  christos struct sec_shard_s {
     64  1.1  christos 	/*
     65  1.1  christos 	 * We don't keep per-bin mutexes, even though that would allow more
     66  1.1  christos 	 * sharding; this allows global cache-eviction, which in turn allows for
     67  1.1  christos 	 * better balancing across free lists.
     68  1.1  christos 	 */
     69  1.1  christos 	malloc_mutex_t mtx;
     70  1.1  christos 	/*
     71  1.1  christos 	 * A SEC may need to be shut down (i.e. flushed of its contents and
     72  1.1  christos 	 * prevented from further caching).  To avoid tricky synchronization
     73  1.1  christos 	 * issues, we just track enabled-status in each shard, guarded by a
     74  1.1  christos 	 * mutex.  In practice, this is only ever checked during brief races,
     75  1.1  christos 	 * since the arena-level atomic boolean tracking HPA enabled-ness means
     76  1.1  christos 	 * that we won't go down these pathways very often after custom extent
     77  1.1  christos 	 * hooks are installed.
     78  1.1  christos 	 */
     79  1.1  christos 	bool enabled;
     80  1.1  christos 	sec_bin_t *bins;
     81  1.1  christos 	/* Number of bytes in all bins in the shard. */
     82  1.1  christos 	size_t bytes_cur;
     83  1.1  christos 	/* The next pszind to flush in the flush-some pathways. */
     84  1.1  christos 	pszind_t to_flush_next;
     85  1.1  christos };
     86  1.1  christos 
     87  1.1  christos typedef struct sec_s sec_t;
     88  1.1  christos struct sec_s {
     89  1.1  christos 	pai_t pai;
     90  1.1  christos 	pai_t *fallback;
     91  1.1  christos 
     92  1.1  christos 	sec_opts_t opts;
     93  1.1  christos 	sec_shard_t *shards;
     94  1.1  christos 	pszind_t npsizes;
     95  1.1  christos };
     96  1.1  christos 
     97  1.1  christos bool sec_init(tsdn_t *tsdn, sec_t *sec, base_t *base, pai_t *fallback,
     98  1.1  christos     const sec_opts_t *opts);
     99  1.1  christos void sec_flush(tsdn_t *tsdn, sec_t *sec);
    100  1.1  christos void sec_disable(tsdn_t *tsdn, sec_t *sec);
    101  1.1  christos 
    102  1.1  christos /*
    103  1.1  christos  * Morally, these two stats methods probably ought to be a single one (and the
    104  1.1  christos  * mutex_prof_data ought to live in the sec_stats_t.  But splitting them apart
    105  1.1  christos  * lets them fit easily into the pa_shard stats framework (which also has this
    106  1.1  christos  * split), which simplifies the stats management.
    107  1.1  christos  */
    108  1.1  christos void sec_stats_merge(tsdn_t *tsdn, sec_t *sec, sec_stats_t *stats);
    109  1.1  christos void sec_mutex_stats_read(tsdn_t *tsdn, sec_t *sec,
    110  1.1  christos     mutex_prof_data_t *mutex_prof_data);
    111  1.1  christos 
    112  1.1  christos /*
    113  1.1  christos  * We use the arena lock ordering; these are acquired in phase 2 of forking, but
    114  1.1  christos  * should be acquired before the underlying allocator mutexes.
    115  1.1  christos  */
    116  1.1  christos void sec_prefork2(tsdn_t *tsdn, sec_t *sec);
    117  1.1  christos void sec_postfork_parent(tsdn_t *tsdn, sec_t *sec);
    118  1.1  christos void sec_postfork_child(tsdn_t *tsdn, sec_t *sec);
    119  1.1  christos 
    120  1.1  christos #endif /* JEMALLOC_INTERNAL_SEC_H */
    121