[cfe-dev] atomic intrinsics

Howard Hinnant hhinnant at apple.com
Fri Oct 15 19:06:10 PDT 2010


On Oct 15, 2010, at 9:05 PM, John McCall wrote:
>> I see, like:
>> 
>>  bool __atomic_is_lock_free(type);
>> 
>> ?
> 
> That's what I was thinking.

Thanks, I'll update the spec.

>>> The builtins have exactly those names and are "overloaded";  memory ordering parameters are required to be constant expressions but not necessarily literals.
>> 
>> If the memory orderings are required to be constant expressions, this is really Design B, just with some renaming.
> 
> I see what you mean.  I hadn't actually realized that the library actually takes these as runtime parameters;  that seems very un-C++-ish to me.  Certainly it's not very "pay for what you use", although I guess the presumption is that it will quickly optimize to the right thing.

Agreed.  This wouldn't have been the direction I would've designed.  On the other hand, I suspect the front end can handle it.

>> This is not a problem for libc++.  However I've heard rumblings that this won't be ok for the C library.  Want to comment Blaine?
> 
> Are the committees actually going to agree enough here to permit re-use?

I suspect so.  There are some formidable forces on both sides aimed at making it so.  I am not one of them (I don't attend C).  But it is my estimation that the individuals involved in assuring C/C++ compatibility in this department will succeed.

>  The main advantage of requiring the parameters to be constant expressions is that the builtins don't become intimately tied to a specific library.  I'm very concerned about building compiler APIs on top of competing and incomplete standards.

Very valid concern.  As far as I can tell, the C and C++ committees are converging on run time memory orderings.  Am I correct Blaine?

> If we accept this as a runtime argument, we will invoke undefined behavior on out-of-range enumerators.  Is that acceptable to C and C++?

Yes.  Nasal demons encouraged. :-)  This is a very low-level API.  Hand holding is not expected.  Ultimate efficiency is.

>>> Arguments not of fundamental type, or not exactly matching a permitted type for the intrinsic, are not required to be supported by the implementation (so calling swap with a long* and an int, or a Base** and a Derived*, or a ConvertibleToIntPtr and a ConvertibleToInt, may or may not have sensible results).
>> 
>> I'm afraid my spec is ambiguous, sorry.  In:
>> 
>> bool __atomic_compare_exchange_strong(type* atomic_obj,
>>                                     type* expected, type desired,
>>                                     int mem_success, int mem_failure);
>> 
>> It was my intention that in each argument that specifies "type", the types are all required to be the same.
> 
> Right, I just clarifying that.
> 
>> In C++ templates, this would be:
>> 
>> template <class type>
>> bool __atomic_compare_exchange_strong(type* atomic_obj,
>>                                     type* expected, type desired,
>>                                     int mem_success, int mem_failure);
>> 
>> Concerning arguments "type" that are not scalars: I believe I can handle this in libc++ with some fancy template meta programming, and pass them through to the front end type-punned as scalars if there is a scalar of the appropriate size, and otherwise route them to a library-lock function.  I can do this because "type" is a-priori known to be trivially copyable.
> 
> Okay.  If the libraries need to work with arbitrary trivially-copyable types, we should definitely do that in the builtins instead of in the library.  I'm willing to have the builtins take trivially-copyable types.

That's great.  Anything else sent in is undefined behavior.

>>> This doesn't strictly matter for you, but we would implement this in Clang by having the frontend do the ABI-compliant lowerings for the locking implementations and then emitting everything that can be done lock-free as an LLVM intrinsic call.
>> 
>> Does this translate to a call to compiler-rt for the locking implementations?  I ask because I'm probably going to be the one to implement these in compiler-rt if they are needed.
> 
> Multiple calls, I think;  an explicit acquire and release call.  Unless you think there's some benefit in having your compiler-rt function implement memcpy?
> 
> Note that these functions become platform ABI requirements.

I am ignorant in this department and will happily implement whatever specs/API the front end deems necessary.

-Howard





More information about the cfe-dev mailing list