]>
Commit | Line | Data |
---|---|---|
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 | |
28 | #define _LIBSPL_UMEM_H | |
29 | ||
30 | /* | |
31 | * XXX: We should use the real portable umem library if it is detected | |
32 | * at configure time. However, if the library is not available, we can | |
33 | * use a trivial malloc based implementation. This obviously impacts | |
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. | |
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 | */ | |
52 | #define UMEM_DEFAULT 0x0000 /* normal -- may fail */ | |
53 | #define UMEM_NOFAIL 0x0100 /* Never fails */ | |
54 | ||
55 | /* | |
56 | * Flags for umem_cache_create() | |
57 | */ | |
58 | #define UMC_NOTOUCH 0x00010000 | |
59 | #define UMC_NODEBUG 0x00020000 | |
60 | #define UMC_NOMAGAZINE 0x00040000 | |
61 | #define UMC_NOHASH 0x00080000 | |
62 | ||
63 | #define UMEM_CACHE_NAMELEN 31 | |
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 | { | |
85 | void *ptr; | |
86 | ||
87 | do { | |
88 | ptr = malloc(size); | |
89 | } while (ptr == NULL && (flags & UMEM_NOFAIL)); | |
90 | ||
91 | return (ptr); | |
92 | } | |
93 | ||
94 | static inline void * | |
95 | umem_alloc_aligned(size_t size, size_t align, int flags) | |
96 | { | |
97 | void *ptr; | |
98 | int rc; | |
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(); | |
109 | return (NULL); | |
110 | } | |
111 | ||
112 | return (ptr); | |
113 | } | |
114 | ||
115 | static inline void * | |
116 | umem_zalloc(size_t size, int flags) | |
117 | { | |
118 | void *ptr; | |
119 | ||
120 | ptr = umem_alloc(size, flags); | |
121 | if (ptr) | |
122 | memset(ptr, 0, size); | |
123 | ||
124 | return (ptr); | |
125 | } | |
126 | ||
127 | static inline void | |
128 | umem_free(void *ptr, size_t size) | |
129 | { | |
130 | free(ptr); | |
131 | } | |
132 | ||
133 | static inline void | |
134 | umem_nofail_callback(umem_nofail_callback_t *cb) {} | |
135 | ||
136 | static inline umem_cache_t * | |
137 | umem_cache_create( | |
138 | char *name, size_t bufsize, size_t align, | |
139 | umem_constructor_t *constructor, | |
140 | umem_destructor_t *destructor, | |
141 | umem_reclaim_t *reclaim, | |
142 | void *priv, void *vmp, int cflags) | |
143 | { | |
144 | umem_cache_t *cp; | |
145 | ||
146 | cp = umem_alloc(sizeof (umem_cache_t), UMEM_DEFAULT); | |
147 | if (cp) { | |
148 | strncpy(cp->cache_name, name, UMEM_CACHE_NAMELEN); | |
149 | cp->cache_bufsize = bufsize; | |
150 | cp->cache_align = align; | |
151 | cp->cache_constructor = constructor; | |
152 | cp->cache_destructor = destructor; | |
153 | cp->cache_reclaim = reclaim; | |
154 | cp->cache_private = priv; | |
155 | cp->cache_arena = vmp; | |
156 | cp->cache_cflags = cflags; | |
157 | } | |
158 | ||
159 | return (cp); | |
160 | } | |
161 | ||
162 | static inline void | |
163 | umem_cache_destroy(umem_cache_t *cp) | |
164 | { | |
165 | umem_free(cp, sizeof (umem_cache_t)); | |
166 | } | |
167 | ||
168 | static inline void * | |
169 | umem_cache_alloc(umem_cache_t *cp, int flags) | |
170 | { | |
171 | void *ptr; | |
172 | ||
173 | if (cp->cache_align != 0) | |
174 | ptr = umem_alloc_aligned( | |
175 | cp->cache_bufsize, cp->cache_align, flags); | |
176 | else | |
177 | ptr = umem_alloc(cp->cache_bufsize, flags); | |
178 | ||
179 | if (ptr && cp->cache_constructor) | |
180 | cp->cache_constructor(ptr, cp->cache_private, UMEM_DEFAULT); | |
181 | ||
182 | return (ptr); | |
183 | } | |
184 | ||
185 | static inline void | |
186 | umem_cache_free(umem_cache_t *cp, void *ptr) | |
187 | { | |
188 | if (cp->cache_destructor) | |
189 | cp->cache_destructor(ptr, cp->cache_private); | |
190 | ||
191 | umem_free(ptr, cp->cache_bufsize); | |
192 | } | |
193 | ||
194 | #ifdef __cplusplus | |
195 | } | |
196 | #endif | |
197 | ||
198 | #endif |