#ifndef _SYS_POOL_H_
#define _SYS_POOL_H_
#include <sys/stdbool.h>
#include <sys/stdint.h>
struct pool_sysctl {
char pr_wchan[16];
uint64_t pr_flags;
uint64_t pr_size;
uint64_t pr_pagesize;
uint64_t pr_itemsperpage;
uint64_t pr_nitems;
uint64_t pr_nout;
uint64_t pr_hardlimit;
uint64_t pr_npages;
uint64_t pr_minpages;
uint64_t pr_maxpages;
uint64_t pr_nget;
uint64_t pr_nfail;
uint64_t pr_nput;
uint64_t pr_npagealloc;
uint64_t pr_npagefree;
uint64_t pr_hiwat;
uint64_t pr_nidle;
uint64_t pr_cache_meta_size;
uint64_t pr_cache_nfull;
uint64_t pr_cache_npartial;
uint64_t pr_cache_nempty;
uint64_t pr_cache_ncontended;
uint64_t pr_cache_nmiss_global;
uint64_t pr_cache_nhit_global;
uint64_t pr_cache_nmiss_pcpu;
uint64_t pr_cache_nhit_pcpu;
};
#ifdef _KERNEL
#define __POOL_EXPOSE
#endif
#ifdef __POOL_EXPOSE
#include <sys/param.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/queue.h>
#include <sys/time.h>
#include <sys/tree.h>
#include <sys/callback.h>
#ifdef _KERNEL_OPT
#include "opt_pool.h"
#endif
#define POOL_PADDR_INVALID ((paddr_t) -1)
struct pool;
struct pool_allocator {
void *(*pa_alloc)(struct pool *, int);
void (*pa_free)(struct pool *, void *);
unsigned int pa_pagesz;
kmutex_t pa_lock;
TAILQ_HEAD(, pool) pa_list;
uint32_t pa_refcnt;
int pa_pagemask;
int pa_pageshift;
};
LIST_HEAD(pool_pagelist,pool_item_header);
SPLAY_HEAD(phtree, pool_item_header);
#define POOL_QUARANTINE_DEPTH 128
typedef struct {
size_t rotor;
intptr_t list[POOL_QUARANTINE_DEPTH];
} pool_quar_t;
struct pool {
TAILQ_ENTRY(pool)
pr_poollist;
struct pool_pagelist
pr_emptypages;
struct pool_pagelist
pr_fullpages;
struct pool_pagelist
pr_partpages;
struct pool_item_header *pr_curpage;
struct pool *pr_phpool;
struct pool_cache *pr_cache;
unsigned int pr_size;
unsigned int pr_align;
unsigned int pr_itemoffset;
unsigned int pr_minitems;
unsigned int pr_maxitems;
unsigned int pr_minpages;
unsigned int pr_maxpages;
unsigned int pr_npages;
unsigned int pr_itemsperpage;
unsigned int pr_poolid;
unsigned int pr_nitems;
unsigned int pr_nout;
unsigned int pr_hardlimit;
unsigned int pr_refcnt;
struct pool_allocator *pr_alloc;
TAILQ_ENTRY(pool) pr_alloc_list;
void (*pr_drain_hook)(void *, int);
void *pr_drain_hook_arg;
const char *pr_wchan;
unsigned int pr_flags;
unsigned int pr_roflags;
#define PR_WAITOK 0x01
#define PR_NOWAIT 0x02
#define PR_WANTED 0x04
#define PR_PHINPAGE 0x40
#define PR_LIMITFAIL 0x100
#define PR_RECURSIVE 0x200
#define PR_NOTOUCH 0x400
#define PR_NOALIGN 0x800
#define PR_LARGECACHE 0x1000
#define PR_GROWING 0x2000
#define PR_GROWINGNOWAIT 0x4000
#define PR_ZERO 0x8000
#define PR_USEBMAP 0x10000
#define PR_PSERIALIZE 0x20000
kmutex_t pr_lock;
kcondvar_t pr_cv;
int pr_ipl;
struct phtree pr_phtree;
int pr_maxcolor;
int pr_curcolor;
int pr_phoffset;
const char *pr_hardlimit_warning;
struct timeval pr_hardlimit_ratecap;
struct timeval pr_hardlimit_warning_last;
unsigned long pr_nget;
unsigned long pr_nfail;
unsigned long pr_nput;
unsigned long pr_npagealloc;
unsigned long pr_npagefree;
unsigned int pr_hiwat;
unsigned long pr_nidle;
void *pr_freecheck;
void *pr_qcache;
bool pr_redzone;
size_t pr_reqsize;
size_t pr_reqsize_with_redzone;
#ifdef POOL_QUARANTINE
pool_quar_t pr_quar;
#endif
};
#ifdef _LP64
#define PCG_NOBJECTS_NORMAL 15
#define PCG_NOBJECTS_LARGE 63
#else
#define PCG_NOBJECTS_NORMAL 14
#define PCG_NOBJECTS_LARGE 62
#endif
typedef struct pcgpair {
void *pcgo_va;
paddr_t pcgo_pa;
} pcgpair_t;
typedef struct pool_cache_group {
struct pool_cache_group *pcg_next;
u_int pcg_avail;
u_int pcg_size;
pcgpair_t pcg_objects[1];
} pcg_t;
typedef struct pool_cache_cpu {
struct pool_cache_group *cc_current;
struct pool_cache_group *cc_previous;
pcg_t *volatile *cc_pcgcache;
uint64_t cc_misses;
uint64_t cc_hits;
uint64_t cc_pcmisses;
uint64_t cc_contended;
uint32_t cc_nfull;
uint32_t cc_npart;
} pool_cache_cpu_t;
struct pool_cache {
struct pool pc_pool;
TAILQ_ENTRY(pool_cache)
pc_cachelist;
struct pool *pc_pcgpool;
pcg_t *volatile *pc_pcgcache;
int pc_pcgsize;
int pc_ncpu;
int (*pc_ctor)(void *, void *, int);
void (*pc_dtor)(void *, void *);
void *pc_arg;
unsigned int pc_refcnt;
unsigned int pc_roflags;
void *pc_cpus[MAXCPUS];
void *pc_freecheck;
bool pc_redzone;
size_t pc_reqsize;
pcg_t *volatile pc_fullgroups
__aligned(CACHE_LINE_SIZE);
pcg_t *volatile pc_partgroups;
pool_cache_cpu_t pc_cpu0 __aligned(CACHE_LINE_SIZE);
};
#endif
typedef struct pool_cache *pool_cache_t;
#ifdef _KERNEL
extern struct pool_allocator pool_allocator_kmem;
extern struct pool_allocator pool_allocator_nointr;
extern struct pool_allocator pool_allocator_meta;
void pool_subsystem_init(void);
void pool_init(struct pool *, size_t, u_int, u_int,
int, const char *, struct pool_allocator *, int);
void pool_destroy(struct pool *);
void pool_set_drain_hook(struct pool *,
void (*)(void *, int), void *);
void *pool_get(struct pool *, int);
void pool_put(struct pool *, void *);
int pool_reclaim(struct pool *);
void pool_prime(struct pool *, int);
void pool_setlowat(struct pool *, int);
void pool_sethiwat(struct pool *, int);
void pool_sethardlimit(struct pool *, int, const char *, int);
bool pool_drain(struct pool **);
int pool_totalpages(void);
int pool_totalpages_locked(void);
unsigned int pool_nget(struct pool *);
unsigned int pool_nput(struct pool *);
void pool_printit(struct pool *, const char *,
void (*)(const char *, ...) __printflike(1, 2));
void pool_printall(const char *, void (*)(const char *, ...)
__printflike(1, 2));
int pool_chk(struct pool *, const char *);
pool_cache_t pool_cache_init(size_t, u_int, u_int, u_int, const char *,
struct pool_allocator *, int, int (*)(void *, void *, int),
void (*)(void *, void *), void *);
void pool_cache_bootstrap(pool_cache_t, size_t, u_int, u_int, u_int,
const char *, struct pool_allocator *, int,
int (*)(void *, void *, int), void (*)(void *, void *),
void *);
void pool_cache_destroy(pool_cache_t);
void pool_cache_bootstrap_destroy(pool_cache_t);
void *pool_cache_get_paddr(pool_cache_t, int, paddr_t *);
void pool_cache_put_paddr(pool_cache_t, void *, paddr_t);
void pool_cache_destruct_object(pool_cache_t, void *);
void pool_cache_invalidate(pool_cache_t);
bool pool_cache_reclaim(pool_cache_t);
void pool_cache_set_drain_hook(pool_cache_t,
void (*)(void *, int), void *);
void pool_cache_setlowat(pool_cache_t, int);
void pool_cache_sethiwat(pool_cache_t, int);
void pool_cache_sethardlimit(pool_cache_t, int, const char *, int);
void pool_cache_prime(pool_cache_t, int);
void pool_cache_cpu_init(struct cpu_info *);
unsigned int pool_cache_nget(pool_cache_t);
unsigned int pool_cache_nput(pool_cache_t);
#define pool_cache_get(pc, f) pool_cache_get_paddr((pc), (f), NULL)
#define pool_cache_put(pc, o) pool_cache_put_paddr((pc), (o), \
POOL_PADDR_INVALID)
void pool_whatis(uintptr_t, void (*)(const char *, ...)
__printflike(1, 2));
#endif
#endif