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