diff options
Diffstat (limited to 'freebsd/sys/sys/malloc.h')
-rw-r--r-- | freebsd/sys/sys/malloc.h | 76 |
1 files changed, 67 insertions, 9 deletions
diff --git a/freebsd/sys/sys/malloc.h b/freebsd/sys/sys/malloc.h index 8c66fe81..33e1aab9 100644 --- a/freebsd/sys/sys/malloc.h +++ b/freebsd/sys/sys/malloc.h @@ -38,6 +38,9 @@ #define _SYS_MALLOC_H_ #include <sys/param.h> +#ifdef _KERNEL +#include <sys/systm.h> +#endif #include <sys/queue.h> #include <sys/_lock.h> #include <sys/_mutex.h> @@ -46,7 +49,7 @@ #define MINALLOCSIZE UMA_SMALLEST_UNIT /* - * flags to malloc. + * Flags to memory allocation functions. */ #define M_NOWAIT 0x0001 /* do not block */ #define M_WAITOK 0x0002 /* ok to block */ @@ -56,16 +59,10 @@ #define M_NODUMP 0x0800 /* don't dump pages in this allocation */ #define M_FIRSTFIT 0x1000 /* Only for vmem, fast fit. */ #define M_BESTFIT 0x2000 /* Only for vmem, low fragmentation. */ +#define M_EXEC 0x4000 /* allocate executable space. */ #define M_MAGIC 877983977 /* time when first defined :-) */ -#ifdef INVARIANTS -#define M_ZERO_INVARIANTS M_ZERO -#else -#define M_ZERO_INVARIANTS 0 -#endif - - /* * Two malloc type structures are present: malloc_type, which is used by a * type owner to declare the type, and malloc_type_internal, which holds @@ -142,7 +139,6 @@ struct malloc_type_header { #ifdef _KERNEL #ifdef __rtems__ #include <stdlib.h> -#define malloc _bsd_malloc #define realloc _bsd_realloc #define reallocf _bsd_reallocf #define free _bsd_free @@ -188,8 +184,70 @@ void *contigmalloc_domain(unsigned long size, struct malloc_type *type, __malloc_like __result_use_check __alloc_size(1) __alloc_align(6); void free(void *addr, struct malloc_type *type); void free_domain(void *addr, struct malloc_type *type); +#ifndef __rtems__ void *malloc(size_t size, struct malloc_type *type, int flags) __malloc_like __result_use_check __alloc_size(1); +#else /* __rtems__ */ +void *_bsd_malloc(size_t size, struct malloc_type *type, int flags) + __malloc_like __result_use_check __alloc_size(1); +#endif /* __rtems__ */ +/* + * Try to optimize malloc(..., ..., M_ZERO) allocations by doing zeroing in + * place if the size is known at compilation time. + * + * Passing the flag down requires malloc to blindly zero the entire object. + * In practice a lot of the zeroing can be avoided if most of the object + * gets explicitly initialized after the allocation. Letting the compiler + * zero in place gives it the opportunity to take advantage of this state. + * + * Note that the operation is only applicable if both flags and size are + * known at compilation time. If M_ZERO is passed but M_WAITOK is not, the + * allocation can fail and a NULL check is needed. However, if M_WAITOK is + * passed we know the allocation must succeed and the check can be elided. + * + * _malloc_item = malloc(_size, type, (flags) &~ M_ZERO); + * if (((flags) & M_WAITOK) != 0 || _malloc_item != NULL) + * bzero(_malloc_item, _size); + * + * If the flag is set, the compiler knows the left side is always true, + * therefore the entire statement is true and the callsite is: + * + * _malloc_item = malloc(_size, type, (flags) &~ M_ZERO); + * bzero(_malloc_item, _size); + * + * If the flag is not set, the compiler knows the left size is always false + * and the NULL check is needed, therefore the callsite is: + * + * _malloc_item = malloc(_size, type, (flags) &~ M_ZERO); + * if (_malloc_item != NULL) + * bzero(_malloc_item, _size); + * + * The implementation is a macro because of what appears to be a clang 6 bug: + * an inline function variant ended up being compiled to a mere malloc call + * regardless of argument. gcc generates expected code (like the above). + */ +#ifdef __rtems__ +/* + * The macro below was modified without the __rtems__ guards. This macro looks + * quite brittle and it is better to provoke a merge conflict in case of a + * FreeBSD baseline update. + */ +#endif /* __rtems__ */ +#define malloc(size, type, flags) ({ \ + void *_malloc_item; \ + size_t _size = (size); \ + if (__builtin_constant_p(size) && __builtin_constant_p(flags) &&\ + ((flags) & M_ZERO) != 0) { \ + _malloc_item = _bsd_malloc(_size, type, (flags) &~ M_ZERO); \ + if (((flags) & M_WAITOK) != 0 || \ + __predict_true(_malloc_item != NULL)) \ + bzero(_malloc_item, _size); \ + } else { \ + _malloc_item = _bsd_malloc(_size, type, flags); \ + } \ + _malloc_item; \ +}) + void *malloc_domain(size_t size, struct malloc_type *type, int domain, int flags) __malloc_like __result_use_check __alloc_size(1); void *mallocarray(size_t nmemb, size_t size, struct malloc_type *type, |