8385359: [CRaC] aarch64: c7g.medium <-> c8g.medium FAIL: vector length - #331
8385359: [CRaC] aarch64: c7g.medium <-> c8g.medium FAIL: vector length#331jankratochvil wants to merge 41 commits into
Conversation
|
👋 Welcome back jkratochvil! A progress list of the required criteria for merging this PR into |
|
@jankratochvil This change is no longer ready for integration - check the PR body for details. |
|
The image constraints was meant as structured data that is validated by the engine. The check is performed in the engine as to move JVM out of the loop when there are more images and score-based criteria. On the other hand, The only downside of adding @TimPushkin what's your opinion on the suggested API change? |
|
Adding |
|
Nitpick: consider using |
Webrevs
|
| static constexpr char cpuarch_name[] = "cpu.arch"; | ||
| static constexpr char cpufeatures_name[] = "cpu.features"; | ||
|
|
||
| bool CracEngine::pre_restore_bitmap_hook(const unsigned char *value, size_t value_size) const { |
There was a problem hiding this comment.
_image_location is the only thing used from CracEngine, and it's only used in logging which I believe could be cut — we don't include it in any other logs. Then this could be static and CracEngine::pre_restore_bitmap_hook_trampoline wouldn't be needed.
There was a problem hiding this comment.
This comment suggests removing user_data to keep the API minimal for the current use case. My intention, however, was to make the API stable enough for future extensions.
If changes to the existing API are acceptable, the proposed register_label_hook is a superset of require_label and could therefore replace it. The same applies to bitmap.
There was a problem hiding this comment.
As I wrote in the previous comment, I don't suggest removing user_data from the API, just not to use it in the way we do now (which means that for now it'll be unused by us, but that's OK).
If changes to the existing API are acceptable, the proposed register_label_hook is a superset of require_label and could therefore replace it. The same applies to bitmap.
That would require adding more restrictions to how the new API can be used. The engine may use constraints API to select one of many images => the hooks can be called multiple times, including for images that won't end up being the one selected for restore => the hooks should not treat incompatible values as errors (e.g. in the current impl error logs should be replaced with debug logs). This is worth documenting in the API so that people don't call stuff like exit there.
There was a problem hiding this comment.
I do not agree removing standard error reporting to save 8 normal lines of code but OK, implemented.
There was a problem hiding this comment.
I'm not sure with which part of my previous comment you don't agree. None of them were about saving code really.
If with not using user_data, i.e. removing image path from the error messages: I suggest this because we do not do this in any other messages so it's weird to include it in only these particular ones. If you think we need to include it then I'd propose to do that in some more high-level message, e.g. the one reporting the overall restore failure (I think we should have one, not sure).
If with replacing error messages with debug messages: I suggest this because with multi-selection they are not really errors. I agree that this is not great / is incorrect for the non-multi-selection case, but I do not see a way to fix this, the JVM does not know what case this is.
There was a problem hiding this comment.
I expected _image_location to be used in another error message, but I see it isn't. In that case, it's fine that the new error messages don't print _image_location either. My mistake.
If crlib_image_constraints_t is called for multiple images, including those that are not ultimately selected, then I placed the CPU reconfiguration in the wrong place.
For example:
- We are running on a vec256 CPU.
- The selector checks a vec128 image.
set_maximum_sve_vector_length(16)is called.
- The selector then checks and selects a vec256 image.
- The algorithm does nothing because both the image and the native CPU support vec256.
- However, the CPU has already been reconfigured to vec128.
I'll fix this, but it means the CPU may be reconfigured multiple times while evaluating multiple candidate images.
Is there an existing JDK test case or documentation covering multiple images? If so, I should add a corresponding test to test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh.
There was a problem hiding this comment.
I believe we have multi-selection (called auto-selection) only downstream, and even there I'm not sure we have JDK-level tests for it (haven't checked) since it is an engine-level feature
There was a problem hiding this comment.
Maybe it makes sense downstreaming this before integrating the PR in case some other changes will surface
There was a problem hiding this comment.
OK, though I still have to fix JDK-8385359 first.
_ignore_glibc_not_using->_cpu_features_ignore
Co-authored-by: Timofei Pushkin <pushkin.td@gmail.com>
| static constexpr char cpuarch_name[] = "cpu.arch"; | ||
| static constexpr char cpufeatures_name[] = "cpu.features"; | ||
|
|
||
| bool CracEngine::pre_restore_bitmap_hook(const unsigned char *value, size_t value_size) const { |
There was a problem hiding this comment.
As I wrote in the previous comment, I don't suggest removing user_data from the API, just not to use it in the way we do now (which means that for now it'll be unused by us, but that's OK).
If changes to the existing API are acceptable, the proposed register_label_hook is a superset of require_label and could therefore replace it. The same applies to bitmap.
That would require adding more restrictions to how the new API can be used. The engine may use constraints API to select one of many images => the hooks can be called multiple times, including for images that won't end up being the one selected for restore => the hooks should not treat incompatible values as errors (e.g. in the current impl error logs should be replaced with debug logs). This is worth documenting in the API so that people don't call stuff like exit there.
Rename pre_restore_bitmap_hook -> bitmap_constraint_hook
should_skip_cpu_features_check() -> !should_check_cpu_features()
| if (ret == 0) { | ||
| ShouldNotReachHere(); | ||
| } else { |
There was a problem hiding this comment.
Engine is a separate user-provided piece of software. We should not hard-crash if it misbehaves (where possible).
Actually, according to the engine API spec any return code of restore is treated as an error code, even 0, so the previous behavior was also incorrect. We should not check the return value at all, merely log it.
| return _options; | ||
| } | ||
|
|
||
| bool CracEngine::bitmap_constraint_hook(const unsigned char *value, size_t value_size, void *user_data/*unused*/) { |
There was a problem hiding this comment.
Since it does not use anything from CracEngine, why not make it .cpp-level static?
| } | ||
|
|
||
| bool VM_Version::process_image_cpu_features(const VM_Features *image_featuresp) { | ||
| int want; |
There was a problem hiding this comment.
want_sve_vector_length
| if (supports_sve() && get_current_sve_vector_length() == 32) { | ||
| set_feature(CPU_SVE256); | ||
| } |
There was a problem hiding this comment.
The rest of the code seems to assume that !supports_feature(CPU_SVE256) => supports SVE128 (or less?), but I read there are CPUs with SVE vector lengths higher than 256 bits. Not sure JDK can run on them though. Is it guaranteed somewhere that higher lengths are not possible in this code?
There was a problem hiding this comment.
AI also complains about smaller sizes, resending verbatim:
- "get_os_cpu_info sets the bit only when VL is exactly 32, so a VL=64 machine (A64FX etc.) is indistinguishable from VL=16. On restore, want = image_supports_sve256 ? 32 : 16 then hard-sets VL to 16 — including when checkpointing and restoring on the same VL=64 host, where the restored JVM's code was compiled for MaxVectorSize=64. That's a silent miscompile/SIGILL, not a clean failure."
- "process_image_cpu_features(nullptr) recomputes 16/32 from _features rather than restoring what get_current_sve_vector_length() was before the hook ran. With -XX:MaxVectorSize=16 on an SVE256 CPU plus a failed restore and -XX:+CRaCIgnoreRestoreIfUnavailable (where the VM keeps running), the process ends up with VL=32 while its compiled code assumed 16."
| if (!hooks_result) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Maybe it would be a good idea to run all checks instead of failing fast so that the user sees the hole picture?
It will duplicate the error message for the SVE feature, but at least this way CheckCPUFeaturesMessage would be employed which can contain some useful info. BTW, if we make hooks' messages debug (as would be more correct for the multiple-selection case) the duplication could be avoided, otherwise CheckCPUFeaturesMessage should be incorporated into the hooks' messages somehow...
| _hooks.foreach([&](const Hook& hook) { | ||
| bool found = false; | ||
| tags.foreach([&](const Tag& t) { | ||
| if (!hooks_result || strcmp(hook.name, t.name) != 0) { |
There was a problem hiding this comment.
With this, if there are multiple hooks and one fails, every next hook will print the Hook did not find its tag line below
| VM_Features sve256; | ||
| sve256.set_feature(VM_Feature_Flag::CPU_SVE256); | ||
| ss.print("Specified -XX:CPUFeatures=%s have unset CPU_SVE256=%s, this CPU has CPUFeatures=%s but it cannot be disabled as PR_SVE_SET_VL reports %d: %m", | ||
| _features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), got); |
There was a problem hiding this comment.
print_numbers does resource allocation, so ResourceMark could be used.
There are other usages of it without the mark, but they are pre-existing.
| if (!Abstract_VM_Version::should_check_cpu_features()) { | ||
| return true; | ||
| } | ||
| ResourceMark rm; |
There was a problem hiding this comment.
#include "memory/resourceArea.hpp" should be added
| }; | ||
|
|
||
| static bool register_bitmap_hook(crlib_conf_t* conf, const char *name, ImageConstraints::BitmapHook hook, void *user_data) { | ||
| return COMMON(conf)->image_constraints.register_bitmap_hook(name, hook, user_data); | ||
| }; |
There was a problem hiding this comment.
| }; | |
| static bool register_bitmap_hook(crlib_conf_t* conf, const char *name, ImageConstraints::BitmapHook hook, void *user_data) { | |
| return COMMON(conf)->image_constraints.register_bitmap_hook(name, hook, user_data); | |
| }; | |
| } | |
| static bool register_bitmap_hook(crlib_conf_t* conf, const char *name, ImageConstraints::BitmapHook hook, void *user_data) { | |
| return COMMON(conf)->image_constraints.register_bitmap_hook(name, hook, user_data); | |
| } |
| struct VM_Features: public Zero_Features {}; | ||
| static bool cpu_features_binary(VM_Features *data) { return false; } | ||
| static bool check_cpu_features_skip() { return true; } | ||
| static bool can_use_cpu_features() { return false; } |
There was a problem hiding this comment.
The two new methods and restore_failed_check should be added to ppc/riscv/s390
| bash -c 'echo $$' | ||
| (set +x;while [ $(bash -c 'echo $$') -le $tid ];do :;done) | ||
| bash -c 'echo $$' |
There was a problem hiding this comment.
Nitpick: since the script uses dash in its shebang, maybe use dash here as well?
| } | ||
| internal_restore() { | ||
| javasetup | ||
| tid=$(echo cr/core-*.img|tr -cd ' 0-9'|sed 's/^.* //') # highest |
There was a problem hiding this comment.
Breaks when crossing a power of ten because of the lexicographic sort
It is a draft
src/hotspot/share/runtime/crac_engine.cppneeds to be reworked. I believecrlib_image_constraints::get_failed_bitmapshould becomeget_bitmapas this code needs to query image's CPUFeatures to find out its vector length to configure the CPU before restore. Otherwise one could also create some new user data. @rvansa?Progress
Issue
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/crac.git pull/331/head:pull/331$ git checkout pull/331Update a local copy of the PR:
$ git checkout pull/331$ git pull https://git.openjdk.org/crac.git pull/331/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 331View PR using the GUI difftool:
$ git pr show -t 331Using diff file
Download this PR as a diff file:
https://git.openjdk.org/crac/pull/331.diff
Using Webrev
Link to Webrev Comment