Skip to content

[DWARFLinkerParallel] Change more cases of compare_exchange_weak to compare_exchange_strong #138692

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

Merged
merged 2 commits into from
May 7, 2025

Conversation

mstorsjo
Copy link
Member

@mstorsjo mstorsjo commented May 6, 2025

This is a follow-up to 07bc54b; this seems to perhaps fix occasional crashes in dsymutil on Windows on aarch64.

While these are used in loops, which could be tolerant to concurrent accesses, the overall logic seems to assume that they don't have spurious failures; I've observed one case in a debugger, where LastGroup == nullptr within the loop in ArrayList::add().

The remaining uses of compare_exchange_weak() in
DWARFLinkerCompileUnit.h also seem very suspicious; if there would be a true concurrent write, leading to compare_exchange_weak() returning false, it seems like we would get stuck in an endless loop - but changing them to compare_exchange_strong() wouldn't make any difference with respect to that.

…ompare_exchange_strong

This is a follow-up to 07bc54b;
this seems to perhaps fix occasional crashes in dsymutil on
Windows on aarch64.

While these are used in loops, which could be tolerant to
concurrent accesses, the overall logic seems to assume that
they don't have spurious failures; I've observed one case in
a debugger, where LastGroup == nullptr within the loop in
ArrayList::add().

The remaining uses of compare_exchange_weak() in
DWARFLinkerCompileUnit.h also seem very suspicious; if there
would be a true concurrent write, leading to compare_exchange_weak()
returning false, it seems like we would get stuck in an endless
loop - but changing them to compare_exchange_strong() wouldn't
make any difference with respect to that.
@mstorsjo mstorsjo requested a review from avl-llvm May 6, 2025 14:20
@mstorsjo mstorsjo requested a review from JDevlieghere as a code owner May 6, 2025 14:20
@mstorsjo
Copy link
Member Author

mstorsjo commented May 6, 2025

The remaining uses of compare_exchange_weak() in
DWARFLinkerCompileUnit.h also seem very suspicious; if there would be a true concurrent write, leading to compare_exchange_weak() returning false, it seems like we would get stuck in an endless loop - but changing them to compare_exchange_strong() wouldn't make any difference with respect to that.

Can you have a look at these cases? (I haven't run into issues with them, but the code looks like it could lock up.)

@avl-llvm
Copy link
Collaborator

avl-llvm commented May 6, 2025

The remaining uses of compare_exchange_weak() in
DWARFLinkerCompileUnit.h also seem very suspicious; if there would be a true concurrent write, leading to compare_exchange_weak() returning false, it seems like we would get stuck in an endless loop - but changing them to compare_exchange_strong() wouldn't make any difference with respect to that.

Can you have a look at these cases? (I haven't run into issues with them, but the code looks like it could lock up.)

yes, you are right those places look incorrect. Thank you for pointing to this.

Instead of

      auto InputData = Flags.load();
      while (!Flags.compare_exchange_weak(InputData,
                                          ((InputData & ~0x7) | Placement))) {
      }

there should be something like

      do {
        auto InputData = Flags.load();
      while (!Flags.compare_exchange_weak(InputData,
                                          ((InputData & ~0x7) | Placement)));

and loop should be added to:

      auto InputData = Flags.load();
      if ((InputData & 0x7) == NotSet)
        if (Flags.compare_exchange_weak(InputData, (InputData | Placement)))
          return true;

Would you prefer me to do these changes or would you prefer to do these changes youself?

@mstorsjo
Copy link
Member Author

mstorsjo commented May 6, 2025

The remaining uses of compare_exchange_weak() in
DWARFLinkerCompileUnit.h also seem very suspicious; if there would be a true concurrent write, leading to compare_exchange_weak() returning false, it seems like we would get stuck in an endless loop - but changing them to compare_exchange_strong() wouldn't make any difference with respect to that.

Can you have a look at these cases? (I haven't run into issues with them, but the code looks like it could lock up.)

yes, you are right those places look incorrect. Thank you for pointing to this.

Instead of

      auto InputData = Flags.load();
      while (!Flags.compare_exchange_weak(InputData,
                                          ((InputData & ~0x7) | Placement))) {
      }

there should be something like

      do {
        auto InputData = Flags.load();
      while (!Flags.compare_exchange_weak(InputData,
                                          ((InputData & ~0x7) | Placement)));

and loop should be added to:

      auto InputData = Flags.load();
      if ((InputData & 0x7) == NotSet)
        if (Flags.compare_exchange_weak(InputData, (InputData | Placement)))
          return true;

Would you prefer me to do these changes or would you prefer to do these changes youself?

Yes, that looks correct to me. As you're more familiar with the overall intent here (I'm just trying to debug things that show up when running ninja check ;-) ) I'd prefer if you'd open such a PR, but I can review it!

@avl-llvm
Copy link
Collaborator

avl-llvm commented May 6, 2025

Yes, that looks correct to me. As you're more familiar with the overall intent here (I'm just trying to debug things that show up when running ninja check ;-) ) I'd prefer if you'd open such a PR, but I can review it!

Ok, Will do that way(open PR and do changes) Thank you again for finding this!

@mstorsjo mstorsjo merged commit 52f568d into llvm:main May 7, 2025
11 checks passed
@mstorsjo mstorsjo deleted the dwarflinker-weak branch May 7, 2025 06:55
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
…ompare_exchange_strong (llvm#138692)

This is a follow-up to 07bc54b; this
fixes more occasional crashes in dsymutil on Windows on aarch64.
@avl-llvm
Copy link
Collaborator

The remaining uses of compare_exchange_weak() in
DWARFLinkerCompileUnit.h also seem very suspicious; if there would be a true concurrent write, leading to compare_exchange_weak() returning false, it seems like we would get stuck in an endless loop - but changing them to compare_exchange_strong() wouldn't make any difference with respect to that.

Can you have a look at these cases? (I haven't run into issues with them, but the code looks like it could lock up.)

yes, you are right those places look incorrect. Thank you for pointing to this.
Instead of

      auto InputData = Flags.load();
      while (!Flags.compare_exchange_weak(InputData,
                                          ((InputData & ~0x7) | Placement))) {
      }

there should be something like

      do {
        auto InputData = Flags.load();
      while (!Flags.compare_exchange_weak(InputData,
                                          ((InputData & ~0x7) | Placement)));

Would you prefer me to do these changes or would you prefer to do these changes youself?

Yes, that looks correct to me. As you're more familiar with the overall intent here (I'm just trying to debug things that show up when running ninja check ;-) ) I'd prefer if you'd open such a PR, but I can review it!

My answer was too hurry. This code looks OK:

auto InputData = Flags.load();
while (!Flags.compare_exchange_weak(InputData,
                                    ((InputData & ~0x7) | Placement))) {
}

There should not be endless loop here. if there would be a true concurrent write, leading to compare_exchange_weak() returning false, then InputData would be updated with current value of "Flags". Then it would - either match on next iteration and loop will finish, either(in case new concurrent write) it would be updated again.

So, after this MR was integrated, it looks like no more other issues inside dwarflinker parallel with usages of compare_exchange_weak.

@mstorsjo
Copy link
Member Author

The remaining uses of compare_exchange_weak() in
DWARFLinkerCompileUnit.h also seem very suspicious; if there would be a true concurrent write, leading to compare_exchange_weak() returning false, it seems like we would get stuck in an endless loop - but changing them to compare_exchange_strong() wouldn't make any difference with respect to that.

Can you have a look at these cases? (I haven't run into issues with them, but the code looks like it could lock up.)

yes, you are right those places look incorrect. Thank you for pointing to this.
Instead of

      auto InputData = Flags.load();
      while (!Flags.compare_exchange_weak(InputData,
                                          ((InputData & ~0x7) | Placement))) {
      }

there should be something like

      do {
        auto InputData = Flags.load();
      while (!Flags.compare_exchange_weak(InputData,
                                          ((InputData & ~0x7) | Placement)));

Would you prefer me to do these changes or would you prefer to do these changes youself?

Yes, that looks correct to me. As you're more familiar with the overall intent here (I'm just trying to debug things that show up when running ninja check ;-) ) I'd prefer if you'd open such a PR, but I can review it!

My answer was too hurry. This code looks OK:

auto InputData = Flags.load();
while (!Flags.compare_exchange_weak(InputData,
                                    ((InputData & ~0x7) | Placement))) {
}

There should not be endless loop here. if there would be a true concurrent write, leading to compare_exchange_weak() returning false, then InputData would be updated with current value of "Flags". Then it would - either match on next iteration and loop will finish, either(in case new concurrent write) it would be updated again.

So, after this MR was integrated, it looks like no more other issues inside dwarflinker parallel with usages of compare_exchange_weak.

Oh, indeed - you're right, I forgot that it updates the InputData variable with the new value on change. Yes then those things should indeed be ok.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants