On 16.09.19 18:24, Jan Beulich wrote:
Hi, Jan.
+ ROUNDUP_SIZE(tmp_size);
+
+ if ( tmp_size <= curr_size && ((unsigned long)ptr & (align - 1)) == 0 )
+ return ptr; /* the size and alignment fit in already allocated space */
You also don't seem to ever update ptr in case you want to use the
(head) padding, i.e. you'd hand back a pointer to a block which the
caller would assume extends past its actual end. I think you want
to calculate the new tentative pointer (taking the requested
alignment into account), and only from that calculate curr_size
(which perhaps would better be named "usable" or "space" or some
such). Obviously the (head) padding block may need updating, too.
I am afraid I don't completely understand your point here. And sorry for
the maybe naive question, but what is the "(head) padding" here?
The very padding talked about earlier. I did add "(head)" to clarify
it's that specific case - after all tail padding is far more common.
Still unsure, I completely understand your point regarding calculating
tentative pointer and then curr_size.
----------
Does the diff below is close to what you meant?
---
xen/common/xmalloc_tlsf.c | 113
++++++++++++++++++++++++++++++++++++++--------
xen/include/xen/xmalloc.h | 1 +
2 files changed, 96 insertions(+), 18 deletions(-)
diff --git a/xen/common/xmalloc_tlsf.c b/xen/common/xmalloc_tlsf.c
index e98ad65..f24c97c 100644
--- a/xen/common/xmalloc_tlsf.c
+++ b/xen/common/xmalloc_tlsf.c
@@ -554,10 +554,40 @@ static void tlsf_init(void)
#define ZERO_BLOCK_PTR ((void *)-1L)
#endif
+static void *strip_padding(void *p)
+{
+ struct bhdr *b = (struct bhdr *)(p - BHDR_OVERHEAD);
+
+ if ( b->size & FREE_BLOCK )
+ {
+ p -= b->size & ~FREE_BLOCK;
+ b = (struct bhdr *)(p - BHDR_OVERHEAD);
+ ASSERT(!(b->size & FREE_BLOCK));
+ }
+
+ return p;
+}
+
+static void *add_padding(void *p, unsigned long align)
+{
+ u32 pad;
+
+ if ( (pad = -(long)p & (align - 1)) != 0 )
+ {
+ char *q = (char *)p + pad;
+ struct bhdr *b = (struct bhdr *)(q - BHDR_OVERHEAD);
+
+ ASSERT(q > (char *)p);
+ b->size = pad | FREE_BLOCK;
+ p = q;
+ }
+
+ return p;
+}
+
void *_xmalloc(unsigned long size, unsigned long align)
{
void *p = NULL;
- u32 pad;
ASSERT(!in_irq());
@@ -578,14 +608,7 @@ void *_xmalloc(unsigned long size, unsigned long align)
return xmalloc_whole_pages(size - align + MEM_ALIGN, align);
/* Add alignment padding. */
- if ( (pad = -(long)p & (align - 1)) != 0 )
- {
- char *q = (char *)p + pad;
- struct bhdr *b = (struct bhdr *)(q - BHDR_OVERHEAD);
- ASSERT(q > (char *)p);
- b->size = pad | FREE_BLOCK;
- p = q;
- }
+ p = add_padding(p, align);
ASSERT(((unsigned long)p & (align - 1)) == 0);
return p;
@@ -598,10 +621,70 @@ void *_xzalloc(unsigned long size, unsigned long
align)
return p ? memset(p, 0, size) : p;
}
-void xfree(void *p)
+void *_xrealloc(void *ptr, unsigned long size, unsigned long align)
{
- struct bhdr *b;
+ unsigned long curr_size, tmp_size;
+ void *p;
+
+ if ( !size )
+ {
+ xfree(ptr);
+ return ZERO_BLOCK_PTR;
+ }
+
+ if ( ptr == NULL || ptr == ZERO_BLOCK_PTR )
+ return _xmalloc(size, align);
+
+ ASSERT((align & (align - 1)) == 0);
+ if ( align < MEM_ALIGN )
+ align = MEM_ALIGN;
+
+ tmp_size = size + align - MEM_ALIGN;
+
+ if ( tmp_size < PAGE_SIZE )
+ tmp_size = (tmp_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE :
+ ROUNDUP_SIZE(tmp_size);
+
+ if ( !((unsigned long)ptr & (PAGE_SIZE - 1)) )
+ {
+ curr_size = (unsigned long)PFN_ORDER(virt_to_page(ptr)) <<
PAGE_SHIFT;
+
+ if ( tmp_size <= curr_size && ((unsigned long)ptr & (align -
1)) == 0 )
+ return ptr;
+ }
+ else
+ {
+ struct bhdr *b;
+
+ /* Strip alignment padding. */
+ p = strip_padding(ptr);
+
+ b = (struct bhdr *)(p - BHDR_OVERHEAD);
+ curr_size = b->size & BLOCK_SIZE_MASK;
+
+ if ( tmp_size <= curr_size )
+ {
+ /* Add alignment padding. */
+ p = add_padding(p, align);
+
+ ASSERT(((unsigned long)p & (align - 1)) == 0);
+
+ return p;
+ }
+ }
+
+ p = _xzalloc(size, align);
+ if ( p )
+ {
+ memcpy(p, ptr, min(curr_size, size));
+ xfree(ptr);
+ }
+
+ return p;
+}
+
+void xfree(void *p)
+{
if ( p == NULL || p == ZERO_BLOCK_PTR )
return;
@@ -626,13 +709,7 @@ void xfree(void *p)
}
/* Strip alignment padding. */
- b = (struct bhdr *)((char *)p - BHDR_OVERHEAD);
- if ( b->size & FREE_BLOCK )
- {
- p = (char *)p - (b->size & ~FREE_BLOCK);
- b = (struct bhdr *)((char *)p - BHDR_OVERHEAD);
- ASSERT(!(b->size & FREE_BLOCK));
- }
+ p = strip_padding(p);
xmem_pool_free(p, xenpool);
}
diff --git a/xen/include/xen/xmalloc.h b/xen/include/xen/xmalloc.h
index f075d2d..831152f 100644
--- a/xen/include/xen/xmalloc.h
+++ b/xen/include/xen/xmalloc.h
@@ -51,6 +51,7 @@ extern void xfree(void *);
/* Underlying functions */
extern void *_xmalloc(unsigned long size, unsigned long align);
extern void *_xzalloc(unsigned long size, unsigned long align);
+extern void *_xrealloc(void *ptr, unsigned long size, unsigned long align);
static inline void *_xmalloc_array(
unsigned long size, unsigned long align, unsigned long num)
--
2.7.4
--
Regards,
Oleksandr Tyshchenko
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel