summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/sys/malloc.h
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/sys/malloc.h')
-rw-r--r--freebsd/sys/sys/malloc.h76
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,