Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive

Added atomicExchange to core.atomic#2729

Merged
dlang-bot merged 2 commits intodlang:masterfrom
TurkeyMan:atomic_exchange
Aug 12, 2019
Merged

Added atomicExchange to core.atomic#2729
dlang-bot merged 2 commits intodlang:masterfrom
TurkeyMan:atomic_exchange

Conversation

@TurkeyMan
Copy link
Contributor

@TurkeyMan TurkeyMan commented Aug 12, 2019

No description provided.

@dlang-bot
Copy link
Contributor

dlang-bot commented Aug 12, 2019

Thanks for your pull request and interest in making D better, @TurkeyMan! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Auto-close Bugzilla Severity Description
20104 enhancement core.atomic has no exchange function

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub fetch digger
dub run digger -- build "master + druntime#2729"

@TurkeyMan
Copy link
Contributor Author

What is that CI error?

@thewilsonator
Copy link
Contributor

Please add "Fix Issue 20104" to the commit title so that it gets picked up by the bot. Also pure inline asm is likely do cause problems for LDC/GDC optimisers.

@dlang-bot dlang-bot added the Enhancement New functionality label Aug 12, 2019
@TurkeyMan
Copy link
Contributor Author

I'm just following the rest of the code in core.atomic.
There are no intrinsics for the atomic ops...

@thewilsonator
Copy link
Contributor

OK. We should probably fix that at some point though.

@TurkeyMan
Copy link
Contributor Author

Assuming that LDC/GDC have their own druntime forks, they'll need to implement this function such that it pipes through to those compilers intrinsics properly.

@TurkeyMan TurkeyMan force-pushed the atomic_exchange branch 2 times, most recently from ed3ac46 to 757b671 Compare August 12, 2019 05:35
@ibuclaw
Copy link
Member

ibuclaw commented Aug 12, 2019

There's #2596, not merged because people are unsure what to do when atomics aren't supported (currently, fake pure mutex).

}

shared(T) atomicExchange(MemoryOrder ms = MemoryOrder.seq,T,V)( shared(T)* here, V exchangeWith ) pure nothrow @nogc @safe
if ( !is(T == class) && !is(T U : U*) && __traits( compiles, { *here = exchangeWith; } ) )
Copy link
Member

Choose a reason for hiding this comment

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

Just to make sure you've done your homework, are there any invalid memory orders for this operation? (I think I know the answer without checking anyway).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are no invalid orders.
Infact, the order does not affect codegen in any way; it should be routed through to the backend to inform code mobility.

@TurkeyMan
Copy link
Contributor Author

people are unsure what to do when atomics aren't supported

Personally, I'd rather an error in a library called 'druntime'.
If it were a feature of phobos, I'd say spinlock.

@TurkeyMan
Copy link
Contributor Author

wtf is an atomic float?! that's not a thing!

@ibuclaw
Copy link
Member

ibuclaw commented Aug 12, 2019

Personally, I'd rather an error in a library called 'druntime'.
If it were a feature of phobos, I'd say spinlock.

That would be fine if the atomic module wasn't used by druntime in critical places. But this line of discussion is best to be done in the other pr.

... Atomic exchange SGTM.

@thewilsonator
Copy link
Contributor

Of course it is, how else are you supposed to do race free parallel reductions?

@TurkeyMan TurkeyMan force-pushed the atomic_exchange branch 4 times, most recently from 11e6b05 to da02edf Compare August 12, 2019 07:12
@TurkeyMan
Copy link
Contributor Author

This is grueling... how many hours have I been trying to pacify the CI now? >_<

@TurkeyMan
Copy link
Contributor Author

I don't understand what's wrong with the float test... it works for me locally :/

@thewilsonator
Copy link
Contributor

Different calling conv?

Fix Issue 20104 - core.atomic has no exchange function
@TurkeyMan
Copy link
Contributor Author

Doesn't explain why the apveyor test fails, since that's specifically what I'm testing...

@TurkeyMan
Copy link
Contributor Author

Also, this code shouldn't interact with the calling convention; that's handled outside the asm block.

assert( base !is val, T.stringof );
assert( atom is base, T.stringof );

assert( atomicExchange( &atom, val ) is base, T.stringof );
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe do

auto x = atomicExchange( &atom, val );
static if (is(T == float))
    printf("%a, %a\n",x, base);
    assert(x is base, T.stringof);

and see what it thinks?

{
mov exchangeWith, RAX;
}
return exchangeWith;
Copy link
Contributor Author

@TurkeyMan TurkeyMan Aug 12, 2019

Choose a reason for hiding this comment

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

@WalterBright I think there might be a codegen issue with asm in functions... this here assigns RAX to a local, which emits correct code, but then the return doesn't actually return the argument correctly.

I reduced the snippet:

extern(C) float floop(float* r, float x)
{
  asm
  {
    mov EAX, x;
    mov RCX, r;
    xchg [RCX], EAX;
    mov x, EAX;
  }
  return x;
}

And compile with DMD: dmd asmtest.d -c -m64 and emit's this:

0000000000000000 <floop>:
   0:   55                      push   %rbp
   1:   48 8b ec                mov    %rsp,%rbp
   4:   48 83 ec 10             sub    $0x10,%rsp
   8:   48 89 7d f0             mov    %rdi,-0x10(%rbp)
   c:   f3 0f 11 45 f8          movss  %xmm0,-0x8(%rbp)

; the asm block
  11:   8b 45 f8                mov    -0x8(%rbp),%eax
  14:   48 8b 4d f0             mov    -0x10(%rbp),%rcx
  18:   87 01                   xchg   %eax,(%rcx)
  1a:   89 45 f8                mov    %eax,-0x8(%rbp)

; return statement doesn't repopulate xmm0
;   movss  0x8(%rbp),%xmm0   ; <- this is missing!
  1d:   c9                      leaveq
  1e:   c3                      retq

There's a line missing that should load the float back into xmm0 before returning... I suspect DMD is assuming that the asm block did not clobber x.

This is on linux... but when I build for windows, I don't see this issue.

Copy link
Contributor Author

@TurkeyMan TurkeyMan Aug 12, 2019

Choose a reason for hiding this comment

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

Well, the CI here suggests it fails on windows too; perhaps it's just that I can't repro this issue on my local machine...?
Is it possible there's a regression in a DMD more recent than the version I'm running locally? (2.087.0 Windows)
Has anything changed recently that might affect this?

Copy link
Contributor Author

@TurkeyMan TurkeyMan Aug 12, 2019

Choose a reason for hiding this comment

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

-m32 does work properly:

00000000 <floop>:
   0:   55                      push   %ebp
   1:   8b ec                   mov    %esp,%ebp
   3:   8b 45 0c                mov    0xc(%ebp),%eax
   6:   8b 4d 08                mov    0x8(%ebp),%ecx
   9:   87 01                   xchg   %eax,(%ecx)
   b:   89 45 0c                mov    %eax,0xc(%ebp)
   e:   d9 45 0c                flds   0xc(%ebp)  ; <- here it is
  11:   5d                      pop    %ebp
  12:   c3                      ret

So, it's just x64... and only on master DMD, my local compiler works correctly. (2.087.0 Windows)

@TurkeyMan
Copy link
Contributor Author

Mmm, I think is codegen bug.
Fixed it with more explicit asm...

@dlang-bot dlang-bot merged commit 7d006c2 into dlang:master Aug 12, 2019
@TurkeyMan TurkeyMan deleted the atomic_exchange branch August 13, 2019 05:14
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Enhancement New functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants