On 7/26/18 10:55 AM, Mark Millard wrote:
> 
> 
> On 2018-Jul-26, at 10:21 AM, John Baldwin <jhb at FreeBSD.org> wrote:
> 
>> 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.
> 
> Some of my research was when I did not have FreeBSD available and was over
> the web and I did not cross check all of it later. I apparently looked
> at some older source at some point. I now see what you report for the
> #if test.

Yes, but the -E from above was when compiled with external GCC and it didn't 
change
_Atomic(int).  Here's part of the source of bar.c:

#include <sys/cdefs.h>
#include <stdatomic.h>

struct foo {
        _Atomic(int) one;
        _Atomic int two;
        atomic_int three;
};

And here is what that became after -E:

# 4 "bar.c"
struct foo {
 _Atomic(int) one;
 _Atomic int two;
 atomic_int three;
};

So cdefs.h did not define _Atomic.

Ah, if I add '-std=c99' then it does break.  Code that wants to use
C11 atomics via <stdatomic.h> should not be using -std=c99.  Try this:

Index: lib/ofed/librdmacm/Makefile
===================================================================
--- lib/ofed/librdmacm/Makefile (revision 335896)
+++ lib/ofed/librdmacm/Makefile (working copy)
@@ -8,6 +8,7 @@
 SHLIB_MAJOR=   1
 MK_PROFILE=    no
 CFLAGS+=       -I${_spath}
+CSTD=          gnu11
 
 SRCS= \
 acm.c \

If this works then we should probably mark OFED as a BROKEN_OPTION when
building with ancient GCC for now as well.

-- 
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