1*eda14cbcSMatt Macy /* 2*eda14cbcSMatt Macy * CDDL HEADER START 3*eda14cbcSMatt Macy * 4*eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5*eda14cbcSMatt Macy * Common Development and Distribution License, Version 1.0 only 6*eda14cbcSMatt Macy * (the "License"). You may not use this file except in compliance 7*eda14cbcSMatt Macy * with the License. 8*eda14cbcSMatt Macy * 9*eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*eda14cbcSMatt Macy * or http://www.opensolaris.org/os/licensing. 11*eda14cbcSMatt Macy * See the License for the specific language governing permissions 12*eda14cbcSMatt Macy * and limitations under the License. 13*eda14cbcSMatt Macy * 14*eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 15*eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 17*eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 18*eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 19*eda14cbcSMatt Macy * 20*eda14cbcSMatt Macy * CDDL HEADER END 21*eda14cbcSMatt Macy */ 22*eda14cbcSMatt Macy /* 23*eda14cbcSMatt Macy * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*eda14cbcSMatt Macy * Use is subject to license terms. 25*eda14cbcSMatt Macy */ 26*eda14cbcSMatt Macy 27*eda14cbcSMatt Macy #ifndef _LIBSPL_UMEM_H 28*eda14cbcSMatt Macy #define _LIBSPL_UMEM_H 29*eda14cbcSMatt Macy 30*eda14cbcSMatt Macy /* 31*eda14cbcSMatt Macy * XXX: We should use the real portable umem library if it is detected 32*eda14cbcSMatt Macy * at configure time. However, if the library is not available, we can 33*eda14cbcSMatt Macy * use a trivial malloc based implementation. This obviously impacts 34*eda14cbcSMatt Macy * performance, but unless you are using a full userspace build of zpool for 35*eda14cbcSMatt Macy * something other than ztest, you are likely not going to notice or care. 36*eda14cbcSMatt Macy * 37*eda14cbcSMatt Macy * https://labs.omniti.com/trac/portableumem 38*eda14cbcSMatt Macy */ 39*eda14cbcSMatt Macy #include <sys/debug.h> 40*eda14cbcSMatt Macy 41*eda14cbcSMatt Macy #include <stdlib.h> 42*eda14cbcSMatt Macy #include <stdio.h> 43*eda14cbcSMatt Macy #include <string.h> 44*eda14cbcSMatt Macy 45*eda14cbcSMatt Macy #ifdef __cplusplus 46*eda14cbcSMatt Macy extern "C" { 47*eda14cbcSMatt Macy #endif 48*eda14cbcSMatt Macy 49*eda14cbcSMatt Macy typedef void vmem_t; 50*eda14cbcSMatt Macy 51*eda14cbcSMatt Macy /* 52*eda14cbcSMatt Macy * Flags for umem_alloc/umem_free 53*eda14cbcSMatt Macy */ 54*eda14cbcSMatt Macy #define UMEM_DEFAULT 0x0000 /* normal -- may fail */ 55*eda14cbcSMatt Macy #define UMEM_NOFAIL 0x0100 /* Never fails */ 56*eda14cbcSMatt Macy 57*eda14cbcSMatt Macy /* 58*eda14cbcSMatt Macy * Flags for umem_cache_create() 59*eda14cbcSMatt Macy */ 60*eda14cbcSMatt Macy #define UMC_NODEBUG 0x00020000 61*eda14cbcSMatt Macy 62*eda14cbcSMatt Macy #define UMEM_CACHE_NAMELEN 31 63*eda14cbcSMatt Macy 64*eda14cbcSMatt Macy typedef int umem_nofail_callback_t(void); 65*eda14cbcSMatt Macy typedef int umem_constructor_t(void *, void *, int); 66*eda14cbcSMatt Macy typedef void umem_destructor_t(void *, void *); 67*eda14cbcSMatt Macy typedef void umem_reclaim_t(void *); 68*eda14cbcSMatt Macy 69*eda14cbcSMatt Macy typedef struct umem_cache { 70*eda14cbcSMatt Macy char cache_name[UMEM_CACHE_NAMELEN + 1]; 71*eda14cbcSMatt Macy size_t cache_bufsize; 72*eda14cbcSMatt Macy size_t cache_align; 73*eda14cbcSMatt Macy umem_constructor_t *cache_constructor; 74*eda14cbcSMatt Macy umem_destructor_t *cache_destructor; 75*eda14cbcSMatt Macy umem_reclaim_t *cache_reclaim; 76*eda14cbcSMatt Macy void *cache_private; 77*eda14cbcSMatt Macy void *cache_arena; 78*eda14cbcSMatt Macy int cache_cflags; 79*eda14cbcSMatt Macy } umem_cache_t; 80*eda14cbcSMatt Macy 81*eda14cbcSMatt Macy /* Prototypes for functions to provide defaults for umem envvars */ 82*eda14cbcSMatt Macy const char *_umem_debug_init(void); 83*eda14cbcSMatt Macy const char *_umem_options_init(void); 84*eda14cbcSMatt Macy const char *_umem_logging_init(void); 85*eda14cbcSMatt Macy 86*eda14cbcSMatt Macy static inline void * 87*eda14cbcSMatt Macy umem_alloc(size_t size, int flags) 88*eda14cbcSMatt Macy { 89*eda14cbcSMatt Macy void *ptr = NULL; 90*eda14cbcSMatt Macy 91*eda14cbcSMatt Macy do { 92*eda14cbcSMatt Macy ptr = malloc(size); 93*eda14cbcSMatt Macy } while (ptr == NULL && (flags & UMEM_NOFAIL)); 94*eda14cbcSMatt Macy 95*eda14cbcSMatt Macy return (ptr); 96*eda14cbcSMatt Macy } 97*eda14cbcSMatt Macy 98*eda14cbcSMatt Macy static inline void * 99*eda14cbcSMatt Macy umem_alloc_aligned(size_t size, size_t align, int flags) 100*eda14cbcSMatt Macy { 101*eda14cbcSMatt Macy void *ptr = NULL; 102*eda14cbcSMatt Macy int rc = EINVAL; 103*eda14cbcSMatt Macy 104*eda14cbcSMatt Macy do { 105*eda14cbcSMatt Macy rc = posix_memalign(&ptr, align, size); 106*eda14cbcSMatt Macy } while (rc == ENOMEM && (flags & UMEM_NOFAIL)); 107*eda14cbcSMatt Macy 108*eda14cbcSMatt Macy if (rc == EINVAL) { 109*eda14cbcSMatt Macy fprintf(stderr, "%s: invalid memory alignment (%zd)\n", 110*eda14cbcSMatt Macy __func__, align); 111*eda14cbcSMatt Macy if (flags & UMEM_NOFAIL) 112*eda14cbcSMatt Macy abort(); 113*eda14cbcSMatt Macy return (NULL); 114*eda14cbcSMatt Macy } 115*eda14cbcSMatt Macy 116*eda14cbcSMatt Macy return (ptr); 117*eda14cbcSMatt Macy } 118*eda14cbcSMatt Macy 119*eda14cbcSMatt Macy static inline void * 120*eda14cbcSMatt Macy umem_zalloc(size_t size, int flags) 121*eda14cbcSMatt Macy { 122*eda14cbcSMatt Macy void *ptr = NULL; 123*eda14cbcSMatt Macy 124*eda14cbcSMatt Macy ptr = umem_alloc(size, flags); 125*eda14cbcSMatt Macy if (ptr) 126*eda14cbcSMatt Macy memset(ptr, 0, size); 127*eda14cbcSMatt Macy 128*eda14cbcSMatt Macy return (ptr); 129*eda14cbcSMatt Macy } 130*eda14cbcSMatt Macy 131*eda14cbcSMatt Macy static inline void 132*eda14cbcSMatt Macy umem_free(void *ptr, size_t size __maybe_unused) 133*eda14cbcSMatt Macy { 134*eda14cbcSMatt Macy free(ptr); 135*eda14cbcSMatt Macy } 136*eda14cbcSMatt Macy 137*eda14cbcSMatt Macy static inline void 138*eda14cbcSMatt Macy umem_nofail_callback(umem_nofail_callback_t *cb __maybe_unused) 139*eda14cbcSMatt Macy {} 140*eda14cbcSMatt Macy 141*eda14cbcSMatt Macy static inline umem_cache_t * 142*eda14cbcSMatt Macy umem_cache_create( 143*eda14cbcSMatt Macy char *name, size_t bufsize, size_t align, 144*eda14cbcSMatt Macy umem_constructor_t *constructor, 145*eda14cbcSMatt Macy umem_destructor_t *destructor, 146*eda14cbcSMatt Macy umem_reclaim_t *reclaim, 147*eda14cbcSMatt Macy void *priv, void *vmp, int cflags) 148*eda14cbcSMatt Macy { 149*eda14cbcSMatt Macy umem_cache_t *cp; 150*eda14cbcSMatt Macy 151*eda14cbcSMatt Macy cp = (umem_cache_t *)umem_alloc(sizeof (umem_cache_t), UMEM_DEFAULT); 152*eda14cbcSMatt Macy if (cp) { 153*eda14cbcSMatt Macy strlcpy(cp->cache_name, name, UMEM_CACHE_NAMELEN); 154*eda14cbcSMatt Macy cp->cache_bufsize = bufsize; 155*eda14cbcSMatt Macy cp->cache_align = align; 156*eda14cbcSMatt Macy cp->cache_constructor = constructor; 157*eda14cbcSMatt Macy cp->cache_destructor = destructor; 158*eda14cbcSMatt Macy cp->cache_reclaim = reclaim; 159*eda14cbcSMatt Macy cp->cache_private = priv; 160*eda14cbcSMatt Macy cp->cache_arena = vmp; 161*eda14cbcSMatt Macy cp->cache_cflags = cflags; 162*eda14cbcSMatt Macy } 163*eda14cbcSMatt Macy 164*eda14cbcSMatt Macy return (cp); 165*eda14cbcSMatt Macy } 166*eda14cbcSMatt Macy 167*eda14cbcSMatt Macy static inline void 168*eda14cbcSMatt Macy umem_cache_destroy(umem_cache_t *cp) 169*eda14cbcSMatt Macy { 170*eda14cbcSMatt Macy umem_free(cp, sizeof (umem_cache_t)); 171*eda14cbcSMatt Macy } 172*eda14cbcSMatt Macy 173*eda14cbcSMatt Macy static inline void * 174*eda14cbcSMatt Macy umem_cache_alloc(umem_cache_t *cp, int flags) 175*eda14cbcSMatt Macy { 176*eda14cbcSMatt Macy void *ptr = NULL; 177*eda14cbcSMatt Macy 178*eda14cbcSMatt Macy if (cp->cache_align != 0) 179*eda14cbcSMatt Macy ptr = umem_alloc_aligned( 180*eda14cbcSMatt Macy cp->cache_bufsize, cp->cache_align, flags); 181*eda14cbcSMatt Macy else 182*eda14cbcSMatt Macy ptr = umem_alloc(cp->cache_bufsize, flags); 183*eda14cbcSMatt Macy 184*eda14cbcSMatt Macy if (ptr && cp->cache_constructor) 185*eda14cbcSMatt Macy cp->cache_constructor(ptr, cp->cache_private, UMEM_DEFAULT); 186*eda14cbcSMatt Macy 187*eda14cbcSMatt Macy return (ptr); 188*eda14cbcSMatt Macy } 189*eda14cbcSMatt Macy 190*eda14cbcSMatt Macy static inline void 191*eda14cbcSMatt Macy umem_cache_free(umem_cache_t *cp, void *ptr) 192*eda14cbcSMatt Macy { 193*eda14cbcSMatt Macy if (cp->cache_destructor) 194*eda14cbcSMatt Macy cp->cache_destructor(ptr, cp->cache_private); 195*eda14cbcSMatt Macy 196*eda14cbcSMatt Macy umem_free(ptr, cp->cache_bufsize); 197*eda14cbcSMatt Macy } 198*eda14cbcSMatt Macy 199*eda14cbcSMatt Macy static inline void 200*eda14cbcSMatt Macy umem_cache_reap_now(umem_cache_t *cp __maybe_unused) 201*eda14cbcSMatt Macy { 202*eda14cbcSMatt Macy } 203*eda14cbcSMatt Macy 204*eda14cbcSMatt Macy #ifdef __cplusplus 205*eda14cbcSMatt Macy } 206*eda14cbcSMatt Macy #endif 207*eda14cbcSMatt Macy 208*eda14cbcSMatt Macy #endif 209