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 CC: Lai Jiangshan CC: Martin Bligh --- 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 #include #include +#include /* 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 { -- Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/