@ttsc/darwin-arm64 0.14.0-dev.20260529.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/go/VERSION +2 -2
- package/bin/go/bin/go +0 -0
- package/bin/go/bin/gofmt +0 -0
- package/bin/go/pkg/tool/darwin_arm64/asm +0 -0
- package/bin/go/pkg/tool/darwin_arm64/cgo +0 -0
- package/bin/go/pkg/tool/darwin_arm64/compile +0 -0
- package/bin/go/pkg/tool/darwin_arm64/cover +0 -0
- package/bin/go/pkg/tool/darwin_arm64/fix +0 -0
- package/bin/go/pkg/tool/darwin_arm64/link +0 -0
- package/bin/go/pkg/tool/darwin_arm64/preprofile +0 -0
- package/bin/go/pkg/tool/darwin_arm64/vet +0 -0
- package/bin/go/src/archive/tar/format.go +6 -0
- package/bin/go/src/archive/tar/reader.go +24 -4
- package/bin/go/src/builtin/builtin.go +13 -4
- package/bin/go/src/crypto/fips140/fips140.go +6 -0
- package/bin/go/src/crypto/internal/fips140/drbg/entropy_fips140.go +97 -0
- package/bin/go/src/crypto/internal/fips140/drbg/entropy_wasm.go +11 -0
- package/bin/go/src/crypto/internal/fips140/drbg/rand.go +1 -75
- package/bin/go/src/crypto/tls/conn.go +7 -3
- package/bin/go/src/crypto/tls/handshake_client_tls13.go +2 -2
- package/bin/go/src/crypto/tls/handshake_server_tls13.go +2 -2
- package/bin/go/src/crypto/tls/key_schedule.go +24 -3
- package/bin/go/src/crypto/x509/constraints.go +33 -33
- package/bin/go/src/crypto/x509/verify.go +28 -13
- package/bin/go/src/go/types/builtins.go +2 -2
- package/bin/go/src/go/types/signature.go +3 -0
- package/bin/go/src/go/types/under.go +3 -3
- package/bin/go/src/go.mod +1 -1
- package/bin/go/src/go.sum +2 -2
- package/bin/go/src/html/template/attr_string.go +3 -2
- package/bin/go/src/html/template/context.go +21 -1
- package/bin/go/src/html/template/element_string.go +3 -2
- package/bin/go/src/html/template/escape.go +16 -2
- package/bin/go/src/html/template/js.go +1 -0
- package/bin/go/src/html/template/state_string.go +5 -3
- package/bin/go/src/html/template/transition.go +43 -6
- package/bin/go/src/internal/buildcfg/zbootstrap.go +1 -1
- package/bin/go/src/internal/godebugs/table.go +1 -0
- package/bin/go/src/internal/poll/fd_windows.go +64 -38
- package/bin/go/src/internal/poll/fstatat_unix.go +22 -0
- package/bin/go/src/internal/poll/sendfile_windows.go +3 -1
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_386.go +1 -0
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_amd64.go +1 -0
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_arm.go +1 -0
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_arm64.go +1 -0
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_loong64.go +1 -0
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_mips64x.go +1 -0
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_mipsx.go +1 -0
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_ppc64x.go +1 -0
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_riscv64.go +1 -0
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_s390x.go +1 -0
- package/bin/go/src/internal/runtime/syscall/linux/syscall_linux.go +14 -0
- package/bin/go/src/internal/syscall/unix/at.go +0 -17
- package/bin/go/src/internal/syscall/unix/at_sysnum_linux.go +2 -1
- package/bin/go/src/internal/syscall/unix/fchmodat_linux.go +51 -0
- package/bin/go/src/internal/syscall/unix/fchmodat_other.go +29 -0
- package/bin/go/src/internal/syscall/windows/at_windows.go +20 -3
- package/bin/go/src/internal/syscall/windows/registry/key.go +10 -2
- package/bin/go/src/internal/syscall/windows/registry/value.go +5 -1
- package/bin/go/src/internal/syscall/windows/syscall_windows.go +4 -0
- package/bin/go/src/internal/syscall/windows/types_windows.go +82 -0
- package/bin/go/src/internal/syscall/windows/zsyscall_windows.go +27 -0
- package/bin/go/src/net/cgo_unix.go +4 -1
- package/bin/go/src/net/http/doc.go +0 -1
- package/bin/go/src/net/http/h2_bundle.go +3 -3
- package/bin/go/src/net/http/httputil/reverseproxy.go +14 -0
- package/bin/go/src/net/lookup_windows.go +16 -3
- package/bin/go/src/net/mail/message.go +20 -9
- package/bin/go/src/net/sendfile.go +2 -0
- package/bin/go/src/net/sendfile_stub.go +2 -0
- package/bin/go/src/net/sendfile_windows.go +3 -0
- package/bin/go/src/net/url/url.go +22 -16
- package/bin/go/src/os/dir_darwin.go +2 -2
- package/bin/go/src/os/dir_unix.go +2 -2
- package/bin/go/src/os/file.go +0 -3
- package/bin/go/src/os/file_unix.go +9 -5
- package/bin/go/src/os/removeall_at.go +6 -2
- package/bin/go/src/os/removeall_unix.go +0 -8
- package/bin/go/src/os/removeall_windows.go +0 -4
- package/bin/go/src/os/root_unix.go +1 -0
- package/bin/go/src/os/stat.go +3 -0
- package/bin/go/src/os/statat.go +24 -0
- package/bin/go/src/os/statat_other.go +12 -0
- package/bin/go/src/os/statat_unix.go +20 -0
- package/bin/go/src/reflect/value.go +3 -2
- package/bin/go/src/runtime/defs_linux_386.go +4 -3
- package/bin/go/src/runtime/defs_linux_arm.go +4 -3
- package/bin/go/src/runtime/defs_linux_mips64x.go +1 -1
- package/bin/go/src/runtime/defs_linux_mipsx.go +5 -4
- package/bin/go/src/runtime/malloc.go +1 -53
- package/bin/go/src/runtime/mem.go +104 -9
- package/bin/go/src/runtime/metrics/doc.go +5 -0
- package/bin/go/src/runtime/os_linux.go +62 -0
- package/bin/go/src/runtime/os_linux32.go +14 -24
- package/bin/go/src/runtime/os_linux64.go +2 -0
- package/bin/go/src/runtime/print.go +16 -4
- package/bin/go/src/runtime/race/README +9 -9
- package/bin/go/src/runtime/race/internal/amd64v1/race_darwin.patch +63 -0
- package/bin/go/src/runtime/race/internal/amd64v1/race_darwin.syso +0 -0
- package/bin/go/src/runtime/race/internal/amd64v1/race_freebsd.patch +63 -0
- package/bin/go/src/runtime/race/internal/amd64v1/race_freebsd.syso +0 -0
- package/bin/go/src/runtime/race/internal/amd64v1/race_linux.patch +63 -0
- package/bin/go/src/runtime/race/internal/amd64v1/race_linux.syso +0 -0
- package/bin/go/src/runtime/race/internal/amd64v1/race_windows.patch +63 -0
- package/bin/go/src/runtime/race/internal/amd64v1/race_windows.syso +0 -0
- package/bin/go/src/runtime/race/internal/amd64v3/race_linux.patch +63 -0
- package/bin/go/src/runtime/race/internal/amd64v3/race_linux.syso +0 -0
- package/bin/go/src/runtime/race/race_darwin_arm64.patch +63 -0
- package/bin/go/src/runtime/race/race_darwin_arm64.syso +0 -0
- package/bin/go/src/runtime/race/race_linux_arm64.patch +63 -0
- package/bin/go/src/runtime/race/race_linux_arm64.syso +0 -0
- package/bin/go/src/runtime/race/race_linux_loong64.patch +63 -0
- package/bin/go/src/runtime/race/race_linux_loong64.syso +0 -0
- package/bin/go/src/runtime/race/race_linux_s390x.patch +63 -0
- package/bin/go/src/runtime/race/race_linux_s390x.syso +0 -0
- package/bin/go/src/syscall/syscall_windows.go +5 -1
- package/bin/go/src/vendor/modules.txt +1 -1
- package/bin/ttsc +0 -0
- package/bin/ttscserver +0 -0
- package/package.json +1 -1
|
@@ -788,7 +788,7 @@ func (h *mheap) sysAlloc(n uintptr, hintList **arenaHint, arenaList *[]arenaIdx)
|
|
|
788
788
|
// particular, this is already how Windows behaves, so
|
|
789
789
|
// it would simplify things there.
|
|
790
790
|
if v != nil {
|
|
791
|
-
|
|
791
|
+
sysUnreserve(v, n)
|
|
792
792
|
}
|
|
793
793
|
*hintList = hint.next
|
|
794
794
|
h.arenaHintAlloc.free(unsafe.Pointer(hint))
|
|
@@ -921,58 +921,6 @@ mapped:
|
|
|
921
921
|
return
|
|
922
922
|
}
|
|
923
923
|
|
|
924
|
-
// sysReserveAligned is like sysReserve, but the returned pointer is
|
|
925
|
-
// aligned to align bytes. It may reserve either n or n+align bytes,
|
|
926
|
-
// so it returns the size that was reserved.
|
|
927
|
-
func sysReserveAligned(v unsafe.Pointer, size, align uintptr, vmaName string) (unsafe.Pointer, uintptr) {
|
|
928
|
-
if isSbrkPlatform {
|
|
929
|
-
if v != nil {
|
|
930
|
-
throw("unexpected heap arena hint on sbrk platform")
|
|
931
|
-
}
|
|
932
|
-
return sysReserveAlignedSbrk(size, align)
|
|
933
|
-
}
|
|
934
|
-
// Since the alignment is rather large in uses of this
|
|
935
|
-
// function, we're not likely to get it by chance, so we ask
|
|
936
|
-
// for a larger region and remove the parts we don't need.
|
|
937
|
-
retries := 0
|
|
938
|
-
retry:
|
|
939
|
-
p := uintptr(sysReserve(v, size+align, vmaName))
|
|
940
|
-
switch {
|
|
941
|
-
case p == 0:
|
|
942
|
-
return nil, 0
|
|
943
|
-
case p&(align-1) == 0:
|
|
944
|
-
return unsafe.Pointer(p), size + align
|
|
945
|
-
case GOOS == "windows":
|
|
946
|
-
// On Windows we can't release pieces of a
|
|
947
|
-
// reservation, so we release the whole thing and
|
|
948
|
-
// re-reserve the aligned sub-region. This may race,
|
|
949
|
-
// so we may have to try again.
|
|
950
|
-
sysFreeOS(unsafe.Pointer(p), size+align)
|
|
951
|
-
p = alignUp(p, align)
|
|
952
|
-
p2 := sysReserve(unsafe.Pointer(p), size, vmaName)
|
|
953
|
-
if p != uintptr(p2) {
|
|
954
|
-
// Must have raced. Try again.
|
|
955
|
-
sysFreeOS(p2, size)
|
|
956
|
-
if retries++; retries == 100 {
|
|
957
|
-
throw("failed to allocate aligned heap memory; too many retries")
|
|
958
|
-
}
|
|
959
|
-
goto retry
|
|
960
|
-
}
|
|
961
|
-
// Success.
|
|
962
|
-
return p2, size
|
|
963
|
-
default:
|
|
964
|
-
// Trim off the unaligned parts.
|
|
965
|
-
pAligned := alignUp(p, align)
|
|
966
|
-
sysFreeOS(unsafe.Pointer(p), pAligned-p)
|
|
967
|
-
end := pAligned + size
|
|
968
|
-
endLen := (p + size + align) - end
|
|
969
|
-
if endLen > 0 {
|
|
970
|
-
sysFreeOS(unsafe.Pointer(end), endLen)
|
|
971
|
-
}
|
|
972
|
-
return unsafe.Pointer(pAligned), size
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
|
|
976
924
|
// enableMetadataHugePages enables huge pages for various sources of heap metadata.
|
|
977
925
|
//
|
|
978
926
|
// A note on latency: for sufficiently small heaps (<10s of GiB) this function will take constant
|
|
@@ -120,14 +120,21 @@ func sysHugePageCollapse(v unsafe.Pointer, n uintptr) {
|
|
|
120
120
|
//
|
|
121
121
|
// sysStat must be non-nil.
|
|
122
122
|
//
|
|
123
|
+
// The size and start address must exactly match the size and returned address
|
|
124
|
+
// from the original sysAlloc/sysReserve/sysReserveAligned call. That is,
|
|
125
|
+
// sysFree cannot be used to free a subset of a memory region.
|
|
126
|
+
//
|
|
123
127
|
// Don't split the stack as this function may be invoked without a valid G,
|
|
124
128
|
// which prevents us from allocating more stack.
|
|
125
129
|
//
|
|
126
130
|
//go:nosplit
|
|
127
131
|
func sysFree(v unsafe.Pointer, n uintptr, sysStat *sysMemStat) {
|
|
128
|
-
// When using ASAN leak detection, the memory being freed is
|
|
129
|
-
//
|
|
130
|
-
//
|
|
132
|
+
// When using ASAN leak detection, the memory being freed is known by
|
|
133
|
+
// the sanitizer. We need to unregister it so it's not accessed by it.
|
|
134
|
+
//
|
|
135
|
+
// lsanunregisterrootregion matches regions by start address and size,
|
|
136
|
+
// so it is not possible to unregister a subset of the region. This is
|
|
137
|
+
// why sysFree requires the full region from the initial allocation.
|
|
131
138
|
if asanenabled {
|
|
132
139
|
lsanunregisterrootregion(v, n)
|
|
133
140
|
}
|
|
@@ -156,13 +163,12 @@ func sysFault(v unsafe.Pointer, n uintptr) {
|
|
|
156
163
|
// (either via permissions or not committing the memory). Such a reservation is
|
|
157
164
|
// thus never backed by physical memory.
|
|
158
165
|
//
|
|
159
|
-
// If the pointer passed to it is non-nil, the caller wants the
|
|
160
|
-
//
|
|
161
|
-
//
|
|
166
|
+
// If the pointer passed to it is non-nil, the caller wants the reservation
|
|
167
|
+
// there, but sysReserve can still choose another location if that one is
|
|
168
|
+
// unavailable.
|
|
162
169
|
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
// memory obtained by sysReserve.
|
|
170
|
+
// sysReserve returns OS-aligned memory. If a larger alignment is required, use
|
|
171
|
+
// sysReservedAligned.
|
|
166
172
|
func sysReserve(v unsafe.Pointer, n uintptr, vmaName string) unsafe.Pointer {
|
|
167
173
|
p := sysReserveOS(v, n, vmaName)
|
|
168
174
|
|
|
@@ -175,6 +181,95 @@ func sysReserve(v unsafe.Pointer, n uintptr, vmaName string) unsafe.Pointer {
|
|
|
175
181
|
return p
|
|
176
182
|
}
|
|
177
183
|
|
|
184
|
+
// sysReserveAligned transitions a memory region from None to Reserved.
|
|
185
|
+
//
|
|
186
|
+
// Semantics are equivlent to sysReserve, but the returned pointer is aligned
|
|
187
|
+
// to align bytes. It may reserve either n or n+align bytes, so it returns the
|
|
188
|
+
// size that was reserved.
|
|
189
|
+
func sysReserveAligned(v unsafe.Pointer, size, align uintptr, vmaName string) (unsafe.Pointer, uintptr) {
|
|
190
|
+
if isSbrkPlatform {
|
|
191
|
+
if v != nil {
|
|
192
|
+
throw("unexpected heap arena hint on sbrk platform")
|
|
193
|
+
}
|
|
194
|
+
return sysReserveAlignedSbrk(size, align)
|
|
195
|
+
}
|
|
196
|
+
// Since the alignment is rather large in uses of this
|
|
197
|
+
// function, we're not likely to get it by chance, so we ask
|
|
198
|
+
// for a larger region and remove the parts we don't need.
|
|
199
|
+
retries := 0
|
|
200
|
+
retry:
|
|
201
|
+
p := uintptr(sysReserve(v, size+align, vmaName))
|
|
202
|
+
switch {
|
|
203
|
+
case p == 0:
|
|
204
|
+
return nil, 0
|
|
205
|
+
case p&(align-1) == 0:
|
|
206
|
+
return unsafe.Pointer(p), size + align
|
|
207
|
+
case GOOS == "windows":
|
|
208
|
+
// On Windows we can't release pieces of a
|
|
209
|
+
// reservation, so we release the whole thing and
|
|
210
|
+
// re-reserve the aligned sub-region. This may race,
|
|
211
|
+
// so we may have to try again.
|
|
212
|
+
sysUnreserve(unsafe.Pointer(p), size+align)
|
|
213
|
+
p = alignUp(p, align)
|
|
214
|
+
p2 := sysReserve(unsafe.Pointer(p), size, vmaName)
|
|
215
|
+
if p != uintptr(p2) {
|
|
216
|
+
// Must have raced. Try again.
|
|
217
|
+
sysUnreserve(p2, size)
|
|
218
|
+
if retries++; retries == 100 {
|
|
219
|
+
throw("failed to allocate aligned heap memory; too many retries")
|
|
220
|
+
}
|
|
221
|
+
goto retry
|
|
222
|
+
}
|
|
223
|
+
// Success.
|
|
224
|
+
return p2, size
|
|
225
|
+
default:
|
|
226
|
+
// Trim off the unaligned parts.
|
|
227
|
+
pAligned := alignUp(p, align)
|
|
228
|
+
end := pAligned + size
|
|
229
|
+
endLen := (p + size + align) - end
|
|
230
|
+
|
|
231
|
+
// sysUnreserve does not allow unreserving a subset of the
|
|
232
|
+
// region because LSAN does not allow unregistering a subset.
|
|
233
|
+
// So we can't call sysUnreserve. Instead we simply unregister
|
|
234
|
+
// the entire region from LSAN and re-register with the smaller
|
|
235
|
+
// region before freeing the unecessary portions, which does
|
|
236
|
+
// allow subsets of the region.
|
|
237
|
+
if asanenabled {
|
|
238
|
+
lsanunregisterrootregion(unsafe.Pointer(p), size+align)
|
|
239
|
+
lsanregisterrootregion(unsafe.Pointer(pAligned), size)
|
|
240
|
+
}
|
|
241
|
+
sysFreeOS(unsafe.Pointer(p), pAligned-p)
|
|
242
|
+
if endLen > 0 {
|
|
243
|
+
sysFreeOS(unsafe.Pointer(end), endLen)
|
|
244
|
+
}
|
|
245
|
+
return unsafe.Pointer(pAligned), size
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// sysUnreserve transitions a memory region from Reserved to None.
|
|
250
|
+
//
|
|
251
|
+
// The size and start address must exactly match the size and returned address
|
|
252
|
+
// from sysReserve/sysReserveAligned. That is, sysUnreserve cannot be used to
|
|
253
|
+
// unreserve a subset of a memory region.
|
|
254
|
+
//
|
|
255
|
+
// Don't split the stack as this function may be invoked without a valid G,
|
|
256
|
+
// which prevents us from allocating more stack.
|
|
257
|
+
//
|
|
258
|
+
//go:nosplit
|
|
259
|
+
func sysUnreserve(v unsafe.Pointer, n uintptr) {
|
|
260
|
+
// When using ASAN leak detection, the memory being freed is known by
|
|
261
|
+
// the sanitizer. We need to unregister it so it's not accessed by it.
|
|
262
|
+
//
|
|
263
|
+
// lsanunregisterrootregion matches regions by start address and size,
|
|
264
|
+
// so it is not possible to unregister a subset of the region. This is
|
|
265
|
+
// why sysUnreserve requires the full region from sysReserve.
|
|
266
|
+
if asanenabled {
|
|
267
|
+
lsanunregisterrootregion(v, n)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
sysFreeOS(v, n)
|
|
271
|
+
}
|
|
272
|
+
|
|
178
273
|
// sysMap transitions a memory region from Reserved to Prepared. It ensures the
|
|
179
274
|
// memory region can be efficiently transitioned to Ready.
|
|
180
275
|
//
|
|
@@ -306,6 +306,11 @@ Below is the full list of supported metrics, ordered lexicographically.
|
|
|
306
306
|
The number of non-default behaviors executed by the go/types
|
|
307
307
|
package due to a non-default GODEBUG=gotypesalias=... setting.
|
|
308
308
|
|
|
309
|
+
/godebug/non-default-behavior/htmlmetacontenturlescape:events
|
|
310
|
+
The number of non-default behaviors executed by
|
|
311
|
+
the html/template package due to a non-default
|
|
312
|
+
GODEBUG=htmlmetacontenturlescape=... setting.
|
|
313
|
+
|
|
309
314
|
/godebug/non-default-behavior/http2client:events
|
|
310
315
|
The number of non-default behaviors executed by the net/http
|
|
311
316
|
package due to a non-default GODEBUG=http2client=... setting.
|
|
@@ -354,6 +354,7 @@ func osinit() {
|
|
|
354
354
|
numCPUStartup = getCPUCount()
|
|
355
355
|
physHugePageSize = getHugePageSize()
|
|
356
356
|
vgetrandomInit()
|
|
357
|
+
configure64bitsTimeOn32BitsArchitectures()
|
|
357
358
|
}
|
|
358
359
|
|
|
359
360
|
var urandom_dev = []byte("/dev/urandom\x00")
|
|
@@ -935,3 +936,64 @@ func mprotect(addr unsafe.Pointer, n uintptr, prot int32) (ret int32, errno int3
|
|
|
935
936
|
r, _, err := linux.Syscall6(linux.SYS_MPROTECT, uintptr(addr), n, uintptr(prot), 0, 0, 0)
|
|
936
937
|
return int32(r), int32(err)
|
|
937
938
|
}
|
|
939
|
+
|
|
940
|
+
type kernelVersion struct {
|
|
941
|
+
major int
|
|
942
|
+
minor int
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
// getKernelVersion returns major and minor kernel version numbers
|
|
946
|
+
// parsed from the uname release field.
|
|
947
|
+
func getKernelVersion() kernelVersion {
|
|
948
|
+
var buf linux.Utsname
|
|
949
|
+
if e := linux.Uname(&buf); e != 0 {
|
|
950
|
+
throw("uname failed")
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
rel := gostringnocopy(&buf.Release[0])
|
|
954
|
+
major, minor, _, ok := parseRelease(rel)
|
|
955
|
+
if !ok {
|
|
956
|
+
throw("failed to parse kernel version from uname")
|
|
957
|
+
}
|
|
958
|
+
return kernelVersion{major: major, minor: minor}
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// parseRelease parses a dot-separated version number. It follows the
|
|
962
|
+
// semver syntax, but allows the minor and patch versions to be
|
|
963
|
+
// elided.
|
|
964
|
+
func parseRelease(rel string) (major, minor, patch int, ok bool) {
|
|
965
|
+
// Strip anything after a dash or plus.
|
|
966
|
+
for i := 0; i < len(rel); i++ {
|
|
967
|
+
if rel[i] == '-' || rel[i] == '+' {
|
|
968
|
+
rel = rel[:i]
|
|
969
|
+
break
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
next := func() (int, bool) {
|
|
974
|
+
for i := 0; i < len(rel); i++ {
|
|
975
|
+
if rel[i] == '.' {
|
|
976
|
+
ver, err := strconv.Atoi(rel[:i])
|
|
977
|
+
rel = rel[i+1:]
|
|
978
|
+
return ver, err == nil
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
ver, err := strconv.Atoi(rel)
|
|
982
|
+
rel = ""
|
|
983
|
+
return ver, err == nil
|
|
984
|
+
}
|
|
985
|
+
if major, ok = next(); !ok || rel == "" {
|
|
986
|
+
return
|
|
987
|
+
}
|
|
988
|
+
if minor, ok = next(); !ok || rel == "" {
|
|
989
|
+
return
|
|
990
|
+
}
|
|
991
|
+
patch, ok = next()
|
|
992
|
+
return
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
// GE checks if the running kernel version
|
|
996
|
+
// is greater than or equal to the provided version.
|
|
997
|
+
func (kv kernelVersion) GE(x, y int) bool {
|
|
998
|
+
return kv.major > x || (kv.major == x && kv.minor >= y)
|
|
999
|
+
}
|
|
@@ -7,33 +7,31 @@
|
|
|
7
7
|
package runtime
|
|
8
8
|
|
|
9
9
|
import (
|
|
10
|
-
"internal/runtime/atomic"
|
|
11
10
|
"unsafe"
|
|
12
11
|
)
|
|
13
12
|
|
|
13
|
+
func configure64bitsTimeOn32BitsArchitectures() {
|
|
14
|
+
use64bitsTimeOn32bits = getKernelVersion().GE(5, 1)
|
|
15
|
+
}
|
|
16
|
+
|
|
14
17
|
//go:noescape
|
|
15
18
|
func futex_time32(addr unsafe.Pointer, op int32, val uint32, ts *timespec32, addr2 unsafe.Pointer, val3 uint32) int32
|
|
16
19
|
|
|
17
20
|
//go:noescape
|
|
18
21
|
func futex_time64(addr unsafe.Pointer, op int32, val uint32, ts *timespec, addr2 unsafe.Pointer, val3 uint32) int32
|
|
19
22
|
|
|
20
|
-
var
|
|
23
|
+
var use64bitsTimeOn32bits bool
|
|
21
24
|
|
|
22
25
|
//go:nosplit
|
|
23
26
|
func futex(addr unsafe.Pointer, op int32, val uint32, ts *timespec, addr2 unsafe.Pointer, val3 uint32) int32 {
|
|
24
|
-
if
|
|
25
|
-
|
|
26
|
-
// futex_time64 is only supported on Linux 5.0+
|
|
27
|
-
if ret != -_ENOSYS {
|
|
28
|
-
return ret
|
|
29
|
-
}
|
|
30
|
-
isFutexTime32bitOnly.Store(true)
|
|
27
|
+
if use64bitsTimeOn32bits {
|
|
28
|
+
return futex_time64(addr, op, val, ts, addr2, val3)
|
|
31
29
|
}
|
|
32
30
|
// Downgrade ts.
|
|
33
31
|
var ts32 timespec32
|
|
34
32
|
var pts32 *timespec32
|
|
35
33
|
if ts != nil {
|
|
36
|
-
ts32.setNsec(ts.tv_sec*1e9 + ts.tv_nsec)
|
|
34
|
+
ts32.setNsec(ts.tv_sec*1e9 + int64(ts.tv_nsec))
|
|
37
35
|
pts32 = &ts32
|
|
38
36
|
}
|
|
39
37
|
return futex_time32(addr, op, val, pts32, addr2, val3)
|
|
@@ -45,34 +43,26 @@ func timer_settime32(timerid int32, flags int32, new, old *itimerspec32) int32
|
|
|
45
43
|
//go:noescape
|
|
46
44
|
func timer_settime64(timerid int32, flags int32, new, old *itimerspec) int32
|
|
47
45
|
|
|
48
|
-
var isSetTime32bitOnly atomic.Bool
|
|
49
|
-
|
|
50
46
|
//go:nosplit
|
|
51
47
|
func timer_settime(timerid int32, flags int32, new, old *itimerspec) int32 {
|
|
52
|
-
if
|
|
53
|
-
|
|
54
|
-
// timer_settime64 is only supported on Linux 5.0+
|
|
55
|
-
if ret != -_ENOSYS {
|
|
56
|
-
return ret
|
|
57
|
-
}
|
|
58
|
-
isSetTime32bitOnly.Store(true)
|
|
48
|
+
if use64bitsTimeOn32bits {
|
|
49
|
+
return timer_settime64(timerid, flags, new, old)
|
|
59
50
|
}
|
|
60
51
|
|
|
61
52
|
var newts, oldts itimerspec32
|
|
62
53
|
var new32, old32 *itimerspec32
|
|
63
54
|
|
|
64
55
|
if new != nil {
|
|
65
|
-
newts.it_interval.setNsec(new.it_interval.tv_sec*1e9 + new.it_interval.tv_nsec)
|
|
66
|
-
newts.it_value.setNsec(new.it_value.tv_sec*1e9 + new.it_value.tv_nsec)
|
|
56
|
+
newts.it_interval.setNsec(new.it_interval.tv_sec*1e9 + int64(new.it_interval.tv_nsec))
|
|
57
|
+
newts.it_value.setNsec(new.it_value.tv_sec*1e9 + int64(new.it_value.tv_nsec))
|
|
67
58
|
new32 = &newts
|
|
68
59
|
}
|
|
69
60
|
|
|
70
61
|
if old != nil {
|
|
71
|
-
oldts.it_interval.setNsec(old.it_interval.tv_sec*1e9 + old.it_interval.tv_nsec)
|
|
72
|
-
oldts.it_value.setNsec(old.it_value.tv_sec*1e9 + old.it_value.tv_nsec)
|
|
62
|
+
oldts.it_interval.setNsec(old.it_interval.tv_sec*1e9 + int64(old.it_interval.tv_nsec))
|
|
63
|
+
oldts.it_value.setNsec(old.it_value.tv_sec*1e9 + int64(old.it_value.tv_nsec))
|
|
73
64
|
old32 = &oldts
|
|
74
65
|
}
|
|
75
66
|
|
|
76
|
-
// Fall back to 32-bit timer
|
|
77
67
|
return timer_settime32(timerid, flags, new32, old32)
|
|
78
68
|
}
|
|
@@ -122,23 +122,35 @@ func printbool(v bool) {
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
// float64 requires 1+17+1+1+1+3 = 24 bytes max (sign+digits+decimal point+e+sign+exponent digits).
|
|
126
|
+
const float64Bytes = 24
|
|
127
|
+
|
|
125
128
|
func printfloat64(v float64) {
|
|
126
|
-
var buf [
|
|
129
|
+
var buf [float64Bytes]byte
|
|
127
130
|
gwrite(strconv.AppendFloat(buf[:0], v, 'g', -1, 64))
|
|
128
131
|
}
|
|
129
132
|
|
|
133
|
+
// float32 requires 1+9+1+1+1+2 = 15 bytes max (sign+digits+decimal point+e+sign+exponent digits).
|
|
134
|
+
const float32Bytes = 15
|
|
135
|
+
|
|
130
136
|
func printfloat32(v float32) {
|
|
131
|
-
var buf [
|
|
137
|
+
var buf [float32Bytes]byte
|
|
132
138
|
gwrite(strconv.AppendFloat(buf[:0], float64(v), 'g', -1, 32))
|
|
133
139
|
}
|
|
134
140
|
|
|
141
|
+
// complex128 requires 24+24+1+1+1 = 51 bytes max (paren+float64+float64+i+paren).
|
|
142
|
+
const complex128Bytes = 2*float64Bytes + 3
|
|
143
|
+
|
|
135
144
|
func printcomplex128(c complex128) {
|
|
136
|
-
var buf [
|
|
145
|
+
var buf [complex128Bytes]byte
|
|
137
146
|
gwrite(strconv.AppendComplex(buf[:0], c, 'g', -1, 128))
|
|
138
147
|
}
|
|
139
148
|
|
|
149
|
+
// complex64 requires 15+15+1+1+1 = 33 bytes max (paren+float32+float32+i+paren).
|
|
150
|
+
const complex64Bytes = 2*float32Bytes + 3
|
|
151
|
+
|
|
140
152
|
func printcomplex64(c complex64) {
|
|
141
|
-
var buf [
|
|
153
|
+
var buf [complex64Bytes]byte
|
|
142
154
|
gwrite(strconv.AppendComplex(buf[:0], complex128(c), 'g', -1, 64))
|
|
143
155
|
}
|
|
144
156
|
|
|
@@ -4,16 +4,16 @@ the LLVM project (https://github.com/llvm/llvm-project/tree/main/compiler-rt).
|
|
|
4
4
|
|
|
5
5
|
To update the .syso files use golang.org/x/build/cmd/racebuild.
|
|
6
6
|
|
|
7
|
-
internal/amd64v1/race_darwin.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 and Go
|
|
8
|
-
internal/amd64v1/race_freebsd.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 and Go
|
|
9
|
-
internal/amd64v1/race_linux.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 and Go
|
|
7
|
+
internal/amd64v1/race_darwin.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 with patch internal/amd64v1/race_darwin.patch and Go a61fd428974822a8c57a2b2840fc237e6711b24d.
|
|
8
|
+
internal/amd64v1/race_freebsd.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 with patch internal/amd64v1/race_freebsd.patch and Go a61fd428974822a8c57a2b2840fc237e6711b24d.
|
|
9
|
+
internal/amd64v1/race_linux.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 with patch internal/amd64v1/race_linux.patch and Go a61fd428974822a8c57a2b2840fc237e6711b24d.
|
|
10
10
|
internal/amd64v1/race_netbsd.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 and Go e7d582b55dda36e76ce4d0ce770139ca0915b7c5.
|
|
11
11
|
internal/amd64v1/race_openbsd.syso built with LLVM fcf6ae2f070eba73074b6ec8d8281e54d29dbeeb and Go 8f2db14cd35bbd674cb2988a508306de6655e425.
|
|
12
|
-
internal/amd64v1/race_windows.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 and Go
|
|
13
|
-
internal/amd64v3/race_linux.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 and Go
|
|
14
|
-
race_darwin_arm64.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 and Go
|
|
15
|
-
race_linux_arm64.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 and Go
|
|
16
|
-
race_linux_loong64.syso built with LLVM 83fe85115da9dc25fa270d2ea8140113c8d49670 and Go
|
|
12
|
+
internal/amd64v1/race_windows.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 with patch internal/amd64v1/race_windows.patch and Go a61fd428974822a8c57a2b2840fc237e6711b24d.
|
|
13
|
+
internal/amd64v3/race_linux.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 with patch internal/amd64v3/race_linux.patch and Go a61fd428974822a8c57a2b2840fc237e6711b24d.
|
|
14
|
+
race_darwin_arm64.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 with patch race_darwin_arm64.patch and Go a61fd428974822a8c57a2b2840fc237e6711b24d.
|
|
15
|
+
race_linux_arm64.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 with patch race_linux_arm64.patch and Go a61fd428974822a8c57a2b2840fc237e6711b24d.
|
|
16
|
+
race_linux_loong64.syso built with LLVM 83fe85115da9dc25fa270d2ea8140113c8d49670 with patch race_linux_loong64.patch and Go a61fd428974822a8c57a2b2840fc237e6711b24d.
|
|
17
17
|
race_linux_ppc64le.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 and Go e7d582b55dda36e76ce4d0ce770139ca0915b7c5.
|
|
18
18
|
race_linux_riscv64.syso built with LLVM c3c24be13f7928460ca1e2fe613a1146c868854e and Go a21249436b6e1fd47356361d53dc053bbc074f90.
|
|
19
|
-
race_linux_s390x.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 and Go
|
|
19
|
+
race_linux_s390x.syso built with LLVM 51bfeff0e4b0757ff773da6882f4d538996c9b04 with patch race_linux_s390x.patch and Go a61fd428974822a8c57a2b2840fc237e6711b24d.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
From cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca Mon Sep 17 00:00:00 2001
|
|
2
|
+
From: Michael Pratt <michael@prattmic.com>
|
|
3
|
+
Date: Fri, 12 Dec 2025 16:31:44 +1100
|
|
4
|
+
Subject: [PATCH] [TSan] Zero-initialize Trace.local_head
|
|
5
|
+
|
|
6
|
+
Trace.local_head is currently uninitialized when Trace is created. It is
|
|
7
|
+
first initialized when the first event is added to the trace, via the
|
|
8
|
+
first call to TraceSwitchPartImpl.
|
|
9
|
+
|
|
10
|
+
However, ThreadContext::OnFinished uses local_head, assuming that it is
|
|
11
|
+
initialized. If it has not been initialized, we have undefined behavior,
|
|
12
|
+
likely crashing if the contents are garbage. The allocator (Alloc)
|
|
13
|
+
reuses previously allocations, so the contents of the uninitialized
|
|
14
|
+
memory are arbitrary.
|
|
15
|
+
|
|
16
|
+
In a C/C++ TSAN binary it is likely very difficult for a thread to start
|
|
17
|
+
and exit without a single event inbetween. For Go programs, code running
|
|
18
|
+
in the Go runtime itself is not TSan-instrumented, so goroutines that
|
|
19
|
+
exclusively run runtime code (such as GC workers) can quite reasonably
|
|
20
|
+
have no TSan events.
|
|
21
|
+
|
|
22
|
+
The addition of such a goroutine to the Go test.c is sufficient to
|
|
23
|
+
trigger this case, though for reliable failure (segfault) I've found it
|
|
24
|
+
necessary to poison the ThreadContext allocation like so:
|
|
25
|
+
|
|
26
|
+
(Example patch redacted because patch tries to apply this as a real
|
|
27
|
+
patch. See full commit at
|
|
28
|
+
https://github.com/llvm/llvm-project/commit/cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca).
|
|
29
|
+
|
|
30
|
+
The fix is trivial: local_head should be zero-initialized.
|
|
31
|
+
---
|
|
32
|
+
compiler-rt/lib/tsan/go/test.c | 4 ++++
|
|
33
|
+
compiler-rt/lib/tsan/rtl/tsan_trace.h | 2 +-
|
|
34
|
+
2 files changed, 5 insertions(+), 1 deletion(-)
|
|
35
|
+
|
|
36
|
+
diff --git a/compiler-rt/lib/tsan/go/test.c b/compiler-rt/lib/tsan/go/test.c
|
|
37
|
+
index d328ab1b331d7..fcd396227a4ab 100644
|
|
38
|
+
--- a/compiler-rt/lib/tsan/go/test.c
|
|
39
|
+
+++ b/compiler-rt/lib/tsan/go/test.c
|
|
40
|
+
@@ -91,6 +91,10 @@ int main(void) {
|
|
41
|
+
__tsan_go_start(thr0, &thr1, (char*)&barfoo + 1);
|
|
42
|
+
void *thr2 = 0;
|
|
43
|
+
__tsan_go_start(thr0, &thr2, (char*)&barfoo + 1);
|
|
44
|
+
+ // Goroutine that exits without a single event.
|
|
45
|
+
+ void *thr3 = 0;
|
|
46
|
+
+ __tsan_go_start(thr0, &thr3, (char*)&barfoo + 1);
|
|
47
|
+
+ __tsan_go_end(thr3);
|
|
48
|
+
__tsan_func_exit(thr0);
|
|
49
|
+
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
50
|
+
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
51
|
+
diff --git a/compiler-rt/lib/tsan/rtl/tsan_trace.h b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
52
|
+
index 01bb7b34f43a2..1e791ff765fec 100644
|
|
53
|
+
--- a/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
54
|
+
+++ b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
55
|
+
@@ -190,7 +190,7 @@ struct Trace {
|
|
56
|
+
Mutex mtx;
|
|
57
|
+
IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
|
|
58
|
+
// First node non-queued into ctx->trace_part_recycle.
|
|
59
|
+
- TracePart* local_head;
|
|
60
|
+
+ TracePart* local_head = nullptr;
|
|
61
|
+
// Final position in the last part for finished threads.
|
|
62
|
+
Event* final_pos = nullptr;
|
|
63
|
+
// Number of trace parts allocated on behalf of this trace specifically.
|
|
Binary file
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
From cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca Mon Sep 17 00:00:00 2001
|
|
2
|
+
From: Michael Pratt <michael@prattmic.com>
|
|
3
|
+
Date: Fri, 12 Dec 2025 16:31:44 +1100
|
|
4
|
+
Subject: [PATCH] [TSan] Zero-initialize Trace.local_head
|
|
5
|
+
|
|
6
|
+
Trace.local_head is currently uninitialized when Trace is created. It is
|
|
7
|
+
first initialized when the first event is added to the trace, via the
|
|
8
|
+
first call to TraceSwitchPartImpl.
|
|
9
|
+
|
|
10
|
+
However, ThreadContext::OnFinished uses local_head, assuming that it is
|
|
11
|
+
initialized. If it has not been initialized, we have undefined behavior,
|
|
12
|
+
likely crashing if the contents are garbage. The allocator (Alloc)
|
|
13
|
+
reuses previously allocations, so the contents of the uninitialized
|
|
14
|
+
memory are arbitrary.
|
|
15
|
+
|
|
16
|
+
In a C/C++ TSAN binary it is likely very difficult for a thread to start
|
|
17
|
+
and exit without a single event inbetween. For Go programs, code running
|
|
18
|
+
in the Go runtime itself is not TSan-instrumented, so goroutines that
|
|
19
|
+
exclusively run runtime code (such as GC workers) can quite reasonably
|
|
20
|
+
have no TSan events.
|
|
21
|
+
|
|
22
|
+
The addition of such a goroutine to the Go test.c is sufficient to
|
|
23
|
+
trigger this case, though for reliable failure (segfault) I've found it
|
|
24
|
+
necessary to poison the ThreadContext allocation like so:
|
|
25
|
+
|
|
26
|
+
(Example patch redacted because patch tries to apply this as a real
|
|
27
|
+
patch. See full commit at
|
|
28
|
+
https://github.com/llvm/llvm-project/commit/cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca).
|
|
29
|
+
|
|
30
|
+
The fix is trivial: local_head should be zero-initialized.
|
|
31
|
+
---
|
|
32
|
+
compiler-rt/lib/tsan/go/test.c | 4 ++++
|
|
33
|
+
compiler-rt/lib/tsan/rtl/tsan_trace.h | 2 +-
|
|
34
|
+
2 files changed, 5 insertions(+), 1 deletion(-)
|
|
35
|
+
|
|
36
|
+
diff --git a/compiler-rt/lib/tsan/go/test.c b/compiler-rt/lib/tsan/go/test.c
|
|
37
|
+
index d328ab1b331d7..fcd396227a4ab 100644
|
|
38
|
+
--- a/compiler-rt/lib/tsan/go/test.c
|
|
39
|
+
+++ b/compiler-rt/lib/tsan/go/test.c
|
|
40
|
+
@@ -91,6 +91,10 @@ int main(void) {
|
|
41
|
+
__tsan_go_start(thr0, &thr1, (char*)&barfoo + 1);
|
|
42
|
+
void *thr2 = 0;
|
|
43
|
+
__tsan_go_start(thr0, &thr2, (char*)&barfoo + 1);
|
|
44
|
+
+ // Goroutine that exits without a single event.
|
|
45
|
+
+ void *thr3 = 0;
|
|
46
|
+
+ __tsan_go_start(thr0, &thr3, (char*)&barfoo + 1);
|
|
47
|
+
+ __tsan_go_end(thr3);
|
|
48
|
+
__tsan_func_exit(thr0);
|
|
49
|
+
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
50
|
+
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
51
|
+
diff --git a/compiler-rt/lib/tsan/rtl/tsan_trace.h b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
52
|
+
index 01bb7b34f43a2..1e791ff765fec 100644
|
|
53
|
+
--- a/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
54
|
+
+++ b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
55
|
+
@@ -190,7 +190,7 @@ struct Trace {
|
|
56
|
+
Mutex mtx;
|
|
57
|
+
IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
|
|
58
|
+
// First node non-queued into ctx->trace_part_recycle.
|
|
59
|
+
- TracePart* local_head;
|
|
60
|
+
+ TracePart* local_head = nullptr;
|
|
61
|
+
// Final position in the last part for finished threads.
|
|
62
|
+
Event* final_pos = nullptr;
|
|
63
|
+
// Number of trace parts allocated on behalf of this trace specifically.
|
|
Binary file
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
From cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca Mon Sep 17 00:00:00 2001
|
|
2
|
+
From: Michael Pratt <michael@prattmic.com>
|
|
3
|
+
Date: Fri, 12 Dec 2025 16:31:44 +1100
|
|
4
|
+
Subject: [PATCH] [TSan] Zero-initialize Trace.local_head
|
|
5
|
+
|
|
6
|
+
Trace.local_head is currently uninitialized when Trace is created. It is
|
|
7
|
+
first initialized when the first event is added to the trace, via the
|
|
8
|
+
first call to TraceSwitchPartImpl.
|
|
9
|
+
|
|
10
|
+
However, ThreadContext::OnFinished uses local_head, assuming that it is
|
|
11
|
+
initialized. If it has not been initialized, we have undefined behavior,
|
|
12
|
+
likely crashing if the contents are garbage. The allocator (Alloc)
|
|
13
|
+
reuses previously allocations, so the contents of the uninitialized
|
|
14
|
+
memory are arbitrary.
|
|
15
|
+
|
|
16
|
+
In a C/C++ TSAN binary it is likely very difficult for a thread to start
|
|
17
|
+
and exit without a single event inbetween. For Go programs, code running
|
|
18
|
+
in the Go runtime itself is not TSan-instrumented, so goroutines that
|
|
19
|
+
exclusively run runtime code (such as GC workers) can quite reasonably
|
|
20
|
+
have no TSan events.
|
|
21
|
+
|
|
22
|
+
The addition of such a goroutine to the Go test.c is sufficient to
|
|
23
|
+
trigger this case, though for reliable failure (segfault) I've found it
|
|
24
|
+
necessary to poison the ThreadContext allocation like so:
|
|
25
|
+
|
|
26
|
+
(Example patch redacted because patch tries to apply this as a real
|
|
27
|
+
patch. See full commit at
|
|
28
|
+
https://github.com/llvm/llvm-project/commit/cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca).
|
|
29
|
+
|
|
30
|
+
The fix is trivial: local_head should be zero-initialized.
|
|
31
|
+
---
|
|
32
|
+
compiler-rt/lib/tsan/go/test.c | 4 ++++
|
|
33
|
+
compiler-rt/lib/tsan/rtl/tsan_trace.h | 2 +-
|
|
34
|
+
2 files changed, 5 insertions(+), 1 deletion(-)
|
|
35
|
+
|
|
36
|
+
diff --git a/compiler-rt/lib/tsan/go/test.c b/compiler-rt/lib/tsan/go/test.c
|
|
37
|
+
index d328ab1b331d7..fcd396227a4ab 100644
|
|
38
|
+
--- a/compiler-rt/lib/tsan/go/test.c
|
|
39
|
+
+++ b/compiler-rt/lib/tsan/go/test.c
|
|
40
|
+
@@ -91,6 +91,10 @@ int main(void) {
|
|
41
|
+
__tsan_go_start(thr0, &thr1, (char*)&barfoo + 1);
|
|
42
|
+
void *thr2 = 0;
|
|
43
|
+
__tsan_go_start(thr0, &thr2, (char*)&barfoo + 1);
|
|
44
|
+
+ // Goroutine that exits without a single event.
|
|
45
|
+
+ void *thr3 = 0;
|
|
46
|
+
+ __tsan_go_start(thr0, &thr3, (char*)&barfoo + 1);
|
|
47
|
+
+ __tsan_go_end(thr3);
|
|
48
|
+
__tsan_func_exit(thr0);
|
|
49
|
+
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
50
|
+
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
51
|
+
diff --git a/compiler-rt/lib/tsan/rtl/tsan_trace.h b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
52
|
+
index 01bb7b34f43a2..1e791ff765fec 100644
|
|
53
|
+
--- a/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
54
|
+
+++ b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
55
|
+
@@ -190,7 +190,7 @@ struct Trace {
|
|
56
|
+
Mutex mtx;
|
|
57
|
+
IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
|
|
58
|
+
// First node non-queued into ctx->trace_part_recycle.
|
|
59
|
+
- TracePart* local_head;
|
|
60
|
+
+ TracePart* local_head = nullptr;
|
|
61
|
+
// Final position in the last part for finished threads.
|
|
62
|
+
Event* final_pos = nullptr;
|
|
63
|
+
// Number of trace parts allocated on behalf of this trace specifically.
|
|
Binary file
|