1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
|
/* $NetBSD: pool.h,v 1.54 2006/08/20 09:35:25 yamt Exp $ */
/*-
* Copyright (c) 1997, 1998, 1999, 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Paul Kranenburg; by Jason R. Thorpe of the Numerical Aerospace
* Simulation Facility, NASA Ames Research Center.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SYS_POOL_H_
#define _SYS_POOL_H_
#ifdef _KERNEL
#define __POOL_EXPOSE
#endif
#if defined(_KERNEL_OPT)
#include "opt_pool.h"
#endif
#ifdef __POOL_EXPOSE
#include <sys/lock.h>
#include <sys/queue.h>
#include <sys/time.h>
#include <sys/tree.h>
#if defined(_KERNEL)
#include <sys/callback.h>
#endif /* defined(_KERNEL) */
#endif
#define PCG_NOBJECTS 16
#define POOL_PADDR_INVALID ((paddr_t) -1)
#ifdef __POOL_EXPOSE
/* The pool cache group. */
struct pool_cache_group {
LIST_ENTRY(pool_cache_group)
pcg_list; /* link in the pool cache's group list */
u_int pcg_avail; /* # available objects */
/* pointers to the objects */
struct {
void *pcgo_va; /* cache object virtual address */
paddr_t pcgo_pa;/* cache object physical address */
} pcg_objects[PCG_NOBJECTS];
};
LIST_HEAD(pool_cache_grouplist,pool_cache_group);
struct pool_cache {
LIST_ENTRY(pool_cache)
pc_poollist; /* entry on pool's group list */
struct pool_cache_grouplist
pc_emptygroups; /* list of empty cache groups */
struct pool_cache_grouplist
pc_fullgroups; /* list of full cache groups */
struct pool_cache_grouplist
pc_partgroups; /* list of partial cache groups */
struct pool *pc_pool; /* parent pool */
struct simplelock pc_slock; /* mutex */
int (*pc_ctor)(void *, void *, int);
void (*pc_dtor)(void *, void *);
void *pc_arg;
/* Statistics. */
unsigned long pc_hits; /* cache hits */
unsigned long pc_misses; /* cache misses */
unsigned long pc_ngroups; /* # cache groups */
unsigned long pc_nitems; /* # objects currently in cache */
};
struct pool_allocator {
void *(*pa_alloc)(struct pool *, int);
void (*pa_free)(struct pool *, void *);
unsigned int pa_pagesz;
/* The following fields are for internal use only. */
struct simplelock pa_slock;
TAILQ_HEAD(, pool) pa_list; /* list of pools using this allocator */
int pa_flags;
#define PA_INITIALIZED 0x01
int pa_pagemask;
int pa_pageshift;
struct vm_map *pa_backingmap;
#if defined(_KERNEL)
struct vm_map **pa_backingmapptr;
SLIST_ENTRY(pool_allocator) pa_q;
#endif /* defined(_KERNEL) */
};
LIST_HEAD(pool_pagelist,pool_item_header);
struct pool {
LIST_ENTRY(pool)
pr_poollist;
struct pool_pagelist
pr_emptypages; /* Empty pages */
struct pool_pagelist
pr_fullpages; /* Full pages */
struct pool_pagelist
pr_partpages; /* Partially-allocated pages */
struct pool_item_header *pr_curpage;
struct pool *pr_phpool; /* Pool item header pool */
LIST_HEAD(,pool_cache)
pr_cachelist; /* Caches for this pool */
unsigned int pr_size; /* Size of item */
unsigned int pr_align; /* Requested alignment, must be 2^n */
unsigned int pr_itemoffset; /* Align this offset in item */
unsigned int pr_minitems; /* minimum # of items to keep */
unsigned int pr_minpages; /* same in page units */
unsigned int pr_maxpages; /* maximum # of pages to keep */
unsigned int pr_npages; /* # of pages allocated */
unsigned int pr_itemsperpage;/* # items that fit in a page */
unsigned int pr_slack; /* unused space in a page */
unsigned int pr_nitems; /* number of available items in pool */
unsigned int pr_nout; /* # items currently allocated */
unsigned int pr_hardlimit; /* hard limit to number of allocated
items */
struct pool_allocator *pr_alloc;/* back-end allocator */
TAILQ_ENTRY(pool) pr_alloc_list;/* link on allocator's pool list */
/* Drain hook. */
void (*pr_drain_hook)(void *, int);
void *pr_drain_hook_arg;
const char *pr_wchan; /* tsleep(9) identifier */
unsigned int pr_flags; /* r/w flags */
unsigned int pr_roflags; /* r/o flags */
#define PR_NOWAIT 0x00 /* for symmetry */
#define PR_WAITOK 0x02
#define PR_WANTED 0x04
#define PR_PHINPAGE 0x40
#define PR_LOGGING 0x80
#define PR_LIMITFAIL 0x100 /* even if waiting, fail if we hit limit */
#define PR_RECURSIVE 0x200 /* pool contains pools, for vmstat(8) */
#define PR_NOTOUCH 0x400 /* don't use free items to keep internal state*/
#define PR_NOALIGN 0x800 /* don't assume backend alignment */
/*
* `pr_slock' protects the pool's data structures when removing
* items from or returning items to the pool, or when reading
* or updating read/write fields in the pool descriptor.
*
* We assume back-end page allocators provide their own locking
* scheme. They will be called with the pool descriptor _unlocked_,
* since the page allocators may block.
*/
struct simplelock pr_slock;
SPLAY_HEAD(phtree, pool_item_header) pr_phtree;
int pr_maxcolor; /* Cache colouring */
int pr_curcolor;
int pr_phoffset; /* Offset in page of page header */
/*
* Warning message to be issued, and a per-time-delta rate cap,
* if the hard limit is reached.
*/
const char *pr_hardlimit_warning;
struct timeval pr_hardlimit_ratecap;
struct timeval pr_hardlimit_warning_last;
/*
* Instrumentation
*/
unsigned long pr_nget; /* # of successful requests */
unsigned long pr_nfail; /* # of unsuccessful requests */
unsigned long pr_nput; /* # of releases */
unsigned long pr_npagealloc; /* # of pages allocated */
unsigned long pr_npagefree; /* # of pages released */
unsigned int pr_hiwat; /* max # of pages in pool */
unsigned long pr_nidle; /* # of idle pages */
/*
* Diagnostic aides.
*/
struct pool_log *pr_log;
int pr_curlogentry;
int pr_logsize;
const char *pr_entered_file; /* reentrancy check */
long pr_entered_line;
#if defined(_KERNEL)
struct callback_entry pr_reclaimerentry;
#endif
};
#endif /* __POOL_EXPOSE */
#ifdef _KERNEL
/*
* pool_allocator_kmem is the default that all pools get unless
* otherwise specified. pool_allocator_nointr is provided for
* pools that know they will never be accessed in interrupt
* context.
*/
extern struct pool_allocator pool_allocator_kmem;
extern struct pool_allocator pool_allocator_nointr;
#ifdef POOL_SUBPAGE
/* The above are subpage allocators in this case. */
extern struct pool_allocator pool_allocator_kmem_fullpage;
extern struct pool_allocator pool_allocator_nointr_fullpage;
#endif
struct link_pool_init { /* same as args to pool_init() */
struct pool *pp;
size_t size;
u_int align;
u_int align_offset;
int flags;
const char *wchan;
struct pool_allocator *palloc;
};
#define POOL_INIT(pp, size, align, align_offset, flags, wchan, palloc) \
struct pool pp; \
static const struct link_pool_init _link_ ## pp[1] = { \
{ &pp, size, align, align_offset, flags, wchan, palloc } \
}; \
__link_set_add_rodata(pools, _link_ ## pp)
void pool_subsystem_init(void);
void pool_init(struct pool *, size_t, u_int, u_int,
int, const char *, struct pool_allocator *);
void pool_destroy(struct pool *);
void pool_set_drain_hook(struct pool *,
void (*)(void *, int), void *);
void *pool_get(struct pool *, int);
void pool_put(struct pool *, void *);
int pool_reclaim(struct pool *);
#ifdef POOL_DIAGNOSTIC
/*
* These versions do reentrancy checking.
*/
void *_pool_get(struct pool *, int, const char *, long);
void _pool_put(struct pool *, void *, const char *, long);
int _pool_reclaim(struct pool *, const char *, long);
#define pool_get(h, f) _pool_get((h), (f), __FILE__, __LINE__)
#define pool_put(h, v) _pool_put((h), (v), __FILE__, __LINE__)
#define pool_reclaim(h) _pool_reclaim((h), __FILE__, __LINE__)
#endif /* POOL_DIAGNOSTIC */
int pool_prime(struct pool *, int);
void pool_setlowat(struct pool *, int);
void pool_sethiwat(struct pool *, int);
void pool_sethardlimit(struct pool *, int, const char *, int);
void pool_drain(void *);
/*
* Debugging and diagnostic aides.
*/
void pool_print(struct pool *, const char *);
void pool_printit(struct pool *, const char *,
void (*)(const char *, ...));
void pool_printall(const char *, void (*)(const char *, ...));
int pool_chk(struct pool *, const char *);
/*
* Pool cache routines.
*/
void pool_cache_init(struct pool_cache *, struct pool *,
int (*)(void *, void *, int),
void (*)(void *, void *),
void *);
void pool_cache_destroy(struct pool_cache *);
void *pool_cache_get_paddr(struct pool_cache *, int, paddr_t *);
#define pool_cache_get(pc, f) pool_cache_get_paddr((pc), (f), NULL)
void pool_cache_put_paddr(struct pool_cache *, void *, paddr_t);
#define pool_cache_put(pc, o) pool_cache_put_paddr((pc), (o), \
POOL_PADDR_INVALID)
void pool_cache_destruct_object(struct pool_cache *, void *);
void pool_cache_invalidate(struct pool_cache *);
#endif /* _KERNEL */
#endif /* _SYS_POOL_H_ */
|