[RFC patch 09/41] LTTng optimize write to page function deal with unaligned access

Mathieu Desnoyers
2009-03-05T23:33:53Z

[-- Attachment #1: lttng-optimize-write-to-page-function-deal-with-unaligned.patch --]
[-- Type: text/plain, Size: 5847 bytes --]

Make sure we don't end up doing unaligned accesses on architectures which lack
support for efficient unaligned access.

Standard configurations are either :

If architecture defines
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-> !CONFIG_LTT_ALIGNMENT (to save space)

or if the architecture does not define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-> CONFIG_LTT_ALIGNMENT (to speed up tracing)

Compiling a kernel with tracing active :

Tests done only on x86_64 (which has efficient unaligned access) :

CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
!CONFIG_LTT_ALIGNMENT
real 1m29.349s

CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
CONFIG_LTT_ALIGNMENT
real 1m29.309s

!CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS (forced by modifying arch/x86/Kconfig)
CONFIG_LTT_ALIGNMENT
real 1m29.162s

So even with this supplementary test, the fast path stays fast.

Testing the variations on an architecture without efficient unaligned
access would be welcome.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
CC: Lai Jiangshan <laijs@cn.fujitsu.com>
CC: Martin Bligh <mbligh@google.com>
---
include/linux/ltt-core.h | 35 ++++++++++++++++++++++++++++++++
include/linux/ltt-relay.h | 49 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/ltt-tracer.h | 35 --------------------------------
3 files changed, 84 insertions(+), 35 deletions(-)

Index: linux-2.6-lttng/include/linux/ltt-relay.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/ltt-relay.h 2009-03-05 15:23:53.000000000 -0500
+++ linux-2.6-lttng/include/linux/ltt-relay.h 2009-03-05 15:24:23.000000000 -0500
@@ -20,6 +20,7 @@
#include <linux/poll.h>
#include <linux/kref.h>
#include <linux/mm.h>
+#include <linux/ltt-core.h>

/* Needs a _much_ better name... */
#define FIX_SIZE(x) ((((x) - 1) & PAGE_MASK) + PAGE_SIZE)
@@ -199,6 +200,7 @@ static inline struct buf_page *ltt_relay
return page;
}

+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
static inline void ltt_relay_do_copy(void *dest, const void *src, size_t len)
{
switch (len) {
@@ -222,6 +224,53 @@ static inline void ltt_relay_do_copy(voi
memcpy(dest, src, len);
}
}
+#else
+/*
+ * Returns whether the dest and src addresses are aligned on
+ * min(sizeof(void *), len). Call this with statically known len for efficiency.
+ */
+static inline int addr_aligned(const void *dest, const void *src, size_t len)
+{
+ if (ltt_align((size_t)dest, len))
+ return 0;
+ if (ltt_align((size_t)src, len))
+ return 0;
+ return 1;
+}
+
+static inline void ltt_relay_do_copy(void *dest, const void *src, size_t len)
+{
+ switch (len) {
+ case 0:
+ break;
+ case 1:
+ *(u8 *)dest = *(const u8 *)src;
+ break;
+ case 2:
+ if (unlikely(!addr_aligned(dest, src, 2)))
+ goto memcpy_fallback;
+ *(u16 *)dest = *(const u16 *)src;
+ break;
+ case 4:
+ if (unlikely(!addr_aligned(dest, src, 4)))
+ goto memcpy_fallback;
+ *(u32 *)dest = *(const u32 *)src;
+ break;
+#if (BITS_PER_LONG == 64)
+ case 8:
+ if (unlikely(!addr_aligned(dest, src, 8)))
+ goto memcpy_fallback;
+ *(u64 *)dest = *(const u64 *)src;
+ break;
+#endif
+ default:
+ goto memcpy_fallback;
+ }
+ return;
+memcpy_fallback:
+ memcpy(dest, src, len);
+}
+#endif

static inline int ltt_relay_write(struct rchan_buf *buf, size_t offset,
const void *src, size_t len)
Index: linux-2.6-lttng/include/linux/ltt-core.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/ltt-core.h 2009-03-05 15:22:42.000000000 -0500
+++ linux-2.6-lttng/include/linux/ltt-core.h 2009-03-05 15:23:58.000000000 -0500
@@ -44,4 +44,39 @@ extern ltt_run_filter_functor ltt_run_fi
extern void ltt_filter_register(ltt_run_filter_functor func);
extern void ltt_filter_unregister(void);

+#if defined(CONFIG_LTT) && defined(CONFIG_LTT_ALIGNMENT)
+
+/*
+ * Calculate the offset needed to align the type.
+ * size_of_type must be non-zero.
+ */
+static inline unsigned int ltt_align(size_t align_drift, size_t size_of_type)
+{
+ size_t alignment = min(sizeof(void *), size_of_type);
+ return (alignment - align_drift) & (alignment - 1);
+}
+/* Default arch alignment */
+#define LTT_ALIGN
+
+static inline int ltt_get_alignment(void)
+{
+ return sizeof(void *);
+}
+
+#else
+
+static inline unsigned int ltt_align(size_t align_drift,
+ size_t size_of_type)
+{
+ return 0;
+}
+
+#define LTT_ALIGN __attribute__((packed))
+
+static inline int ltt_get_alignment(void)
+{
+ return 0;
+}
+#endif /* defined(CONFIG_LTT) && defined(CONFIG_LTT_ALIGNMENT) */
+
#endif /* LTT_CORE_H */
Index: linux-2.6-lttng/include/linux/ltt-tracer.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/ltt-tracer.h 2009-03-05 15:23:56.000000000 -0500
+++ linux-2.6-lttng/include/linux/ltt-tracer.h 2009-03-05 15:23:58.000000000 -0500
@@ -138,41 +138,6 @@ static inline enum marker_id marker_id_t
return MARKER_ID_DYNAMIC;
}

-#if defined(CONFIG_LTT) && defined(CONFIG_LTT_ALIGNMENT)
-
-/*
- * Calculate the offset needed to align the type.
- * size_of_type must be non-zero.
- */
-static inline unsigned int ltt_align(size_t align_drift, size_t size_of_type)
-{
- size_t alignment = min(sizeof(void *), size_of_type);
- return (alignment - align_drift) & (alignment - 1);
-}
-/* Default arch alignment */
-#define LTT_ALIGN
-
-static inline int ltt_get_alignment(void)
-{
- return sizeof(void *);
-}
-
-#else
-
-static inline unsigned int ltt_align(size_t align_drift,
- size_t size_of_type)
-{
- return 0;
-}
-
-#define LTT_ALIGN __attribute__((packed))
-
-static inline int ltt_get_alignment(void)
-{
- return 0;
-}
-#endif /* CONFIG_LTT_ALIGNMENT */
-
#ifdef CONFIG_LTT

struct user_dbg_data {