root / lab4 / .minix-src / include / sys / pool.h @ 14
History | View | Annotate | Download (11.3 KB)
1 | 13 | up20180614 | /* $NetBSD: pool.h,v 1.79 2015/07/29 00:10:25 christos Exp $ */
|
---|---|---|---|
2 | |||
3 | /*-
|
||
4 | * Copyright (c) 1997, 1998, 1999, 2000, 2007 The NetBSD Foundation, Inc.
|
||
5 | * All rights reserved.
|
||
6 | *
|
||
7 | * This code is derived from software contributed to The NetBSD Foundation
|
||
8 | * by Paul Kranenburg; by Jason R. Thorpe of the Numerical Aerospace
|
||
9 | * Simulation Facility, NASA Ames Research Center.
|
||
10 | *
|
||
11 | * Redistribution and use in source and binary forms, with or without
|
||
12 | * modification, are permitted provided that the following conditions
|
||
13 | * are met:
|
||
14 | * 1. Redistributions of source code must retain the above copyright
|
||
15 | * notice, this list of conditions and the following disclaimer.
|
||
16 | * 2. Redistributions in binary form must reproduce the above copyright
|
||
17 | * notice, this list of conditions and the following disclaimer in the
|
||
18 | * documentation and/or other materials provided with the distribution.
|
||
19 | *
|
||
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
30 | * POSSIBILITY OF SUCH DAMAGE.
|
||
31 | */
|
||
32 | |||
33 | #ifndef _SYS_POOL_H_
|
||
34 | #define _SYS_POOL_H_
|
||
35 | |||
36 | #include <sys/stdbool.h> |
||
37 | #include <sys/stdint.h> |
||
38 | |||
39 | struct pool_sysctl {
|
||
40 | char pr_wchan[16]; |
||
41 | uint64_t pr_flags; |
||
42 | uint64_t pr_size; |
||
43 | uint64_t pr_pagesize; |
||
44 | uint64_t pr_itemsperpage; |
||
45 | uint64_t pr_nitems; |
||
46 | uint64_t pr_nout; |
||
47 | uint64_t pr_hardlimit; |
||
48 | uint64_t pr_npages; |
||
49 | uint64_t pr_minpages; |
||
50 | uint64_t pr_maxpages; |
||
51 | |||
52 | uint64_t pr_nget; |
||
53 | uint64_t pr_nfail; |
||
54 | uint64_t pr_nput; |
||
55 | uint64_t pr_npagealloc; |
||
56 | uint64_t pr_npagefree; |
||
57 | uint64_t pr_hiwat; |
||
58 | uint64_t pr_nidle; |
||
59 | |||
60 | uint64_t pr_cache_meta_size; |
||
61 | uint64_t pr_cache_nfull; |
||
62 | uint64_t pr_cache_npartial; |
||
63 | uint64_t pr_cache_nempty; |
||
64 | uint64_t pr_cache_ncontended; |
||
65 | uint64_t pr_cache_nmiss_global; |
||
66 | uint64_t pr_cache_nhit_global; |
||
67 | uint64_t pr_cache_nmiss_pcpu; |
||
68 | uint64_t pr_cache_nhit_pcpu; |
||
69 | }; |
||
70 | |||
71 | #ifdef _KERNEL
|
||
72 | #define __POOL_EXPOSE
|
||
73 | #endif
|
||
74 | |||
75 | #ifdef __POOL_EXPOSE
|
||
76 | #include <sys/param.h> |
||
77 | #include <sys/mutex.h> |
||
78 | #include <sys/condvar.h> |
||
79 | #include <sys/queue.h> |
||
80 | #include <sys/time.h> |
||
81 | #include <sys/tree.h> |
||
82 | #include <sys/callback.h> |
||
83 | |||
84 | #define POOL_PADDR_INVALID ((paddr_t) -1) |
||
85 | |||
86 | struct pool;
|
||
87 | |||
88 | struct pool_allocator {
|
||
89 | void *(*pa_alloc)(struct pool *, int); |
||
90 | void (*pa_free)(struct pool *, void *); |
||
91 | unsigned int pa_pagesz; |
||
92 | |||
93 | /* The following fields are for internal use only. */
|
||
94 | kmutex_t pa_lock; |
||
95 | TAILQ_HEAD(, pool) pa_list; /* list of pools using this allocator */
|
||
96 | uint32_t pa_refcnt; /* number of pools using this allocator */
|
||
97 | int pa_pagemask;
|
||
98 | int pa_pageshift;
|
||
99 | }; |
||
100 | |||
101 | LIST_HEAD(pool_pagelist,pool_item_header); |
||
102 | SPLAY_HEAD(phtree, pool_item_header); |
||
103 | |||
104 | struct pool {
|
||
105 | TAILQ_ENTRY(pool) |
||
106 | pr_poollist; |
||
107 | struct pool_pagelist
|
||
108 | pr_emptypages; /* Empty pages */
|
||
109 | struct pool_pagelist
|
||
110 | pr_fullpages; /* Full pages */
|
||
111 | struct pool_pagelist
|
||
112 | pr_partpages; /* Partially-allocated pages */
|
||
113 | struct pool_item_header *pr_curpage;
|
||
114 | struct pool *pr_phpool; /* Pool item header pool */ |
||
115 | struct pool_cache *pr_cache; /* Cache for this pool */ |
||
116 | unsigned int pr_size; /* Size of item */ |
||
117 | unsigned int pr_align; /* Requested alignment, must be 2^n */ |
||
118 | unsigned int pr_itemoffset; /* Align this offset in item */ |
||
119 | unsigned int pr_minitems; /* minimum # of items to keep */ |
||
120 | unsigned int pr_minpages; /* same in page units */ |
||
121 | unsigned int pr_maxpages; /* maximum # of pages to keep */ |
||
122 | unsigned int pr_npages; /* # of pages allocated */ |
||
123 | unsigned int pr_itemsperpage;/* # items that fit in a page */ |
||
124 | unsigned int pr_slack; /* unused space in a page */ |
||
125 | unsigned int pr_nitems; /* number of available items in pool */ |
||
126 | unsigned int pr_nout; /* # items currently allocated */ |
||
127 | unsigned int pr_hardlimit; /* hard limit to number of allocated |
||
128 | items */
|
||
129 | unsigned int pr_refcnt; /* ref count for pagedaemon, etc */ |
||
130 | struct pool_allocator *pr_alloc;/* back-end allocator */ |
||
131 | TAILQ_ENTRY(pool) pr_alloc_list;/* link on allocator's pool list */
|
||
132 | |||
133 | /* Drain hook. */
|
||
134 | void (*pr_drain_hook)(void *, int); |
||
135 | void *pr_drain_hook_arg;
|
||
136 | |||
137 | const char *pr_wchan; /* tsleep(9) identifier */ |
||
138 | unsigned int pr_flags; /* r/w flags */ |
||
139 | unsigned int pr_roflags; /* r/o flags */ |
||
140 | #define PR_WAITOK 0x01 /* Note: matches KM_SLEEP */ |
||
141 | #define PR_NOWAIT 0x02 /* Note: matches KM_NOSLEEP */ |
||
142 | #define PR_WANTED 0x04 |
||
143 | #define PR_PHINPAGE 0x40 |
||
144 | #define PR_LOGGING 0x80 |
||
145 | #define PR_LIMITFAIL 0x100 /* even if waiting, fail if we hit limit */ |
||
146 | #define PR_RECURSIVE 0x200 /* pool contains pools, for vmstat(8) */ |
||
147 | #define PR_NOTOUCH 0x400 /* don't use free items to keep internal state*/ |
||
148 | #define PR_NOALIGN 0x800 /* don't assume backend alignment */ |
||
149 | #define PR_LARGECACHE 0x1000 /* use large cache groups */ |
||
150 | |||
151 | /*
|
||
152 | * `pr_lock' protects the pool's data structures when removing
|
||
153 | * items from or returning items to the pool, or when reading
|
||
154 | * or updating read/write fields in the pool descriptor.
|
||
155 | *
|
||
156 | * We assume back-end page allocators provide their own locking
|
||
157 | * scheme. They will be called with the pool descriptor _unlocked_,
|
||
158 | * since the page allocators may block.
|
||
159 | */
|
||
160 | kmutex_t pr_lock; |
||
161 | kcondvar_t pr_cv; |
||
162 | int pr_ipl;
|
||
163 | |||
164 | struct phtree pr_phtree;
|
||
165 | |||
166 | int pr_maxcolor; /* Cache colouring */ |
||
167 | int pr_curcolor;
|
||
168 | int pr_phoffset; /* Offset in page of page header */ |
||
169 | |||
170 | /*
|
||
171 | * Warning message to be issued, and a per-time-delta rate cap,
|
||
172 | * if the hard limit is reached.
|
||
173 | */
|
||
174 | const char *pr_hardlimit_warning; |
||
175 | struct timeval pr_hardlimit_ratecap;
|
||
176 | struct timeval pr_hardlimit_warning_last;
|
||
177 | |||
178 | /*
|
||
179 | * Instrumentation
|
||
180 | */
|
||
181 | unsigned long pr_nget; /* # of successful requests */ |
||
182 | unsigned long pr_nfail; /* # of unsuccessful requests */ |
||
183 | unsigned long pr_nput; /* # of releases */ |
||
184 | unsigned long pr_npagealloc; /* # of pages allocated */ |
||
185 | unsigned long pr_npagefree; /* # of pages released */ |
||
186 | unsigned int pr_hiwat; /* max # of pages in pool */ |
||
187 | unsigned long pr_nidle; /* # of idle pages */ |
||
188 | |||
189 | /*
|
||
190 | * Diagnostic aides.
|
||
191 | */
|
||
192 | void *pr_freecheck;
|
||
193 | void *pr_qcache;
|
||
194 | bool pr_redzone;
|
||
195 | size_t pr_reqsize; |
||
196 | }; |
||
197 | |||
198 | /*
|
||
199 | * Cache group sizes, assuming 4-byte paddr_t on !_LP64.
|
||
200 | * All groups will be aligned to CACHE_LINE_SIZE.
|
||
201 | */
|
||
202 | #ifdef _LP64
|
||
203 | #define PCG_NOBJECTS_NORMAL 15 /* 256 byte group */ |
||
204 | #define PCG_NOBJECTS_LARGE 63 /* 1024 byte group */ |
||
205 | #else
|
||
206 | #define PCG_NOBJECTS_NORMAL 14 /* 124 byte group */ |
||
207 | #define PCG_NOBJECTS_LARGE 62 /* 508 byte group */ |
||
208 | #endif
|
||
209 | |||
210 | typedef struct pcgpair { |
||
211 | void *pcgo_va; /* object virtual address */ |
||
212 | paddr_t pcgo_pa; /* object physical address */
|
||
213 | } pcgpair_t; |
||
214 | |||
215 | /* The pool cache group. */
|
||
216 | typedef struct pool_cache_group { |
||
217 | struct pool_cache_group *pcg_next; /* link to next group */ |
||
218 | u_int pcg_avail; /* # available objects */
|
||
219 | u_int pcg_size; /* max number objects */
|
||
220 | pcgpair_t pcg_objects[1]; /* the objects */ |
||
221 | } pcg_t; |
||
222 | |||
223 | typedef struct pool_cache_cpu { |
||
224 | uint64_t cc_misses; |
||
225 | uint64_t cc_hits; |
||
226 | struct pool_cache_group *cc_current;
|
||
227 | struct pool_cache_group *cc_previous;
|
||
228 | struct pool_cache *cc_cache;
|
||
229 | int cc_ipl;
|
||
230 | int cc_cpuindex;
|
||
231 | #ifdef _KERNEL
|
||
232 | ipl_cookie_t cc_iplcookie; |
||
233 | #endif
|
||
234 | } pool_cache_cpu_t; |
||
235 | |||
236 | struct pool_cache {
|
||
237 | /* Pool layer. */
|
||
238 | struct pool pc_pool;
|
||
239 | |||
240 | /* Cache layer. */
|
||
241 | kmutex_t pc_lock; /* locks cache layer */
|
||
242 | TAILQ_ENTRY(pool_cache) |
||
243 | pc_cachelist; /* entry on global cache list */
|
||
244 | pcg_t *pc_emptygroups;/* list of empty cache groups */
|
||
245 | pcg_t *pc_fullgroups; /* list of full cache groups */
|
||
246 | pcg_t *pc_partgroups; /* groups for reclamation */
|
||
247 | struct pool *pc_pcgpool; /* Pool of cache groups */ |
||
248 | int pc_pcgsize; /* Use large cache groups? */ |
||
249 | int pc_ncpu; /* number cpus set up */ |
||
250 | int (*pc_ctor)(void *, void *, int); |
||
251 | void (*pc_dtor)(void *, void *); |
||
252 | void *pc_arg; /* for ctor/ctor */ |
||
253 | uint64_t pc_hits; /* cache layer hits */
|
||
254 | uint64_t pc_misses; /* cache layer misses */
|
||
255 | uint64_t pc_contended; /* contention events on cache */
|
||
256 | unsigned int pc_nempty; /* empty groups in cache */ |
||
257 | unsigned int pc_nfull; /* full groups in cache */ |
||
258 | unsigned int pc_npart; /* partial groups in cache */ |
||
259 | unsigned int pc_refcnt; /* ref count for pagedaemon, etc */ |
||
260 | |||
261 | /* Diagnostic aides. */
|
||
262 | void *pc_freecheck;
|
||
263 | bool pc_redzone;
|
||
264 | size_t pc_reqsize; |
||
265 | |||
266 | /* CPU layer. */
|
||
267 | pool_cache_cpu_t pc_cpu0 __aligned(CACHE_LINE_SIZE); |
||
268 | void *pc_cpus[MAXCPUS] __aligned(CACHE_LINE_SIZE);
|
||
269 | }; |
||
270 | |||
271 | #endif /* __POOL_EXPOSE */ |
||
272 | |||
273 | typedef struct pool_cache *pool_cache_t; |
||
274 | |||
275 | #ifdef _KERNEL
|
||
276 | /*
|
||
277 | * pool_allocator_kmem is the default that all pools get unless
|
||
278 | * otherwise specified. pool_allocator_nointr is provided for
|
||
279 | * pools that know they will never be accessed in interrupt
|
||
280 | * context.
|
||
281 | */
|
||
282 | extern struct pool_allocator pool_allocator_kmem; |
||
283 | extern struct pool_allocator pool_allocator_nointr; |
||
284 | extern struct pool_allocator pool_allocator_meta; |
||
285 | #ifdef POOL_SUBPAGE
|
||
286 | /* The above are subpage allocators in this case. */
|
||
287 | extern struct pool_allocator pool_allocator_kmem_fullpage; |
||
288 | extern struct pool_allocator pool_allocator_nointr_fullpage; |
||
289 | #endif
|
||
290 | |||
291 | void pool_subsystem_init(void); |
||
292 | |||
293 | void pool_init(struct pool *, size_t, u_int, u_int, |
||
294 | int, const char *, struct pool_allocator *, int); |
||
295 | void pool_destroy(struct pool *); |
||
296 | |||
297 | void pool_set_drain_hook(struct pool *, |
||
298 | void (*)(void *, int), void *); |
||
299 | |||
300 | void *pool_get(struct pool *, int); |
||
301 | void pool_put(struct pool *, void *); |
||
302 | int pool_reclaim(struct pool *); |
||
303 | |||
304 | int pool_prime(struct pool *, int); |
||
305 | void pool_setlowat(struct pool *, int); |
||
306 | void pool_sethiwat(struct pool *, int); |
||
307 | void pool_sethardlimit(struct pool *, int, const char *, int); |
||
308 | bool pool_drain(struct pool **); |
||
309 | |||
310 | /*
|
||
311 | * Debugging and diagnostic aides.
|
||
312 | */
|
||
313 | void pool_printit(struct pool *, const char *, |
||
314 | void (*)(const char *, ...) __printflike(1, 2)); |
||
315 | void pool_printall(const char *, void (*)(const char *, ...) |
||
316 | __printflike(1, 2)); |
||
317 | int pool_chk(struct pool *, const char *); |
||
318 | |||
319 | /*
|
||
320 | * Pool cache routines.
|
||
321 | */
|
||
322 | pool_cache_t pool_cache_init(size_t, u_int, u_int, u_int, const char *, |
||
323 | struct pool_allocator *, int, int (*)(void *, void *, int), |
||
324 | void (*)(void *, void *), void *); |
||
325 | void pool_cache_bootstrap(pool_cache_t, size_t, u_int, u_int, u_int,
|
||
326 | const char *, struct pool_allocator *, int, |
||
327 | int (*)(void *, void *, int), void (*)(void *, void *), |
||
328 | void *);
|
||
329 | void pool_cache_destroy(pool_cache_t);
|
||
330 | void pool_cache_bootstrap_destroy(pool_cache_t);
|
||
331 | void *pool_cache_get_paddr(pool_cache_t, int, paddr_t *); |
||
332 | void pool_cache_put_paddr(pool_cache_t, void *, paddr_t); |
||
333 | void pool_cache_destruct_object(pool_cache_t, void *); |
||
334 | void pool_cache_invalidate(pool_cache_t);
|
||
335 | bool pool_cache_reclaim(pool_cache_t);
|
||
336 | void pool_cache_set_drain_hook(pool_cache_t,
|
||
337 | void (*)(void *, int), void *); |
||
338 | void pool_cache_setlowat(pool_cache_t, int); |
||
339 | void pool_cache_sethiwat(pool_cache_t, int); |
||
340 | void pool_cache_sethardlimit(pool_cache_t, int, const char *, int); |
||
341 | void pool_cache_cpu_init(struct cpu_info *); |
||
342 | |||
343 | #define pool_cache_get(pc, f) pool_cache_get_paddr((pc), (f), NULL) |
||
344 | #define pool_cache_put(pc, o) pool_cache_put_paddr((pc), (o), \
|
||
345 | POOL_PADDR_INVALID) |
||
346 | |||
347 | void pool_whatis(uintptr_t, void (*)(const char *, ...) |
||
348 | __printflike(1, 2)); |
||
349 | #endif /* _KERNEL */ |
||
350 | |||
351 | #endif /* _SYS_POOL_H_ */ |