All of lore.kernel.org
 help / color / mirror / Atom feed
From: "René Scharfe" <l.s.r@web.de>
To: Jeff King <peff@peff.net>
Cc: Duy Nguyen <pclouds@gmail.com>, Git List <git@vger.kernel.org>,
	Junio C Hamano <gitster@pobox.com>,
	Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: Re: [PATCH 1/5] add SWAP macro
Date: Tue, 2 May 2017 07:29:35 +0200	[thread overview]
Message-ID: <57741b45-81b4-5940-3ffb-10c3b067cce3@web.de> (raw)
In-Reply-To: <20170430031154.qurrbdb3wqrdxd37@sigill.intra.peff.net>

Am 30.04.2017 um 05:11 schrieb Jeff King:
> On Sat, Apr 29, 2017 at 08:16:17PM +0200, René Scharfe wrote:
> 
>>> I dunno. I could go either way. Or we could leave it as-is, and let
>>> valgrind find the problem. That has zero run-time cost, but of course
>>> nobody bothers to run valgrind outside of the test suite, so the inputs
>>> are not usually very exotic.
>>
>> It would be  problematic on platforms where memcpy has to erase the
>> destination before writing new values (I don't know any example).
>>
>> We could use two temporary buffers.  The object code is the same with
>> GCC around 5 and Clang 3.2 or higher -- at least for prio-queue.c.
> 
> Hmm, yeah, that's an easy solution that covers the overlap case, too. If
> the generated code is the same, that seems like it might not be bad (I
> am a little sad how complex this simple swap operation is getting,
> though).

Patch below.

All is well if the compiler can (and is allowed to) see through the
memcpy calls, otherwise we get a performance hit and this change makes
that slow path slower.  FWIW, I didn't see any slowdown in our perf
tests, though.

It's not too late to switch to a macro that takes a type parameter, as
Dscho suggested earlier:

  #define swap_t(T, a, b) do {T t_ = (a); (a) = (b); (b) = t_;} while (0)

Much simpler and with full type check, but harder to use (needs correct
type parameter and its other parameters must not have side effects).

-- >8 --
Subject: [PATCH] avoid calling memcpy on overlapping objects in SWAP

Copy both objects into their own buffers before swapping to make sure we
don't call memcpy with overlapping memory ranges, as that's undefined.
Compilers that inline the memcpy calls optimize the extra operations
away.  That allows calls like SWAP(x, x) without ill effect and without
extra checks.

Signed-off-by: Rene Scharfe <l.s.r@web.de>
---
 git-compat-util.h | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/git-compat-util.h b/git-compat-util.h
index bd04564..a843f04 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -528,13 +528,15 @@ static inline int ends_with(const char *str, const char *suffix)
 }
 
 #define SWAP(a, b) do {						\
-	void *_swap_a_ptr = &(a);				\
-	void *_swap_b_ptr = &(b);				\
-	unsigned char _swap_buffer[sizeof(a)];			\
-	memcpy(_swap_buffer, _swap_a_ptr, sizeof(a));		\
-	memcpy(_swap_a_ptr, _swap_b_ptr, sizeof(a) +		\
-	       BUILD_ASSERT_OR_ZERO(sizeof(a) == sizeof(b)));	\
-	memcpy(_swap_b_ptr, _swap_buffer, sizeof(a));		\
+	void *swap_a_ptr_ = &(a);				\
+	void *swap_b_ptr_ = &(b);				\
+	unsigned char swap_a_buffer_[sizeof(a)];		\
+	unsigned char swap_b_buffer_[sizeof(a) +		\
+		BUILD_ASSERT_OR_ZERO(sizeof(a) == sizeof(b))];	\
+	memcpy(swap_a_buffer_, swap_a_ptr_, sizeof(a));		\
+	memcpy(swap_b_buffer_, swap_b_ptr_, sizeof(a));		\
+	memcpy(swap_a_ptr_, swap_b_buffer_, sizeof(a));		\
+	memcpy(swap_b_ptr_, swap_a_buffer_, sizeof(a));		\
 } while (0)
 
 #if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
-- 
2.1.4

  reply	other threads:[~2017-05-02  5:29 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-28 21:13 [PATCH 0/5] introduce SWAP macro René Scharfe
2017-01-28 21:38 ` [PATCH 1/5] add " René Scharfe
2017-01-30 15:39   ` Johannes Schindelin
2017-01-30 16:48     ` René Scharfe
2017-01-30 20:48       ` Johannes Schindelin
2017-01-30 21:46         ` René Scharfe
2017-01-31 12:13           ` Johannes Schindelin
2017-01-31 21:02             ` René Scharfe
2017-02-01  0:44               ` Ramsay Jones
2017-02-01 11:39               ` Johannes Schindelin
2017-01-30 16:01   ` Johannes Schindelin
2017-01-30 16:59     ` René Scharfe
2017-01-30 18:41     ` Johannes Sixt
2017-01-30 21:03       ` Johannes Schindelin
2017-01-30 22:09         ` René Scharfe
2017-01-30 22:21           ` Brandon Williams
2017-01-31 21:03             ` René Scharfe
2017-01-31 21:35               ` Jeff King
2017-01-31 22:29                 ` Junio C Hamano
2017-01-31 22:36                   ` Jeff King
2017-02-01 11:28                 ` Johannes Schindelin
2017-02-01 11:47                   ` Jeff King
2017-02-01 18:06                     ` René Scharfe
2017-02-01 18:33                       ` Junio C Hamano
2017-02-07 22:04                         ` René Scharfe
2017-02-07 22:30                           ` Junio C Hamano
2017-02-08 15:14                             ` Johannes Schindelin
2017-01-31 12:03           ` Johannes Schindelin
2017-04-24 11:29   ` Jeff King
2017-04-24 11:49     ` Jeff King
2017-04-24 13:13       ` Duy Nguyen
2017-04-28 17:04     ` René Scharfe
2017-04-28 21:49       ` Jeff King
2017-04-29 18:16         ` René Scharfe
2017-04-30  3:11           ` Jeff King
2017-05-02  5:29             ` René Scharfe [this message]
2017-01-28 21:40 ` [PATCH 2/5] apply: use " René Scharfe
2017-01-28 21:40 ` [PATCH 3/5] " René Scharfe
2017-01-30 16:03   ` Johannes Schindelin
2017-01-30 17:18     ` René Scharfe
2017-01-30 22:22   ` Junio C Hamano
2017-01-31 21:02     ` René Scharfe
2017-01-28 21:41 ` [PATCH 4/5] diff: " René Scharfe
2017-01-30 16:04   ` Johannes Schindelin
2017-01-30 17:26     ` René Scharfe
2017-01-30 22:22   ` Junio C Hamano
2017-01-28 21:42 ` [PATCH 5/5] graph: " René Scharfe
2017-01-30 16:16   ` Johannes Schindelin
2017-01-30 17:41     ` René Scharfe
2017-01-30 23:20 ` [PATCH 0/5] introduce " Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=57741b45-81b4-5940-3ffb-10c3b067cce3@web.de \
    --to=l.s.r@web.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=johannes.schindelin@gmx.de \
    --cc=pclouds@gmail.com \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.