From 1ed418e77ee2a9c7baf159e73b4a657b5c21a2d9 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Wed, 15 Oct 2025 12:59:09 +0800 Subject: [PATCH] tls: document package and guard helpers --- runtime/internal/clite/bdwgc/bdwgc.go | 8 +++++ runtime/internal/clite/tls/tls_common.go | 40 ++++++++++++++++++++++++ runtime/internal/clite/tls/tls_gc.go | 23 +++++++++++++- runtime/internal/clite/tls/tls_nogc.go | 16 ++++++++++ runtime/internal/clite/tls/tls_test.go | 16 ++++++++++ ssa/di_test.go | 16 ++++++++++ 6 files changed, 118 insertions(+), 1 deletion(-) diff --git a/runtime/internal/clite/bdwgc/bdwgc.go b/runtime/internal/clite/bdwgc/bdwgc.go index 690059b4..8f0af818 100644 --- a/runtime/internal/clite/bdwgc/bdwgc.go +++ b/runtime/internal/clite/bdwgc/bdwgc.go @@ -40,9 +40,17 @@ func Realloc(ptr c.Pointer, size uintptr) c.Pointer //go:linkname Free C.GC_free func Free(ptr c.Pointer) +// AddRoots registers a memory region [start, end) as a GC root. The caller +// must ensure that the range remains valid until RemoveRoots is invoked with +// the same boundaries. This is typically used for TLS slots that store Go +// pointers. +// //go:linkname AddRoots C.GC_add_roots func AddRoots(start, end c.Pointer) +// RemoveRoots unregisters a region previously registered with AddRoots. The +// start and end pointers must exactly match the earlier AddRoots call. +// //go:linkname RemoveRoots C.GC_remove_roots func RemoveRoots(start, end c.Pointer) diff --git a/runtime/internal/clite/tls/tls_common.go b/runtime/internal/clite/tls/tls_common.go index b1feef82..4741365e 100644 --- a/runtime/internal/clite/tls/tls_common.go +++ b/runtime/internal/clite/tls/tls_common.go @@ -1,5 +1,45 @@ //go:build llgo +/* + * Copyright (c) 2025 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Package tls provides generic thread-local storage backed by POSIX pthread +// TLS. When built with the GC-enabled configuration (llgo && !nogc), TLS slots +// are automatically registered with the BDWGC garbage collector so pointers +// stored in thread-local state remain visible to the collector. Builds without +// GC integration (llgo && nogc) simply fall back to pthread TLS without root +// registration. +// +// Basic usage: +// +// h := tls.Alloc[int](nil) +// h.Set(42) +// val := h.Get() // returns 42 +// +// With destructor: +// +// h := tls.Alloc[*Resource](func(r **Resource) { +// if r != nil && *r != nil { +// (*r).Close() +// } +// }) +// +// Build tags: +// - llgo && !nogc: Enables GC-aware slot registration via BDWGC +// - llgo && nogc: Disables GC integration; TLS acts as plain pthread TLS package tls import ( diff --git a/runtime/internal/clite/tls/tls_gc.go b/runtime/internal/clite/tls/tls_gc.go index 430aa83d..d6341827 100644 --- a/runtime/internal/clite/tls/tls_gc.go +++ b/runtime/internal/clite/tls/tls_gc.go @@ -1,5 +1,21 @@ //go:build llgo && !nogc +/* + * Copyright (c) 2025 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package tls import ( @@ -48,6 +64,11 @@ func deregisterSlot[T any](s *slot[T]) { func (s *slot[T]) rootRange() (start, end c.Pointer) { begin := unsafe.Pointer(s) - endPtr := unsafe.Pointer(uintptr(begin) + unsafe.Sizeof(*s)) + size := unsafe.Sizeof(*s) + beginAddr := uintptr(begin) + if beginAddr > ^uintptr(0)-size { + panic("tls: pointer arithmetic overflow in rootRange") + } + endPtr := unsafe.Pointer(beginAddr + size) return c.Pointer(begin), c.Pointer(endPtr) } diff --git a/runtime/internal/clite/tls/tls_nogc.go b/runtime/internal/clite/tls/tls_nogc.go index 15813613..15f7cd1e 100644 --- a/runtime/internal/clite/tls/tls_nogc.go +++ b/runtime/internal/clite/tls/tls_nogc.go @@ -1,5 +1,21 @@ //go:build llgo && nogc +/* + * Copyright (c) 2025 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package tls type slot[T any] struct { diff --git a/runtime/internal/clite/tls/tls_test.go b/runtime/internal/clite/tls/tls_test.go index 608064c8..9c0bd307 100644 --- a/runtime/internal/clite/tls/tls_test.go +++ b/runtime/internal/clite/tls/tls_test.go @@ -1,5 +1,21 @@ //go:build llgo +/* + * Copyright (c) 2025 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package tls_test import ( diff --git a/ssa/di_test.go b/ssa/di_test.go index d300d689..2d5da93c 100644 --- a/ssa/di_test.go +++ b/ssa/di_test.go @@ -1,5 +1,21 @@ //go:build !llgo +/* + * Copyright (c) 2025 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package ssa import (