summaryrefslogtreecommitdiffstats
path: root/lib/libspl/include/umem.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libspl/include/umem.h')
-rw-r--r--lib/libspl/include/umem.h195
1 files changed, 195 insertions, 0 deletions
diff --git a/lib/libspl/include/umem.h b/lib/libspl/include/umem.h
new file mode 100644
index 000000000..87db1f451
--- /dev/null
+++ b/lib/libspl/include/umem.h
@@ -0,0 +1,195 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LIBSPL_UMEM_H
+#define _LIBSPL_UMEM_H
+
+/* XXX: We should use the real portable umem library if it is detected
+ * at configure time. However, if the library is not available we can
+ * use a trivial malloc based implementation. This obviously impacts
+ * performance but unless you using a full userspace build of zpool for
+ * something other than ztest your likely not going to notice or care.
+ *
+ * https://labs.omniti.com/trac/portableumem
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void vmem_t;
+
+/*
+ * Flags for umem_alloc/umem_free
+ */
+#define UMEM_DEFAULT 0x0000 /* normal -- may fail */
+#define UMEM_NOFAIL 0x0100 /* Never fails */
+
+/*
+ * Flags for umem_cache_create()
+ */
+#define UMC_NOTOUCH 0x00010000
+#define UMC_NODEBUG 0x00020000
+#define UMC_NOMAGAZINE 0x00040000
+#define UMC_NOHASH 0x00080000
+
+#define UMEM_CACHE_NAMELEN 31
+
+typedef int umem_nofail_callback_t(void);
+typedef int umem_constructor_t(void *, void *, int);
+typedef void umem_destructor_t(void *, void *);
+typedef void umem_reclaim_t(void *);
+
+typedef struct umem_cache {
+ char cache_name[UMEM_CACHE_NAMELEN + 1];
+ size_t cache_bufsize;
+ size_t cache_align;
+ umem_constructor_t *cache_constructor;
+ umem_destructor_t *cache_destructor;
+ umem_reclaim_t *cache_reclaim;
+ void *cache_private;
+ void *cache_arena;
+ int cache_cflags;
+} umem_cache_t;
+
+static inline void *
+umem_alloc(size_t size, int flags)
+{
+ void *ptr;
+
+ do {
+ ptr = malloc(size);
+ } while (ptr == NULL && (flags & UMEM_NOFAIL));
+
+ return ptr;
+}
+
+static inline void *
+umem_alloc_aligned(size_t size, size_t align, int flags)
+{
+ void *ptr;
+ int rc;
+
+ do {
+ rc = posix_memalign(&ptr, align, size);
+ } while (rc == ENOMEM && (flags & UMEM_NOFAIL));
+
+ if (rc == EINVAL) {
+ fprintf(stderr, "%s: invalid memory alignment (%zd)\n",
+ __func__, align);
+ if (flags & UMEM_NOFAIL)
+ abort();
+ return NULL;
+ }
+
+ return ptr;
+}
+
+static inline void *
+umem_zalloc(size_t size, int flags)
+{
+ void *ptr;
+
+ ptr = umem_alloc(size, flags);
+ if (ptr)
+ memset(ptr, 0, size);
+
+ return ptr;
+}
+
+static inline void
+umem_free(void *ptr, size_t size)
+{
+ free(ptr);
+}
+
+static inline void
+umem_nofail_callback(umem_nofail_callback_t *cb) {}
+
+static inline umem_cache_t *
+umem_cache_create(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)
+{
+ umem_cache_t *cp;
+
+ cp = umem_alloc(sizeof(umem_cache_t), UMEM_DEFAULT);
+ if (cp) {
+ strncpy(cp->cache_name, name, UMEM_CACHE_NAMELEN);
+ cp->cache_bufsize = bufsize;
+ cp->cache_align = align;
+ cp->cache_constructor = constructor;
+ cp->cache_destructor = destructor;
+ cp->cache_reclaim = reclaim;
+ cp->cache_private = priv;
+ cp->cache_arena = vmp;
+ cp->cache_cflags = cflags;
+ }
+
+ return cp;
+}
+
+static inline void
+umem_cache_destroy(umem_cache_t *cp)
+{
+ umem_free(cp, sizeof(umem_cache_t));
+}
+
+static inline void *
+umem_cache_alloc(umem_cache_t *cp, int flags)
+{
+ void *ptr;
+
+ if (cp->cache_align != 0)
+ ptr = umem_alloc_aligned(cp->cache_bufsize, cp->cache_align, flags);
+ else
+ ptr = umem_alloc(cp->cache_bufsize, flags);
+
+ if (ptr && cp->cache_constructor)
+ cp->cache_constructor(ptr, cp->cache_private, UMEM_DEFAULT);
+
+ return ptr;
+}
+
+static inline void
+umem_cache_free(umem_cache_t *cp, void *ptr)
+{
+ if (cp->cache_destructor)
+ cp->cache_destructor(ptr, cp->cache_private);
+
+ umem_free(ptr, cp->cache_bufsize);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif