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