]>
Commit | Line | Data |
---|---|---|
a26baf28 BB |
1 | /* |
2 | * CDDL HEADER START | |
3 | * | |
4 | * The contents of this file are subject to the terms of the | |
5 | * Common Development and Distribution License, Version 1.0 only | |
6 | * (the "License"). You may not use this file except in compliance | |
7 | * with the License. | |
8 | * | |
9 | * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
10 | * or http://www.opensolaris.org/os/licensing. | |
11 | * See the License for the specific language governing permissions | |
12 | * and limitations under the License. | |
13 | * | |
14 | * When distributing Covered Code, include this CDDL HEADER in each | |
15 | * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
16 | * If applicable, add the following below this CDDL HEADER, with the | |
17 | * fields enclosed by brackets "[]" replaced with your own identifying | |
18 | * information: Portions Copyright [yyyy] [name of copyright owner] | |
19 | * | |
20 | * CDDL HEADER END | |
21 | */ | |
22 | /* | |
23 | * Copyright 2008 Sun Microsystems, Inc. All rights reserved. | |
24 | * Use is subject to license terms. | |
25 | */ | |
26 | ||
27 | #ifndef _LIBSPL_UMEM_H | |
a08ee875 | 28 | #define _LIBSPL_UMEM_H |
a26baf28 | 29 | |
a08ee875 LG |
30 | /* |
31 | * XXX: We should use the real portable umem library if it is detected | |
c06d4368 | 32 | * at configure time. However, if the library is not available, we can |
a26baf28 | 33 | * use a trivial malloc based implementation. This obviously impacts |
c06d4368 AX |
34 | * performance, but unless you are using a full userspace build of zpool for |
35 | * something other than ztest, you are likely not going to notice or care. | |
a26baf28 BB |
36 | * |
37 | * https://labs.omniti.com/trac/portableumem | |
38 | */ | |
39 | ||
40 | #include <stdlib.h> | |
41 | #include <stdio.h> | |
42 | ||
43 | #ifdef __cplusplus | |
44 | extern "C" { | |
45 | #endif | |
46 | ||
47 | typedef void vmem_t; | |
48 | ||
49 | /* | |
50 | * Flags for umem_alloc/umem_free | |
51 | */ | |
a08ee875 LG |
52 | #define UMEM_DEFAULT 0x0000 /* normal -- may fail */ |
53 | #define UMEM_NOFAIL 0x0100 /* Never fails */ | |
a26baf28 BB |
54 | |
55 | /* | |
56 | * Flags for umem_cache_create() | |
57 | */ | |
a08ee875 LG |
58 | #define UMC_NOTOUCH 0x00010000 |
59 | #define UMC_NODEBUG 0x00020000 | |
60 | #define UMC_NOMAGAZINE 0x00040000 | |
61 | #define UMC_NOHASH 0x00080000 | |
a26baf28 | 62 | |
a08ee875 | 63 | #define UMEM_CACHE_NAMELEN 31 |
a26baf28 BB |
64 | |
65 | typedef int umem_nofail_callback_t(void); | |
66 | typedef int umem_constructor_t(void *, void *, int); | |
67 | typedef void umem_destructor_t(void *, void *); | |
68 | typedef void umem_reclaim_t(void *); | |
69 | ||
70 | typedef struct umem_cache { | |
71 | char cache_name[UMEM_CACHE_NAMELEN + 1]; | |
72 | size_t cache_bufsize; | |
73 | size_t cache_align; | |
74 | umem_constructor_t *cache_constructor; | |
75 | umem_destructor_t *cache_destructor; | |
76 | umem_reclaim_t *cache_reclaim; | |
77 | void *cache_private; | |
78 | void *cache_arena; | |
79 | int cache_cflags; | |
80 | } umem_cache_t; | |
81 | ||
82 | static inline void * | |
83 | umem_alloc(size_t size, int flags) | |
84 | { | |
ea04106b | 85 | void *ptr = NULL; |
a26baf28 BB |
86 | |
87 | do { | |
88 | ptr = malloc(size); | |
89 | } while (ptr == NULL && (flags & UMEM_NOFAIL)); | |
90 | ||
a08ee875 | 91 | return (ptr); |
a26baf28 BB |
92 | } |
93 | ||
94 | static inline void * | |
95 | umem_alloc_aligned(size_t size, size_t align, int flags) | |
96 | { | |
ea04106b AX |
97 | void *ptr = NULL; |
98 | int rc = EINVAL; | |
a26baf28 BB |
99 | |
100 | do { | |
101 | rc = posix_memalign(&ptr, align, size); | |
102 | } while (rc == ENOMEM && (flags & UMEM_NOFAIL)); | |
103 | ||
104 | if (rc == EINVAL) { | |
105 | fprintf(stderr, "%s: invalid memory alignment (%zd)\n", | |
106 | __func__, align); | |
107 | if (flags & UMEM_NOFAIL) | |
108 | abort(); | |
a08ee875 | 109 | return (NULL); |
a26baf28 BB |
110 | } |
111 | ||
a08ee875 | 112 | return (ptr); |
a26baf28 BB |
113 | } |
114 | ||
115 | static inline void * | |
116 | umem_zalloc(size_t size, int flags) | |
117 | { | |
ea04106b | 118 | void *ptr = NULL; |
a26baf28 BB |
119 | |
120 | ptr = umem_alloc(size, flags); | |
121 | if (ptr) | |
122 | memset(ptr, 0, size); | |
123 | ||
a08ee875 | 124 | return (ptr); |
a26baf28 BB |
125 | } |
126 | ||
127 | static inline void | |
128 | umem_free(void *ptr, size_t size) | |
129 | { | |
130 | free(ptr); | |
131 | } | |
132 | ||
133 | static inline void | |
cae5b340 AX |
134 | umem_nofail_callback(umem_nofail_callback_t *cb) |
135 | {} | |
a26baf28 BB |
136 | |
137 | static inline umem_cache_t * | |
a08ee875 LG |
138 | umem_cache_create( |
139 | char *name, size_t bufsize, size_t align, | |
140 | umem_constructor_t *constructor, | |
141 | umem_destructor_t *destructor, | |
142 | umem_reclaim_t *reclaim, | |
143 | void *priv, void *vmp, int cflags) | |
a26baf28 BB |
144 | { |
145 | umem_cache_t *cp; | |
146 | ||
a08ee875 | 147 | cp = umem_alloc(sizeof (umem_cache_t), UMEM_DEFAULT); |
a26baf28 BB |
148 | if (cp) { |
149 | strncpy(cp->cache_name, name, UMEM_CACHE_NAMELEN); | |
150 | cp->cache_bufsize = bufsize; | |
151 | cp->cache_align = align; | |
152 | cp->cache_constructor = constructor; | |
153 | cp->cache_destructor = destructor; | |
154 | cp->cache_reclaim = reclaim; | |
155 | cp->cache_private = priv; | |
156 | cp->cache_arena = vmp; | |
157 | cp->cache_cflags = cflags; | |
158 | } | |
159 | ||
a08ee875 | 160 | return (cp); |
a26baf28 BB |
161 | } |
162 | ||
163 | static inline void | |
164 | umem_cache_destroy(umem_cache_t *cp) | |
165 | { | |
a08ee875 | 166 | umem_free(cp, sizeof (umem_cache_t)); |
a26baf28 BB |
167 | } |
168 | ||
169 | static inline void * | |
170 | umem_cache_alloc(umem_cache_t *cp, int flags) | |
171 | { | |
ea04106b | 172 | void *ptr = NULL; |
a26baf28 BB |
173 | |
174 | if (cp->cache_align != 0) | |
a08ee875 LG |
175 | ptr = umem_alloc_aligned( |
176 | cp->cache_bufsize, cp->cache_align, flags); | |
a26baf28 BB |
177 | else |
178 | ptr = umem_alloc(cp->cache_bufsize, flags); | |
179 | ||
180 | if (ptr && cp->cache_constructor) | |
181 | cp->cache_constructor(ptr, cp->cache_private, UMEM_DEFAULT); | |
182 | ||
a08ee875 | 183 | return (ptr); |
a26baf28 BB |
184 | } |
185 | ||
186 | static inline void | |
187 | umem_cache_free(umem_cache_t *cp, void *ptr) | |
188 | { | |
189 | if (cp->cache_destructor) | |
190 | cp->cache_destructor(ptr, cp->cache_private); | |
191 | ||
192 | umem_free(ptr, cp->cache_bufsize); | |
193 | } | |
194 | ||
e10b0808 AX |
195 | static inline void |
196 | umem_cache_reap_now(umem_cache_t *cp) | |
197 | { | |
198 | } | |
199 | ||
a26baf28 BB |
200 | #ifdef __cplusplus |
201 | } | |
202 | #endif | |
203 | ||
204 | #endif |