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 10271171e0SMartin 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 86be181ee2SMartin Matuska __attribute__((alloc_size(1))) 87eda14cbcSMatt Macy static inline void * 88eda14cbcSMatt Macy umem_alloc(size_t size, int flags) 89eda14cbcSMatt Macy { 90eda14cbcSMatt Macy void *ptr = NULL; 91eda14cbcSMatt Macy 92eda14cbcSMatt Macy do { 93eda14cbcSMatt Macy ptr = malloc(size); 94eda14cbcSMatt Macy } while (ptr == NULL && (flags & UMEM_NOFAIL)); 95eda14cbcSMatt Macy 96eda14cbcSMatt Macy return (ptr); 97eda14cbcSMatt Macy } 98eda14cbcSMatt Macy 99be181ee2SMartin Matuska __attribute__((alloc_size(1))) 100eda14cbcSMatt Macy static inline void * 101eda14cbcSMatt Macy umem_alloc_aligned(size_t size, size_t align, int flags) 102eda14cbcSMatt Macy { 103eda14cbcSMatt Macy void *ptr = NULL; 104eda14cbcSMatt Macy int rc = EINVAL; 105eda14cbcSMatt Macy 106eda14cbcSMatt Macy do { 107eda14cbcSMatt Macy rc = posix_memalign(&ptr, align, size); 108eda14cbcSMatt Macy } while (rc == ENOMEM && (flags & UMEM_NOFAIL)); 109eda14cbcSMatt Macy 110eda14cbcSMatt Macy if (rc == EINVAL) { 111eda14cbcSMatt Macy fprintf(stderr, "%s: invalid memory alignment (%zd)\n", 112eda14cbcSMatt Macy __func__, align); 113eda14cbcSMatt Macy if (flags & UMEM_NOFAIL) 114eda14cbcSMatt Macy abort(); 115eda14cbcSMatt Macy return (NULL); 116eda14cbcSMatt Macy } 117eda14cbcSMatt Macy 118eda14cbcSMatt Macy return (ptr); 119eda14cbcSMatt Macy } 120eda14cbcSMatt Macy 121be181ee2SMartin Matuska __attribute__((alloc_size(1))) 122eda14cbcSMatt Macy static inline void * 123eda14cbcSMatt Macy umem_zalloc(size_t size, int flags) 124eda14cbcSMatt Macy { 125eda14cbcSMatt Macy void *ptr = NULL; 126eda14cbcSMatt Macy 127eda14cbcSMatt Macy ptr = umem_alloc(size, flags); 128eda14cbcSMatt Macy if (ptr) 129eda14cbcSMatt Macy memset(ptr, 0, size); 130eda14cbcSMatt Macy 131eda14cbcSMatt Macy return (ptr); 132eda14cbcSMatt Macy } 133eda14cbcSMatt Macy 134eda14cbcSMatt Macy static inline void 135e92ffd9bSMartin Matuska umem_free(const void *ptr, size_t size __maybe_unused) 136eda14cbcSMatt Macy { 137e92ffd9bSMartin Matuska free((void *)ptr); 138eda14cbcSMatt Macy } 139eda14cbcSMatt Macy 140*dbd5678dSMartin Matuska /* 141*dbd5678dSMartin Matuska * umem_free_aligned was added for supporting portability 142*dbd5678dSMartin Matuska * with non-POSIX platforms that require a different free 143*dbd5678dSMartin Matuska * to be used with aligned allocations. 144*dbd5678dSMartin Matuska */ 145*dbd5678dSMartin Matuska static inline void 146*dbd5678dSMartin Matuska umem_free_aligned(void *ptr, size_t size __maybe_unused) 147*dbd5678dSMartin Matuska { 148*dbd5678dSMartin Matuska #ifndef _WIN32 149*dbd5678dSMartin Matuska free((void *)ptr); 150*dbd5678dSMartin Matuska #else 151*dbd5678dSMartin Matuska _aligned_free(ptr); 152*dbd5678dSMartin Matuska #endif 153*dbd5678dSMartin Matuska } 154*dbd5678dSMartin Matuska 155eda14cbcSMatt Macy static inline void 156eda14cbcSMatt Macy umem_nofail_callback(umem_nofail_callback_t *cb __maybe_unused) 157eda14cbcSMatt Macy {} 158eda14cbcSMatt Macy 159eda14cbcSMatt Macy static inline umem_cache_t * 160eda14cbcSMatt Macy umem_cache_create( 161a0b956f5SMartin Matuska const char *name, size_t bufsize, size_t align, 162eda14cbcSMatt Macy umem_constructor_t *constructor, 163eda14cbcSMatt Macy umem_destructor_t *destructor, 164eda14cbcSMatt Macy umem_reclaim_t *reclaim, 165eda14cbcSMatt Macy void *priv, void *vmp, int cflags) 166eda14cbcSMatt Macy { 167eda14cbcSMatt Macy umem_cache_t *cp; 168eda14cbcSMatt Macy 169eda14cbcSMatt Macy cp = (umem_cache_t *)umem_alloc(sizeof (umem_cache_t), UMEM_DEFAULT); 170eda14cbcSMatt Macy if (cp) { 171eda14cbcSMatt Macy strlcpy(cp->cache_name, name, UMEM_CACHE_NAMELEN); 172eda14cbcSMatt Macy cp->cache_bufsize = bufsize; 173eda14cbcSMatt Macy cp->cache_align = align; 174eda14cbcSMatt Macy cp->cache_constructor = constructor; 175eda14cbcSMatt Macy cp->cache_destructor = destructor; 176eda14cbcSMatt Macy cp->cache_reclaim = reclaim; 177eda14cbcSMatt Macy cp->cache_private = priv; 178eda14cbcSMatt Macy cp->cache_arena = vmp; 179eda14cbcSMatt Macy cp->cache_cflags = cflags; 180eda14cbcSMatt Macy } 181eda14cbcSMatt Macy 182eda14cbcSMatt Macy return (cp); 183eda14cbcSMatt Macy } 184eda14cbcSMatt Macy 185eda14cbcSMatt Macy static inline void 186eda14cbcSMatt Macy umem_cache_destroy(umem_cache_t *cp) 187eda14cbcSMatt Macy { 188eda14cbcSMatt Macy umem_free(cp, sizeof (umem_cache_t)); 189eda14cbcSMatt Macy } 190eda14cbcSMatt Macy 191eda14cbcSMatt Macy static inline void * 192eda14cbcSMatt Macy umem_cache_alloc(umem_cache_t *cp, int flags) 193eda14cbcSMatt Macy { 194eda14cbcSMatt Macy void *ptr = NULL; 195eda14cbcSMatt Macy 196eda14cbcSMatt Macy if (cp->cache_align != 0) 197eda14cbcSMatt Macy ptr = umem_alloc_aligned( 198eda14cbcSMatt Macy cp->cache_bufsize, cp->cache_align, flags); 199eda14cbcSMatt Macy else 200eda14cbcSMatt Macy ptr = umem_alloc(cp->cache_bufsize, flags); 201eda14cbcSMatt Macy 202eda14cbcSMatt Macy if (ptr && cp->cache_constructor) 203eda14cbcSMatt Macy cp->cache_constructor(ptr, cp->cache_private, UMEM_DEFAULT); 204eda14cbcSMatt Macy 205eda14cbcSMatt Macy return (ptr); 206eda14cbcSMatt Macy } 207eda14cbcSMatt Macy 208eda14cbcSMatt Macy static inline void 209eda14cbcSMatt Macy umem_cache_free(umem_cache_t *cp, void *ptr) 210eda14cbcSMatt Macy { 211eda14cbcSMatt Macy if (cp->cache_destructor) 212eda14cbcSMatt Macy cp->cache_destructor(ptr, cp->cache_private); 213eda14cbcSMatt Macy 214*dbd5678dSMartin Matuska if (cp->cache_align != 0) 215*dbd5678dSMartin Matuska umem_free_aligned(ptr, cp->cache_bufsize); 216*dbd5678dSMartin Matuska else 217eda14cbcSMatt Macy umem_free(ptr, cp->cache_bufsize); 218eda14cbcSMatt Macy } 219eda14cbcSMatt Macy 220eda14cbcSMatt Macy static inline void 221eda14cbcSMatt Macy umem_cache_reap_now(umem_cache_t *cp __maybe_unused) 222eda14cbcSMatt Macy { 223eda14cbcSMatt Macy } 224eda14cbcSMatt Macy 225eda14cbcSMatt Macy #ifdef __cplusplus 226eda14cbcSMatt Macy } 227eda14cbcSMatt Macy #endif 228eda14cbcSMatt Macy 229eda14cbcSMatt Macy #endif 230