Skip to content
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

Merged
merged 2 commits into from
Feb 6, 2018
Merged

Memmove fix #2151

merged 2 commits into from
Feb 6, 2018

Conversation

ChrisJefferson
Copy link
Contributor

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.

@ChrisJefferson ChrisJefferson changed the base branch from master to stable-4.9 February 2, 2018 14:01
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);
Copy link
Contributor

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.

Copy link
Contributor Author

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

Copy link
Member

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);
Copy link
Member

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
Copy link
Member

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.
Copy link
Member

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--;
}
Copy link
Member

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.

@ChrisJefferson ChrisJefferson changed the base branch from stable-4.9 to master February 5, 2018 15:19
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.
@ChrisJefferson
Copy link
Contributor Author

Now fixed up (hopefully)

Copy link
Member

@fingolfin fingolfin left a 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.
Copy link
Member

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?

Copy link
Contributor Author

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.

@fingolfin fingolfin added kind: bug Issues describing general bugs, and PRs fixing them kind: bug: crash Issues describing bugs that cause GAP to crash, and PRs fixing them (used for release notes) topic: kernel labels Feb 5, 2018
@codecov
Copy link

codecov bot commented Feb 5, 2018

Codecov Report

Merging #2151 into master will increase coverage by 0.04%.
The diff coverage is 97.61%.

@@            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
Impacted Files Coverage Δ
src/permutat.c 78.02% <ø> (-0.03%) ⬇️
src/system.c 66.6% <0%> (-0.5%) ⬇️
src/listfunc.c 80.26% <100%> (ø) ⬆️
src/opers.c 81.41% <100%> (+0.23%) ⬆️
src/sysfiles.c 36.52% <100%> (+1.16%) ⬆️
src/set.c 91.08% <100%> (ø) ⬆️
src/gasman.c 84.68% <100%> (ø) ⬆️
src/hpc/guards.h 80.55% <0%> (-11.45%) ⬇️
src/debug.c 26.92% <0%> (-9.92%) ⬇️
src/hpc/thread.c 51.48% <0%> (-4.23%) ⬇️
... and 43 more

@markuspf markuspf merged commit 544f1e2 into gap-system:master Feb 6, 2018
@fingolfin fingolfin added release notes: added PRs introducing changes that have since been mentioned in the release notes backport-to-4.9 labels Mar 22, 2018
@ChrisJefferson ChrisJefferson deleted the memmove-fix branch June 12, 2018 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: bug: crash Issues describing bugs that cause GAP to crash, and PRs fixing them (used for release notes) kind: bug Issues describing general bugs, and PRs fixing them release notes: added PRs introducing changes that have since been mentioned in the release notes topic: kernel
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants