Project

General

Profile

Statistics
| Revision:

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_ */