Skip to content

[WIP] Use portable code for aligned memory allocation#884

Closed
concatime wants to merge 4 commits intozlib-ng:developfrom
concatime:portable-aligned-malloc
Closed

[WIP] Use portable code for aligned memory allocation#884
concatime wants to merge 4 commits intozlib-ng:developfrom
concatime:portable-aligned-malloc

Conversation

@concatime
Copy link
Copy Markdown

@concatime concatime commented Mar 17, 2021

This is a quick reborn of #766.
@Dead2, can you review this approach? I focused on standards instead of operating systems.
It should probably fix #873, will see.

We now have two standard “backends” and a fallback one:

  • Set C standard to 11 for aligned_alloc;
  • Set POSIX to 2001 (-D _POSIX_C_SOURCE=200112L) for posix_memalign;
  • Otherwise fallback to non-standard memalign;

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 17, 2021

Codecov Report

Merging #884 (9c1d420) into develop (b7af2db) will increase coverage by 0.01%.
The diff coverage is 33.33%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop     #884      +/-   ##
===========================================
+ Coverage    75.43%   75.45%   +0.01%     
===========================================
  Files           73       73              
  Lines         8220     8216       -4     
  Branches      1359     1359              
===========================================
- Hits          6201     6199       -2     
+ Misses        1494     1492       -2     
  Partials       525      525              
Flag Coverage Δ
macos_clang 68.72% <0.00%> (-0.01%) ⬇️
macos_gcc 67.77% <0.00%> (+0.01%) ⬆️
ubuntu_clang 68.91% <0.00%> (-0.01%) ⬇️
ubuntu_clang_debug 68.36% <0.00%> (ø)
ubuntu_clang_inflate_allow_invalid_dist 68.90% <0.00%> (-0.02%) ⬇️
ubuntu_clang_inflate_strict 69.16% <0.00%> (-0.02%) ⬇️
ubuntu_clang_mmap 68.91% <0.00%> (-0.02%) ⬇️
ubuntu_clang_msan 69.16% <0.00%> (-0.02%) ⬇️
ubuntu_gcc 69.83% <0.00%> (-0.03%) ⬇️
ubuntu_gcc_aarch64 70.04% <0.00%> (-0.03%) ⬇️
ubuntu_gcc_aarch64_compat_no_opt 67.76% <0.00%> (-0.02%) ⬇️
ubuntu_gcc_aarch64_no_acle 68.29% <0.00%> (-0.02%) ⬇️
ubuntu_gcc_aarch64_no_neon 67.98% <0.00%> (-0.02%) ⬇️
ubuntu_gcc_armhf 70.46% <0.00%> (-0.03%) ⬇️
ubuntu_gcc_armhf_compat_no_opt 67.76% <0.00%> (-0.02%) ⬇️
ubuntu_gcc_armhf_no_acle 69.50% <0.00%> (-0.05%) ⬇️
ubuntu_gcc_armhf_no_neon 69.81% <0.00%> (-0.05%) ⬇️
ubuntu_gcc_armsf 70.46% <0.00%> (-0.03%) ⬇️
ubuntu_gcc_armsf_compat_no_opt 67.76% <0.00%> (-0.02%) ⬇️
ubuntu_gcc_compat_no_opt 69.10% <0.00%> (-0.05%) ⬇️
ubuntu_gcc_mingw_i686 0.00% <0.00%> (ø)
ubuntu_gcc_mingw_x86_64 0.00% <0.00%> (ø)
ubuntu_gcc_no_avx2 69.40% <0.00%> (-0.02%) ⬇️
ubuntu_gcc_no_pclmulqdq 66.51% <0.00%> (-0.02%) ⬇️
ubuntu_gcc_no_sse2 67.76% <0.00%> (-0.02%) ⬇️
ubuntu_gcc_no_sse4 66.51% <0.00%> (-0.02%) ⬇️
ubuntu_gcc_o3 69.09% <0.00%> (-0.03%) ⬇️
ubuntu_gcc_osb 70.66% <0.00%> (-0.02%) ⬇️
ubuntu_gcc_ppc 70.88% <0.00%> (-0.03%) ⬇️
ubuntu_gcc_ppc64 70.06% <0.00%> (-0.03%) ⬇️
ubuntu_gcc_ppc64le 69.03% <0.00%> (-0.03%) ⬇️
ubuntu_gcc_s390x 68.26% <0.00%> (-0.02%) ⬇️
ubuntu_gcc_sparc64 70.76% <0.00%> (-0.03%) ⬇️
win64_gcc 73.02% <100.00%> (ø)
win64_gcc_compat_no_opt 74.46% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
test/minigzip.c 43.95% <ø> (ø)
zutil_p.h 40.00% <33.33%> (ø)
gzlib.c 57.09% <0.00%> (+0.09%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b7af2db...9c1d420. Read the comment docs.

@concatime
Copy link
Copy Markdown
Author

FreeBSD 11 works with cmake -D CMAKE_C_STANDARD=11: https://builds.sr.ht/~iemaghni/job/462260

@concatime
Copy link
Copy Markdown
Author

FreeBSD 11 works with cmake -D 'CMAKE_C_FLAGS=-D _POSIX_C_SOURCE=200112L': https://builds.sr.ht/~iemaghni/job/462268

@Dead2
Copy link
Copy Markdown
Member

Dead2 commented Mar 17, 2021

This is an interesting approach for sure.

It does make me wonder whether one of these new methods could replace or be preferred before the apple one. Are there any macos users in the house? 😄

@nmoinvaz
Copy link
Copy Markdown
Member

nmoinvaz commented Mar 17, 2021

I would prefer to see configure and CMake (see check_function_exists) check for available functions, rather than doing #ifdef for each platform. It becomes a mess as more platforms are encountered. Then all you need to do is #ifdef HAVE_ALIGNED_ALLOC.

@concatime
Copy link
Copy Markdown
Author

concatime commented Mar 17, 2021

I don’t have, neither plan to, a MacOS system.

  • Neither std::aligned_alloc from C++17 nor aligned_alloc from C11 are supported! Source.
  • posix_memalign is present. Source.

@concatime
Copy link
Copy Markdown
Author

I would prefer to see configure and CMake (see check_function_exists) check for available functions, rather than doing #ifdef for each platform. It becomes a mess as more platforms are encountered. Then all you need to do is #ifdef HAVE_ALIGNED_ALLOC.

This should not be required. We know for a fact that aligned_alloc exists in C11, except for MacOS, which would use posix_memalign. I can rework my PR to include this.

@nmoinvaz
Copy link
Copy Markdown
Member

I was saying it would be good to have a unified way of detecting support for those functions, and I think it should be done in the build scripts versus doing the platform #ifdef checks.

@nmoinvaz
Copy link
Copy Markdown
Member

I have experience with minizip-ng on this same thing, I kept getting commit requests for people needing to change the platform #ifdef checks for their particular variant. As soon as I moved the check to the build script, that stopped happening.

@concatime
Copy link
Copy Markdown
Author

But my PR focuses on standard, not platforms. The platforms should either support C11 or POSIX. We don’t care about FreeBSD or OpenBSD or any of that. What we can do on the build system is ensure one of C11 or a forced value to _POSIX_C_SOURCE if the system is not Windows.
One question: Is aligned_alloc supported in C11 Windows?

@Dead2
Copy link
Copy Markdown
Member

Dead2 commented Mar 17, 2021

One issue here is that we target C99, and not C11.

@concatime
Copy link
Copy Markdown
Author

And I think POSIX 2001 is "next generation" enough, even 2008.

@mtl1979
Copy link
Copy Markdown
Collaborator

mtl1979 commented Mar 17, 2021

It's also common knowledge that gcc is not POSIX-compliant by default... so requiring either C11 or POSIX is just recipe for disaster...

POSIX is pretty much deprecated standard as far as gcc goes.

@concatime
Copy link
Copy Markdown
Author

concatime commented Mar 17, 2021

It's also common knowledge that gcc is not POSIX-compliant by default... so requiring either C11 or POSIX is just recipe for disaster...

POSIX is pretty much deprecated standard as far as gcc goes.

As far as I understand, POSIX is relevant to libc, not the compiler. So Glibc/musl instead of GCC. But C11 is revelant to the compiler of course.

@mtl1979
Copy link
Copy Markdown
Collaborator

mtl1979 commented Mar 17, 2021

Even though Linux is BSD-based, we decided to avoid any legacy BSD functions... As such we should also try to avoid POSIX functions if there is GNU equivalent...

@concatime
Copy link
Copy Markdown
Author

Even though Linux is BSD-based

Since when?

we decided to avoid any legacy BSD functions...

Make sens to avoid legacy functions, BSD or not.

As such we should also try to avoid POSIX functions if there is GNU equivalent...

I disagree. We should avoid GNU equivalent and instead focus on POSIX. By doing this, we support *BSD, musl-based distros, Android (bionic libc) and even partially MacOS.

@mtl1979
Copy link
Copy Markdown
Collaborator

mtl1979 commented Mar 17, 2021

@concatime We have limited Android support... we can't support all older SDK versions due to missing functions... What comes to other BSD variants (including MacOS, FreeBSD, OpenBSD, NetBSD, Haiku), they are being handled currently...

@Dead2
Copy link
Copy Markdown
Member

Dead2 commented Mar 17, 2021

I think we should support the Posix alternative.
When it comes to what to prefer over the other when both exist, I really don't currently have a preference.

If Posix support needs a compiler parameter to be set, then this would need to be detected and added by configure and cmake. So I see what @nmoinvaz means about doing the detection there.
When it comes to doing the entire detection and selection of malloc type in cmake/configure, I think that should probably be a separate PR that targets Next.

@mtl1979
Copy link
Copy Markdown
Collaborator

mtl1979 commented Mar 17, 2021

@Dead2 I still haven't decided what alternatives we should support... It's too early to exclude anything... Even if we have C99 as recommended standard, I think we should not exclude newer standards if doing so doesn't complicate the code too much...

@concatime concatime force-pushed the portable-aligned-malloc branch 2 times, most recently from c76cf8b to b034439 Compare March 17, 2021 20:35
@concatime
Copy link
Copy Markdown
Author

I recommend picking the ISO C11 aligned_alloc over POSIX.1-2001 posix_memalign when available (except for MacOS). I updated my PR to reflect this.

@concatime concatime force-pushed the portable-aligned-malloc branch 2 times, most recently from 5dfe2f0 to aa88244 Compare March 17, 2021 22:11
@concatime
Copy link
Copy Markdown
Author

concatime commented Mar 17, 2021

So, we should edit the build systems to reflect this logic:

@concatime concatime force-pushed the portable-aligned-malloc branch 4 times, most recently from f23363c to 7327351 Compare March 18, 2021 01:56
@nmoinvaz
Copy link
Copy Markdown
Member

nmoinvaz commented Mar 18, 2021

I have made a PR that shows kind of what I had in mind with the build system check. If you want to take from it feel free.

@concatime concatime force-pushed the portable-aligned-malloc branch 2 times, most recently from 8d5e0b8 to 813fedf Compare March 18, 2021 05:46
@concatime
Copy link
Copy Markdown
Author

Now, FreeBSD builds w/o any added CMake CLI flags: https://builds.sr.ht/~iemaghni/job/462711

@concatime concatime force-pushed the portable-aligned-malloc branch from 224b9fa to 49d1c34 Compare March 18, 2021 06:08
Comment thread CMakeLists.txt Outdated
include(CheckFunctionExists)
include(CheckIncludeFile)
include(CheckSymbolExists)
include(CheckTypeSize)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why reorder these? This makes it more difficult to review, since we cannot easily spot any actual changes.
CMakePushCheckState certainly looks interesting though.

Just to be clear, we prefer to have each commit do one thing (We should put this in the wiki, I guess).
So code-moving/reordering/cleanup in a separate commit/PR to make reviews/audits easier.
Changes like CMakePushCheckState is the kind of thing I'd like to se a separate PR for, and that it changes the old code to use it as well, to keep an common code style.

The more involved the changes of this PR, the less likely I can merge it into the mostly-fixes 2.0 branch. It can still make the 2.1 branch of course, but that does not have an estimated release-date yet.

My preference would be this: (I can still be persuaded otherwise though)
PR1. A minimal fix that enables building on FreeBSD, but does not touch other platforms.
PR2. Rewrite cmake to use CMakePushCheckState.
PR3. Rewrite aligned malloc detection/selection (Effectively this PR).

Copy link
Copy Markdown
Author

@concatime concatime Mar 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just ordered them in alphabetical order. This way, each include() has only one possible place. I can revert this and simply add include(CMakePushCheckState) at the end.

EDIT: Done.

Comment thread CMakeLists.txt Outdated
@Dead2
Copy link
Copy Markdown
Member

Dead2 commented Mar 18, 2021

Not sure whether it is a bug in the code or a bug with coverage measurements, but it doesn't look like posix_memalign() or memalign() gets used. It might be due to compiler builtins being used instead perhaps, and gcov being unable to detect that.

@concatime concatime force-pushed the portable-aligned-malloc branch from 49d1c34 to d0eb14b Compare March 18, 2021 13:34
@concatime
Copy link
Copy Markdown
Author

I never used codecov. So folks, I need your help to fix the check “codecov/patch”.

Comment thread zutil_p.h
# include <stdlib.h>
#if !defined(MAL_IMPL) && !defined(_WIN32)
# if __STDC_VERSION__+0 >= 201112L
# define MAL_IMPL 2 /* ISO C11 `aligned_alloc` */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having the MAL_IMPL with number codes I think hurts readability. Perhaps we can use something more descriptive and also get away from using numbers to represent the different methods. I would be in favor of not having an intermediary MAL_IMPL.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I need a way to force a certain implementation from the build system. For Apple, I need to explicitly use the POSIX (MAL_IMPL=1) implementation. For Android, depending on the API level, I need to explicitly use either C11 (MAL_IMPL=2) or POSIX (MAL_IMPL=1) or the fallback memalign() (MAL_IMPL=0). If you have a cleaner way, I’m hearing.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about just using separate names for them? HAVE_POSIX_MEMALIGN or HAVE_ALIGNED_ALLOC, etc..?

Copy link
Copy Markdown
Author

@concatime concatime Mar 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then you would have something like this:

#if !defined(USE_ALIGNED_ALLOC) && !defined(USE_POSIX_MEMALIGN) && !defined(USE_MEMALIGN) && !defined(WIN32)
...

which is way too long. Also, I don’t have to set HAVE_ALIGNED_ALLOC, HAVE_POSIX_MEMALIGN and HAVE_MEMALIGN by using my method. I want the code to be platform (unix) agnostic (except for Windows) and only the build systems should problematic platforms like macOS and to a lesser extent Android (only if we decided to support older API levels). For example, the build system should not have to handle FreeBSD because it supports portable functions, nor Linux nor OpenBSD, nor Haiku, etc.

Copy link
Copy Markdown
Member

@nmoinvaz nmoinvaz Mar 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be longer but it is also more readable. I'm not sure that this auto-detection based on _POSIX_C_SOURCE or __STDC_VERSION__ is necessary. The build system should just determine what is available and set HAVE_XYZ_ALLOC. zng_alloc would use the first available.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we don’t need HAVE_... for standard functions (ISO C or POSIX)! If a system does not implement standard functions, then they should be handled in the build system, not the code. I don’t want my code to be dependent on the presence of a build system. That’s why I have auto-detection based on __STDC_VERSION__ and _POSIX_C_SOURCE.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't detect by value of _POSIX_C_SOURCE as it is defined as minimum supported version, not maximum... The build system must detect what is the maximum supported value for the compiler and then add it to compiler command line.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@concatime I see conflicting definitions of _POSIX_C_SOURCE in configure now... In other projects we only define -D_GNU_SOURCE -D_DEFAULT_SOURCE which selects the latest supported _POSIX_C_SOURCE value on all modern compilers... The define name was recently changed, so both should be and can be safely defined.

Comment thread zutil_p.h Outdated
Comment thread cmake/detect-malloc.cmake
@@ -0,0 +1,32 @@
# Neither Windows nor macOS support ISO C11 `aligned_alloc`.
Copy link
Copy Markdown
Member

@nmoinvaz nmoinvaz Mar 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is almost the same thing as before but in comment form. Where when a new platform/sdk comes along are there going to be new commits for everybody wanting to add in their own URL for the docs. I guess that it is separated in its own .cmake helps.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these new "platform/sdk" support portable functions (e.g. Fuchsia), then no action is required in the build system.

Comment thread zutil_p.h Outdated
Comment thread cmake/detect-malloc.cmake
# libandroid_support.a, which is linked by default when targeting API 16).
# https://github.com/aosp-mirror/platform_bionic/commit/85aad909560508410101c18c6ecc6633df39c596
# https://github.com/aosp-mirror/platform_bionic/commit/e219cefc173bf93b8ff710431784e5de30ffab8f
if(WIN32)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be MSVC I think.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I might be wrong actually.

@Dead2 Dead2 added the Next Devel Targeting next devel release (does not mean accepted) label Mar 18, 2021
@concatime concatime force-pushed the portable-aligned-malloc branch from d0eb14b to 9c1d420 Compare March 18, 2021 20:03
@concatime
Copy link
Copy Markdown
Author

concatime commented Mar 19, 2021

Relevant informations found:

This function was introduced in ISO C11 and hence may have better portability to modern non-POSIX systems than posix_memalign.

This function was introduced in POSIX 1003.1d. Although this function is superseded by aligned_alloc, it is more portable to older POSIX systems that do not support ISO C11.

The memalign function is obsolete and aligned_alloc or posix_memalign should be used instead.

https://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html

That’s why we should use standard functions instead of GNU ones.

(emphasis mine)

@Dead2 Dead2 added the Rebase needed Please do a 'git rebase develop yourbranch' label Jun 25, 2021
@Dead2
Copy link
Copy Markdown
Member

Dead2 commented Jun 25, 2021

This needs a rebase, and probably some redesign due to recent changes.

@Dead2 Dead2 marked this pull request as draft July 7, 2021 17:55
@Dead2
Copy link
Copy Markdown
Member

Dead2 commented Jan 7, 2022

I think this is already fixed in develop.

@Dead2 Dead2 closed this Jan 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Next Devel Targeting next devel release (does not mean accepted) Rebase needed Please do a 'git rebase develop yourbranch'

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compilation fails on FreeBSD < 12

4 participants