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