xref: /netbsd-src/external/cddl/osnet/sys/kern/kmem.c (revision cef8759bd76c1b621f8eab8faa6f208faabc2e15)
1 /*	$NetBSD: kmem.c,v 1.2 2019/05/23 08:32:30 hannken Exp $	*/
2 
3 /*-
4  * Copyright (c) 2017 The NetBSD Foundation, Inc.
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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/kmem.h>
30 
31 struct kmem_cache {
32 	pool_cache_t km_pool;
33 	void *km_private;
34 	int (*km_constructor)(void *, void *, int);
35 	void (*km_destructor)(void *, void *);
36 	void (*km_reclaim)(void *);
37 };
38 
39 static int
40 solaris_constructor(void *private, void *object, int flag)
41 {
42 	kmem_cache_t *km = private;
43 
44 	if (km->km_constructor)
45 		return (*km->km_constructor)(object, km->km_private, flag);
46 
47 	return 0;
48 }
49 
50 static void
51 solaris_destructor(void *private, void *object)
52 {
53 	kmem_cache_t *km = private;
54 
55 	if (km->km_destructor)
56 		(*km->km_destructor)(object, km->km_private);
57 }
58 
59 static void
60 solaris_reclaim(void *private, int flag)
61 {
62 
63 	kmem_cache_t *km = private;
64 
65 	if (km->km_reclaim)
66 		(*km->km_reclaim)(km->km_private);
67 }
68 
69 kmem_cache_t *
70 kmem_cache_create(char *name, size_t bufsize, size_t align,
71     int (*constructor)(void *, void *, int), void (*destructor)(void *, void *),
72     void (*reclaim)(void *) __unused, void *private, vmem_t *vmp, int flags)
73 {
74 	kmem_cache_t *km;
75 
76 	KASSERT(ISSET(flags, ~(KMC_NOTOUCH | KMC_NODEBUG)) == 0);
77 	KASSERT(private == NULL);
78 	KASSERT(vmp == NULL);
79 
80 	km = kmem_zalloc(sizeof(*km), KM_SLEEP);
81 	km->km_private = private;
82 	km->km_constructor = constructor;
83 	km->km_destructor = destructor;
84 	km->km_reclaim = reclaim;
85 	km->km_pool = pool_cache_init(bufsize, align, 0, 0, name, NULL,
86 	    IPL_NONE, solaris_constructor, solaris_destructor, km);
87 	if (km->km_pool == NULL) {
88 		kmem_free(km, sizeof(*km));
89 		return NULL;
90 	}
91 	if (reclaim)
92 		pool_cache_set_drain_hook(km->km_pool, solaris_reclaim, km);
93 
94 	return km;
95 }
96 void
97 kmem_cache_destroy(kmem_cache_t *km)
98 {
99 
100 	pool_cache_destroy(km->km_pool);
101 	kmem_free(km, sizeof(*km));
102 }
103 
104 void *
105 kmem_cache_alloc(kmem_cache_t *km, int flags)
106 {
107 
108 	KASSERT(ISSET(flags, ~(KM_SLEEP | KM_NOSLEEP | KM_PUSHPAGE)) == 0);
109 
110 	return pool_cache_get(km->km_pool, flags);
111 }
112 
113 void
114 kmem_cache_free(kmem_cache_t *km, void *object)
115 {
116 
117 	pool_cache_put(km->km_pool, object);
118 }
119 
120 void
121 kmem_cache_reap_now(kmem_cache_t *km)
122 {
123 
124 	pool_cache_invalidate(km->km_pool);
125 }
126 
127 #undef kmem_alloc
128 #undef kmem_zalloc
129 #undef kmem_free
130 
131 /*
132  * Solaris allows allocating zero bytes (which returns NULL)
133  * and freeing a NULL pointer (which does nothing),
134  * so allow that here with wrappers around the native functions
135  * (which do not allow those things).
136  */
137 
138 void *
139 solaris_kmem_alloc(size_t size, int flags)
140 {
141 
142 	if (size == 0)
143 		return NULL;
144 	return kmem_alloc(size, flags);
145 }
146 
147 void *
148 solaris_kmem_zalloc(size_t size, int flags)
149 {
150 
151 	if (size == 0)
152 		return NULL;
153 	return kmem_zalloc(size, flags);
154 }
155 
156 void
157 solaris_kmem_free(void *buf, size_t size)
158 {
159 
160 	if (buf == NULL)
161 		return;
162 	kmem_free(buf, size);
163 }
164