1 /*        $NetBSD: vmem_impl.h,v 1.8 2023/12/03 19:34:08 thorpej Exp $          */
2 
3 /*-
4  * Copyright (c)2006 YAMAMOTO Takashi,
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 /*
30  * Data structures private to vmem.
31  */
32 
33 #ifndef _SYS_VMEM_IMPL_H_
34 #define   _SYS_VMEM_IMPL_H_
35 
36 #include <sys/types.h>
37 
38 #if defined(_KERNEL)
39 #define   QCACHE
40 #include <sys/pool.h>
41 #include <sys/vmem.h>
42 
43 #define   LOCK_DECL(name)               \
44     kmutex_t name; char lockpad[COHERENCY_UNIT - sizeof(kmutex_t)]
45 
46 #define CONDVAR_DECL(name)    \
47     kcondvar_t name
48 
49 #else /* defined(_KERNEL) */
50 #include <stdio.h>
51 #include <errno.h>
52 #include <assert.h>
53 #include <stdlib.h>
54 #include <string.h>
55 
56 #include "vmem.h"
57 
58 #define   LOCK_DECL(name)               /* nothing */
59 #define   CONDVAR_DECL(name)  /* nothing */
60 #endif /* defined(_KERNEL) */
61 
62 #define   VMEM_MAXORDER                 (sizeof(vmem_size_t) * CHAR_BIT)
63 
64 typedef struct vmem_btag bt_t;
65 
66 TAILQ_HEAD(vmem_seglist, vmem_btag);
67 LIST_HEAD(vmem_freelist, vmem_btag);
68 LIST_HEAD(vmem_hashlist, vmem_btag);
69 
70 #if defined(QCACHE)
71 #define   VMEM_QCACHE_IDX_MAX 16
72 
73 #define   QC_NAME_MAX         16
74 
75 struct qcache {
76           pool_cache_t qc_cache;
77           vmem_t *qc_vmem;
78           char qc_name[QC_NAME_MAX];
79 };
80 typedef struct qcache qcache_t;
81 #define   QC_POOL_TO_QCACHE(pool)       ((qcache_t *)(pool->pr_qcache))
82 #endif /* defined(QCACHE) */
83 
84 #define   VMEM_NAME_MAX       16
85 
86 /* vmem arena */
87 struct vmem {
88           CONDVAR_DECL(vm_cv);
89           LOCK_DECL(vm_lock);
90           vm_flag_t vm_flags;
91           vmem_import_t *vm_importfn;
92           vmem_release_t *vm_releasefn;
93           size_t vm_nfreetags;
94           LIST_HEAD(, vmem_btag) vm_freetags;
95           void *vm_arg;
96           struct vmem_seglist vm_seglist;
97           struct vmem_freelist vm_freelist[VMEM_MAXORDER];
98           size_t vm_hashsize;
99           size_t vm_hashmask;
100           size_t vm_nbusytag;
101           size_t vm_maxbusytag;
102           struct vmem_hashlist *vm_hashlist;
103           struct vmem_hashlist vm_hash0;
104           size_t vm_quantum_mask;
105           int vm_quantum_shift;
106           size_t vm_size;
107           size_t vm_inuse;
108           char vm_name[VMEM_NAME_MAX+1];
109           LIST_ENTRY(vmem) vm_alllist;
110 
111 #if defined(QCACHE)
112           /* quantum cache */
113           size_t vm_qcache_max;
114           struct pool_allocator vm_qcache_allocator;
115           qcache_t vm_qcache_store[VMEM_QCACHE_IDX_MAX];
116           qcache_t *vm_qcache[VMEM_QCACHE_IDX_MAX];
117 #endif /* defined(QCACHE) */
118 };
119 
120 /* boundary tag */
121 struct vmem_btag {
122           TAILQ_ENTRY(vmem_btag) bt_seglist;
123           union {
124                     LIST_ENTRY(vmem_btag) u_freelist; /* BT_TYPE_FREE */
125                     LIST_ENTRY(vmem_btag) u_hashlist; /* BT_TYPE_BUSY */
126           } bt_u;
127 #define   bt_hashlist         bt_u.u_hashlist
128 #define   bt_freelist         bt_u.u_freelist
129           vmem_addr_t bt_start;
130           vmem_size_t bt_size;
131           short bt_type;
132           short bt_flags;
133 };
134 
135 #define   BT_TYPE_SPAN                  1
136 #define   BT_TYPE_SPAN_STATIC 2
137 #define   BT_TYPE_FREE                  3
138 #define   BT_TYPE_BUSY                  4
139 #define   BT_ISSPAN_P(bt)     ((bt)->bt_type <= BT_TYPE_SPAN_STATIC)
140 
141 #define   BT_F_PRIVATE                  0x0001
142 
143 #define   BT_END(bt)          ((bt)->bt_start + (bt)->bt_size - 1)
144 
145 /*
146  * Provide an estimated number of boundary tags needed for a given
147  * number of allocations from the vmem arena.  This estimate is
148  * based on 2 boundary tags per allocation (see vmem_xalloc()) and
149  * 2 boundary tags per added span (one to describe the span, one to
150  * describe the span's free space; see vmem_add1()).
151  */
152 #define   VMEM_EST_BTCOUNT(ns, na)      (((ns) * 2) + ((na) * 2))
153 
154 vmem_t *  vmem_init(vmem_t *, const char *, vmem_addr_t, vmem_size_t,
155                         vmem_size_t, vmem_import_t *, vmem_release_t *, vmem_t *,
156                         vmem_size_t, vm_flag_t, int);
157 void                vmem_add_bts(vmem_t *, struct vmem_btag *, unsigned int);
158 
159 #endif /* !_SYS_VMEM_IMPL_H_ */
160