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