-
Notifications
You must be signed in to change notification settings - Fork 162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memmove fix #2151
Memmove fix #2151
Conversation
src/sysfiles.h
Outdated
@@ -612,6 +613,9 @@ extern Obj SyReadStringFid(Int fid); | |||
extern Obj SyReadStringFile(Int fid); | |||
extern Obj SyReadStringFileGeneric(Int fid); | |||
|
|||
// Internal implementation of memmove, to avoid issues with glibc | |||
void *SyMemmove(void *dst, const void* src, UInt size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to get the memmove
back inline in 64 bit environments so that small moves can be integrated with the surrounding code. Presumably that could be done by having a static inline function in the header that compiled to either memmove or a call to the real implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, or even (which I normally disaprove) just doing #define SyMemmove memmove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, what I'd expect here is something like this:
#ifdef USE_CUSTOM_MEMMOVE
void *SyMemmove(void *dst, const void* src, size_t size);
#else
#define SyMemmove(dst, src, size) memmove(dst, src, size)
#endif
Note the use of size_t
instead of UInt
for size
, to make sure we match the memmove
signature.
src/sysfiles.h
Outdated
@@ -612,6 +613,9 @@ extern Obj SyReadStringFid(Int fid); | |||
extern Obj SyReadStringFile(Int fid); | |||
extern Obj SyReadStringFileGeneric(Int fid); | |||
|
|||
// Internal implementation of memmove, to avoid issues with glibc | |||
void *SyMemmove(void *dst, const void* src, UInt size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, what I'd expect here is something like this:
#ifdef USE_CUSTOM_MEMMOVE
void *SyMemmove(void *dst, const void* src, size_t size);
#else
#define SyMemmove(dst, src, size) memmove(dst, src, size)
#endif
Note the use of size_t
instead of UInt
for size
, to make sure we match the memmove
signature.
src/sysfiles.c
Outdated
@@ -3598,6 +3598,56 @@ Obj SyReadStringFid(Int fid) { | |||
#endif | |||
|
|||
|
|||
#ifdef SYS_IS_64_BIT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dislike hurting all 32bit systems, even those which use glibc. E.g. insert this into the .h
file (of course a proper configure check would be better)
#if !defined(SYS_IS_64_BIT) && defined(__GNU_LIBRARY__)
#define USE_CUSTOM_MEMMOVE 1
#endif
src/sysfiles.c
Outdated
// The memmove in glibc on 32-bit SSE2 systems, contained in | ||
// __memmove_sse2_unaligned, is buggy in at least versions | ||
// 2.21 - 2.25 when crossing the 2GB boundary, so GAP must | ||
// include it's own simple memmove implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"it's" -> "its"
Perhaps also link to the glibc bug report. Oh, and they just release 2.26 which also has the bug.
while (size > 0) { | ||
*d-- = *s--; | ||
size--; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once again, we could really benefit from test setup for pure C code, so that one can write unit tests for functions like this.
1bf49c1
to
9a95882
Compare
The memmove in glibc on 32-bit SSE2 systems, contained in __memmove_sse2_unaligned, is buggy in at least versions 2.21 - 2.25 when crossing the 2GB boundary, so GAP must include it's own simple memmove implementation.
9a95882
to
3e6f4f7
Compare
Now fixed up (hopefully) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me, just a small question, and of course tests should run.
// This is about 4x slower than glibc, but | ||
// is simple and also complicated enough that | ||
// gcc or clang seem unable to "optimise" it back | ||
// into a call to memmove. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Under which condition did you test this? E.g. did you also try it with -O3
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried with -O3
and -flto
. I checked using objdump -t
that the resulting GAP executable doesn't have any references to memmove
.
Codecov Report
@@ Coverage Diff @@
## master #2151 +/- ##
==========================================
+ Coverage 69.34% 69.39% +0.04%
==========================================
Files 484 485 +1
Lines 253917 255460 +1543
==========================================
+ Hits 176085 177266 +1181
- Misses 77832 78194 +362
|
This is a basic attempt to fix the problem of broken memmove on 32-bit glibc.
This is purposefully designed to be as simple as possible. We could obviously do various cleverer things than this, but I find the bug hard to test, so I didn't want to do anything particularly complicated.