Re: [HACKERS] Broken atomics code on PPC with FreeBSD 10.3 - Mailing list pgsql-hackers

From Tom Lane
Subject Re: [HACKERS] Broken atomics code on PPC with FreeBSD 10.3
Date
Msg-id 15009.1483112902@sss.pgh.pa.us
Whole thread Raw
In response to [HACKERS] Broken atomics code on PPC with FreeBSD 10.3  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: [HACKERS] Broken atomics code on PPC with FreeBSD 10.3
Re: [HACKERS] Broken atomics code on PPC with FreeBSD 10.3
List pgsql-hackers
Andres Freund <andres@anarazel.de> writes:
> On 2016-12-30 00:44:33 -0500, Tom Lane wrote:
>> Perhaps it could be argued that there's a FreeBSD compiler bug here,
>> but what I'm wondering is why configure believes that this:
>> 
>> [char lock = 0;
>> __sync_lock_test_and_set(&lock, 1);
>> __sync_lock_release(&lock);])],
>> 
>> is going to draw a hard error on platforms without byte-wide atomics.
>> My sense of C semantics is that the best you could hope for is a
>> warning

> Well, in theory these aren't actual functions but intrinsics with
> special behaviour ("by being overloaded so that they work on multiple
> types."). The compiler is supposed to warn and link to an external
> function if a certain operation is not available:

Yeah, I read that.  But configure tests don't normally notice warnings.
Therefore, even if the compiler is behaving fully per spec (and I think
FreeBSD's might not be), we are going to think that char and word-wide
operations are interchangeable even when one is an efficient, in-line
operation and the other is inefficiently emulated by a function or
kernel trap.  This doesn't really seem good enough, especially for
standard architectures where we know darn well what ought to happen.

There's a reason why we've not converted s_lock.h to rely on compiler
intrinsics everywhere, and this is exactly it: the quality of the
intrinsics implementations are horridly variable.

> So that assumption made in that configure test doesn't seem that
> unreasonable.  What assembler do byte-wide atomics generate on that
> platform?  Which compiler/version is this?

$ gcc -v
Using built-in specs.
Target: powerpc-undermydesk-freebsd
Configured with: FreeBSD/powerpc system compiler
Thread model: posix
gcc version 4.2.1 20070831 patched [FreeBSD]

I tried "gcc -Wall -O0 -g -S bogus.c" on this input:

int
test_tas_char(volatile char *ptr)
{
  return __sync_lock_test_and_set(ptr, 1) == 0;
}

int
test_tas_int(volatile int *ptr)
{
  return __sync_lock_test_and_set(ptr, 1) == 0;
}

and got no warnings and the attached output.  I'm not very good at reading
PPC assembler, but I think what is happening in the "char" case is that
gcc is trying to emulate a byte-wide operation using a word-wide one,
ie an lwarx/stwcx. loop.  Even if that works (and apparently it does not),
we would not want to use it since it implies contention between adjacent
atomic flags.

BTW, I looked around to see why the PPC critters in the buildfarm aren't
failing, and the answer is that they all have compilers that are too old
to have __sync_lock_test_and_set at all, so that the configure probes
just fail outright.  But the probes can't tell the difference between
implementations we want to use and implementations we don't.

            regards, tom lane

    .file    "bogus.c"
    .section    .debug_abbrev,"",@progbits
.Ldebug_abbrev0:
    .section    .debug_info,"",@progbits
.Ldebug_info0:
    .section    .debug_line,"",@progbits
.Ldebug_line0:
    .section    ".text"
.Ltext0:
    .align 2
    .globl test_tas_char
    .type    test_tas_char, @function
test_tas_char:
.LFB2:
    .file 1 "bogus.c"
    .loc 1 3 0
    stwu 1,-32(1)
.LCFI0:
    stw 31,28(1)
.LCFI1:
    mr 31,1
.LCFI2:
    stw 3,8(31)
    .loc 1 4 0
    lwz 7,8(31)
    stw 7,12(31)
    lwz 8,12(31)
    lbz 8,0(8)
    stb 8,17(31)
.L2:
    lbz 9,17(31)
    stb 9,16(31)
    li 11,1
    lwz 10,12(31)
    rlwinm 9,10,3,27,28
    xori 9,9,24
    lbz 0,16(31)
    rlwinm 10,0,0,24,31
    slw 10,10,9
    rlwinm 0,11,0,0xff
    rlwinm 11,0,0,24,31
    slw 11,11,9
    li 0,255
    slw 0,0,9
    lwz 7,12(31)
    rlwinm 9,7,0,0,29
    sync
.L4:
    lwarx 8,0,9
    and 7,8,0
    cmpw 0,7,10
    bne- 0,.L5
    andc 8,8,0
    or 8,8,11
    stwcx. 8,0,9
    bne- 0,.L4
    isync
.L5:
    mr 0,7
    stb 0,17(31)
    lbz 9,17(31)
    lbz 0,16(31)
    cmpw 7,9,0
    bne 7,.L2
    lbz 0,16(31)
    cmpwi 7,0,0
    mfcr 0
    rlwinm 0,0,31,1
    .loc 1 5 0
    mr 3,0
    lwz 11,0(1)
    lwz 31,-4(11)
    mr 1,11
    blr
.LFE2:
    .size    test_tas_char,.-test_tas_char
    .align 2
    .globl test_tas_int
    .type    test_tas_int, @function
test_tas_int:
.LFB3:
    .loc 1 9 0
    stwu 1,-32(1)
.LCFI3:
    stw 31,28(1)
.LCFI4:
    mr 31,1
.LCFI5:
    stw 3,8(31)
    .loc 1 10 0
    lwz 9,8(31)
    li 10,1
    sync
.L8:
    lwarx 0,0,9
    mr 11,10
    stwcx. 11,0,9
    bne- 0,.L8
    isync
    cmpwi 7,0,0
    mfcr 0
    rlwinm 0,0,31,1
    .loc 1 11 0
    mr 3,0
    lwz 11,0(1)
    lwz 31,-4(11)
    mr 1,11
    blr
.LFE3:
    .size    test_tas_int,.-test_tas_int
    .section    .debug_frame,"",@progbits
.Lframe0:
    .4byte    .LECIE0-.LSCIE0
.LSCIE0:
    .4byte    0xffffffff
    .byte    0x1
    .string    ""
    .uleb128 0x1
    .sleb128 -4
    .byte    0x6c
    .byte    0xc
    .uleb128 0x1
    .uleb128 0x0
    .align 2
.LECIE0:
.LSFDE0:
    .4byte    .LEFDE0-.LASFDE0
.LASFDE0:
    .4byte    .Lframe0
    .4byte    .LFB2
    .4byte    .LFE2-.LFB2
    .byte    0x4
    .4byte    .LCFI0-.LFB2
    .byte    0xe
    .uleb128 0x20
    .byte    0x4
    .4byte    .LCFI1-.LCFI0
    .byte    0x9f
    .uleb128 0x1
    .byte    0x4
    .4byte    .LCFI2-.LCFI1
    .byte    0xd
    .uleb128 0x1f
    .align 2
.LEFDE0:
.LSFDE2:
    .4byte    .LEFDE2-.LASFDE2
.LASFDE2:
    .4byte    .Lframe0
    .4byte    .LFB3
    .4byte    .LFE3-.LFB3
    .byte    0x4
    .4byte    .LCFI3-.LFB3
    .byte    0xe
    .uleb128 0x20
    .byte    0x4
    .4byte    .LCFI4-.LCFI3
    .byte    0x9f
    .uleb128 0x1
    .byte    0x4
    .4byte    .LCFI5-.LCFI4
    .byte    0xd
    .uleb128 0x1f
    .align 2
.LEFDE2:
    .section    ".text"
.Letext0:
    .section    .debug_loc,"",@progbits
.Ldebug_loc0:
.LLST0:
    .4byte    .LFB2-.Ltext0
    .4byte    .LCFI0-.Ltext0
    .2byte    0x1
    .byte    0x51
    .4byte    .LCFI0-.Ltext0
    .4byte    .LCFI2-.Ltext0
    .2byte    0x2
    .byte    0x71
    .sleb128 32
    .4byte    .LCFI2-.Ltext0
    .4byte    .LFE2-.Ltext0
    .2byte    0x2
    .byte    0x8f
    .sleb128 32
    .4byte    0x0
    .4byte    0x0
.LLST1:
    .4byte    .LFB3-.Ltext0
    .4byte    .LCFI3-.Ltext0
    .2byte    0x1
    .byte    0x51
    .4byte    .LCFI3-.Ltext0
    .4byte    .LCFI5-.Ltext0
    .2byte    0x2
    .byte    0x71
    .sleb128 32
    .4byte    .LCFI5-.Ltext0
    .4byte    .LFE3-.Ltext0
    .2byte    0x2
    .byte    0x8f
    .sleb128 32
    .4byte    0x0
    .4byte    0x0
    .section    .debug_info
    .4byte    0xdf
    .2byte    0x2
    .4byte    .Ldebug_abbrev0
    .byte    0x4
    .uleb128 0x1
    .string    "GNU C 4.2.1 20070831 patched [FreeBSD]"
    .byte    0x1
    .string    "bogus.c"
    .string    "/home/tgl"
    .4byte    .Ltext0
    .4byte    .Letext0
    .4byte    .Ldebug_line0
    .uleb128 0x2
    .byte    0x1
    .string    "test_tas_char"
    .byte    0x1
    .byte    0x3
    .byte    0x1
    .4byte    0x88
    .4byte    .LFB2
    .4byte    .LFE2
    .4byte    .LLST0
    .4byte    0x88
    .uleb128 0x3
    .string    "ptr"
    .byte    0x1
    .byte    0x2
    .4byte    0x8f
    .byte    0x2
    .byte    0x91
    .sleb128 -24
    .byte    0x0
    .uleb128 0x4
    .byte    0x4
    .byte    0x5
    .string    "int"
    .uleb128 0x5
    .byte    0x4
    .4byte    0x95
    .uleb128 0x6
    .4byte    0x9a
    .uleb128 0x4
    .byte    0x1
    .byte    0x8
    .string    "char"
    .uleb128 0x2
    .byte    0x1
    .string    "test_tas_int"
    .byte    0x1
    .byte    0x9
    .byte    0x1
    .4byte    0x88
    .4byte    .LFB3
    .4byte    .LFE3
    .4byte    .LLST1
    .4byte    0xd7
    .uleb128 0x3
    .string    "ptr"
    .byte    0x1
    .byte    0x8
    .4byte    0xd7
    .byte    0x2
    .byte    0x91
    .sleb128 -24
    .byte    0x0
    .uleb128 0x5
    .byte    0x4
    .4byte    0xdd
    .uleb128 0x6
    .4byte    0x88
    .byte    0x0
    .section    .debug_abbrev
    .uleb128 0x1
    .uleb128 0x11
    .byte    0x1
    .uleb128 0x25
    .uleb128 0x8
    .uleb128 0x13
    .uleb128 0xb
    .uleb128 0x3
    .uleb128 0x8
    .uleb128 0x1b
    .uleb128 0x8
    .uleb128 0x11
    .uleb128 0x1
    .uleb128 0x12
    .uleb128 0x1
    .uleb128 0x10
    .uleb128 0x6
    .byte    0x0
    .byte    0x0
    .uleb128 0x2
    .uleb128 0x2e
    .byte    0x1
    .uleb128 0x3f
    .uleb128 0xc
    .uleb128 0x3
    .uleb128 0x8
    .uleb128 0x3a
    .uleb128 0xb
    .uleb128 0x3b
    .uleb128 0xb
    .uleb128 0x27
    .uleb128 0xc
    .uleb128 0x49
    .uleb128 0x13
    .uleb128 0x11
    .uleb128 0x1
    .uleb128 0x12
    .uleb128 0x1
    .uleb128 0x40
    .uleb128 0x6
    .uleb128 0x1
    .uleb128 0x13
    .byte    0x0
    .byte    0x0
    .uleb128 0x3
    .uleb128 0x5
    .byte    0x0
    .uleb128 0x3
    .uleb128 0x8
    .uleb128 0x3a
    .uleb128 0xb
    .uleb128 0x3b
    .uleb128 0xb
    .uleb128 0x49
    .uleb128 0x13
    .uleb128 0x2
    .uleb128 0xa
    .byte    0x0
    .byte    0x0
    .uleb128 0x4
    .uleb128 0x24
    .byte    0x0
    .uleb128 0xb
    .uleb128 0xb
    .uleb128 0x3e
    .uleb128 0xb
    .uleb128 0x3
    .uleb128 0x8
    .byte    0x0
    .byte    0x0
    .uleb128 0x5
    .uleb128 0xf
    .byte    0x0
    .uleb128 0xb
    .uleb128 0xb
    .uleb128 0x49
    .uleb128 0x13
    .byte    0x0
    .byte    0x0
    .uleb128 0x6
    .uleb128 0x35
    .byte    0x0
    .uleb128 0x49
    .uleb128 0x13
    .byte    0x0
    .byte    0x0
    .byte    0x0
    .section    .debug_pubnames,"",@progbits
    .4byte    0x31
    .2byte    0x2
    .4byte    .Ldebug_info0
    .4byte    0xe3
    .4byte    0x52
    .string    "test_tas_char"
    .4byte    0xa2
    .string    "test_tas_int"
    .4byte    0x0
    .section    .debug_aranges,"",@progbits
    .4byte    0x1c
    .2byte    0x2
    .4byte    .Ldebug_info0
    .byte    0x4
    .byte    0x0
    .2byte    0x0
    .2byte    0x0
    .4byte    .Ltext0
    .4byte    .Letext0-.Ltext0
    .4byte    0x0
    .4byte    0x0
    .ident    "GCC: (GNU) 4.2.1 20070831 patched [FreeBSD]"
    .section    .note.GNU-stack,"",@progbits

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

pgsql-hackers by date:

Previous
From: Craig Ringer
Date:
Subject: Re: [HACKERS] Add doc advice about systemd RemoveIPC
Next
From: Erik Rijkers
Date:
Subject: Re: [HACKERS] Logical Replication WIP