On 7/25/18 6:52 PM, Mark Millard wrote:
> 
> 
> On 2018-Jul-25, at 2:10 PM, Mark Millard <marklmi at yahoo.com> wrote:
> 
> 
> 
>> On 2018-Jul-25, at 10:09 AM, Mark Millard <marklmi at yahoo.com> wrote:
>>
>>> On 2018-Jul-25, at 8:39 AM, John Baldwin <jhb at freebsd.org> wrote:
>>>
>>>> On 7/24/18 11:39 PM, Mark Millard wrote:
>>>>> On 2018-Jul-24, at 10:32 PM, Mark Millard <marklmi at yahoo.com> wrote:
>>>>>
>>>>>> https://ci.freebsd.org/job/FreeBSD-head-amd64-gcc/6597/consoleText
>>>>>> (head -r336573 after the prior 6596's -r336565 ):
>>>>>>
>>>>>> --- all_subdir_lib/ofed ---
>>>>>> In file included from /workspace/src/contrib/ofed/librdmacm/cma.h:43:0,
>>>>>>              from /workspace/src/contrib/ofed/librdmacm/acm.c:42:
>>>>>> /workspace/src/contrib/ofed/librdmacm/cma.h: In function 'fastlock_init':
>>>>>> /workspace/src/contrib/ofed/librdmacm/cma.h:60:2: error: invalid 
>>>>>> initializer
>>>>>> atomic_store(&lock->cnt, 0);
>>>>>> ^
>>>>>> In file included from /workspace/src/contrib/ofed/librdmacm/acm.c:42:0:
>>>>>> /workspace/src/contrib/ofed/librdmacm/cma.h: In function 
>>>>>> 'fastlock_acquire':
>>>>>> /workspace/src/contrib/ofed/librdmacm/cma.h:68:2: error: operand type 
>>>>>> 'struct <anonymous> *' is incompatible with argument 1 of 
>>>>>> '__atomic_fetch_add'
>>>>>> if (atomic_fetch_add(&lock->cnt, 1) > 0)
>>>>>> ^~
>>>>>> /workspace/src/contrib/ofed/librdmacm/cma.h: In function 
>>>>>> 'fastlock_release':
>>>>>> /workspace/src/contrib/ofed/librdmacm/cma.h:73:2: error: operand type 
>>>>>> 'struct <anonymous> *' is incompatible with argument 1 of 
>>>>>> '__atomic_fetch_sub'
>>>>>> if (atomic_fetch_sub(&lock->cnt, 1) > 1)
>>>>>> ^~
>>>>>> . . .
>>>>>> --- all_subdir_lib/ofed ---
>>>>>> *** [acm.o] Error code 1
>>>>>>
>>>>>>
>>>>>> https://ci.freebsd.org/job/FreeBSD-head-amd64-gcc/6621/consoleText ( for
>>>>>> -r336700 ) still shows this type of error.
>>>>>
>>>>>
>>>>> [I should have a subject with "head -r336568 through -r336570 . . .".]
>>>>>
>>>>> From what I can tell looking around having something like:
>>>>>
>>>>> if (atomic_fetch_add(&lock->cnt, 1) > 0)
>>>>>
>>>>> involve a __atomic_fetch_add indicates that:
>>>>>
>>>>> /usr/local/lib/gcc/x86_64-unknown-freebsd12.0/6.4.0/include/stdatomic.h
>>>>>
>>>>> was in use instead of FreeBSD's stdatomic.h file.
>>>>>
>>>>> If this is right, then the issue may be tied to head -r335782
>>>>> implicitly changing the order of the include file directory
>>>>> searching for builds via the devel/*-gcc .
>>>>>
>>>>> (I reverted -r335782 in my environment some time ago and have
>>>>> not run into this problem in my context so far.)
>>>>
>>>> C11 atomics should work fine with compiler-provided headers since they
>>>> are a part of the language (and the system stdatomic.h simply attempts
>>>> to mimic the compiler-provided header in case it is missing).
>>>>
>>>> Simple standalone tests of _Atomic(int) with GCC don't trigger those
>>>> failures when using its stdatomic.h, so there is probably something else
>>>> going on with kernel includes being used while building the library,
>>>> etc.  The last time we had this issue with stdarg.h it was because a
>>>> header shared between the kernel and userland always used 
>>>> '<machine/stdarg.h>'
>>>> which is correct for the kernel but not for userland.
>>>
>>> I did misread the headers. FreeBSD has the likes of:
>>>
>>> #if defined(__CLANG_ATOMICS)
>>> . . .
>>> #define     atomic_fetch_add_explicit(object, operand, order)               
>>> \
>>>     __c11_atomic_fetch_add(object, operand, order)
>>> . . .
>>> #elif defined(__GNUC_ATOMICS)
>>> . . .
>>> #define     atomic_fetch_add_explicit(object, operand, order)               
>>> \
>>>     __atomic_fetch_add(&(object)->__val, operand, order)
>>> . . .
>>> #endif
>>> . . .
>>> #define     atomic_fetch_add(object, operand)                               
>>> \
>>>     atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
>>>
>>> so __atomic_fetch_add would occur.
>>>
>>> But so far I do not see the problem with -r335782 reverted. I last built
>>> -r336693 last night via devel/amd64-gcc (via xtoolchain).
>>>
>>> From what I can tell FreeBSD defines:
>>>
>>> #if !defined(__CLANG_ATOMICS)
>>> #define     _Atomic(T)                      struct { volatile T __val; }
>>> #endif
>>>
>>> and that struct is being used in &(object)->__val is what the
>>> error reports are about. So that would be, for example,
>>>
>>> &(&lock->cnt)->__val
>>>
>>> This would appear to suggest that __val itself had a type meeting:
>>>
>>> operand type struct <anonymous>
>>>
>>> for T in _Atomic(T) .
>>>
>>> (This is independent of just what the issue traces back to: just
>>> the net result on ci.freebsd.org . No claim that you are right
>>> or wrong here. I'll not be looking any more until this afternoon
>>> or night.)
>>
>> Going in a somewhat different direction . . .
>>
>> Looking around I found https://bugs.llvm.org/show_bug.cgi?id=26462
>> which is titled:
>>
>> 26462 – GCC/clang C11 _Atomic incompatibility
>>
>> It appears that the normal source of platform ABI definitions are
>> not explicit/detailed in the area and allow for incompatibilities
>> in this area. clang and gcc made differing choices absent being
>> constrained to match.
>>
>> An example (a powerpc64 context was indicated):
>>
>> struct A16 { char val[16]; }; 
>> _Atomic struct A16 a16; 
>> // GCC:
>> _Static_assert(_Alignof(a16) == 16, ""); 
>> // Clang:
>> _Static_assert(_Alignof(a16) == 1, ""); 
>>
>>
>> Non-power-of-2 is a general problem
>> (not a powerpc64 context from what I can
>> tell):
>>
>> struct A3 { char val[3]; };
>> _Atomic struct A3 a3;
>> // GCC:
>> _Static_assert(sizeof(a3) == 3, "");
>> _Static_assert(_Alignof(a3) == 1, "");
>> // Clang:
>> _Static_assert(sizeof(a3) == 4, "");
>> _Static_assert(_Alignof(a3) == 4, "");
>>
>>
>>
>> Comment 6 (by John McCall) is relevant:
>>
>> QUOTE
>> Anyway, while I prefer the Clang rule, the GCC rule is defensible, as are 
>> any number of other rules.  The important point, however, is that having 
>> this discussion is not the right approach to solving this problem.  The 
>> layout of _Atomic(T) is ABI.  ABI rules are not generally determined by 
>> compiler implementors making things up as they go along, or at least they 
>> shouldn't be.  The Darwin ABI for _Atomic is the rule implemented in Clang, 
>> which we actually did think about carefully when we adopted it.  Other 
>> platforms need to make their own call, and it probably shouldn't just be 
>> "whatever's implemented in GCC", especially on other platforms where GCC is 
>> not the system compiler.
>> END QUOTE
>>
>>
>> (I do nto claim to have proivided all the material that should
>> be read in https://bugs.llvm.org/show_bug.cgi?id=26462 .)
>>
>> It may be that FreeBSD needs to be the source of the ABI definitions
>> involved if clang and gcc freeBSD builds are to be interoperable in
>> this area. But this could mean avoiding builtins?
>>
>> If any of this is inlined and so not behind a more stable interface,
>> it looks like clang and gcc can not be mixed for the same instances
>> of various _Atomic possibilities.
>>
>>
> 
> 
> Going back to the code being compiled and 
> confirming your note:
> ( /usr/src/contrib/ofed/librdmacm/cma.h )
> 
> typedef struct {
>         sem_t sem;
>         _Atomic(int) cnt;
> } fastlock_t;
> . . .
> static inline void fastlock_acquire(fastlock_t *lock)
> {
>         if (atomic_fetch_add(&lock->cnt, 1) > 0)
>                 sem_wait(&lock->sem);
> }
> 
> So lock->cnt is an _Atomic(int) , i.e.,
> 
> struct { volatile int __val; }
> 
> so overall:
> 
> typedef struct {
>         sem_t sem;
>         struct { volatile int __val; } cnt;
> } fastlock_t;
> 
> 
> for which: atomic_fetch_add(&lock->cnt, 1) has
> for A filled-in in the C11 language official:
> 
> atomic_fetch_add (volatile A* obj, M arg)
> 
> (generic function) being:
> 
> atomic_fetch_add (volatile struct { volatile int __val; }* obj, M arg)
> 
> and a direct type-check of that notation for obj would find:
> 
> operand type 'struct <anonymous> *'
> 
> and that would propagate to GCC's translation to __atomic_fetch_add
> via gcc's stdatomic.h :
> 
> #define atomic_fetch_add(PTR, VAL) __atomic_fetch_add ((PTR), (VAL),  \
>                                                      __ATOMIC_SEQ_CST)
> 
> So, yes, it looks like the:
> 
> #if !defined(__CLANG_ATOMICS)
> #define       _Atomic(T)                      struct { volatile T __val; }
> #endif

So where are you seeing this btw?  In head the conditional is different:

#if !defined(__cplusplus) && !__has_extension(c_atomic) && \
    !__has_extension(cxx_atomic)
/*
 * No native support for _Atomic(). Place object in structure to prevent
 * most forms of direct non-atomic access.
 */
#define _Atomic(T)              struct { T volatile __val; }
#endif

And external GCC does support those extensions so should end up not defining
an _Atomic macro, and in fact when I use -E with external GCC it leaves
_Atomic(int) alone:

% x86_64-unknown-freebsd11.2-gcc -E bar.c
...
# 1 "bar.c"
# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 2 "bar.c" 2
# 1 "/usr/local/lib/gcc/x86_64-unknown-freebsd11.2/6.4.0/include/stdatomic.h" 1 
3 4
# 29 "/usr/local/lib/gcc/x86_64-unknown-freebsd11.2/6.4.0/include/stdatomic.h" 
3 4

# 29 "/usr/local/lib/gcc/x86_64-unknown-freebsd11.2/6.4.0/include/stdatomic.h" 
3 4
typedef enum
  {
    memory_order_relaxed = 0,
    memory_order_consume = 1,
    memory_order_acquire = 2,
    memory_order_release = 3,
    memory_order_acq_rel = 4,
    memory_order_seq_cst = 5
  } memory_order;


typedef _Atomic _Bool atomic_bool;
typedef _Atomic char atomic_char;
...

So cdefs.h isn't overriding _Atomic and should be using the CLANG_ATOMICS case
for external GCC.

-- 
John Baldwin
_______________________________________________
freebsd-current@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"

Reply via email to