Atomic test-and-set instruction does not work on qemu-user
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
QEMU |
Expired
|
Undecided
|
Unassigned |
Bug Description
I try to compile and run PostgreSQL/
```
host: CentOS7 x86_64
container: centos:
qemu-user-static: https:/
```
However, GP/PG's spinlock always gets stuck and reports PANIC errors. It seems its spinlock
has something wrong.
```
https:/
https:/
```
So I extract its spinlock implementation into one test C source file (see attachment file),
and get reprodcued:
```
$ gcc spinlock_qemu.c
$ ./a.out
C -- slock inited, lock value is: 0
parent 139642, child 139645
P -- slock lock before, lock value is: 0
P -- slock locked, lock value is: 1
P -- slock unlock after, lock value is: 0
C -- slock lock before, lock value is: 1
P -- slock lock before, lock value is: 1
C -- slock locked, lock value is: 1
C -- slock unlock after, lock value is: 0
C -- slock lock before, lock value is: 1
P -- slock locked, lock value is: 1
P -- slock unlock after, lock value is: 0
P -- slock lock before, lock value is: 1
C -- slock locked, lock value is: 1
C -- slock unlock after, lock value is: 0
P -- slock locked, lock value is: 1
C -- slock lock before, lock value is: 1
P -- slock unlock after, lock value is: 0
C -- slock locked, lock value is: 1
P -- slock lock before, lock value is: 1
C -- slock unlock after, lock value is: 0
P -- slock locked, lock value is: 1
C -- slock lock before, lock value is: 1
P -- slock unlock after, lock value is: 0
C -- slock locked, lock value is: 1
P -- slock lock before, lock value is: 1
C -- slock unlock after, lock value is: 0
P -- slock locked, lock value is: 1
C -- slock lock before, lock value is: 1
P -- slock unlock after, lock value is: 0
P -- slock lock before, lock value is: 1
spin timeout, lock value is 1 (pid 139642)
spin timeout, lock value is 1 (pid 139645)
spin timeout, lock value is 1 (pid 139645)
spin timeout, lock value is 1 (pid 139642)
spin timeout, lock value is 1 (pid 139645)
spin timeout, lock value is 1 (pid 139642)
...
...
...
```
NOTE: this code always works on PHYSICAL ARM64 server.
Changed in qemu: | |
status: | Expired → New |
Interestingly, the spinlock test works after I change tas() implementation lock_test_ and_set( lock, 1); val_compare_ and_swap( lock, 0, 1);
FROM
__sync_
TO
__sync_
## gcc (GCC) 8.3.1 20190311 (Red Hat 8.3.1-3)
==== lock_test_ and_set( lock, 1) disassembly:
__sync_
```
objdump -S a.out
000000000040073c <tas>:
40073c: d10043ff sub sp, sp, #0x10
400740: f90007e0 str x0, [sp, #8]
400744: f94007e0 ldr x0, [sp, #8]
400748: 52800021 mov w1, #0x1 // #1
40074c: 885f7c02 ldxr w2, [x0]
400750: 88037c01 stxr w3, w1, [x0]
400754: 35ffffc3 cbnz w3, 40074c <tas+0x10>
400758: d5033bbf dmb ish
40075c: 2a0203e0 mov w0, w2
400760: 910043ff add sp, sp, #0x10
400764: d65f03c0 ret
```
==== val_compare_ and_swap( lock, 0, 1); disassembly:
__sync_
```
objdump -S a.out
000000000040073c <tas>:
40073c: d10043ff sub sp, sp, #0x10
400740: f90007e0 str x0, [sp, #8]
400744: f94007e0 ldr x0, [sp, #8]
400748: 52800021 mov w1, #0x1 // #1
40074c: 885f7c02 ldxr w2, [x0]
400750: 35000062 cbnz w2, 40075c <tas+0x20>
400754: 8803fc01 stlxr w3, w1, [x0]
400758: 35ffffa3 cbnz w3, 40074c <tas+0x10>
40075c: 7100005f cmp w2, #0x0
400760: d5033bbf dmb ish
400764: 2a0203e0 mov w0, w2
400768: 910043ff add sp, sp, #0x10
40076c: d65f03c0 ret
```