summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Kondratyev <wulf@FreeBSD.org>2020-08-29 19:26:31 +0000
committerVladimir Kondratyev <wulf@FreeBSD.org>2020-08-29 19:26:31 +0000
commit5d4bf0578f0c665f2f28f8ca0970a3368fad6e7b (patch)
treef1059fc907da1517fdad1552ff15f3befab2308e
parent8ea469ebbb7eab772f2968179f29c12b1cd734e1 (diff)
Notes
-rw-r--r--share/man/man9/malloc.911
-rw-r--r--sys/compat/linuxkpi/common/include/linux/slab.h6
-rw-r--r--sys/kern/kern_malloc.c36
-rw-r--r--sys/sys/malloc.h1
-rw-r--r--sys/vm/memguard.c6
-rw-r--r--sys/vm/memguard.h2
6 files changed, 61 insertions, 1 deletions
diff --git a/share/man/man9/malloc.9 b/share/man/man9/malloc.9
index c10a007ec2cb..5ce77d336cae 100644
--- a/share/man/man9/malloc.9
+++ b/share/man/man9/malloc.9
@@ -29,7 +29,7 @@
.\" $NetBSD: malloc.9,v 1.3 1996/11/11 00:05:11 lukem Exp $
.\" $FreeBSD$
.\"
-.Dd August 3, 2020
+.Dd August 28, 2020
.Dt MALLOC 9
.Os
.Sh NAME
@@ -55,6 +55,8 @@
.Fn realloc "void *addr" "size_t size" "struct malloc_type *type" "int flags"
.Ft void *
.Fn reallocf "void *addr" "size_t size" "struct malloc_type *type" "int flags"
+.Ft size_t
+.Fn malloc_usable_size "const void *addr"
.Fn MALLOC_DECLARE type
.In sys/param.h
.In sys/malloc.h
@@ -150,6 +152,13 @@ function is identical to
except that it
will free the passed pointer when the requested memory cannot be allocated.
.Pp
+The
+.Fn malloc_usable_size
+function returns the usable size of the allocation pointed to by
+.Fa addr .
+The return value may be larger than the size that was requested during
+allocation.
+.Pp
Unlike its standard C library counterpart
.Pq Xr malloc 3 ,
the kernel version takes two more arguments.
diff --git a/sys/compat/linuxkpi/common/include/linux/slab.h b/sys/compat/linuxkpi/common/include/linux/slab.h
index 5ff7000f3658..ae1c9d81843e 100644
--- a/sys/compat/linuxkpi/common/include/linux/slab.h
+++ b/sys/compat/linuxkpi/common/include/linux/slab.h
@@ -154,6 +154,12 @@ kfree(const void *ptr)
free(__DECONST(void *, ptr), M_KMALLOC);
}
+static inline size_t
+ksize(const void *ptr)
+{
+ return (malloc_usable_size(ptr));
+}
+
extern struct linux_kmem_cache *linux_kmem_cache_create(const char *name,
size_t size, size_t align, unsigned flags, linux_kmem_ctor_t *ctor);
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c
index 300a1692e7df..4ec2cc4a219a 100644
--- a/sys/kern/kern_malloc.c
+++ b/sys/kern/kern_malloc.c
@@ -938,6 +938,42 @@ reallocf(void *addr, size_t size, struct malloc_type *mtp, int flags)
return (mem);
}
+/*
+ * malloc_usable_size: returns the usable size of the allocation.
+ */
+size_t
+malloc_usable_size(const void *addr)
+{
+#ifndef DEBUG_REDZONE
+ uma_zone_t zone;
+ uma_slab_t slab;
+#endif
+ u_long size;
+
+ if (addr == NULL)
+ return (0);
+
+#ifdef DEBUG_MEMGUARD
+ if (is_memguard_addr(__DECONST(void *, addr)))
+ return (memguard_get_req_size(addr));
+#endif
+
+#ifdef DEBUG_REDZONE
+ size = redzone_get_size(__DECONST(void *, addr));
+#else
+ vtozoneslab((vm_offset_t)addr & (~UMA_SLAB_MASK), &zone, &slab);
+ if (slab == NULL)
+ panic("malloc_usable_size: address %p(%p) is not allocated.\n",
+ addr, (void *)((u_long)addr & (~UMA_SLAB_MASK)));
+
+ if (!malloc_large_slab(slab))
+ size = zone->uz_size;
+ else
+ size = malloc_large_size(slab);
+#endif
+ return (size);
+}
+
CTASSERT(VM_KMEM_SIZE_SCALE >= 1);
/*
diff --git a/sys/sys/malloc.h b/sys/sys/malloc.h
index 403d85feecb8..270f51527c04 100644
--- a/sys/sys/malloc.h
+++ b/sys/sys/malloc.h
@@ -244,6 +244,7 @@ void malloc_type_allocated(struct malloc_type *type, unsigned long size);
void malloc_type_freed(struct malloc_type *type, unsigned long size);
void malloc_type_list(malloc_type_list_func_t *, void *);
void malloc_uninit(void *);
+size_t malloc_usable_size(const void *);
void *realloc(void *addr, size_t size, struct malloc_type *type, int flags)
__result_use_check __alloc_size(2);
void *reallocf(void *addr, size_t size, struct malloc_type *type, int flags)
diff --git a/sys/vm/memguard.c b/sys/vm/memguard.c
index 9f7461c43790..2dda494f9c7a 100644
--- a/sys/vm/memguard.c
+++ b/sys/vm/memguard.c
@@ -504,3 +504,9 @@ memguard_cmp_zone(uma_zone_t zone)
*/
return (strcmp(zone->uz_name, vm_memguard_desc) == 0);
}
+
+unsigned long
+memguard_get_req_size(const void *addr)
+{
+ return (*v2sizep(trunc_page((uintptr_t)addr)));
+}
diff --git a/sys/vm/memguard.h b/sys/vm/memguard.h
index 9abfc362d40a..d541a1bcda05 100644
--- a/sys/vm/memguard.h
+++ b/sys/vm/memguard.h
@@ -43,6 +43,7 @@ void memguard_init(struct vmem *);
void *memguard_alloc(unsigned long, int);
void *memguard_realloc(void *, unsigned long, struct malloc_type *, int);
void memguard_free(void *);
+unsigned long memguard_get_req_size(const void *);
int memguard_cmp_mtp(struct malloc_type *, unsigned long);
int memguard_cmp_zone(uma_zone_t);
int is_memguard_addr(void *);
@@ -52,6 +53,7 @@ int is_memguard_addr(void *);
#define memguard_alloc(size, flags) NULL
#define memguard_realloc(a, s, mtp, f) NULL
#define memguard_free(addr) do { } while (0)
+#define memguard_get_req_size(addr) 0
#define memguard_cmp_mtp(mtp, size) 0
#define memguard_cmp_zone(zone) 0
#define is_memguard_addr(addr) 0