Add linux libspl support
[zfs.git] / lib / libspl / include / umem.h
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 /* XXX: We should use the real portable umem library if it is detected
31  * at configure time.  However, if the library is not available we can
32  * use a trivial malloc based implementation.  This obviously impacts
33  * performance but unless you using a full userspace build of zpool for
34  * something other than ztest your likely not going to notice or care.
35  *
36  * https://labs.omniti.com/trac/portableumem
37  */
38
39 #include <stdlib.h>
40 #include <stdio.h>
41
42 #ifdef  __cplusplus
43 extern "C" {
44 #endif
45
46 typedef void vmem_t;
47
48 /*
49  * Flags for umem_alloc/umem_free
50  */
51 #define UMEM_DEFAULT            0x0000  /* normal -- may fail */
52 #define UMEM_NOFAIL             0x0100  /* Never fails */
53
54 /*
55  * Flags for umem_cache_create()
56  */
57 #define UMC_NOTOUCH             0x00010000
58 #define UMC_NODEBUG             0x00020000
59 #define UMC_NOMAGAZINE          0x00040000
60 #define UMC_NOHASH              0x00080000
61
62 #define UMEM_CACHE_NAMELEN      31
63
64 typedef int umem_nofail_callback_t(void);
65 typedef int umem_constructor_t(void *, void *, int);
66 typedef void umem_destructor_t(void *, void *);
67 typedef void umem_reclaim_t(void *);
68
69 typedef struct umem_cache {
70         char                    cache_name[UMEM_CACHE_NAMELEN + 1];
71         size_t                  cache_bufsize;
72         size_t                  cache_align;
73         umem_constructor_t      *cache_constructor;
74         umem_destructor_t       *cache_destructor;
75         umem_reclaim_t          *cache_reclaim;
76         void                    *cache_private;
77         void                    *cache_arena;
78         int                     cache_cflags;
79 } umem_cache_t;
80
81 static inline void *
82 umem_alloc(size_t size, int flags)
83 {
84         void *ptr;
85
86         do {
87                 ptr = malloc(size);
88         } while (ptr == NULL && (flags & UMEM_NOFAIL));
89
90         return ptr;
91 }
92
93 static inline void *
94 umem_alloc_aligned(size_t size, size_t align, int flags)
95 {
96         void *ptr;
97         int rc;
98
99         do {
100                 rc = posix_memalign(&ptr, align, size);
101         } while (rc == ENOMEM && (flags & UMEM_NOFAIL));
102
103         if (rc == EINVAL) {
104                 fprintf(stderr, "%s: invalid memory alignment (%zd)\n",
105                     __func__, align);
106                 if (flags & UMEM_NOFAIL)
107                         abort();
108                 return NULL;
109         }
110
111         return ptr;
112 }
113
114 static inline void *
115 umem_zalloc(size_t size, int flags)
116 {
117         void *ptr;
118
119         ptr = umem_alloc(size, flags);
120         if (ptr)
121                 memset(ptr, 0, size);
122
123         return ptr;
124 }
125
126 static inline void
127 umem_free(void *ptr, size_t size)
128 {
129         free(ptr);
130 }
131
132 static inline void
133 umem_nofail_callback(umem_nofail_callback_t *cb) {}
134
135 static inline umem_cache_t *
136 umem_cache_create(char *name, size_t bufsize, size_t align,
137                   umem_constructor_t *constructor,
138                   umem_destructor_t *destructor,
139                   umem_reclaim_t *reclaim,
140                   void *priv, void *vmp, int cflags)
141 {
142         umem_cache_t *cp;
143
144         cp = umem_alloc(sizeof(umem_cache_t), UMEM_DEFAULT);
145         if (cp) {
146                 strncpy(cp->cache_name, name, UMEM_CACHE_NAMELEN);
147                 cp->cache_bufsize = bufsize;
148                 cp->cache_align = align;
149                 cp->cache_constructor = constructor;
150                 cp->cache_destructor = destructor;
151                 cp->cache_reclaim = reclaim;
152                 cp->cache_private = priv;
153                 cp->cache_arena = vmp;
154                 cp->cache_cflags = cflags;
155         }
156
157         return cp;
158 }
159
160 static inline void
161 umem_cache_destroy(umem_cache_t *cp)
162 {
163         umem_free(cp, sizeof(umem_cache_t));
164 }
165
166 static inline void *
167 umem_cache_alloc(umem_cache_t *cp, int flags)
168 {
169         void *ptr;
170
171         if (cp->cache_align != 0)
172                 ptr = umem_alloc_aligned(cp->cache_bufsize, cp->cache_align, flags);
173         else
174                 ptr = umem_alloc(cp->cache_bufsize, flags);
175
176         if (ptr && cp->cache_constructor)
177                 cp->cache_constructor(ptr, cp->cache_private, UMEM_DEFAULT);
178
179         return ptr;
180 }
181
182 static inline void
183 umem_cache_free(umem_cache_t *cp, void *ptr)
184 {
185         if (cp->cache_destructor)
186                 cp->cache_destructor(ptr, cp->cache_private);
187
188         umem_free(ptr, cp->cache_bufsize);
189 }
190
191 #ifdef  __cplusplus
192 }
193 #endif
194
195 #endif