Files
mirror_zfs/lib/libspl/include/umem.h
T

232 lines
5.3 KiB
C
Raw Normal View History

2025-01-04 11:04:27 +11:00
// SPDX-License-Identifier: CDDL-1.0
2010-08-26 11:50:56 -07:00
/*
* 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
2022-07-11 23:16:13 +02:00
* or https://opensource.org/licenses/CDDL-1.0.
2010-08-26 11:50:56 -07:00
* 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
2013-11-01 20:26:11 +01:00
#define _LIBSPL_UMEM_H
2010-08-26 11:50:56 -07:00
2013-11-01 20:26:11 +01:00
/*
* 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
2010-08-26 11:50:56 -07:00
* use a trivial malloc based implementation. This obviously impacts
* performance, but unless you are using a full userspace build of zpool for
* something other than ztest, you are likely not going to notice or care.
2010-08-26 11:50:56 -07:00
*
* https://labs.omniti.com/trac/portableumem
*/
#include <sys/debug.h>
2010-08-26 11:50:56 -07:00
#include <stdlib.h>
#include <stdio.h>
2018-02-15 17:53:18 -08:00
#include <string.h>
2010-08-26 11:50:56 -07:00
#ifdef __cplusplus
extern "C" {
#endif
typedef void vmem_t;
/*
* Flags for umem_alloc/umem_free
*/
2013-11-01 20:26:11 +01:00
#define UMEM_DEFAULT 0x0000 /* normal -- may fail */
#define UMEM_NOFAIL 0x0100 /* Never fails */
2010-08-26 11:50:56 -07:00
/*
* Flags for umem_cache_create()
*/
2013-11-01 20:26:11 +01:00
#define UMC_NODEBUG 0x00020000
2010-08-26 11:50:56 -07:00
2013-11-01 20:26:11 +01:00
#define UMEM_CACHE_NAMELEN 31
2010-08-26 11:50:56 -07:00
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;
2020-06-11 16:38:25 -04:00
/* Prototypes for functions to provide defaults for umem envvars */
const char *_umem_debug_init(void);
const char *_umem_options_init(void);
const char *_umem_logging_init(void);
__attribute__((malloc, alloc_size(1)))
2010-08-26 11:50:56 -07:00
static inline void *
umem_alloc(size_t size, int flags)
{
2014-05-21 11:17:23 +02:00
void *ptr = NULL;
2010-08-26 11:50:56 -07:00
do {
ptr = malloc(size);
} while (ptr == NULL && (flags & UMEM_NOFAIL));
2013-11-01 20:26:11 +01:00
return (ptr);
2010-08-26 11:50:56 -07:00
}
__attribute__((malloc, alloc_size(1)))
2010-08-26 11:50:56 -07:00
static inline void *
umem_alloc_aligned(size_t size, size_t align, int flags)
{
2014-05-21 11:17:23 +02:00
void *ptr = NULL;
int rc;
2010-08-26 11:50:56 -07:00
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();
2013-11-01 20:26:11 +01:00
return (NULL);
2010-08-26 11:50:56 -07:00
}
2013-11-01 20:26:11 +01:00
return (ptr);
2010-08-26 11:50:56 -07:00
}
__attribute__((malloc, alloc_size(1)))
2010-08-26 11:50:56 -07:00
static inline void *
umem_zalloc(size_t size, int flags)
{
2014-05-21 11:17:23 +02:00
void *ptr = NULL;
2010-08-26 11:50:56 -07:00
ptr = umem_alloc(size, flags);
if (ptr)
memset(ptr, 0, size);
2013-11-01 20:26:11 +01:00
return (ptr);
2010-08-26 11:50:56 -07:00
}
static inline void
2022-01-15 00:37:55 +01:00
umem_free(const void *ptr, size_t size __maybe_unused)
2010-08-26 11:50:56 -07:00
{
2022-01-15 00:37:55 +01:00
free((void *)ptr);
2010-08-26 11:50:56 -07:00
}
2022-10-27 06:08:31 +08:00
/*
* umem_free_aligned was added for supporting portability
* with non-POSIX platforms that require a different free
* to be used with aligned allocations.
*/
static inline void
umem_free_aligned(void *ptr, size_t size __maybe_unused)
{
#ifndef _WIN32
free((void *)ptr);
#else
_aligned_free(ptr);
#endif
}
2010-08-26 11:50:56 -07:00
static inline void
umem_nofail_callback(umem_nofail_callback_t *cb __maybe_unused)
{}
2010-08-26 11:50:56 -07:00
static inline umem_cache_t *
2013-11-01 20:26:11 +01:00
umem_cache_create(
2022-04-19 20:38:30 +02:00
const char *name, size_t bufsize, size_t align,
2013-11-01 20:26:11 +01:00
umem_constructor_t *constructor,
umem_destructor_t *destructor,
umem_reclaim_t *reclaim,
void *priv, void *vmp, int cflags)
2010-08-26 11:50:56 -07:00
{
umem_cache_t *cp;
2020-06-06 15:54:04 -04:00
cp = (umem_cache_t *)umem_alloc(sizeof (umem_cache_t), UMEM_DEFAULT);
2010-08-26 11:50:56 -07:00
if (cp) {
strlcpy(cp->cache_name, name, UMEM_CACHE_NAMELEN);
2010-08-26 11:50:56 -07:00
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;
}
2013-11-01 20:26:11 +01:00
return (cp);
2010-08-26 11:50:56 -07:00
}
static inline void
umem_cache_destroy(umem_cache_t *cp)
{
2013-11-01 20:26:11 +01:00
umem_free(cp, sizeof (umem_cache_t));
2010-08-26 11:50:56 -07:00
}
__attribute__((malloc))
2010-08-26 11:50:56 -07:00
static inline void *
umem_cache_alloc(umem_cache_t *cp, int flags)
{
2014-05-21 11:17:23 +02:00
void *ptr = NULL;
2010-08-26 11:50:56 -07:00
if (cp->cache_align != 0)
2013-11-01 20:26:11 +01:00
ptr = umem_alloc_aligned(
cp->cache_bufsize, cp->cache_align, flags);
2010-08-26 11:50:56 -07:00
else
ptr = umem_alloc(cp->cache_bufsize, flags);
if (ptr && cp->cache_constructor)
cp->cache_constructor(ptr, cp->cache_private, UMEM_DEFAULT);
2013-11-01 20:26:11 +01:00
return (ptr);
2010-08-26 11:50:56 -07:00
}
static inline void
umem_cache_free(umem_cache_t *cp, void *ptr)
{
if (cp->cache_destructor)
cp->cache_destructor(ptr, cp->cache_private);
2022-10-27 06:08:31 +08:00
if (cp->cache_align != 0)
umem_free_aligned(ptr, cp->cache_bufsize);
else
umem_free(ptr, cp->cache_bufsize);
2010-08-26 11:50:56 -07:00
}
static inline void
umem_cache_reap_now(umem_cache_t *cp __maybe_unused)
{
}
2010-08-26 11:50:56 -07:00
#ifdef __cplusplus
}
#endif
#endif