diff mbox

[ovs-dev] util: Add PADDED_MEMBERS_CACHELINE_MARKER macro to mark cachelines.

Message ID 1500956084-45269-1-git-send-email-bhanuprakash.bodireddy@intel.com
State Accepted
Headers show

Commit Message

Bodireddy, Bhanuprakash July 25, 2017, 4:14 a.m. UTC
PADDED_MEMBERS_CACHELINE_MARKER macro introduces a way to mark
cachelines.

This macro expands to an anonymous union containing cacheline marker,
members in nested anonymous structure, followed by array of bytes that
is multiple of UNIT bytes.

Signed-off-by: Bhanuprakash Bodireddy <bhanuprakash.bodireddy@intel.com>
---
 include/openvswitch/util.h | 38 ++++++++++++++++++++++++++++++++++++++
 lib/util.h                 |  6 ++++++
 2 files changed, 44 insertions(+)

Comments

Ben Pfaff Aug. 3, 2017, 6:34 p.m. UTC | #1
On Tue, Jul 25, 2017 at 05:14:43AM +0100, Bhanuprakash Bodireddy wrote:
> PADDED_MEMBERS_CACHELINE_MARKER macro introduces a way to mark
> cachelines.
> 
> This macro expands to an anonymous union containing cacheline marker,
> members in nested anonymous structure, followed by array of bytes that
> is multiple of UNIT bytes.
> 
> Signed-off-by: Bhanuprakash Bodireddy <bhanuprakash.bodireddy@intel.com>

Applied, thanks!  I had to add a C++ acceptable alternative but it was
not difficult:

#ifndef __cplusplus
#define PADDED_MEMBERS_CACHELINE_MARKER(UNIT, CACHELINE, MEMBERS)   \
    union {                                                         \
        OVS_CACHE_LINE_MARKER CACHELINE;                            \
        struct { MEMBERS };                                         \
        uint8_t PAD_ID[ROUND_UP(sizeof(struct { MEMBERS }), UNIT)]; \
    }
#else
#define PADDED_MEMBERS_CACHELINE_MARKER(UNIT, CACHELINE, MEMBERS)   \
    union {                                                         \
        OVS_CACHE_LINE_MARKER CACHELINE;                            \
        struct { MEMBERS };                                         \
        struct { MEMBERS } named_member__;                          \
        uint8_t PAD_ID[ROUND_UP(sizeof named_member__, UNIT)];      \
    }
#endif
diff mbox

Patch

diff --git a/include/openvswitch/util.h b/include/openvswitch/util.h
index 17b0652..5ecfaab 100644
--- a/include/openvswitch/util.h
+++ b/include/openvswitch/util.h
@@ -181,6 +181,44 @@  OVS_NO_RETURN void ovs_assert_failure(const char *, const char *, const char *);
         uint8_t PAD_ID[ROUND_UP(sizeof(struct { MEMBERS }), UNIT)]; \
     }
 
+/* Similar to PADDED_MEMBERS with additional cacheline marker:
+ *
+ *    - OVS_CACHE_LINE_MARKER is a cacheline marker
+ *    - MEMBERS in a nested anonymous struct.
+ *    - An array as large as MEMBERS plus padding to a multiple of UNIT bytes.
+ *
+ * The effect is to add cacheline marker and pad MEMBERS to a multiple of
+ * UNIT bytes.
+ *
+ * Example:
+ *     struct padded_struct {
+ *         PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline0,
+ *             uint8_t x;
+ *             uint8_t y;
+ *         );
+ *     };
+ *
+ * The PADDED_MEMBERS_CACHELINE_MARKER macro in above structure expands as:
+ *
+ *     struct padded_struct {
+ *            union {
+ *                    OVS_CACHE_LINE_MARKER cacheline0;
+ *                    struct {
+ *                            uint8_t x;
+ *                            uint8_t y;
+ *                    };
+ *                    uint8_t         pad0[64];
+ *            };
+ *            *--- cacheline 1 boundary (64 bytes) ---*
+ *     };
+ */
+#define PADDED_MEMBERS_CACHELINE_MARKER(UNIT, CACHELINE, MEMBERS)   \
+    union {                                                         \
+        OVS_CACHE_LINE_MARKER CACHELINE;                            \
+        struct { MEMBERS };                                         \
+        uint8_t PAD_ID[ROUND_UP(sizeof(struct { MEMBERS }), UNIT)]; \
+    }
+
 static inline bool
 is_pow2(uintmax_t x)
 {
diff --git a/lib/util.h b/lib/util.h
index 4706c99..83989bf 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -51,6 +51,12 @@  extern char *program_name;
 #define CACHE_LINE_SIZE 64
 BUILD_ASSERT_DECL(IS_POW2(CACHE_LINE_SIZE));
 
+/* Cacheline marking is typically done using zero-sized array.
+ * However MSVC doesn't like zero-sized array in struct/union.
+ * C4200: https://msdn.microsoft.com/en-us/library/79wf64bc.aspx
+ */
+typedef uint8_t OVS_CACHE_LINE_MARKER[1];
+
 static inline void
 ovs_prefetch_range(const void *start, size_t size)
 {