xref: /freebsd/sys/contrib/openzfs/lib/libspl/include/umem.h (revision 271171e0d97b88ba2a7c3bf750c9672b484c1c13)
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
10*271171e0SMartin 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 
86eda14cbcSMatt Macy static inline void *
87eda14cbcSMatt Macy umem_alloc(size_t size, int flags)
88eda14cbcSMatt Macy {
89eda14cbcSMatt Macy 	void *ptr = NULL;
90eda14cbcSMatt Macy 
91eda14cbcSMatt Macy 	do {
92eda14cbcSMatt Macy 		ptr = malloc(size);
93eda14cbcSMatt Macy 	} while (ptr == NULL && (flags & UMEM_NOFAIL));
94eda14cbcSMatt Macy 
95eda14cbcSMatt Macy 	return (ptr);
96eda14cbcSMatt Macy }
97eda14cbcSMatt Macy 
98eda14cbcSMatt Macy static inline void *
99eda14cbcSMatt Macy umem_alloc_aligned(size_t size, size_t align, int flags)
100eda14cbcSMatt Macy {
101eda14cbcSMatt Macy 	void *ptr = NULL;
102eda14cbcSMatt Macy 	int rc = EINVAL;
103eda14cbcSMatt Macy 
104eda14cbcSMatt Macy 	do {
105eda14cbcSMatt Macy 		rc = posix_memalign(&ptr, align, size);
106eda14cbcSMatt Macy 	} while (rc == ENOMEM && (flags & UMEM_NOFAIL));
107eda14cbcSMatt Macy 
108eda14cbcSMatt Macy 	if (rc == EINVAL) {
109eda14cbcSMatt Macy 		fprintf(stderr, "%s: invalid memory alignment (%zd)\n",
110eda14cbcSMatt Macy 		    __func__, align);
111eda14cbcSMatt Macy 		if (flags & UMEM_NOFAIL)
112eda14cbcSMatt Macy 			abort();
113eda14cbcSMatt Macy 		return (NULL);
114eda14cbcSMatt Macy 	}
115eda14cbcSMatt Macy 
116eda14cbcSMatt Macy 	return (ptr);
117eda14cbcSMatt Macy }
118eda14cbcSMatt Macy 
119eda14cbcSMatt Macy static inline void *
120eda14cbcSMatt Macy umem_zalloc(size_t size, int flags)
121eda14cbcSMatt Macy {
122eda14cbcSMatt Macy 	void *ptr = NULL;
123eda14cbcSMatt Macy 
124eda14cbcSMatt Macy 	ptr = umem_alloc(size, flags);
125eda14cbcSMatt Macy 	if (ptr)
126eda14cbcSMatt Macy 		memset(ptr, 0, size);
127eda14cbcSMatt Macy 
128eda14cbcSMatt Macy 	return (ptr);
129eda14cbcSMatt Macy }
130eda14cbcSMatt Macy 
131eda14cbcSMatt Macy static inline void
132e92ffd9bSMartin Matuska umem_free(const void *ptr, size_t size __maybe_unused)
133eda14cbcSMatt Macy {
134e92ffd9bSMartin Matuska 	free((void *)ptr);
135eda14cbcSMatt Macy }
136eda14cbcSMatt Macy 
137eda14cbcSMatt Macy static inline void
138eda14cbcSMatt Macy umem_nofail_callback(umem_nofail_callback_t *cb __maybe_unused)
139eda14cbcSMatt Macy {}
140eda14cbcSMatt Macy 
141eda14cbcSMatt Macy static inline umem_cache_t *
142eda14cbcSMatt Macy umem_cache_create(
143a0b956f5SMartin Matuska     const char *name, size_t bufsize, size_t align,
144eda14cbcSMatt Macy     umem_constructor_t *constructor,
145eda14cbcSMatt Macy     umem_destructor_t *destructor,
146eda14cbcSMatt Macy     umem_reclaim_t *reclaim,
147eda14cbcSMatt Macy     void *priv, void *vmp, int cflags)
148eda14cbcSMatt Macy {
149eda14cbcSMatt Macy 	umem_cache_t *cp;
150eda14cbcSMatt Macy 
151eda14cbcSMatt Macy 	cp = (umem_cache_t *)umem_alloc(sizeof (umem_cache_t), UMEM_DEFAULT);
152eda14cbcSMatt Macy 	if (cp) {
153eda14cbcSMatt Macy 		strlcpy(cp->cache_name, name, UMEM_CACHE_NAMELEN);
154eda14cbcSMatt Macy 		cp->cache_bufsize = bufsize;
155eda14cbcSMatt Macy 		cp->cache_align = align;
156eda14cbcSMatt Macy 		cp->cache_constructor = constructor;
157eda14cbcSMatt Macy 		cp->cache_destructor = destructor;
158eda14cbcSMatt Macy 		cp->cache_reclaim = reclaim;
159eda14cbcSMatt Macy 		cp->cache_private = priv;
160eda14cbcSMatt Macy 		cp->cache_arena = vmp;
161eda14cbcSMatt Macy 		cp->cache_cflags = cflags;
162eda14cbcSMatt Macy 	}
163eda14cbcSMatt Macy 
164eda14cbcSMatt Macy 	return (cp);
165eda14cbcSMatt Macy }
166eda14cbcSMatt Macy 
167eda14cbcSMatt Macy static inline void
168eda14cbcSMatt Macy umem_cache_destroy(umem_cache_t *cp)
169eda14cbcSMatt Macy {
170eda14cbcSMatt Macy 	umem_free(cp, sizeof (umem_cache_t));
171eda14cbcSMatt Macy }
172eda14cbcSMatt Macy 
173eda14cbcSMatt Macy static inline void *
174eda14cbcSMatt Macy umem_cache_alloc(umem_cache_t *cp, int flags)
175eda14cbcSMatt Macy {
176eda14cbcSMatt Macy 	void *ptr = NULL;
177eda14cbcSMatt Macy 
178eda14cbcSMatt Macy 	if (cp->cache_align != 0)
179eda14cbcSMatt Macy 		ptr = umem_alloc_aligned(
180eda14cbcSMatt Macy 		    cp->cache_bufsize, cp->cache_align, flags);
181eda14cbcSMatt Macy 	else
182eda14cbcSMatt Macy 		ptr = umem_alloc(cp->cache_bufsize, flags);
183eda14cbcSMatt Macy 
184eda14cbcSMatt Macy 	if (ptr && cp->cache_constructor)
185eda14cbcSMatt Macy 		cp->cache_constructor(ptr, cp->cache_private, UMEM_DEFAULT);
186eda14cbcSMatt Macy 
187eda14cbcSMatt Macy 	return (ptr);
188eda14cbcSMatt Macy }
189eda14cbcSMatt Macy 
190eda14cbcSMatt Macy static inline void
191eda14cbcSMatt Macy umem_cache_free(umem_cache_t *cp, void *ptr)
192eda14cbcSMatt Macy {
193eda14cbcSMatt Macy 	if (cp->cache_destructor)
194eda14cbcSMatt Macy 		cp->cache_destructor(ptr, cp->cache_private);
195eda14cbcSMatt Macy 
196eda14cbcSMatt Macy 	umem_free(ptr, cp->cache_bufsize);
197eda14cbcSMatt Macy }
198eda14cbcSMatt Macy 
199eda14cbcSMatt Macy static inline void
200eda14cbcSMatt Macy umem_cache_reap_now(umem_cache_t *cp __maybe_unused)
201eda14cbcSMatt Macy {
202eda14cbcSMatt Macy }
203eda14cbcSMatt Macy 
204eda14cbcSMatt Macy #ifdef  __cplusplus
205eda14cbcSMatt Macy }
206eda14cbcSMatt Macy #endif
207eda14cbcSMatt Macy 
208eda14cbcSMatt Macy #endif
209