[BACK]Return to subr_pool.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/subr_pool.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: subr_pool.c,v 1.55 2007/08/16 15:18:54 art Exp $      */
        !             2: /*     $NetBSD: subr_pool.c,v 1.61 2001/09/26 07:14:56 chs Exp $       */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1997, 1999, 2000 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Paul Kranenburg; by Jason R. Thorpe of the Numerical Aerospace
        !            10:  * Simulation Facility, NASA Ames Research Center.
        !            11:  *
        !            12:  * Redistribution and use in source and binary forms, with or without
        !            13:  * modification, are permitted provided that the following conditions
        !            14:  * are met:
        !            15:  * 1. Redistributions of source code must retain the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer.
        !            17:  * 2. Redistributions in binary form must reproduce the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer in the
        !            19:  *    documentation and/or other materials provided with the distribution.
        !            20:  * 3. All advertising materials mentioning features or use of this software
        !            21:  *    must display the following acknowledgement:
        !            22:  *     This product includes software developed by the NetBSD
        !            23:  *     Foundation, Inc. and its contributors.
        !            24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            25:  *    contributors may be used to endorse or promote products derived
        !            26:  *    from this software without specific prior written permission.
        !            27:  *
        !            28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            38:  * POSSIBILITY OF SUCH DAMAGE.
        !            39:  */
        !            40:
        !            41: #include <sys/param.h>
        !            42: #include <sys/systm.h>
        !            43: #include <sys/proc.h>
        !            44: #include <sys/errno.h>
        !            45: #include <sys/kernel.h>
        !            46: #include <sys/malloc.h>
        !            47: #include <sys/lock.h>
        !            48: #include <sys/pool.h>
        !            49: #include <sys/syslog.h>
        !            50: #include <sys/sysctl.h>
        !            51:
        !            52: #include <uvm/uvm.h>
        !            53:
        !            54: /*
        !            55:  * XXX - for now.
        !            56:  */
        !            57: #ifdef LOCKDEBUG
        !            58: #define simple_lock_freecheck(a, s) do { /* nothing */ } while (0)
        !            59: #define simple_lock_only_held(lkp, str) do { /* nothing */ } while (0)
        !            60: #endif
        !            61:
        !            62: /*
        !            63:  * Pool resource management utility.
        !            64:  *
        !            65:  * Memory is allocated in pages which are split into pieces according to
        !            66:  * the pool item size. Each page is kept on one of three lists in the
        !            67:  * pool structure: `pr_emptypages', `pr_fullpages' and `pr_partpages',
        !            68:  * for empty, full and partially-full pages respectively. The individual
        !            69:  * pool items are on a linked list headed by `ph_itemlist' in each page
        !            70:  * header. The memory for building the page list is either taken from
        !            71:  * the allocated pages themselves (for small pool items) or taken from
        !            72:  * an internal pool of page headers (`phpool').
        !            73:  */
        !            74:
        !            75: /* List of all pools */
        !            76: TAILQ_HEAD(,pool) pool_head = TAILQ_HEAD_INITIALIZER(pool_head);
        !            77:
        !            78: /* Private pool for page header structures */
        !            79: static struct pool phpool;
        !            80:
        !            81: /* This spin lock protects both pool_head */
        !            82: struct simplelock pool_head_slock;
        !            83:
        !            84: struct pool_item_header {
        !            85:        /* Page headers */
        !            86:        LIST_ENTRY(pool_item_header)
        !            87:                                ph_pagelist;    /* pool page list */
        !            88:        TAILQ_HEAD(,pool_item)  ph_itemlist;    /* chunk list for this page */
        !            89:        SPLAY_ENTRY(pool_item_header)
        !            90:                                ph_node;        /* Off-page page headers */
        !            91:        int                     ph_nmissing;    /* # of chunks in use */
        !            92:        caddr_t                 ph_page;        /* this page's address */
        !            93: };
        !            94:
        !            95: struct pool_item {
        !            96: #ifdef DIAGNOSTIC
        !            97:        int pi_magic;
        !            98: #endif
        !            99: #ifdef DEADBEEF1
        !           100: #define        PI_MAGIC DEADBEEF1
        !           101: #else
        !           102: #define        PI_MAGIC 0xdeafbeef
        !           103: #endif
        !           104:        /* Other entries use only this list entry */
        !           105:        TAILQ_ENTRY(pool_item)  pi_list;
        !           106: };
        !           107:
        !           108: #define        POOL_NEEDS_CATCHUP(pp)                                          \
        !           109:        ((pp)->pr_nitems < (pp)->pr_minitems)
        !           110:
        !           111: /*
        !           112:  * Every pool gets a unique serial number assigned to it. If this counter
        !           113:  * wraps, we're screwed, but we shouldn't create so many pools anyway.
        !           114:  */
        !           115: unsigned int pool_serial;
        !           116:
        !           117: /*
        !           118:  * Pool cache management.
        !           119:  *
        !           120:  * Pool caches provide a way for constructed objects to be cached by the
        !           121:  * pool subsystem.  This can lead to performance improvements by avoiding
        !           122:  * needless object construction/destruction; it is deferred until absolutely
        !           123:  * necessary.
        !           124:  *
        !           125:  * Caches are grouped into cache groups.  Each cache group references
        !           126:  * up to 16 constructed objects.  When a cache allocates an object
        !           127:  * from the pool, it calls the object's constructor and places it into
        !           128:  * a cache group.  When a cache group frees an object back to the pool,
        !           129:  * it first calls the object's destructor.  This allows the object to
        !           130:  * persist in constructed form while freed to the cache.
        !           131:  *
        !           132:  * Multiple caches may exist for each pool.  This allows a single
        !           133:  * object type to have multiple constructed forms.  The pool references
        !           134:  * each cache, so that when a pool is drained by the pagedaemon, it can
        !           135:  * drain each individual cache as well.  Each time a cache is drained,
        !           136:  * the most idle cache group is freed to the pool in its entirety.
        !           137:  *
        !           138:  * Pool caches are layed on top of pools.  By layering them, we can avoid
        !           139:  * the complexity of cache management for pools which would not benefit
        !           140:  * from it.
        !           141:  */
        !           142:
        !           143: /* The cache group pool. */
        !           144: static struct pool pcgpool;
        !           145:
        !           146: /* The pool cache group. */
        !           147: #define        PCG_NOBJECTS            16
        !           148: struct pool_cache_group {
        !           149:        TAILQ_ENTRY(pool_cache_group)
        !           150:                pcg_list;       /* link in the pool cache's group list */
        !           151:        u_int   pcg_avail;      /* # available objects */
        !           152:                                /* pointers to the objects */
        !           153:        void    *pcg_objects[PCG_NOBJECTS];
        !           154: };
        !           155:
        !           156: void   pool_cache_reclaim(struct pool_cache *);
        !           157: void   pool_cache_do_invalidate(struct pool_cache *, int,
        !           158:     void (*)(struct pool *, void *));
        !           159:
        !           160: int    pool_catchup(struct pool *);
        !           161: void   pool_prime_page(struct pool *, caddr_t, struct pool_item_header *);
        !           162: void   pool_update_curpage(struct pool *);
        !           163: void   pool_do_put(struct pool *, void *);
        !           164: void   pr_rmpage(struct pool *, struct pool_item_header *,
        !           165:     struct pool_pagelist *);
        !           166: int    pool_chk_page(struct pool *, const char *, struct pool_item_header *);
        !           167:
        !           168: void   *pool_allocator_alloc(struct pool *, int);
        !           169: void   pool_allocator_free(struct pool *, void *);
        !           170:
        !           171: #ifdef DDB
        !           172: void pool_print_pagelist(struct pool_pagelist *, int (*)(const char *, ...));
        !           173: void pool_print1(struct pool *, const char *, int (*)(const char *, ...));
        !           174: #endif
        !           175:
        !           176:
        !           177: /*
        !           178:  * Pool log entry. An array of these is allocated in pool_init().
        !           179:  */
        !           180: struct pool_log {
        !           181:        const char      *pl_file;
        !           182:        long            pl_line;
        !           183:        int             pl_action;
        !           184: #define        PRLOG_GET       1
        !           185: #define        PRLOG_PUT       2
        !           186:        void            *pl_addr;
        !           187: };
        !           188:
        !           189: /* Number of entries in pool log buffers */
        !           190: #ifndef POOL_LOGSIZE
        !           191: #define        POOL_LOGSIZE    10
        !           192: #endif
        !           193:
        !           194: int pool_logsize = POOL_LOGSIZE;
        !           195:
        !           196: #ifdef POOL_DIAGNOSTIC
        !           197: static __inline void
        !           198: pr_log(struct pool *pp, void *v, int action, const char *file, long line)
        !           199: {
        !           200:        int n = pp->pr_curlogentry;
        !           201:        struct pool_log *pl;
        !           202:
        !           203:        if ((pp->pr_roflags & PR_LOGGING) == 0)
        !           204:                return;
        !           205:
        !           206:        /*
        !           207:         * Fill in the current entry. Wrap around and overwrite
        !           208:         * the oldest entry if necessary.
        !           209:         */
        !           210:        pl = &pp->pr_log[n];
        !           211:        pl->pl_file = file;
        !           212:        pl->pl_line = line;
        !           213:        pl->pl_action = action;
        !           214:        pl->pl_addr = v;
        !           215:        if (++n >= pp->pr_logsize)
        !           216:                n = 0;
        !           217:        pp->pr_curlogentry = n;
        !           218: }
        !           219:
        !           220: static void
        !           221: pr_printlog(struct pool *pp, struct pool_item *pi,
        !           222:     int (*pr)(const char *, ...))
        !           223: {
        !           224:        int i = pp->pr_logsize;
        !           225:        int n = pp->pr_curlogentry;
        !           226:
        !           227:        if ((pp->pr_roflags & PR_LOGGING) == 0)
        !           228:                return;
        !           229:
        !           230:        /*
        !           231:         * Print all entries in this pool's log.
        !           232:         */
        !           233:        while (i-- > 0) {
        !           234:                struct pool_log *pl = &pp->pr_log[n];
        !           235:                if (pl->pl_action != 0) {
        !           236:                        if (pi == NULL || pi == pl->pl_addr) {
        !           237:                                (*pr)("\tlog entry %d:\n", i);
        !           238:                                (*pr)("\t\taction = %s, addr = %p\n",
        !           239:                                    pl->pl_action == PRLOG_GET ? "get" : "put",
        !           240:                                    pl->pl_addr);
        !           241:                                (*pr)("\t\tfile: %s at line %lu\n",
        !           242:                                    pl->pl_file, pl->pl_line);
        !           243:                        }
        !           244:                }
        !           245:                if (++n >= pp->pr_logsize)
        !           246:                        n = 0;
        !           247:        }
        !           248: }
        !           249:
        !           250: static __inline void
        !           251: pr_enter(struct pool *pp, const char *file, long line)
        !           252: {
        !           253:
        !           254:        if (__predict_false(pp->pr_entered_file != NULL)) {
        !           255:                printf("pool %s: reentrancy at file %s line %ld\n",
        !           256:                    pp->pr_wchan, file, line);
        !           257:                printf("         previous entry at file %s line %ld\n",
        !           258:                    pp->pr_entered_file, pp->pr_entered_line);
        !           259:                panic("pr_enter");
        !           260:        }
        !           261:
        !           262:        pp->pr_entered_file = file;
        !           263:        pp->pr_entered_line = line;
        !           264: }
        !           265:
        !           266: static __inline void
        !           267: pr_leave(struct pool *pp)
        !           268: {
        !           269:
        !           270:        if (__predict_false(pp->pr_entered_file == NULL)) {
        !           271:                printf("pool %s not entered?\n", pp->pr_wchan);
        !           272:                panic("pr_leave");
        !           273:        }
        !           274:
        !           275:        pp->pr_entered_file = NULL;
        !           276:        pp->pr_entered_line = 0;
        !           277: }
        !           278:
        !           279: static __inline void
        !           280: pr_enter_check(struct pool *pp, int (*pr)(const char *, ...))
        !           281: {
        !           282:
        !           283:        if (pp->pr_entered_file != NULL)
        !           284:                (*pr)("\n\tcurrently entered from file %s line %ld\n",
        !           285:                    pp->pr_entered_file, pp->pr_entered_line);
        !           286: }
        !           287: #else
        !           288: #define        pr_log(pp, v, action, file, line)
        !           289: #define        pr_printlog(pp, pi, pr)
        !           290: #define        pr_enter(pp, file, line)
        !           291: #define        pr_leave(pp)
        !           292: #define        pr_enter_check(pp, pr)
        !           293: #endif /* POOL_DIAGNOSTIC */
        !           294:
        !           295: static __inline int
        !           296: phtree_compare(struct pool_item_header *a, struct pool_item_header *b)
        !           297: {
        !           298:        if (a->ph_page < b->ph_page)
        !           299:                return (-1);
        !           300:        else if (a->ph_page > b->ph_page)
        !           301:                return (1);
        !           302:        else
        !           303:                return (0);
        !           304: }
        !           305:
        !           306: SPLAY_PROTOTYPE(phtree, pool_item_header, ph_node, phtree_compare);
        !           307: SPLAY_GENERATE(phtree, pool_item_header, ph_node, phtree_compare);
        !           308:
        !           309: /*
        !           310:  * Return the pool page header based on page address.
        !           311:  */
        !           312: static __inline struct pool_item_header *
        !           313: pr_find_pagehead(struct pool *pp, caddr_t page)
        !           314: {
        !           315:        struct pool_item_header *ph, tmp;
        !           316:
        !           317:        if ((pp->pr_roflags & PR_PHINPAGE) != 0)
        !           318:                return ((struct pool_item_header *)(page + pp->pr_phoffset));
        !           319:
        !           320:        tmp.ph_page = page;
        !           321:        ph = SPLAY_FIND(phtree, &pp->pr_phtree, &tmp);
        !           322:        return ph;
        !           323: }
        !           324:
        !           325: /*
        !           326:  * Remove a page from the pool.
        !           327:  */
        !           328: void
        !           329: pr_rmpage(struct pool *pp, struct pool_item_header *ph,
        !           330:      struct pool_pagelist *pq)
        !           331: {
        !           332:        int s;
        !           333:
        !           334:        /*
        !           335:         * If the page was idle, decrement the idle page count.
        !           336:         */
        !           337:        if (ph->ph_nmissing == 0) {
        !           338: #ifdef DIAGNOSTIC
        !           339:                if (pp->pr_nidle == 0)
        !           340:                        panic("pr_rmpage: nidle inconsistent");
        !           341:                if (pp->pr_nitems < pp->pr_itemsperpage)
        !           342:                        panic("pr_rmpage: nitems inconsistent");
        !           343: #endif
        !           344:                pp->pr_nidle--;
        !           345:        }
        !           346:
        !           347:        pp->pr_nitems -= pp->pr_itemsperpage;
        !           348:
        !           349:        /*
        !           350:         * Unlink a page from the pool and release it (or queue it for release).
        !           351:         */
        !           352:        LIST_REMOVE(ph, ph_pagelist);
        !           353:        if (pq) {
        !           354:                LIST_INSERT_HEAD(pq, ph, ph_pagelist);
        !           355:        } else {
        !           356:                pool_allocator_free(pp, ph->ph_page);
        !           357:                if ((pp->pr_roflags & PR_PHINPAGE) == 0) {
        !           358:                        SPLAY_REMOVE(phtree, &pp->pr_phtree, ph);
        !           359:                        s = splhigh();
        !           360:                        pool_put(&phpool, ph);
        !           361:                        splx(s);
        !           362:                }
        !           363:        }
        !           364:        pp->pr_npages--;
        !           365:        pp->pr_npagefree++;
        !           366:
        !           367:        pool_update_curpage(pp);
        !           368: }
        !           369:
        !           370: /*
        !           371:  * Initialize the given pool resource structure.
        !           372:  *
        !           373:  * We export this routine to allow other kernel parts to declare
        !           374:  * static pools that must be initialized before malloc() is available.
        !           375:  */
        !           376: void
        !           377: pool_init(struct pool *pp, size_t size, u_int align, u_int ioff, int flags,
        !           378:     const char *wchan, struct pool_allocator *palloc)
        !           379: {
        !           380:        int off, slack;
        !           381:
        !           382: #ifdef POOL_DIAGNOSTIC
        !           383:        /*
        !           384:         * Always log if POOL_DIAGNOSTIC is defined.
        !           385:         */
        !           386:        if (pool_logsize != 0)
        !           387:                flags |= PR_LOGGING;
        !           388: #endif
        !           389:
        !           390: #ifdef MALLOC_DEBUG
        !           391:        if ((flags & PR_DEBUG) && (ioff != 0 || align != 0))
        !           392:                flags &= ~PR_DEBUG;
        !           393: #endif
        !           394:        /*
        !           395:         * Check arguments and construct default values.
        !           396:         */
        !           397:        if (palloc == NULL)
        !           398:                palloc = &pool_allocator_nointr;
        !           399:        if ((palloc->pa_flags & PA_INITIALIZED) == 0) {
        !           400:                if (palloc->pa_pagesz == 0)
        !           401:                        palloc->pa_pagesz = PAGE_SIZE;
        !           402:
        !           403:                TAILQ_INIT(&palloc->pa_list);
        !           404:
        !           405:                simple_lock_init(&palloc->pa_slock);
        !           406:                palloc->pa_pagemask = ~(palloc->pa_pagesz - 1);
        !           407:                palloc->pa_pageshift = ffs(palloc->pa_pagesz) - 1;
        !           408:                palloc->pa_flags |= PA_INITIALIZED;
        !           409:        }
        !           410:
        !           411:        if (align == 0)
        !           412:                align = ALIGN(1);
        !           413:
        !           414:        if (size < sizeof(struct pool_item))
        !           415:                size = sizeof(struct pool_item);
        !           416:
        !           417:        size = roundup(size, align);
        !           418: #ifdef DIAGNOSTIC
        !           419:        if (size > palloc->pa_pagesz)
        !           420:                panic("pool_init: pool item size (%lu) too large",
        !           421:                      (u_long)size);
        !           422: #endif
        !           423:
        !           424:        /*
        !           425:         * Initialize the pool structure.
        !           426:         */
        !           427:        LIST_INIT(&pp->pr_emptypages);
        !           428:        LIST_INIT(&pp->pr_fullpages);
        !           429:        LIST_INIT(&pp->pr_partpages);
        !           430:        TAILQ_INIT(&pp->pr_cachelist);
        !           431:        pp->pr_curpage = NULL;
        !           432:        pp->pr_npages = 0;
        !           433:        pp->pr_minitems = 0;
        !           434:        pp->pr_minpages = 0;
        !           435:        pp->pr_maxpages = 8;
        !           436:        pp->pr_roflags = flags;
        !           437:        pp->pr_flags = 0;
        !           438:        pp->pr_size = size;
        !           439:        pp->pr_align = align;
        !           440:        pp->pr_wchan = wchan;
        !           441:        pp->pr_alloc = palloc;
        !           442:        pp->pr_nitems = 0;
        !           443:        pp->pr_nout = 0;
        !           444:        pp->pr_hardlimit = UINT_MAX;
        !           445:        pp->pr_hardlimit_warning = NULL;
        !           446:        pp->pr_hardlimit_ratecap.tv_sec = 0;
        !           447:        pp->pr_hardlimit_ratecap.tv_usec = 0;
        !           448:        pp->pr_hardlimit_warning_last.tv_sec = 0;
        !           449:        pp->pr_hardlimit_warning_last.tv_usec = 0;
        !           450:        pp->pr_serial = ++pool_serial;
        !           451:        if (pool_serial == 0)
        !           452:                panic("pool_init: too much uptime");
        !           453:
        !           454:        /*
        !           455:         * Decide whether to put the page header off page to avoid
        !           456:         * wasting too large a part of the page. Off-page page headers
        !           457:         * go on a hash table, so we can match a returned item
        !           458:         * with its header based on the page address.
        !           459:         * We use 1/16 of the page size as the threshold (XXX: tune)
        !           460:         */
        !           461:        if (pp->pr_size < palloc->pa_pagesz/16) {
        !           462:                /* Use the end of the page for the page header */
        !           463:                pp->pr_roflags |= PR_PHINPAGE;
        !           464:                pp->pr_phoffset = off = palloc->pa_pagesz -
        !           465:                    ALIGN(sizeof(struct pool_item_header));
        !           466:        } else {
        !           467:                /* The page header will be taken from our page header pool */
        !           468:                pp->pr_phoffset = 0;
        !           469:                off = palloc->pa_pagesz;
        !           470:                SPLAY_INIT(&pp->pr_phtree);
        !           471:        }
        !           472:
        !           473:        /*
        !           474:         * Alignment is to take place at `ioff' within the item. This means
        !           475:         * we must reserve up to `align - 1' bytes on the page to allow
        !           476:         * appropriate positioning of each item.
        !           477:         *
        !           478:         * Silently enforce `0 <= ioff < align'.
        !           479:         */
        !           480:        pp->pr_itemoffset = ioff = ioff % align;
        !           481:        pp->pr_itemsperpage = (off - ((align - ioff) % align)) / pp->pr_size;
        !           482:        KASSERT(pp->pr_itemsperpage != 0);
        !           483:
        !           484:        /*
        !           485:         * Use the slack between the chunks and the page header
        !           486:         * for "cache coloring".
        !           487:         */
        !           488:        slack = off - pp->pr_itemsperpage * pp->pr_size;
        !           489:        pp->pr_maxcolor = (slack / align) * align;
        !           490:        pp->pr_curcolor = 0;
        !           491:
        !           492:        pp->pr_nget = 0;
        !           493:        pp->pr_nfail = 0;
        !           494:        pp->pr_nput = 0;
        !           495:        pp->pr_npagealloc = 0;
        !           496:        pp->pr_npagefree = 0;
        !           497:        pp->pr_hiwat = 0;
        !           498:        pp->pr_nidle = 0;
        !           499:
        !           500: #ifdef POOL_DIAGNOSTIC
        !           501:        if (flags & PR_LOGGING) {
        !           502:                if (kmem_map == NULL ||
        !           503:                    (pp->pr_log = malloc(pool_logsize * sizeof(struct pool_log),
        !           504:                     M_TEMP, M_NOWAIT)) == NULL)
        !           505:                        pp->pr_roflags &= ~PR_LOGGING;
        !           506:                pp->pr_curlogentry = 0;
        !           507:                pp->pr_logsize = pool_logsize;
        !           508:        }
        !           509: #endif
        !           510:
        !           511:        pp->pr_entered_file = NULL;
        !           512:        pp->pr_entered_line = 0;
        !           513:
        !           514:        simple_lock_init(&pp->pr_slock);
        !           515:
        !           516:        pp->pr_ipl = -1;
        !           517:
        !           518:        /*
        !           519:         * Initialize private page header pool and cache magazine pool if we
        !           520:         * haven't done so yet.
        !           521:         * XXX LOCKING.
        !           522:         */
        !           523:        if (phpool.pr_size == 0) {
        !           524:                pool_init(&phpool, sizeof(struct pool_item_header), 0, 0,
        !           525:                    0, "phpool", NULL);
        !           526:                pool_init(&pcgpool, sizeof(struct pool_cache_group), 0, 0,
        !           527:                    0, "pcgpool", NULL);
        !           528:        }
        !           529:
        !           530:        simple_lock_init(&pool_head_slock);
        !           531:
        !           532:        /* Insert this into the list of all pools. */
        !           533:        simple_lock(&pool_head_slock);
        !           534:        TAILQ_INSERT_TAIL(&pool_head, pp, pr_poollist);
        !           535:        simple_unlock(&pool_head_slock);
        !           536:
        !           537:        /* Insert into the list of pools using this allocator. */
        !           538:        simple_lock(&palloc->pa_slock);
        !           539:        TAILQ_INSERT_TAIL(&palloc->pa_list, pp, pr_alloc_list);
        !           540:        simple_unlock(&palloc->pa_slock);
        !           541: }
        !           542:
        !           543: #ifdef DIAGNOSTIC
        !           544: void
        !           545: pool_setipl(struct pool *pp, int ipl)
        !           546: {
        !           547:        pp->pr_ipl = ipl;
        !           548: }
        !           549: #endif
        !           550:
        !           551: /*
        !           552:  * Decommission a pool resource.
        !           553:  */
        !           554: void
        !           555: pool_destroy(struct pool *pp)
        !           556: {
        !           557:        struct pool_item_header *ph;
        !           558:        struct pool_cache *pc;
        !           559:
        !           560:        /* Locking order: pool_allocator -> pool */
        !           561:        simple_lock(&pp->pr_alloc->pa_slock);
        !           562:        TAILQ_REMOVE(&pp->pr_alloc->pa_list, pp, pr_alloc_list);
        !           563:        simple_unlock(&pp->pr_alloc->pa_slock);
        !           564:
        !           565:        /* Destroy all caches for this pool. */
        !           566:        while ((pc = TAILQ_FIRST(&pp->pr_cachelist)) != NULL)
        !           567:                pool_cache_destroy(pc);
        !           568:
        !           569: #ifdef DIAGNOSTIC
        !           570:        if (pp->pr_nout != 0) {
        !           571:                pr_printlog(pp, NULL, printf);
        !           572:                panic("pool_destroy: pool busy: still out: %u",
        !           573:                    pp->pr_nout);
        !           574:        }
        !           575: #endif
        !           576:
        !           577:        /* Remove all pages */
        !           578:        while ((ph = LIST_FIRST(&pp->pr_emptypages)) != NULL)
        !           579:                pr_rmpage(pp, ph, NULL);
        !           580:        KASSERT(LIST_EMPTY(&pp->pr_fullpages));
        !           581:        KASSERT(LIST_EMPTY(&pp->pr_partpages));
        !           582:
        !           583:        /* Remove from global pool list */
        !           584:        simple_lock(&pool_head_slock);
        !           585:        TAILQ_REMOVE(&pool_head, pp, pr_poollist);
        !           586:        simple_unlock(&pool_head_slock);
        !           587:
        !           588: #ifdef POOL_DIAGNOSTIC
        !           589:        if ((pp->pr_roflags & PR_LOGGING) != 0)
        !           590:                free(pp->pr_log, M_TEMP);
        !           591: #endif
        !           592: }
        !           593:
        !           594: static struct pool_item_header *
        !           595: pool_alloc_item_header(struct pool *pp, caddr_t storage, int flags)
        !           596: {
        !           597:        struct pool_item_header *ph;
        !           598:        int s;
        !           599:
        !           600:        LOCK_ASSERT(simple_lock_held(&pp->pr_slock) == 0);
        !           601:
        !           602:        if ((pp->pr_roflags & PR_PHINPAGE) != 0)
        !           603:                ph = (struct pool_item_header *) (storage + pp->pr_phoffset);
        !           604:        else {
        !           605:                s = splhigh();
        !           606:                ph = pool_get(&phpool, flags);
        !           607:                splx(s);
        !           608:        }
        !           609:
        !           610:        return (ph);
        !           611: }
        !           612:
        !           613: /*
        !           614:  * Grab an item from the pool; must be called at appropriate spl level
        !           615:  */
        !           616: void *
        !           617: #ifdef POOL_DIAGNOSTIC
        !           618: _pool_get(struct pool *pp, int flags, const char *file, long line)
        !           619: #else
        !           620: pool_get(struct pool *pp, int flags)
        !           621: #endif
        !           622: {
        !           623:        struct pool_item *pi;
        !           624:        struct pool_item_header *ph;
        !           625:        void *v;
        !           626:
        !           627: #ifdef DIAGNOSTIC
        !           628:        if ((flags & PR_WAITOK) != 0)
        !           629:                splassert(IPL_NONE);
        !           630:        if (pp->pr_ipl != -1)
        !           631:                splassert(pp->pr_ipl);
        !           632:        if (__predict_false(curproc == NULL && /* doing_shutdown == 0 && XXX*/
        !           633:                            (flags & PR_WAITOK) != 0))
        !           634:                panic("pool_get: %s:must have NOWAIT", pp->pr_wchan);
        !           635:
        !           636: #ifdef LOCKDEBUG
        !           637:        if (flags & PR_WAITOK)
        !           638:                simple_lock_only_held(NULL, "pool_get(PR_WAITOK)");
        !           639: #endif
        !           640: #endif /* DIAGNOSTIC */
        !           641:
        !           642: #ifdef MALLOC_DEBUG
        !           643:        if (pp->pr_roflags & PR_DEBUG) {
        !           644:                void *addr;
        !           645:
        !           646:                addr = NULL;
        !           647:                debug_malloc(pp->pr_size, M_DEBUG,
        !           648:                    (flags & PR_WAITOK) ? M_WAITOK : M_NOWAIT, &addr);
        !           649:                return (addr);
        !           650:        }
        !           651: #endif
        !           652:
        !           653:        simple_lock(&pp->pr_slock);
        !           654:        pr_enter(pp, file, line);
        !           655:
        !           656:  startover:
        !           657:        /*
        !           658:         * Check to see if we've reached the hard limit.  If we have,
        !           659:         * and we can wait, then wait until an item has been returned to
        !           660:         * the pool.
        !           661:         */
        !           662: #ifdef DIAGNOSTIC
        !           663:        if (__predict_false(pp->pr_nout > pp->pr_hardlimit)) {
        !           664:                pr_leave(pp);
        !           665:                simple_unlock(&pp->pr_slock);
        !           666:                panic("pool_get: %s: crossed hard limit", pp->pr_wchan);
        !           667:        }
        !           668: #endif
        !           669:        if (__predict_false(pp->pr_nout == pp->pr_hardlimit)) {
        !           670:                if ((flags & PR_WAITOK) && !(flags & PR_LIMITFAIL)) {
        !           671:                        /*
        !           672:                         * XXX: A warning isn't logged in this case.  Should
        !           673:                         * it be?
        !           674:                         */
        !           675:                        pp->pr_flags |= PR_WANTED;
        !           676:                        pr_leave(pp);
        !           677:                        ltsleep(pp, PSWP, pp->pr_wchan, 0, &pp->pr_slock);
        !           678:                        pr_enter(pp, file, line);
        !           679:                        goto startover;
        !           680:                }
        !           681:
        !           682:                /*
        !           683:                 * Log a message that the hard limit has been hit.
        !           684:                 */
        !           685:                if (pp->pr_hardlimit_warning != NULL &&
        !           686:                    ratecheck(&pp->pr_hardlimit_warning_last,
        !           687:                              &pp->pr_hardlimit_ratecap))
        !           688:                        log(LOG_ERR, "%s\n", pp->pr_hardlimit_warning);
        !           689:
        !           690:                pp->pr_nfail++;
        !           691:
        !           692:                pr_leave(pp);
        !           693:                simple_unlock(&pp->pr_slock);
        !           694:                return (NULL);
        !           695:        }
        !           696:
        !           697:        /*
        !           698:         * The convention we use is that if `curpage' is not NULL, then
        !           699:         * it points at a non-empty bucket. In particular, `curpage'
        !           700:         * never points at a page header which has PR_PHINPAGE set and
        !           701:         * has no items in its bucket.
        !           702:         */
        !           703:        if ((ph = pp->pr_curpage) == NULL) {
        !           704: #ifdef DIAGNOSTIC
        !           705:                if (pp->pr_nitems != 0) {
        !           706:                        simple_unlock(&pp->pr_slock);
        !           707:                        printf("pool_get: %s: curpage NULL, nitems %u\n",
        !           708:                            pp->pr_wchan, pp->pr_nitems);
        !           709:                        panic("pool_get: nitems inconsistent");
        !           710:                }
        !           711: #endif
        !           712:
        !           713:                /*
        !           714:                 * Call the back-end page allocator for more memory.
        !           715:                 * Release the pool lock, as the back-end page allocator
        !           716:                 * may block.
        !           717:                 */
        !           718:                pr_leave(pp);
        !           719:                simple_unlock(&pp->pr_slock);
        !           720:                v = pool_allocator_alloc(pp, flags);
        !           721:                if (__predict_true(v != NULL))
        !           722:                        ph = pool_alloc_item_header(pp, v, flags);
        !           723:                simple_lock(&pp->pr_slock);
        !           724:                pr_enter(pp, file, line);
        !           725:
        !           726:                if (__predict_false(v == NULL || ph == NULL)) {
        !           727:                        if (v != NULL)
        !           728:                                pool_allocator_free(pp, v);
        !           729:
        !           730:                        /*
        !           731:                         * We were unable to allocate a page or item
        !           732:                         * header, but we released the lock during
        !           733:                         * allocation, so perhaps items were freed
        !           734:                         * back to the pool.  Check for this case.
        !           735:                         */
        !           736:                        if (pp->pr_curpage != NULL)
        !           737:                                goto startover;
        !           738:
        !           739:                        if ((flags & PR_WAITOK) == 0) {
        !           740:                                pp->pr_nfail++;
        !           741:                                pr_leave(pp);
        !           742:                                simple_unlock(&pp->pr_slock);
        !           743:                                return (NULL);
        !           744:                        }
        !           745:
        !           746:                        /*
        !           747:                         * Wait for items to be returned to this pool.
        !           748:                         *
        !           749:                         * XXX: maybe we should wake up once a second and
        !           750:                         * try again?
        !           751:                         */
        !           752:                        pp->pr_flags |= PR_WANTED;
        !           753:                        /* PA_WANTED is already set on the allocator. */
        !           754:                        pr_leave(pp);
        !           755:                        ltsleep(pp, PSWP, pp->pr_wchan, 0, &pp->pr_slock);
        !           756:                        pr_enter(pp, file, line);
        !           757:                        goto startover;
        !           758:                }
        !           759:
        !           760:                /* We have more memory; add it to the pool */
        !           761:                pool_prime_page(pp, v, ph);
        !           762:                pp->pr_npagealloc++;
        !           763:
        !           764:                /* Start the allocation process over. */
        !           765:                goto startover;
        !           766:        }
        !           767:        if (__predict_false((v = pi = TAILQ_FIRST(&ph->ph_itemlist)) == NULL)) {
        !           768:                pr_leave(pp);
        !           769:                simple_unlock(&pp->pr_slock);
        !           770:                panic("pool_get: %s: page empty", pp->pr_wchan);
        !           771:        }
        !           772: #ifdef DIAGNOSTIC
        !           773:        if (__predict_false(pp->pr_nitems == 0)) {
        !           774:                pr_leave(pp);
        !           775:                simple_unlock(&pp->pr_slock);
        !           776:                printf("pool_get: %s: items on itemlist, nitems %u\n",
        !           777:                    pp->pr_wchan, pp->pr_nitems);
        !           778:                panic("pool_get: nitems inconsistent");
        !           779:        }
        !           780: #endif
        !           781:
        !           782: #ifdef POOL_DIAGNOSTIC
        !           783:        pr_log(pp, v, PRLOG_GET, file, line);
        !           784: #endif
        !           785:
        !           786: #ifdef DIAGNOSTIC
        !           787:        if (__predict_false(pi->pi_magic != PI_MAGIC)) {
        !           788:                pr_printlog(pp, pi, printf);
        !           789:                panic("pool_get(%s): free list modified: magic=%x; page %p;"
        !           790:                       " item addr %p",
        !           791:                        pp->pr_wchan, pi->pi_magic, ph->ph_page, pi);
        !           792:        }
        !           793: #endif
        !           794:
        !           795:        /*
        !           796:         * Remove from item list.
        !           797:         */
        !           798:        TAILQ_REMOVE(&ph->ph_itemlist, pi, pi_list);
        !           799:        pp->pr_nitems--;
        !           800:        pp->pr_nout++;
        !           801:        if (ph->ph_nmissing == 0) {
        !           802: #ifdef DIAGNOSTIC
        !           803:                if (__predict_false(pp->pr_nidle == 0))
        !           804:                        panic("pool_get: nidle inconsistent");
        !           805: #endif
        !           806:                pp->pr_nidle--;
        !           807:
        !           808:                /*
        !           809:                 * This page was previously empty.  Move it to the list of
        !           810:                 * partially-full pages.  This page is already curpage.
        !           811:                 */
        !           812:                LIST_REMOVE(ph, ph_pagelist);
        !           813:                LIST_INSERT_HEAD(&pp->pr_partpages, ph, ph_pagelist);
        !           814:        }
        !           815:        ph->ph_nmissing++;
        !           816:        if (TAILQ_EMPTY(&ph->ph_itemlist)) {
        !           817: #ifdef DIAGNOSTIC
        !           818:                if (__predict_false(ph->ph_nmissing != pp->pr_itemsperpage)) {
        !           819:                        pr_leave(pp);
        !           820:                        simple_unlock(&pp->pr_slock);
        !           821:                        panic("pool_get: %s: nmissing inconsistent",
        !           822:                            pp->pr_wchan);
        !           823:                }
        !           824: #endif
        !           825:                /*
        !           826:                 * This page is now full.  Move it to the full list
        !           827:                 * and select a new current page.
        !           828:                 */
        !           829:                LIST_REMOVE(ph, ph_pagelist);
        !           830:                LIST_INSERT_HEAD(&pp->pr_fullpages, ph, ph_pagelist);
        !           831:                pool_update_curpage(pp);
        !           832:        }
        !           833:
        !           834:        pp->pr_nget++;
        !           835:
        !           836:        /*
        !           837:         * If we have a low water mark and we are now below that low
        !           838:         * water mark, add more items to the pool.
        !           839:         */
        !           840:        if (POOL_NEEDS_CATCHUP(pp) && pool_catchup(pp) != 0) {
        !           841:                /*
        !           842:                 * XXX: Should we log a warning?  Should we set up a timeout
        !           843:                 * to try again in a second or so?  The latter could break
        !           844:                 * a caller's assumptions about interrupt protection, etc.
        !           845:                 */
        !           846:        }
        !           847:
        !           848:        pr_leave(pp);
        !           849:        simple_unlock(&pp->pr_slock);
        !           850:        return (v);
        !           851: }
        !           852:
        !           853: /*
        !           854:  * Internal version of pool_put().  Pool is already locked/entered.
        !           855:  */
        !           856: void
        !           857: pool_do_put(struct pool *pp, void *v)
        !           858: {
        !           859:        struct pool_item *pi = v;
        !           860:        struct pool_item_header *ph;
        !           861:        caddr_t page;
        !           862:
        !           863: #ifdef MALLOC_DEBUG
        !           864:        if (pp->pr_roflags & PR_DEBUG) {
        !           865:                debug_free(v, M_DEBUG);
        !           866:                return;
        !           867:        }
        !           868: #endif
        !           869:
        !           870:        LOCK_ASSERT(simple_lock_held(&pp->pr_slock));
        !           871:
        !           872:        page = (caddr_t)((vaddr_t)v & pp->pr_alloc->pa_pagemask);
        !           873:
        !           874: #ifdef DIAGNOSTIC
        !           875:        if (pp->pr_ipl != -1)
        !           876:                splassert(pp->pr_ipl);
        !           877:
        !           878:        if (__predict_false(pp->pr_nout == 0)) {
        !           879:                printf("pool %s: putting with none out\n",
        !           880:                    pp->pr_wchan);
        !           881:                panic("pool_put");
        !           882:        }
        !           883: #endif
        !           884:
        !           885:        if (__predict_false((ph = pr_find_pagehead(pp, page)) == NULL)) {
        !           886:                pr_printlog(pp, NULL, printf);
        !           887:                panic("pool_put: %s: page header missing", pp->pr_wchan);
        !           888:        }
        !           889:
        !           890: #ifdef LOCKDEBUG
        !           891:        /*
        !           892:         * Check if we're freeing a locked simple lock.
        !           893:         */
        !           894:        simple_lock_freecheck((caddr_t)pi, ((caddr_t)pi) + pp->pr_size);
        !           895: #endif
        !           896:
        !           897:        /*
        !           898:         * Return to item list.
        !           899:         */
        !           900: #ifdef DIAGNOSTIC
        !           901:        pi->pi_magic = PI_MAGIC;
        !           902: #endif
        !           903: #ifdef DEBUG
        !           904:        {
        !           905:                int i, *ip = v;
        !           906:
        !           907:                for (i = 0; i < pp->pr_size / sizeof(int); i++) {
        !           908:                        *ip++ = PI_MAGIC;
        !           909:                }
        !           910:        }
        !           911: #endif
        !           912:
        !           913:        TAILQ_INSERT_HEAD(&ph->ph_itemlist, pi, pi_list);
        !           914:        ph->ph_nmissing--;
        !           915:        pp->pr_nput++;
        !           916:        pp->pr_nitems++;
        !           917:        pp->pr_nout--;
        !           918:
        !           919:        /* Cancel "pool empty" condition if it exists */
        !           920:        if (pp->pr_curpage == NULL)
        !           921:                pp->pr_curpage = ph;
        !           922:
        !           923:        if (pp->pr_flags & PR_WANTED) {
        !           924:                pp->pr_flags &= ~PR_WANTED;
        !           925:                if (ph->ph_nmissing == 0)
        !           926:                        pp->pr_nidle++;
        !           927:                wakeup(pp);
        !           928:                return;
        !           929:        }
        !           930:
        !           931:        /*
        !           932:         * If this page is now empty, do one of two things:
        !           933:         *
        !           934:         *      (1) If we have more pages than the page high water mark,
        !           935:         *          free the page back to the system.
        !           936:         *
        !           937:         *      (2) Otherwise, move the page to the empty page list.
        !           938:         *
        !           939:         * Either way, select a new current page (so we use a partially-full
        !           940:         * page if one is available).
        !           941:         */
        !           942:        if (ph->ph_nmissing == 0) {
        !           943:                pp->pr_nidle++;
        !           944:                if (pp->pr_nidle > pp->pr_maxpages ||
        !           945:                    (pp->pr_alloc->pa_flags & PA_WANT) != 0) {
        !           946:                        pr_rmpage(pp, ph, NULL);
        !           947:                } else {
        !           948:                        LIST_REMOVE(ph, ph_pagelist);
        !           949:                        LIST_INSERT_HEAD(&pp->pr_emptypages, ph, ph_pagelist);
        !           950:                }
        !           951:                pool_update_curpage(pp);
        !           952:        }
        !           953:
        !           954:        /*
        !           955:         * If the page was previously completely full, move it to the
        !           956:         * partially-full list and make it the current page.  The next
        !           957:         * allocation will get the item from this page, instead of
        !           958:         * further fragmenting the pool.
        !           959:         */
        !           960:        else if (ph->ph_nmissing == (pp->pr_itemsperpage - 1)) {
        !           961:                LIST_REMOVE(ph, ph_pagelist);
        !           962:                LIST_INSERT_HEAD(&pp->pr_partpages, ph, ph_pagelist);
        !           963:                pp->pr_curpage = ph;
        !           964:        }
        !           965: }
        !           966:
        !           967: /*
        !           968:  * Return resource to the pool; must be called at appropriate spl level
        !           969:  */
        !           970: #ifdef POOL_DIAGNOSTIC
        !           971: void
        !           972: _pool_put(struct pool *pp, void *v, const char *file, long line)
        !           973: {
        !           974:
        !           975:        simple_lock(&pp->pr_slock);
        !           976:        pr_enter(pp, file, line);
        !           977:
        !           978:        pr_log(pp, v, PRLOG_PUT, file, line);
        !           979:
        !           980:        pool_do_put(pp, v);
        !           981:
        !           982:        pr_leave(pp);
        !           983:        simple_unlock(&pp->pr_slock);
        !           984: }
        !           985: #undef pool_put
        !           986: #endif /* POOL_DIAGNOSTIC */
        !           987:
        !           988: void
        !           989: pool_put(struct pool *pp, void *v)
        !           990: {
        !           991:
        !           992:        simple_lock(&pp->pr_slock);
        !           993:
        !           994:        pool_do_put(pp, v);
        !           995:
        !           996:        simple_unlock(&pp->pr_slock);
        !           997: }
        !           998:
        !           999: #ifdef POOL_DIAGNOSTIC
        !          1000: #define                pool_put(h, v)  _pool_put((h), (v), __FILE__, __LINE__)
        !          1001: #endif
        !          1002:
        !          1003: /*
        !          1004:  * Add N items to the pool.
        !          1005:  */
        !          1006: int
        !          1007: pool_prime(struct pool *pp, int n)
        !          1008: {
        !          1009:        struct pool_item_header *ph;
        !          1010:        caddr_t cp;
        !          1011:        int newpages;
        !          1012:
        !          1013:        simple_lock(&pp->pr_slock);
        !          1014:
        !          1015:        newpages = roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage;
        !          1016:
        !          1017:        while (newpages-- > 0) {
        !          1018:                simple_unlock(&pp->pr_slock);
        !          1019:                cp = pool_allocator_alloc(pp, PR_NOWAIT);
        !          1020:                if (__predict_true(cp != NULL))
        !          1021:                        ph = pool_alloc_item_header(pp, cp, PR_NOWAIT);
        !          1022:                simple_lock(&pp->pr_slock);
        !          1023:
        !          1024:                if (__predict_false(cp == NULL || ph == NULL)) {
        !          1025:                        if (cp != NULL)
        !          1026:                                pool_allocator_free(pp, cp);
        !          1027:                        break;
        !          1028:                }
        !          1029:
        !          1030:                pool_prime_page(pp, cp, ph);
        !          1031:                pp->pr_npagealloc++;
        !          1032:                pp->pr_minpages++;
        !          1033:        }
        !          1034:
        !          1035:        if (pp->pr_minpages >= pp->pr_maxpages)
        !          1036:                pp->pr_maxpages = pp->pr_minpages + 1;  /* XXX */
        !          1037:
        !          1038:        simple_unlock(&pp->pr_slock);
        !          1039:        return (0);
        !          1040: }
        !          1041:
        !          1042: /*
        !          1043:  * Add a page worth of items to the pool.
        !          1044:  *
        !          1045:  * Note, we must be called with the pool descriptor LOCKED.
        !          1046:  */
        !          1047: void
        !          1048: pool_prime_page(struct pool *pp, caddr_t storage, struct pool_item_header *ph)
        !          1049: {
        !          1050:        struct pool_item *pi;
        !          1051:        caddr_t cp = storage;
        !          1052:        unsigned int align = pp->pr_align;
        !          1053:        unsigned int ioff = pp->pr_itemoffset;
        !          1054:        int n;
        !          1055:
        !          1056: #ifdef DIAGNOSTIC
        !          1057:        if (((u_long)cp & (pp->pr_alloc->pa_pagesz - 1)) != 0)
        !          1058:                panic("pool_prime_page: %s: unaligned page", pp->pr_wchan);
        !          1059: #endif
        !          1060:
        !          1061:        /*
        !          1062:         * Insert page header.
        !          1063:         */
        !          1064:        LIST_INSERT_HEAD(&pp->pr_emptypages, ph, ph_pagelist);
        !          1065:        TAILQ_INIT(&ph->ph_itemlist);
        !          1066:        ph->ph_page = storage;
        !          1067:        ph->ph_nmissing = 0;
        !          1068:        if ((pp->pr_roflags & PR_PHINPAGE) == 0)
        !          1069:                SPLAY_INSERT(phtree, &pp->pr_phtree, ph);
        !          1070:
        !          1071:        pp->pr_nidle++;
        !          1072:
        !          1073:        /*
        !          1074:         * Color this page.
        !          1075:         */
        !          1076:        cp = (caddr_t)(cp + pp->pr_curcolor);
        !          1077:        if ((pp->pr_curcolor += align) > pp->pr_maxcolor)
        !          1078:                pp->pr_curcolor = 0;
        !          1079:
        !          1080:        /*
        !          1081:         * Adjust storage to apply aligment to `pr_itemoffset' in each item.
        !          1082:         */
        !          1083:        if (ioff != 0)
        !          1084:                cp = (caddr_t)(cp + (align - ioff));
        !          1085:
        !          1086:        /*
        !          1087:         * Insert remaining chunks on the bucket list.
        !          1088:         */
        !          1089:        n = pp->pr_itemsperpage;
        !          1090:        pp->pr_nitems += n;
        !          1091:
        !          1092:        while (n--) {
        !          1093:                pi = (struct pool_item *)cp;
        !          1094:
        !          1095:                KASSERT(((((vaddr_t)pi) + ioff) & (align - 1)) == 0);
        !          1096:
        !          1097:                /* Insert on page list */
        !          1098:                TAILQ_INSERT_TAIL(&ph->ph_itemlist, pi, pi_list);
        !          1099: #ifdef DIAGNOSTIC
        !          1100:                pi->pi_magic = PI_MAGIC;
        !          1101: #endif
        !          1102:                cp = (caddr_t)(cp + pp->pr_size);
        !          1103:        }
        !          1104:
        !          1105:        /*
        !          1106:         * If the pool was depleted, point at the new page.
        !          1107:         */
        !          1108:        if (pp->pr_curpage == NULL)
        !          1109:                pp->pr_curpage = ph;
        !          1110:
        !          1111:        if (++pp->pr_npages > pp->pr_hiwat)
        !          1112:                pp->pr_hiwat = pp->pr_npages;
        !          1113: }
        !          1114:
        !          1115: /*
        !          1116:  * Used by pool_get() when nitems drops below the low water mark.  This
        !          1117:  * is used to catch up pr_nitems with the low water mark.
        !          1118:  *
        !          1119:  * Note 1, we never wait for memory here, we let the caller decide what to do.
        !          1120:  *
        !          1121:  * Note 2, we must be called with the pool already locked, and we return
        !          1122:  * with it locked.
        !          1123:  */
        !          1124: int
        !          1125: pool_catchup(struct pool *pp)
        !          1126: {
        !          1127:        struct pool_item_header *ph;
        !          1128:        caddr_t cp;
        !          1129:        int error = 0;
        !          1130:
        !          1131:        while (POOL_NEEDS_CATCHUP(pp)) {
        !          1132:                /*
        !          1133:                 * Call the page back-end allocator for more memory.
        !          1134:                 *
        !          1135:                 * XXX: We never wait, so should we bother unlocking
        !          1136:                 * the pool descriptor?
        !          1137:                 */
        !          1138:                simple_unlock(&pp->pr_slock);
        !          1139:                cp = pool_allocator_alloc(pp, PR_NOWAIT);
        !          1140:                if (__predict_true(cp != NULL))
        !          1141:                        ph = pool_alloc_item_header(pp, cp, PR_NOWAIT);
        !          1142:                simple_lock(&pp->pr_slock);
        !          1143:                if (__predict_false(cp == NULL || ph == NULL)) {
        !          1144:                        if (cp != NULL)
        !          1145:                                pool_allocator_free(pp, cp);
        !          1146:                        error = ENOMEM;
        !          1147:                        break;
        !          1148:                }
        !          1149:                pool_prime_page(pp, cp, ph);
        !          1150:                pp->pr_npagealloc++;
        !          1151:        }
        !          1152:
        !          1153:        return (error);
        !          1154: }
        !          1155:
        !          1156: void
        !          1157: pool_update_curpage(struct pool *pp)
        !          1158: {
        !          1159:
        !          1160:        pp->pr_curpage = LIST_FIRST(&pp->pr_partpages);
        !          1161:        if (pp->pr_curpage == NULL) {
        !          1162:                pp->pr_curpage = LIST_FIRST(&pp->pr_emptypages);
        !          1163:        }
        !          1164: }
        !          1165:
        !          1166: void
        !          1167: pool_setlowat(struct pool *pp, int n)
        !          1168: {
        !          1169:
        !          1170:        simple_lock(&pp->pr_slock);
        !          1171:
        !          1172:        pp->pr_minitems = n;
        !          1173:        pp->pr_minpages = (n == 0)
        !          1174:                ? 0
        !          1175:                : roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage;
        !          1176:
        !          1177:        /* Make sure we're caught up with the newly-set low water mark. */
        !          1178:        if (POOL_NEEDS_CATCHUP(pp) && pool_catchup(pp) != 0) {
        !          1179:                /*
        !          1180:                 * XXX: Should we log a warning?  Should we set up a timeout
        !          1181:                 * to try again in a second or so?  The latter could break
        !          1182:                 * a caller's assumptions about interrupt protection, etc.
        !          1183:                 */
        !          1184:        }
        !          1185:
        !          1186:        simple_unlock(&pp->pr_slock);
        !          1187: }
        !          1188:
        !          1189: void
        !          1190: pool_sethiwat(struct pool *pp, int n)
        !          1191: {
        !          1192:
        !          1193:        simple_lock(&pp->pr_slock);
        !          1194:
        !          1195:        pp->pr_maxpages = (n == 0)
        !          1196:                ? 0
        !          1197:                : roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage;
        !          1198:
        !          1199:        simple_unlock(&pp->pr_slock);
        !          1200: }
        !          1201:
        !          1202: int
        !          1203: pool_sethardlimit(struct pool *pp, unsigned n, const char *warnmess, int ratecap)
        !          1204: {
        !          1205:        int error = 0;
        !          1206:
        !          1207:        simple_lock(&pp->pr_slock);
        !          1208:
        !          1209:        if (n < pp->pr_nout) {
        !          1210:                error = EINVAL;
        !          1211:                goto done;
        !          1212:        }
        !          1213:
        !          1214:        pp->pr_hardlimit = n;
        !          1215:        pp->pr_hardlimit_warning = warnmess;
        !          1216:        pp->pr_hardlimit_ratecap.tv_sec = ratecap;
        !          1217:        pp->pr_hardlimit_warning_last.tv_sec = 0;
        !          1218:        pp->pr_hardlimit_warning_last.tv_usec = 0;
        !          1219:
        !          1220:        /*
        !          1221:         * In-line version of pool_sethiwat(), because we don't want to
        !          1222:         * release the lock.
        !          1223:         */
        !          1224:        pp->pr_maxpages = (n == 0 || n == UINT_MAX)
        !          1225:                ? n
        !          1226:                : roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage;
        !          1227:
        !          1228:  done:
        !          1229:        simple_unlock(&pp->pr_slock);
        !          1230:
        !          1231:        return (error);
        !          1232: }
        !          1233:
        !          1234: /*
        !          1235:  * Release all complete pages that have not been used recently.
        !          1236:  *
        !          1237:  * Returns non-zero if any pages have been reclaimed.
        !          1238:  */
        !          1239: int
        !          1240: #ifdef POOL_DIAGNOSTIC
        !          1241: _pool_reclaim(struct pool *pp, const char *file, long line)
        !          1242: #else
        !          1243: pool_reclaim(struct pool *pp)
        !          1244: #endif
        !          1245: {
        !          1246:        struct pool_item_header *ph, *phnext;
        !          1247:        struct pool_cache *pc;
        !          1248:        struct pool_pagelist pq;
        !          1249:        int s;
        !          1250:
        !          1251:        if (simple_lock_try(&pp->pr_slock) == 0)
        !          1252:                return (0);
        !          1253:        pr_enter(pp, file, line);
        !          1254:
        !          1255:        LIST_INIT(&pq);
        !          1256:
        !          1257:        /*
        !          1258:         * Reclaim items from the pool's caches.
        !          1259:         */
        !          1260:        TAILQ_FOREACH(pc, &pp->pr_cachelist, pc_poollist)
        !          1261:                pool_cache_reclaim(pc);
        !          1262:
        !          1263:        for (ph = LIST_FIRST(&pp->pr_emptypages); ph != NULL; ph = phnext) {
        !          1264:                phnext = LIST_NEXT(ph, ph_pagelist);
        !          1265:
        !          1266:                /* Check our minimum page claim */
        !          1267:                if (pp->pr_npages <= pp->pr_minpages)
        !          1268:                        break;
        !          1269:
        !          1270:                KASSERT(ph->ph_nmissing == 0);
        !          1271:
        !          1272:                /*
        !          1273:                 * If freeing this page would put us below
        !          1274:                 * the low water mark, stop now.
        !          1275:                 */
        !          1276:                if ((pp->pr_nitems - pp->pr_itemsperpage) <
        !          1277:                    pp->pr_minitems)
        !          1278:                        break;
        !          1279:
        !          1280:                pr_rmpage(pp, ph, &pq);
        !          1281:        }
        !          1282:
        !          1283:        pr_leave(pp);
        !          1284:        simple_unlock(&pp->pr_slock);
        !          1285:        if (LIST_EMPTY(&pq))
        !          1286:                return (0);
        !          1287:        while ((ph = LIST_FIRST(&pq)) != NULL) {
        !          1288:                LIST_REMOVE(ph, ph_pagelist);
        !          1289:                pool_allocator_free(pp, ph->ph_page);
        !          1290:                if (pp->pr_roflags & PR_PHINPAGE) {
        !          1291:                        continue;
        !          1292:                }
        !          1293:                SPLAY_REMOVE(phtree, &pp->pr_phtree, ph);
        !          1294:                s = splhigh();
        !          1295:                pool_put(&phpool, ph);
        !          1296:                splx(s);
        !          1297:        }
        !          1298:
        !          1299:        return (1);
        !          1300: }
        !          1301:
        !          1302: #ifdef DDB
        !          1303: #include <machine/db_machdep.h>
        !          1304: #include <ddb/db_interface.h>
        !          1305: #include <ddb/db_output.h>
        !          1306:
        !          1307: /*
        !          1308:  * Diagnostic helpers.
        !          1309:  */
        !          1310: void
        !          1311: pool_printit(struct pool *pp, const char *modif, int (*pr)(const char *, ...))
        !          1312: {
        !          1313:        int s;
        !          1314:
        !          1315:        s = splvm();
        !          1316:        if (simple_lock_try(&pp->pr_slock) == 0) {
        !          1317:                pr("pool %s is locked; try again later\n",
        !          1318:                    pp->pr_wchan);
        !          1319:                splx(s);
        !          1320:                return;
        !          1321:        }
        !          1322:        pool_print1(pp, modif, pr);
        !          1323:        simple_unlock(&pp->pr_slock);
        !          1324:        splx(s);
        !          1325: }
        !          1326:
        !          1327: void
        !          1328: pool_print_pagelist(struct pool_pagelist *pl, int (*pr)(const char *, ...))
        !          1329: {
        !          1330:        struct pool_item_header *ph;
        !          1331: #ifdef DIAGNOSTIC
        !          1332:        struct pool_item *pi;
        !          1333: #endif
        !          1334:
        !          1335:        LIST_FOREACH(ph, pl, ph_pagelist) {
        !          1336:                (*pr)("\t\tpage %p, nmissing %d\n",
        !          1337:                    ph->ph_page, ph->ph_nmissing);
        !          1338: #ifdef DIAGNOSTIC
        !          1339:                TAILQ_FOREACH(pi, &ph->ph_itemlist, pi_list) {
        !          1340:                        if (pi->pi_magic != PI_MAGIC) {
        !          1341:                                (*pr)("\t\t\titem %p, magic 0x%x\n",
        !          1342:                                    pi, pi->pi_magic);
        !          1343:                        }
        !          1344:                }
        !          1345: #endif
        !          1346:        }
        !          1347: }
        !          1348:
        !          1349: void
        !          1350: pool_print1(struct pool *pp, const char *modif, int (*pr)(const char *, ...))
        !          1351: {
        !          1352:        struct pool_item_header *ph;
        !          1353:        struct pool_cache *pc;
        !          1354:        struct pool_cache_group *pcg;
        !          1355:        int i, print_log = 0, print_pagelist = 0, print_cache = 0;
        !          1356:        char c;
        !          1357:
        !          1358:        while ((c = *modif++) != '\0') {
        !          1359:                if (c == 'l')
        !          1360:                        print_log = 1;
        !          1361:                if (c == 'p')
        !          1362:                        print_pagelist = 1;
        !          1363:                if (c == 'c')
        !          1364:                        print_cache = 1;
        !          1365:                modif++;
        !          1366:        }
        !          1367:
        !          1368:        (*pr)("POOL %s: size %u, align %u, ioff %u, roflags 0x%08x\n",
        !          1369:            pp->pr_wchan, pp->pr_size, pp->pr_align, pp->pr_itemoffset,
        !          1370:            pp->pr_roflags);
        !          1371:        (*pr)("\talloc %p\n", pp->pr_alloc);
        !          1372:        (*pr)("\tminitems %u, minpages %u, maxpages %u, npages %u\n",
        !          1373:            pp->pr_minitems, pp->pr_minpages, pp->pr_maxpages, pp->pr_npages);
        !          1374:        (*pr)("\titemsperpage %u, nitems %u, nout %u, hardlimit %u\n",
        !          1375:            pp->pr_itemsperpage, pp->pr_nitems, pp->pr_nout, pp->pr_hardlimit);
        !          1376:
        !          1377:        (*pr)("\n\tnget %lu, nfail %lu, nput %lu\n",
        !          1378:            pp->pr_nget, pp->pr_nfail, pp->pr_nput);
        !          1379:        (*pr)("\tnpagealloc %lu, npagefree %lu, hiwat %u, nidle %lu\n",
        !          1380:            pp->pr_npagealloc, pp->pr_npagefree, pp->pr_hiwat, pp->pr_nidle);
        !          1381:
        !          1382:        if (print_pagelist == 0)
        !          1383:                goto skip_pagelist;
        !          1384:
        !          1385:        if ((ph = LIST_FIRST(&pp->pr_emptypages)) != NULL)
        !          1386:                (*pr)("\n\tempty page list:\n");
        !          1387:        pool_print_pagelist(&pp->pr_emptypages, pr);
        !          1388:        if ((ph = LIST_FIRST(&pp->pr_fullpages)) != NULL)
        !          1389:                (*pr)("\n\tfull page list:\n");
        !          1390:        pool_print_pagelist(&pp->pr_fullpages, pr);
        !          1391:        if ((ph = LIST_FIRST(&pp->pr_partpages)) != NULL)
        !          1392:                (*pr)("\n\tpartial-page list:\n");
        !          1393:        pool_print_pagelist(&pp->pr_partpages, pr);
        !          1394:
        !          1395:        if (pp->pr_curpage == NULL)
        !          1396:                (*pr)("\tno current page\n");
        !          1397:        else
        !          1398:                (*pr)("\tcurpage %p\n", pp->pr_curpage->ph_page);
        !          1399:
        !          1400: skip_pagelist:
        !          1401:        if (print_log == 0)
        !          1402:                goto skip_log;
        !          1403:
        !          1404:        (*pr)("\n");
        !          1405:        if ((pp->pr_roflags & PR_LOGGING) == 0)
        !          1406:                (*pr)("\tno log\n");
        !          1407:        else
        !          1408:                pr_printlog(pp, NULL, pr);
        !          1409:
        !          1410: skip_log:
        !          1411:        if (print_cache == 0)
        !          1412:                goto skip_cache;
        !          1413:
        !          1414:        TAILQ_FOREACH(pc, &pp->pr_cachelist, pc_poollist) {
        !          1415:                (*pr)("\tcache %p: allocfrom %p freeto %p\n", pc,
        !          1416:                    pc->pc_allocfrom, pc->pc_freeto);
        !          1417:                (*pr)("\t    hits %lu misses %lu ngroups %lu nitems %lu\n",
        !          1418:                    pc->pc_hits, pc->pc_misses, pc->pc_ngroups, pc->pc_nitems);
        !          1419:                TAILQ_FOREACH(pcg, &pc->pc_grouplist, pcg_list) {
        !          1420:                        (*pr)("\t\tgroup %p: avail %d\n", pcg, pcg->pcg_avail);
        !          1421:                        for (i = 0; i < PCG_NOBJECTS; i++)
        !          1422:                                (*pr)("\t\t\t%p\n", pcg->pcg_objects[i]);
        !          1423:                }
        !          1424:        }
        !          1425:
        !          1426: skip_cache:
        !          1427:        pr_enter_check(pp, pr);
        !          1428: }
        !          1429:
        !          1430: void
        !          1431: db_show_all_pools(db_expr_t expr, int haddr, db_expr_t count, char *modif)
        !          1432: {
        !          1433:        struct pool *pp;
        !          1434:        char maxp[16];
        !          1435:        int ovflw;
        !          1436:        char mode;
        !          1437:
        !          1438:        mode = modif[0];
        !          1439:        if (mode != '\0' && mode != 'a') {
        !          1440:                db_printf("usage: show all pools [/a]\n");
        !          1441:                return;
        !          1442:        }
        !          1443:
        !          1444:        if (mode == '\0')
        !          1445:                db_printf("%-10s%4s%9s%5s%9s%6s%6s%6s%6s%6s%6s%5s\n",
        !          1446:                    "Name",
        !          1447:                    "Size",
        !          1448:                    "Requests",
        !          1449:                    "Fail",
        !          1450:                    "Releases",
        !          1451:                    "Pgreq",
        !          1452:                    "Pgrel",
        !          1453:                    "Npage",
        !          1454:                    "Hiwat",
        !          1455:                    "Minpg",
        !          1456:                    "Maxpg",
        !          1457:                    "Idle");
        !          1458:        else
        !          1459:                db_printf("%-10s %18s %18s\n",
        !          1460:                    "Name", "Address", "Allocator");
        !          1461:
        !          1462:        TAILQ_FOREACH(pp, &pool_head, pr_poollist) {
        !          1463:                if (mode == 'a') {
        !          1464:                        db_printf("%-10s %18p %18p\n", pp->pr_wchan, pp,
        !          1465:                            pp->pr_alloc);
        !          1466:                        continue;
        !          1467:                }
        !          1468:
        !          1469:                if (!pp->pr_nget)
        !          1470:                        continue;
        !          1471:
        !          1472:                if (pp->pr_maxpages == UINT_MAX)
        !          1473:                        snprintf(maxp, sizeof maxp, "inf");
        !          1474:                else
        !          1475:                        snprintf(maxp, sizeof maxp, "%u", pp->pr_maxpages);
        !          1476:
        !          1477: #define PRWORD(ovflw, fmt, width, fixed, val) do {     \
        !          1478:        (ovflw) += db_printf((fmt),                     \
        !          1479:            (width) - (fixed) - (ovflw) > 0 ?           \
        !          1480:            (width) - (fixed) - (ovflw) : 0,            \
        !          1481:            (val)) - (width);                           \
        !          1482:        if ((ovflw) < 0)                                \
        !          1483:                (ovflw) = 0;                            \
        !          1484: } while (/* CONSTCOND */0)
        !          1485:
        !          1486:                ovflw = 0;
        !          1487:                PRWORD(ovflw, "%-*s", 10, 0, pp->pr_wchan);
        !          1488:                PRWORD(ovflw, " %*u", 4, 1, pp->pr_size);
        !          1489:                PRWORD(ovflw, " %*lu", 9, 1, pp->pr_nget);
        !          1490:                PRWORD(ovflw, " %*lu", 5, 1, pp->pr_nfail);
        !          1491:                PRWORD(ovflw, " %*lu", 9, 1, pp->pr_nput);
        !          1492:                PRWORD(ovflw, " %*lu", 6, 1, pp->pr_npagealloc);
        !          1493:                PRWORD(ovflw, " %*lu", 6, 1, pp->pr_npagefree);
        !          1494:                PRWORD(ovflw, " %*d", 6, 1, pp->pr_npages);
        !          1495:                PRWORD(ovflw, " %*d", 6, 1, pp->pr_hiwat);
        !          1496:                PRWORD(ovflw, " %*d", 6, 1, pp->pr_minpages);
        !          1497:                PRWORD(ovflw, " %*s", 6, 1, maxp);
        !          1498:                PRWORD(ovflw, " %*lu\n", 5, 1, pp->pr_nidle);
        !          1499:        }
        !          1500: }
        !          1501:
        !          1502: int
        !          1503: pool_chk_page(struct pool *pp, const char *label, struct pool_item_header *ph)
        !          1504: {
        !          1505:        struct pool_item *pi;
        !          1506:        caddr_t page;
        !          1507:        int n;
        !          1508:
        !          1509:        page = (caddr_t)((u_long)ph & pp->pr_alloc->pa_pagemask);
        !          1510:        if (page != ph->ph_page &&
        !          1511:            (pp->pr_roflags & PR_PHINPAGE) != 0) {
        !          1512:                if (label != NULL)
        !          1513:                        printf("%s: ", label);
        !          1514:                printf("pool(%p:%s): page inconsistency: page %p;"
        !          1515:                       " at page head addr %p (p %p)\n", pp,
        !          1516:                        pp->pr_wchan, ph->ph_page,
        !          1517:                        ph, page);
        !          1518:                return 1;
        !          1519:        }
        !          1520:
        !          1521:        for (pi = TAILQ_FIRST(&ph->ph_itemlist), n = 0;
        !          1522:             pi != NULL;
        !          1523:             pi = TAILQ_NEXT(pi,pi_list), n++) {
        !          1524:
        !          1525: #ifdef DIAGNOSTIC
        !          1526:                if (pi->pi_magic != PI_MAGIC) {
        !          1527:                        if (label != NULL)
        !          1528:                                printf("%s: ", label);
        !          1529:                        printf("pool(%s): free list modified: magic=%x;"
        !          1530:                               " page %p; item ordinal %d;"
        !          1531:                               " addr %p (p %p)\n",
        !          1532:                                pp->pr_wchan, pi->pi_magic, ph->ph_page,
        !          1533:                                n, pi, page);
        !          1534:                        panic("pool");
        !          1535:                }
        !          1536: #endif
        !          1537:                page =
        !          1538:                    (caddr_t)((u_long)pi & pp->pr_alloc->pa_pagemask);
        !          1539:                if (page == ph->ph_page)
        !          1540:                        continue;
        !          1541:
        !          1542:                if (label != NULL)
        !          1543:                        printf("%s: ", label);
        !          1544:                printf("pool(%p:%s): page inconsistency: page %p;"
        !          1545:                       " item ordinal %d; addr %p (p %p)\n", pp,
        !          1546:                        pp->pr_wchan, ph->ph_page,
        !          1547:                        n, pi, page);
        !          1548:                return 1;
        !          1549:        }
        !          1550:        return 0;
        !          1551: }
        !          1552:
        !          1553: int
        !          1554: pool_chk(struct pool *pp, const char *label)
        !          1555: {
        !          1556:        struct pool_item_header *ph;
        !          1557:        int r = 0;
        !          1558:
        !          1559:        simple_lock(&pp->pr_slock);
        !          1560:        LIST_FOREACH(ph, &pp->pr_emptypages, ph_pagelist) {
        !          1561:                r = pool_chk_page(pp, label, ph);
        !          1562:                if (r) {
        !          1563:                        goto out;
        !          1564:                }
        !          1565:        }
        !          1566:        LIST_FOREACH(ph, &pp->pr_fullpages, ph_pagelist) {
        !          1567:                r = pool_chk_page(pp, label, ph);
        !          1568:                if (r) {
        !          1569:                        goto out;
        !          1570:                }
        !          1571:        }
        !          1572:        LIST_FOREACH(ph, &pp->pr_partpages, ph_pagelist) {
        !          1573:                r = pool_chk_page(pp, label, ph);
        !          1574:                if (r) {
        !          1575:                        goto out;
        !          1576:                }
        !          1577:        }
        !          1578:
        !          1579: out:
        !          1580:        simple_unlock(&pp->pr_slock);
        !          1581:        return (r);
        !          1582: }
        !          1583: #endif
        !          1584:
        !          1585: /*
        !          1586:  * pool_cache_init:
        !          1587:  *
        !          1588:  *     Initialize a pool cache.
        !          1589:  *
        !          1590:  *     NOTE: If the pool must be protected from interrupts, we expect
        !          1591:  *     to be called at the appropriate interrupt priority level.
        !          1592:  */
        !          1593: void
        !          1594: pool_cache_init(struct pool_cache *pc, struct pool *pp,
        !          1595:     int (*ctor)(void *, void *, int),
        !          1596:     void (*dtor)(void *, void *),
        !          1597:     void *arg)
        !          1598: {
        !          1599:
        !          1600:        TAILQ_INIT(&pc->pc_grouplist);
        !          1601:        simple_lock_init(&pc->pc_slock);
        !          1602:
        !          1603:        pc->pc_allocfrom = NULL;
        !          1604:        pc->pc_freeto = NULL;
        !          1605:        pc->pc_pool = pp;
        !          1606:
        !          1607:        pc->pc_ctor = ctor;
        !          1608:        pc->pc_dtor = dtor;
        !          1609:        pc->pc_arg  = arg;
        !          1610:
        !          1611:        pc->pc_hits   = 0;
        !          1612:        pc->pc_misses = 0;
        !          1613:
        !          1614:        pc->pc_ngroups = 0;
        !          1615:
        !          1616:        pc->pc_nitems = 0;
        !          1617:
        !          1618:        simple_lock(&pp->pr_slock);
        !          1619:        TAILQ_INSERT_TAIL(&pp->pr_cachelist, pc, pc_poollist);
        !          1620:        simple_unlock(&pp->pr_slock);
        !          1621: }
        !          1622:
        !          1623: /*
        !          1624:  * pool_cache_destroy:
        !          1625:  *
        !          1626:  *     Destroy a pool cache.
        !          1627:  */
        !          1628: void
        !          1629: pool_cache_destroy(struct pool_cache *pc)
        !          1630: {
        !          1631:        struct pool *pp = pc->pc_pool;
        !          1632:
        !          1633:        /* First, invalidate the entire cache. */
        !          1634:        pool_cache_invalidate(pc);
        !          1635:
        !          1636:        /* ...and remove it from the pool's cache list. */
        !          1637:        simple_lock(&pp->pr_slock);
        !          1638:        TAILQ_REMOVE(&pp->pr_cachelist, pc, pc_poollist);
        !          1639:        simple_unlock(&pp->pr_slock);
        !          1640: }
        !          1641:
        !          1642: static __inline void *
        !          1643: pcg_get(struct pool_cache_group *pcg)
        !          1644: {
        !          1645:        void *object;
        !          1646:        u_int idx;
        !          1647:
        !          1648:        KASSERT(pcg->pcg_avail <= PCG_NOBJECTS);
        !          1649:        KASSERT(pcg->pcg_avail != 0);
        !          1650:        idx = --pcg->pcg_avail;
        !          1651:
        !          1652:        KASSERT(pcg->pcg_objects[idx] != NULL);
        !          1653:        object = pcg->pcg_objects[idx];
        !          1654:        pcg->pcg_objects[idx] = NULL;
        !          1655:
        !          1656:        return (object);
        !          1657: }
        !          1658:
        !          1659: static __inline void
        !          1660: pcg_put(struct pool_cache_group *pcg, void *object)
        !          1661: {
        !          1662:        u_int idx;
        !          1663:
        !          1664:        KASSERT(pcg->pcg_avail < PCG_NOBJECTS);
        !          1665:        idx = pcg->pcg_avail++;
        !          1666:
        !          1667:        KASSERT(pcg->pcg_objects[idx] == NULL);
        !          1668:        pcg->pcg_objects[idx] = object;
        !          1669: }
        !          1670:
        !          1671: /*
        !          1672:  * pool_cache_get:
        !          1673:  *
        !          1674:  *     Get an object from a pool cache.
        !          1675:  */
        !          1676: void *
        !          1677: pool_cache_get(struct pool_cache *pc, int flags)
        !          1678: {
        !          1679:        struct pool_cache_group *pcg;
        !          1680:        void *object;
        !          1681:
        !          1682: #ifdef LOCKDEBUG
        !          1683:        if (flags & PR_WAITOK)
        !          1684:                simple_lock_only_held(NULL, "pool_cache_get(PR_WAITOK)");
        !          1685: #endif
        !          1686:
        !          1687:        simple_lock(&pc->pc_slock);
        !          1688:
        !          1689:        if ((pcg = pc->pc_allocfrom) == NULL) {
        !          1690:                TAILQ_FOREACH(pcg, &pc->pc_grouplist, pcg_list) {
        !          1691:                        if (pcg->pcg_avail != 0) {
        !          1692:                                pc->pc_allocfrom = pcg;
        !          1693:                                goto have_group;
        !          1694:                        }
        !          1695:                }
        !          1696:
        !          1697:                /*
        !          1698:                 * No groups with any available objects.  Allocate
        !          1699:                 * a new object, construct it, and return it to
        !          1700:                 * the caller.  We will allocate a group, if necessary,
        !          1701:                 * when the object is freed back to the cache.
        !          1702:                 */
        !          1703:                pc->pc_misses++;
        !          1704:                simple_unlock(&pc->pc_slock);
        !          1705:                object = pool_get(pc->pc_pool, flags);
        !          1706:                if (object != NULL && pc->pc_ctor != NULL) {
        !          1707:                        if ((*pc->pc_ctor)(pc->pc_arg, object, flags) != 0) {
        !          1708:                                pool_put(pc->pc_pool, object);
        !          1709:                                return (NULL);
        !          1710:                        }
        !          1711:                }
        !          1712:                return (object);
        !          1713:        }
        !          1714:
        !          1715:  have_group:
        !          1716:        pc->pc_hits++;
        !          1717:        pc->pc_nitems--;
        !          1718:        object = pcg_get(pcg);
        !          1719:
        !          1720:        if (pcg->pcg_avail == 0)
        !          1721:                pc->pc_allocfrom = NULL;
        !          1722:
        !          1723:        simple_unlock(&pc->pc_slock);
        !          1724:
        !          1725:        return (object);
        !          1726: }
        !          1727:
        !          1728: /*
        !          1729:  * pool_cache_put:
        !          1730:  *
        !          1731:  *     Put an object back to the pool cache.
        !          1732:  */
        !          1733: void
        !          1734: pool_cache_put(struct pool_cache *pc, void *object)
        !          1735: {
        !          1736:        struct pool_cache_group *pcg;
        !          1737:        int s;
        !          1738:
        !          1739:        simple_lock(&pc->pc_slock);
        !          1740:
        !          1741:        if ((pcg = pc->pc_freeto) == NULL) {
        !          1742:                TAILQ_FOREACH(pcg, &pc->pc_grouplist, pcg_list) {
        !          1743:                        if (pcg->pcg_avail != PCG_NOBJECTS) {
        !          1744:                                pc->pc_freeto = pcg;
        !          1745:                                goto have_group;
        !          1746:                        }
        !          1747:                }
        !          1748:
        !          1749:                /*
        !          1750:                 * No empty groups to free the object to.  Attempt to
        !          1751:                 * allocate one.
        !          1752:                 */
        !          1753:                simple_unlock(&pc->pc_slock);
        !          1754:                s = splvm();
        !          1755:                pcg = pool_get(&pcgpool, PR_NOWAIT);
        !          1756:                splx(s);
        !          1757:                if (pcg != NULL) {
        !          1758:                        memset(pcg, 0, sizeof(*pcg));
        !          1759:                        simple_lock(&pc->pc_slock);
        !          1760:                        pc->pc_ngroups++;
        !          1761:                        TAILQ_INSERT_TAIL(&pc->pc_grouplist, pcg, pcg_list);
        !          1762:                        if (pc->pc_freeto == NULL)
        !          1763:                                pc->pc_freeto = pcg;
        !          1764:                        goto have_group;
        !          1765:                }
        !          1766:
        !          1767:                /*
        !          1768:                 * Unable to allocate a cache group; destruct the object
        !          1769:                 * and free it back to the pool.
        !          1770:                 */
        !          1771:                pool_cache_destruct_object(pc, object);
        !          1772:                return;
        !          1773:        }
        !          1774:
        !          1775:  have_group:
        !          1776:        pc->pc_nitems++;
        !          1777:        pcg_put(pcg, object);
        !          1778:
        !          1779:        if (pcg->pcg_avail == PCG_NOBJECTS)
        !          1780:                pc->pc_freeto = NULL;
        !          1781:
        !          1782:        simple_unlock(&pc->pc_slock);
        !          1783: }
        !          1784:
        !          1785: /*
        !          1786:  * pool_cache_destruct_object:
        !          1787:  *
        !          1788:  *     Force destruction of an object and its release back into
        !          1789:  *     the pool.
        !          1790:  */
        !          1791: void
        !          1792: pool_cache_destruct_object(struct pool_cache *pc, void *object)
        !          1793: {
        !          1794:
        !          1795:        if (pc->pc_dtor != NULL)
        !          1796:                (*pc->pc_dtor)(pc->pc_arg, object);
        !          1797:        pool_put(pc->pc_pool, object);
        !          1798: }
        !          1799:
        !          1800: /*
        !          1801:  * pool_cache_do_invalidate:
        !          1802:  *
        !          1803:  *     This internal function implements pool_cache_invalidate() and
        !          1804:  *     pool_cache_reclaim().
        !          1805:  */
        !          1806: void
        !          1807: pool_cache_do_invalidate(struct pool_cache *pc, int free_groups,
        !          1808:     void (*putit)(struct pool *, void *))
        !          1809: {
        !          1810:        struct pool_cache_group *pcg, *npcg;
        !          1811:        void *object;
        !          1812:        int s;
        !          1813:
        !          1814:        for (pcg = TAILQ_FIRST(&pc->pc_grouplist); pcg != NULL;
        !          1815:             pcg = npcg) {
        !          1816:                npcg = TAILQ_NEXT(pcg, pcg_list);
        !          1817:                while (pcg->pcg_avail != 0) {
        !          1818:                        pc->pc_nitems--;
        !          1819:                        object = pcg_get(pcg);
        !          1820:                        if (pcg->pcg_avail == 0 && pc->pc_allocfrom == pcg)
        !          1821:                                pc->pc_allocfrom = NULL;
        !          1822:                        if (pc->pc_dtor != NULL)
        !          1823:                                (*pc->pc_dtor)(pc->pc_arg, object);
        !          1824:                        (*putit)(pc->pc_pool, object);
        !          1825:                }
        !          1826:                if (free_groups) {
        !          1827:                        pc->pc_ngroups--;
        !          1828:                        TAILQ_REMOVE(&pc->pc_grouplist, pcg, pcg_list);
        !          1829:                        if (pc->pc_freeto == pcg)
        !          1830:                                pc->pc_freeto = NULL;
        !          1831:                        s = splvm();
        !          1832:                        pool_put(&pcgpool, pcg);
        !          1833:                        splx(s);
        !          1834:                }
        !          1835:        }
        !          1836: }
        !          1837:
        !          1838: /*
        !          1839:  * pool_cache_invalidate:
        !          1840:  *
        !          1841:  *     Invalidate a pool cache (destruct and release all of the
        !          1842:  *     cached objects).
        !          1843:  */
        !          1844: void
        !          1845: pool_cache_invalidate(struct pool_cache *pc)
        !          1846: {
        !          1847:
        !          1848:        simple_lock(&pc->pc_slock);
        !          1849:        pool_cache_do_invalidate(pc, 0, pool_put);
        !          1850:        simple_unlock(&pc->pc_slock);
        !          1851: }
        !          1852:
        !          1853: /*
        !          1854:  * pool_cache_reclaim:
        !          1855:  *
        !          1856:  *     Reclaim a pool cache for pool_reclaim().
        !          1857:  */
        !          1858: void
        !          1859: pool_cache_reclaim(struct pool_cache *pc)
        !          1860: {
        !          1861:
        !          1862:        simple_lock(&pc->pc_slock);
        !          1863:        pool_cache_do_invalidate(pc, 1, pool_do_put);
        !          1864:        simple_unlock(&pc->pc_slock);
        !          1865: }
        !          1866:
        !          1867: /*
        !          1868:  * We have three different sysctls.
        !          1869:  * kern.pool.npools - the number of pools.
        !          1870:  * kern.pool.pool.<pool#> - the pool struct for the pool#.
        !          1871:  * kern.pool.name.<pool#> - the name for pool#.
        !          1872:  */
        !          1873: int
        !          1874: sysctl_dopool(int *name, u_int namelen, char *where, size_t *sizep)
        !          1875: {
        !          1876:        struct pool *pp, *foundpool = NULL;
        !          1877:        size_t buflen = where != NULL ? *sizep : 0;
        !          1878:        int npools = 0, s;
        !          1879:        unsigned int lookfor;
        !          1880:        size_t len;
        !          1881:
        !          1882:        switch (*name) {
        !          1883:        case KERN_POOL_NPOOLS:
        !          1884:                if (namelen != 1 || buflen != sizeof(int))
        !          1885:                        return (EINVAL);
        !          1886:                lookfor = 0;
        !          1887:                break;
        !          1888:        case KERN_POOL_NAME:
        !          1889:                if (namelen != 2 || buflen < 1)
        !          1890:                        return (EINVAL);
        !          1891:                lookfor = name[1];
        !          1892:                break;
        !          1893:        case KERN_POOL_POOL:
        !          1894:                if (namelen != 2 || buflen != sizeof(struct pool))
        !          1895:                        return (EINVAL);
        !          1896:                lookfor = name[1];
        !          1897:                break;
        !          1898:        default:
        !          1899:                return (EINVAL);
        !          1900:        }
        !          1901:
        !          1902:        s = splvm();
        !          1903:        simple_lock(&pool_head_slock);
        !          1904:
        !          1905:        TAILQ_FOREACH(pp, &pool_head, pr_poollist) {
        !          1906:                npools++;
        !          1907:                if (lookfor == pp->pr_serial) {
        !          1908:                        foundpool = pp;
        !          1909:                        break;
        !          1910:                }
        !          1911:        }
        !          1912:
        !          1913:        simple_unlock(&pool_head_slock);
        !          1914:        splx(s);
        !          1915:
        !          1916:        if (*name != KERN_POOL_NPOOLS && foundpool == NULL)
        !          1917:                return (ENOENT);
        !          1918:
        !          1919:        switch (*name) {
        !          1920:        case KERN_POOL_NPOOLS:
        !          1921:                return copyout(&npools, where, buflen);
        !          1922:        case KERN_POOL_NAME:
        !          1923:                len = strlen(foundpool->pr_wchan) + 1;
        !          1924:                if (*sizep < len)
        !          1925:                        return (ENOMEM);
        !          1926:                *sizep = len;
        !          1927:                return copyout(foundpool->pr_wchan, where, len);
        !          1928:        case KERN_POOL_POOL:
        !          1929:                return copyout(foundpool, where, buflen);
        !          1930:        }
        !          1931:        /* NOTREACHED */
        !          1932:        return (0); /* XXX - Stupid gcc */
        !          1933: }
        !          1934:
        !          1935: /*
        !          1936:  * Pool backend allocators.
        !          1937:  *
        !          1938:  * Each pool has a backend allocator that handles allocation, deallocation
        !          1939:  */
        !          1940: void   *pool_page_alloc_oldnointr(struct pool *, int);
        !          1941: void   pool_page_free_oldnointr(struct pool *, void *);
        !          1942: void   *pool_page_alloc(struct pool *, int);
        !          1943: void   pool_page_free(struct pool *, void *);
        !          1944:
        !          1945: /* previous nointr.  handles large allocations safely */
        !          1946: struct pool_allocator pool_allocator_oldnointr = {
        !          1947:        pool_page_alloc_oldnointr, pool_page_free_oldnointr, 0,
        !          1948: };
        !          1949: /* safe for interrupts, name preserved for compat
        !          1950:  * this is the default allocator */
        !          1951: struct pool_allocator pool_allocator_nointr = {
        !          1952:        pool_page_alloc, pool_page_free, 0,
        !          1953: };
        !          1954:
        !          1955: /*
        !          1956:  * XXX - we have at least three different resources for the same allocation
        !          1957:  *  and each resource can be depleted. First we have the ready elements in
        !          1958:  *  the pool. Then we have the resource (typically a vm_map) for this
        !          1959:  *  allocator, then we have physical memory. Waiting for any of these can
        !          1960:  *  be unnecessary when any other is freed, but the kernel doesn't support
        !          1961:  *  sleeping on multiple addresses, so we have to fake. The caller sleeps on
        !          1962:  *  the pool (so that we can be awakened when an item is returned to the pool),
        !          1963:  *  but we set PA_WANT on the allocator. When a page is returned to
        !          1964:  *  the allocator and PA_WANT is set pool_allocator_free will wakeup all
        !          1965:  *  sleeping pools belonging to this allocator. (XXX - thundering herd).
        !          1966:  *  We also wake up the allocator in case someone without a pool (malloc)
        !          1967:  *  is sleeping waiting for this allocator.
        !          1968:  */
        !          1969:
        !          1970: void *
        !          1971: pool_allocator_alloc(struct pool *pp, int flags)
        !          1972: {
        !          1973:
        !          1974:        return (pp->pr_alloc->pa_alloc(pp, flags));
        !          1975: }
        !          1976:
        !          1977: void
        !          1978: pool_allocator_free(struct pool *pp, void *v)
        !          1979: {
        !          1980:        struct pool_allocator *pa = pp->pr_alloc;
        !          1981:        int s;
        !          1982:
        !          1983:        (*pa->pa_free)(pp, v);
        !          1984:
        !          1985:        s = splvm();
        !          1986:        simple_lock(&pa->pa_slock);
        !          1987:        if ((pa->pa_flags & PA_WANT) == 0) {
        !          1988:                simple_unlock(&pa->pa_slock);
        !          1989:                splx(s);
        !          1990:                return;
        !          1991:        }
        !          1992:
        !          1993:        TAILQ_FOREACH(pp, &pa->pa_list, pr_alloc_list) {
        !          1994:                simple_lock(&pp->pr_slock);
        !          1995:                if ((pp->pr_flags & PR_WANTED) != 0) {
        !          1996:                        pp->pr_flags &= ~PR_WANTED;
        !          1997:                        wakeup(pp);
        !          1998:                }
        !          1999:                simple_unlock(&pp->pr_slock);
        !          2000:        }
        !          2001:        pa->pa_flags &= ~PA_WANT;
        !          2002:        simple_unlock(&pa->pa_slock);
        !          2003:        splx(s);
        !          2004: }
        !          2005:
        !          2006: void *
        !          2007: pool_page_alloc(struct pool *pp, int flags)
        !          2008: {
        !          2009:        boolean_t waitok = (flags & PR_WAITOK) ? TRUE : FALSE;
        !          2010:
        !          2011:        return (uvm_km_getpage(waitok));
        !          2012: }
        !          2013:
        !          2014: void
        !          2015: pool_page_free(struct pool *pp, void *v)
        !          2016: {
        !          2017:
        !          2018:        uvm_km_putpage(v);
        !          2019: }
        !          2020:
        !          2021: void *
        !          2022: pool_page_alloc_oldnointr(struct pool *pp, int flags)
        !          2023: {
        !          2024:        boolean_t waitok = (flags & PR_WAITOK) ? TRUE : FALSE;
        !          2025:
        !          2026:        splassert(IPL_NONE);
        !          2027:
        !          2028:        return ((void *)uvm_km_alloc_poolpage1(kernel_map, uvm.kernel_object,
        !          2029:            waitok));
        !          2030: }
        !          2031:
        !          2032: void
        !          2033: pool_page_free_oldnointr(struct pool *pp, void *v)
        !          2034: {
        !          2035:        splassert(IPL_NONE);
        !          2036:
        !          2037:        uvm_km_free_poolpage1(kernel_map, (vaddr_t)v);
        !          2038: }

CVSweb