Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bazel build requires python2 #8

Closed
vkobel opened this issue May 2, 2018 · 3 comments
Closed

bazel build requires python2 #8

vkobel opened this issue May 2, 2018 · 3 comments

Comments

@vkobel
Copy link

vkobel commented May 2, 2018

When compiling with bazel build runsc, it assumes that the default python version is 2. When using version 3 one can expect error messages such as bytes-like object is required, not 'str' or CRITICAL:root:VDSO contains relocations: b'\nThere are no relocations in this file.\n'.

Changing default python version to python2 fixes this issue.

@prattmic
Copy link
Member

prattmic commented May 2, 2018

Oops. We'll make that script work in Python 2 or 3.

@q3k
Copy link
Contributor

q3k commented May 2, 2018

This is one build error that you get when building against python3:

INFO: Analysed target //runsc:runsc (0 packages loaded).
INFO: Found 1 target...
ERROR: /home/q3k/Software/gvisor/vdso/BUILD:8:1: Executing genrule //vdso:vdso failed (Exit 1)
Traceback (most recent call last):
  File "/home/q3k/.cache/bazel/_bazel_q3k/2a6b2df8cb638e5ef4933f67041a7700/bazel-sandbox/2604803244674486523/execroot/__main__/bazel-out/host/bin/vdso/check_vdso.runfiles/__main__/vdso/check_vdso.py", line 204, in <module>
    main()
  File "/home/q3k/.cache/bazel/_bazel_q3k/2a6b2df8cb638e5ef4933f67041a7700/bazel-sandbox/2604803244674486523/execroot/__main__/bazel-out/host/bin/vdso/check_vdso.runfiles/__main__/vdso/check_vdso.py", line 196, in main
    CheckSegments(args.vdso)
  File "/home/q3k/.cache/bazel/_bazel_q3k/2a6b2df8cb638e5ef4933f67041a7700/bazel-sandbox/2604803244674486523/execroot/__main__/bazel-out/host/bin/vdso/check_vdso.runfiles/__main__/vdso/check_vdso.py", line 69, in CheckSegments
    lines = output.split("\n")
TypeError: a bytes-like object is required, not 'str'
Target //runsc:runsc failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 1.855s, Critical Path: 0.93s
FAILED: Build did NOT complete successfully

Workaround is, of course, to make python in your $PATH point to a Python 2.7 interpreter.

@qrpike qrpike mentioned this issue May 2, 2018
@q3k
Copy link
Contributor

q3k commented May 2, 2018

https://gvisor-review.googlesource.com/#/c/gvisor/+/1420

Here's a fix to make check_vdso.py run on both py2 and py3.

shentubot pushed a commit that referenced this issue May 2, 2018
Updates #8

PiperOrigin-RevId: 195122103
shentubot pushed a commit that referenced this issue May 3, 2018
Also document that linux is required.

Updates #8

PiperOrigin-RevId: 195317016
chanwit pushed a commit to chanwit/gvisor that referenced this issue May 8, 2018
Updates google#8

PiperOrigin-RevId: 195122103
Change-Id: Iff190283961b8ab99ad4f3e47ffeb9ab491d0eb3
chanwit pushed a commit to chanwit/gvisor that referenced this issue May 8, 2018
This makes gVisor build with `python` set to Python 3.

Fixes google#8

PiperOrigin-RevId: 195216683
Change-Id: I1c8b86ad91a0844f7c3c85839d53f3fcba10813e
chanwit pushed a commit to chanwit/gvisor that referenced this issue May 8, 2018
Also document that linux is required.

Updates google#8

PiperOrigin-RevId: 195317016
Change-Id: I4c0305a26339f03772001b56e7a0ac4b39a4352a
shentubot pushed a commit that referenced this issue Jul 3, 2018
glibc's malloc also uses SYS_TIME. Permit it.

#0  0x0000000000de6267 in time ()
#1  0x0000000000db19d8 in get_nprocs ()
#2  0x0000000000d8a31a in arena_get2.part ()
#3  0x0000000000d8ab4a in malloc ()
#4  0x0000000000d3c6b5 in __sanitizer::InternalAlloc(unsigned long, __sanitizer::SizeClassAllocatorLocalCache<__sanitizer::SizeClassAllocator32<0ul, 140737488355328ull, 0ul, __sanitizer::SizeClassMap<3ul, 4ul, 8ul, 17ul, 64ul, 14ul>, 20ul, __sanitizer::TwoLevelByteMap<32768ull, 4096ull, __sanitizer::NoOpMapUnmapCallback>, __sanitizer::NoOpMapUnmapCallback> >*, unsigned long) ()
#5  0x0000000000d4cd70 in __tsan_go_start ()
#6  0x00000000004617a3 in racecall ()
#7  0x00000000010f4ea0 in runtime.findfunctab ()
#8  0x000000000043f193 in runtime.racegostart ()

Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
[mpratt@google.com: updated comments and commit message]
Signed-off-by: Michael Pratt <mpratt@google.com>

Change-Id: Ibe2d0dc3035bf5052d5fb802cfaa37c5e0e7a09a
PiperOrigin-RevId: 203042627
dvyukov added a commit to dvyukov/gvisor that referenced this issue Jul 4, 2018
glibc's malloc also uses SYS_TIME. Permit it.

#0  0x0000000000de6267 in time ()
google#1  0x0000000000db19d8 in get_nprocs ()
google#2  0x0000000000d8a31a in arena_get2.part ()
google#3  0x0000000000d8ab4a in malloc ()
google#4  0x0000000000d3c6b5 in __sanitizer::InternalAlloc(unsigned long, __sanitizer::SizeClassAllocatorLocalCache<__sanitizer::SizeClassAllocator32<0ul, 140737488355328ull, 0ul, __sanitizer::SizeClassMap<3ul, 4ul, 8ul, 17ul, 64ul, 14ul>, 20ul, __sanitizer::TwoLevelByteMap<32768ull, 4096ull, __sanitizer::NoOpMapUnmapCallback>, __sanitizer::NoOpMapUnmapCallback> >*, unsigned long) ()
google#5  0x0000000000d4cd70 in __tsan_go_start ()
google#6  0x00000000004617a3 in racecall ()
google#7  0x00000000010f4ea0 in runtime.findfunctab ()
google#8  0x000000000043f193 in runtime.racegostart ()

Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
[mpratt@google.com: updated comments and commit message]
Signed-off-by: Michael Pratt <mpratt@google.com>

Change-Id: Ibe2d0dc3035bf5052d5fb802cfaa37c5e0e7a09a
PiperOrigin-RevId: 203042627
tonistiigi pushed a commit to tonistiigi/gvisor that referenced this issue Jan 29, 2019
Updates google#8

PiperOrigin-RevId: 195122103
Change-Id: Iff190283961b8ab99ad4f3e47ffeb9ab491d0eb3
Upstream-commit: 6c061ad
tonistiigi pushed a commit to tonistiigi/gvisor that referenced this issue Jan 29, 2019
Also document that linux is required.

Updates google#8

PiperOrigin-RevId: 195317016
Change-Id: I4c0305a26339f03772001b56e7a0ac4b39a4352a
Upstream-commit: 6488f40
tonistiigi pushed a commit to tonistiigi/gvisor that referenced this issue Jan 30, 2019
Updates google#8

PiperOrigin-RevId: 195122103
Change-Id: Iff190283961b8ab99ad4f3e47ffeb9ab491d0eb3
Upstream-commit: 6c061ad
tonistiigi pushed a commit to tonistiigi/gvisor that referenced this issue Jan 30, 2019
This makes gVisor build with `python` set to Python 3.

Fixes google#8

PiperOrigin-RevId: 195216683
Change-Id: I1c8b86ad91a0844f7c3c85839d53f3fcba10813e
Upstream-commit: 9c665c4
tonistiigi pushed a commit to tonistiigi/gvisor that referenced this issue Jan 30, 2019
Also document that linux is required.

Updates google#8

PiperOrigin-RevId: 195317016
Change-Id: I4c0305a26339f03772001b56e7a0ac4b39a4352a
Upstream-commit: 6488f40
tonistiigi pushed a commit to tonistiigi/gvisor that referenced this issue Jan 30, 2019
glibc's malloc also uses SYS_TIME. Permit it.

#0  0x0000000000de6267 in time ()
#1  0x0000000000db19d8 in get_nprocs ()
#2  0x0000000000d8a31a in arena_get2.part ()
#3  0x0000000000d8ab4a in malloc ()
google#4  0x0000000000d3c6b5 in __sanitizer::InternalAlloc(unsigned long, __sanitizer::SizeClassAllocatorLocalCache<__sanitizer::SizeClassAllocator32<0ul, 140737488355328ull, 0ul, __sanitizer::SizeClassMap<3ul, 4ul, 8ul, 17ul, 64ul, 14ul>, 20ul, __sanitizer::TwoLevelByteMap<32768ull, 4096ull, __sanitizer::NoOpMapUnmapCallback>, __sanitizer::NoOpMapUnmapCallback> >*, unsigned long) ()
google#5  0x0000000000d4cd70 in __tsan_go_start ()
google#6  0x00000000004617a3 in racecall ()
google#7  0x00000000010f4ea0 in runtime.findfunctab ()
google#8  0x000000000043f193 in runtime.racegostart ()

Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
[mpratt@google.com: updated comments and commit message]
Signed-off-by: Michael Pratt <mpratt@google.com>

Change-Id: Ibe2d0dc3035bf5052d5fb802cfaa37c5e0e7a09a
PiperOrigin-RevId: 203042627
Upstream-commit: 6144751
copybara-service bot pushed a commit that referenced this issue Oct 11, 2023
sync.SeqCount relies on the following memory orderings:

- All stores following BeginWrite() in program order happen after the atomic
  read-modify-write (RMW) of SeqCount.epoch. In the Go 1.19 memory model, this
  is implied by atomic loads being acquire-seqcst.

- All stores preceding EndWrite() in program order happen before the RMW of
  SeqCount.epoch. In the Go 1.19 memory model, this is implied by atomic stores
  being release-seqcst.

- All loads following BeginRead() in program order happen after the load of
  SeqCount.epoch. In the Go 1.19 memory model, this is implied by atomic loads
  being acquire-seqcst.

- All loads preceding ReadOk() in program order happen before the load of
  SeqCount.epoch. The Go 1.19 memory model does not imply this property.

The x86 memory model *does* imply this final property, and in practice the
current Go compiler does not reorder memory accesses around the load of
SeqCount.epoch, so sync.SeqCount behaves correctly on x86.
However, on ARM64, the instruction that is actually emitted for the atomic load
from SeqCount.epoch is LDAR:

```
gvisor/pkg/sentry/kernel/kernel.SeqAtomicTryLoadTaskGoroutineSchedInfo():
gvisor/pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo_unsafe.go:34
  56371c:       f9400025        ldr     x5, [x1]
  563720:       f9400426        ldr     x6, [x1, #8]
  563724:       f9400822        ldr     x2, [x1, #16]
  563728:       f9400c23        ldr     x3, [x1, #24]
gvisor/pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo_unsafe.go:36
  56372c:       d503201f        nop
gvisor/pkg/sync/sync.(*SeqCount).ReadOk():
gvisor/pkg/sync/seqcount.go:107
  563730:       88dffc07        ldar    w7, [x0]
  563734:       6b0400ff        cmp     w7, w4
```

LDAR is explicitly documented as not implying the required memory ordering:
https://developer.arm.com/documentation/den0024/latest/Memory-Ordering/Barriers/One-way-barriers
Consequently, SeqCount.ReadOk() is incorrectly memory-ordered on weakly-ordered
architectures. To fix this, we need to introduce an explicit memory fence.

On ARM64, there is no way to implement the memory fence in question without
resorting to assembly, so the implementation is straightforward. On x86, we
introduce a compiler fence, since future compilers might otherwise reorder
memory accesses to after atomic loads; the only apparent way to do so is also
by using assembly, which unfortunately introduces overhead:

- After the call to sync.MemoryFenceReads(), callers zero XMM15 and reload the
  runtime.g pointer from %fs:-8, reflecting the switch from ABI0 to
  ABIInternal. This is a relatively small cost.

- Before the call to sync.MemoryFenceReads(), callers spill all registers to
  the stack, since ABI0 function calls clobber all registers. The cost of this
  depends on the state of the caller before the call, and is not reflected in
  BenchmarkSeqCountReadUncontended (which does not read any protected state
  between the calls to BeginRead() and ReadOk()).

Both of these problems are caused by Go assembly functions being restricted to
ABI0. Go provides a way to mark assembly functions as using ABIInternal
instead, but restricts its use to functions in package runtime
(golang/go#44065). runtime.publicationBarrier(),
which is semantically "sync.MemoryFenceWrites()", is implemented as a compiler
fence on x86; defining sync.MemoryFenceReads() as an alias for that function
(using go:linkname) would mitigate the former problem, but not the latter.
Thus, for simplicity, we define sync.MemoryFenceReads() in (ABI0) assembly, and
have no choice but to eat the overhead.

("Fence" and "barrier" are often used interchangeably in this context; Linux
uses "barrier" (e.g. `smp_rmb()`), while C++ uses "fence" (e.g.
`std::atomic_memory_fence()`). We choose "fence" to reduce ambiguity with
"write barriers", since Go is a GC'd language.)

PiperOrigin-RevId: 572675753
copybara-service bot pushed a commit that referenced this issue Oct 16, 2023
sync.SeqCount relies on the following memory orderings:

- All stores following BeginWrite() in program order happen after the atomic
  read-modify-write (RMW) of SeqCount.epoch. In the Go 1.19 memory model, this
  is implied by atomic loads being acquire-seqcst.

- All stores preceding EndWrite() in program order happen before the RMW of
  SeqCount.epoch. In the Go 1.19 memory model, this is implied by atomic stores
  being release-seqcst.

- All loads following BeginRead() in program order happen after the load of
  SeqCount.epoch. In the Go 1.19 memory model, this is implied by atomic loads
  being acquire-seqcst.

- All loads preceding ReadOk() in program order happen before the load of
  SeqCount.epoch. The Go 1.19 memory model does not imply this property.

The x86 memory model *does* imply this final property, and in practice the
current Go compiler does not reorder memory accesses around the load of
SeqCount.epoch, so sync.SeqCount behaves correctly on x86.
However, on ARM64, the instruction that is actually emitted for the atomic load
from SeqCount.epoch is LDAR:

```
gvisor/pkg/sentry/kernel/kernel.SeqAtomicTryLoadTaskGoroutineSchedInfo():
gvisor/pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo_unsafe.go:34
  56371c:       f9400025        ldr     x5, [x1]
  563720:       f9400426        ldr     x6, [x1, #8]
  563724:       f9400822        ldr     x2, [x1, #16]
  563728:       f9400c23        ldr     x3, [x1, #24]
gvisor/pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo_unsafe.go:36
  56372c:       d503201f        nop
gvisor/pkg/sync/sync.(*SeqCount).ReadOk():
gvisor/pkg/sync/seqcount.go:107
  563730:       88dffc07        ldar    w7, [x0]
  563734:       6b0400ff        cmp     w7, w4
```

LDAR is explicitly documented as not implying the required memory ordering:
https://developer.arm.com/documentation/den0024/latest/Memory-Ordering/Barriers/One-way-barriers
Consequently, SeqCount.ReadOk() is incorrectly memory-ordered on weakly-ordered
architectures. To fix this, we need to introduce an explicit memory fence.

On ARM64, there is no way to implement the memory fence in question without
resorting to assembly, so the implementation is straightforward. On x86, we
introduce a compiler fence, since future compilers might otherwise reorder
memory accesses to after atomic loads; the only apparent way to do so is also
by using assembly, which unfortunately introduces overhead:

- After the call to sync.MemoryFenceReads(), callers zero XMM15 and reload the
  runtime.g pointer from %fs:-8, reflecting the switch from ABI0 to
  ABIInternal. This is a relatively small cost.

- Before the call to sync.MemoryFenceReads(), callers spill all registers to
  the stack, since ABI0 function calls clobber all registers. The cost of this
  depends on the state of the caller before the call, and is not reflected in
  BenchmarkSeqCountReadUncontended (which does not read any protected state
  between the calls to BeginRead() and ReadOk()).

Both of these problems are caused by Go assembly functions being restricted to
ABI0. Go provides a way to mark assembly functions as using ABIInternal
instead, but restricts its use to functions in package runtime
(golang/go#44065). runtime.publicationBarrier(),
which is semantically "sync.MemoryFenceWrites()", is implemented as a compiler
fence on x86; defining sync.MemoryFenceReads() as an alias for that function
(using go:linkname) would mitigate the former problem, but not the latter.
Thus, for simplicity, we define sync.MemoryFenceReads() in (ABI0) assembly, and
have no choice but to eat the overhead.

("Fence" and "barrier" are often used interchangeably in this context; Linux
uses "barrier" (e.g. `smp_rmb()`), while C++ uses "fence" (e.g.
`std::atomic_memory_fence()`). We choose "fence" to reduce ambiguity with
"write barriers", since Go is a GC'd language.)

PiperOrigin-RevId: 573861378
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants