1 #ifndef XEN__XVMALLOC_H
2 #define XEN__XVMALLOC_H
3 
4 #include <xen/types.h>
5 
6 /*
7  * Xen malloc/free-style interface, as long as there's no need to have
8  * physically contiguous memory allocated.  These should be used in preference
9  * to xmalloc() et al.
10  */
11 
12 /* Allocate space for typed object. */
13 #define xvmalloc(_type) ((_type *)_xvmalloc(sizeof(_type), __alignof__(_type)))
14 #define xvzalloc(_type) ((_type *)_xvzalloc(sizeof(_type), __alignof__(_type)))
15 
16 /* Allocate space for a typed object and copy an existing instance. */
17 #define xvmemdup(ptr)                                          \
18 ({                                                             \
19     void *p_ = _xvmalloc(sizeof(*(ptr)), __alignof__(*(ptr))); \
20     if ( p_ )                                                  \
21         memcpy(p_, ptr, sizeof(*(ptr)));                       \
22     (typeof(*(ptr)) *)p_;                                      \
23 })
24 
25 #define DIM_MUL1(n) (n)
26 #define DIM_MUL2(n1, n2) ({                                     \
27     unsigned long res_;                                         \
28     __builtin_umull_overflow(n1, n2, &res_) ? ULONG_MAX : res_; \
29 })
30 #define DIM_MUL_(n, nums...) DIM_MUL##n(nums)
31 #define DIM_MUL(n, nums...) DIM_MUL_(n, ## nums)
32 
33 /* Allocate space for array of typed objects. */
34 #define xvmalloc_array(type, num, nums...) \
35     ((type *)_xvmalloc_array(sizeof(type), __alignof__(type), \
36                              DIM_MUL(count_args(num, ## nums), num, ## nums)))
37 #define xvzalloc_array(type, num, nums...) \
38     ((type *)_xvzalloc_array(sizeof(type), __alignof__(type), \
39                              DIM_MUL(count_args(num, ## nums), num, ## nums)))
40 
41 /* Allocate space for a structure with a flexible array of typed objects. */
42 #define xvzalloc_flex_struct(type, field, nr) \
43     ((type *)_xvzalloc(offsetof(type, field[nr]), __alignof__(type)))
44 
45 #define xvmalloc_flex_struct(type, field, nr) \
46     ((type *)_xvmalloc(offsetof(type, field[nr]), __alignof__(type)))
47 
48 /* Re-allocate space for a structure with a flexible array of typed objects. */
49 #define xvrealloc_flex_struct(ptr, field, nr)                          \
50     ((typeof(ptr))_xvrealloc(ptr, offsetof(typeof(*(ptr)), field[nr]), \
51                              __alignof__(typeof(*(ptr)))))
52 
53 #ifdef CONFIG_HAS_VMAP
54 
55 /* Free any of the above. */
56 void xvfree(void *va);
57 
58 /* Underlying functions */
59 void *_xvmalloc(size_t size, unsigned int align);
60 void *_xvzalloc(size_t size, unsigned int align);
61 void *_xvrealloc(void *va, size_t size, unsigned int align);
62 
63 #else /* !CONFIG_HAS_VMAP */
64 
65 #define xvfree      xfree
66 #define _xvmalloc   _xmalloc
67 #define _xvzalloc   _xzalloc
68 #define _xvrealloc  _xrealloc
69 
70 #endif /* CONFIG_HAS_VMAP */
71 
72 /* Free an allocation, and zero the pointer to it. */
73 #define XVFREE(p) do { \
74     xvfree(p);         \
75     (p) = NULL;        \
76 } while ( false )
77 
_xvmalloc_array(size_t size,unsigned int align,unsigned long num)78 static inline void *_xvmalloc_array(
79     size_t size, unsigned int align, unsigned long num)
80 {
81     /* Check for overflow. */
82     if ( size && num > UINT_MAX / size )
83         return NULL;
84     return _xvmalloc(size * num, align);
85 }
86 
_xvzalloc_array(size_t size,unsigned int align,unsigned long num)87 static inline void *_xvzalloc_array(
88     size_t size, unsigned int align, unsigned long num)
89 {
90     /* Check for overflow. */
91     if ( size && num > UINT_MAX / size )
92         return NULL;
93     return _xvzalloc(size * num, align);
94 }
95 
96 #endif /* XEN__XVMALLOC_H */
97