LinuxKPI: Implement ksize() function.

In Linux, ksize() gets the actual amount of memory allocated for a given
object. This commit adds malloc_usable_size() to FreeBSD KPI which does
the same. It also maps LinuxKPI ksize() to newly created function.

ksize() function is used by drm-kmod.

Reviewed by:	hselasky, kib
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D26215
This commit is contained in:
Vladimir Kondratyev 2020-08-29 19:26:31 +00:00
parent 8ea469ebbb
commit 5d4bf0578f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=364964
6 changed files with 61 additions and 1 deletions

View file

@ -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.

View file

@ -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);

View file

@ -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);
/*

View file

@ -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)

View file

@ -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)));
}

View file

@ -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