>Until now, xmalloc_cacheline() has provided its caller memory that does not
>share a cache line, but when posix_memalign() is not available it did not
>provide a full cache line; instead, it returned memory that was offset 8 bytes
>into a cache line.  This makes it hard for clients to design structures to be 
>cache
>line-aligned.  This commit changes
>xmalloc_cacheline() to always return a full cache line instead of memory
>offset into one.
>
>Signed-off-by: Ben Pfaff <[email protected]>
>---
> lib/util.c | 60 ++++++++++++++++++++++++++++++++---------------------------
>-
> 1 file changed, 32 insertions(+), 28 deletions(-)
>
>diff --git a/lib/util.c b/lib/util.c
>index 9e6edd27ae4c..137091a3cd4f 100644
>--- a/lib/util.c
>+++ b/lib/util.c
>@@ -196,15 +196,9 @@ x2nrealloc(void *p, size_t *n, size_t s)
>     return xrealloc(p, *n * s);
> }
>
>-/* The desired minimum alignment for an allocated block of memory. */ -
>#define MEM_ALIGN MAX(sizeof(void *), 8) -
>BUILD_ASSERT_DECL(IS_POW2(MEM_ALIGN));
>-BUILD_ASSERT_DECL(CACHE_LINE_SIZE >= MEM_ALIGN);
>-
>-/* Allocates and returns 'size' bytes of memory in dedicated cache lines.  
>That
>- * is, the memory block returned will not share a cache line with other data,
>- * avoiding "false sharing".  (The memory returned will not be at the start of
>- * a cache line, though, so don't assume such alignment.)
>+/* Allocates and returns 'size' bytes of memory aligned to a cache line
>+and in
>+ * dedicated cache lines.  That is, the memory block returned will not
>+share a
>+ * cache line with other data, avoiding "false sharing".
>  *
>  * Use free_cacheline() to free the returned memory block. */  void * @@ -
>221,28 +215,37 @@ xmalloc_cacheline(size_t size)
>     }
>     return p;
> #else
>-    void **payload;
>-    void *base;
>-
>     /* Allocate room for:
>      *
>-     *     - Up to CACHE_LINE_SIZE - 1 bytes before the payload, so that the
>-     *       start of the payload doesn't potentially share a cache line.
>+     *     - Header padding: Up to CACHE_LINE_SIZE - 1 bytes, to allow the
>+     *       pointer to be aligned exactly sizeof(void *) bytes before the
>+     *       beginning of a cache line.
>      *
>-     *     - A payload consisting of a void *, followed by padding out to
>-     *       MEM_ALIGN bytes, followed by 'size' bytes of user data.
>+     *     - Pointer: A pointer to the start of the header padding, to allow 
>us
>+     *       to free() the block later.
>      *
>-     *     - Space following the payload up to the end of the cache line, so
>-     *       that the end of the payload doesn't potentially share a cache 
>line
>-     *       with some following block. */
>-    base = xmalloc((CACHE_LINE_SIZE - 1)
>-                   + ROUND_UP(MEM_ALIGN + size, CACHE_LINE_SIZE));
>-
>-    /* Locate the payload and store a pointer to the base at the beginning. */
>-    payload = (void **) ROUND_UP((uintptr_t) base, CACHE_LINE_SIZE);
>-    *payload = base;
>-
>-    return (char *) payload + MEM_ALIGN;
>+     *     - User data: 'size' bytes.
>+     *
>+     *     - Trailer padding: Enough to bring the user data up to a cache line
>+     *       multiple.
>+     *
>+     * +---------------+---------+------------------------+---------+
>+     * | header        | pointer | user data              | trailer |
>+     * +---------------+---------+------------------------+---------+
>+     * ^               ^         ^
>+     * |               |         |
>+     * p               q         r
>+     *
>+     */
>+    void *p = xmalloc((CACHE_LINE_SIZE - 1)
>+                      + sizeof(void *)
>+                      + ROUND_UP(size, CACHE_LINE_SIZE));
>+    bool runt = PAD_SIZE((uintptr_t) p, CACHE_LINE_SIZE) < sizeof(void *);
>+    void *r = (void *) ROUND_UP((uintptr_t) p + (runt ? CACHE_LINE_SIZE : 0),
>+                                CACHE_LINE_SIZE);
>+    void **q = (void **) r - 1;
>+    *q = p;
>+    return r;
> #endif
> }
>
>@@ -265,7 +268,8 @@ free_cacheline(void *p)
>     free(p);
> #else
>     if (p) {
>-        free(*(void **) ((uintptr_t) p - MEM_ALIGN));
>+        void **q = (void **) p - 1;
>+        free(*q);
>     }
> #endif
> }
>--

Thanks for the patch.
Reviewed and tested this and now it returns 64 byte aligned address.

Acked-by: Bhanuprakash Bodireddy <[email protected]>

- Bhanuprakash.


_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to