Skip to content

feat(c/pthread): restore native thread APIs and layouts - #46

Draft
MeteorsLiu wants to merge 6 commits into
goplus:mainfrom
MeteorsLiu:codex/c-pthread-native-bindings
Draft

MeteorsLiu wants to merge 6 commits into
goplus:mainfrom
MeteorsLiu:codex/c-pthread-native-bindings

Conversation

@MeteorsLiu

@MeteorsLiu MeteorsLiu commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Generate native pthread APIs and layouts while preserving existing entry-point names where compatible.

The implementation includes:

  • Use glibc 2.24 and macOS 14 headers for native Attr and Key layouts on the three supported targets.
  • Replace duplicate attribute and TLS bindings with generated declarations under their existing method names, using native C callback types.
  • Keep Create and Join GC behavior, with direct C calls available as NativeCreate and NativeJoin; keep other targets’ existing declarations.
  • Pass attribute layout, guarded buffer, TLS, and thread roundtrip tests with GC and nogc on all three targets.

The native APIs share the established names while retaining the separate GC entry points.

@MeteorsLiu
MeteorsLiu force-pushed the codex/c-pthread-native-bindings branch from 9addf11 to cc6e25e Compare October 19, 2026 06:00
@MeteorsLiu MeteorsLiu changed the title feat(c/pthread): add native pthread and synchronization bindings feat(c/pthread): add native pthread bindings Oct 19, 2026
@MeteorsLiu
MeteorsLiu marked this pull request as draft October 19, 2026 06:06
@MeteorsLiu

MeteorsLiu commented Oct 19, 2026 •

Copy link
Copy Markdown
Member Author

Merge order: #45 → #51 → #48 → #49 → #44 → #47 → #46 → #50 → #52.

Each draft changes one folder only. This refresh regenerates native APIs without omitting functions merely to preserve handwritten entry points. Existing compatibility APIs remain available; colliding native names use the Native prefix.

The combined prerequisite snapshot passes llgo build and executed llgo test runs on macOS arm64, Linux amd64 and Linux arm64, both with GC and -tags=nogc (54 package test runs and 6 complete builds). Generation uses unmodified llcppg main da227ff4, macOS SDK 14.0 and Bootlin glibc 2.24 headers. The earlier Timeval receiver and Signal layout failures are resolved.

These PRs remain draft for review. Documented generator/ABI failures and previously approved va_list exclusions remain; there are zero handwritten-retention exclusions.

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

This PR replaces the hand-written pthread/sync type stubs with ABI-exact, llcppg-generated native bindings for linux/amd64 and darwin/arm64, plus supporting types (Iovec, SchedParam, mach port, SigsetT), while keeping a cgo/placeholder fallback for other POSIX targets.

I verified the mechanics:

  • go build ./c/... passes on linux/amd64.
  • All linux/amd64 struct sizes match the glibc C ABI exactly (Mutex 40, Cond 48, RWLock 56, Attr 56, Sem/Barrier 32, attrs 4/8, Key/Spinlock 4).
  • The darwin/arm64 pthread package type-checks cleanly (go vet), including the Thread/OverrideT receiver methods — these compile because Thread/OverrideT are aliases to pointer types, which Go permits as method receivers.
  • Build-tag coverage for Attr/Key and the sync types is complete and non-overlapping across all !windows targets.

Overall this is a solid, correct improvement for the two validated targets. The findings below are mostly generated-code quality/portability items; none block merge.

Portability: a function is free on linux but a method on darwin

pthread_detach, pthread_kill, pthread_getschedparam, and pthread_setschedparam are generated as free functions on linux/amd64 but as Thread methods on darwin/arm64. Cross-platform code cannot call these uniformly (pthread.Detach(t) vs t.Detach()). If portability across the validated targets is a goal, consider unifying the receiver vs. free-function form in the generator. (See inline comment.)

Generated placeholder names leak into the public darwin API

The darwin bindings expose _llcppg_param1, _llcppg_param2, … in exported signatures and in JitWriteCallbackT, and the retained Doxygen @param __attr / @param __pthread blocks reference names that became the receiver. The linux bindings keep meaningful names. Regenerating with real parameter names would improve godoc and cross-platform consistency. (See inline comment.)

Minor documentation artifacts

  • c/signal/types_darwin_arm64.go — // [???] signal set placeholder (the linux counterpart reads "A set of signals…").
  • c/pthread/sync/libc_darwin_arm64.go — stray // this should go in limits.h> carried verbatim onto SEM_VALUE_MAX.

Fallback types stay smaller than the real C ABI (pre-existing, non-validated targets)

c/pthread/types_other.go keeps the 24-byte placeholder Attr and 4-byte Key for non-validated POSIX targets (e.g. darwin/amd64, linux/arm64). The real pthread_attr_t is 56–64 bytes and darwin's pthread_key_t is 8 bytes, so calling the Attr/Key methods there would let libc write past the Go allocation. This predates the PR, which actually fixes it for the two validated targets; worth tracking for the fallback path. (The sync fallback avoids this by using cgo C.pthread_* types.) (See inline comment.)

Note (pre-existing, outside this diff)

sync.go's (*MutexAttr).Init / (*CondAttr).Init / (*RWLockAttr).Init each take an extra *Attr parameter beyond the receiver even though pthread_*attr_init take a single pointer. Not touched by this PR, flagged only for awareness.

Findings without inline locations

  • c/signal/types_darwin_arm64.go:13: // [???] signal set is a generator placeholder left in the doc comment. The linux counterpart (c/signal/types_linux_amd64.go) documents this as "A set of signals to be blocked, unblocked, or waited for." Worth cleaning up before this becomes the darwin baseline.
  • c/pthread/sync/libc_darwin_arm64.go:94: Stray editorial note carried verbatim from the macOS semaphore.h header (// this should go in limits.h>, including the dangling >). It's meaningless as godoc for SEM_VALUE_MAX and should be dropped or replaced.

}

// llgo:link Thread.Detach C.pthread_detach
func (self Thread) Detach() c.Int {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cross-platform inconsistency: pthread_detach is a Thread method here, but a free function on linux/amd64 (func Detach(__th Thread) in libc_linux_amd64.go:113). The same split applies to pthread_kill, pthread_getschedparam, and pthread_setschedparam. Code written against one target won't compile on the other — consider unifying the receiver vs. free-function form in the generator.

}

//go:linkname Equal C.pthread_equal
func Equal(_llcppg_param1 Thread, _llcppg_param2 Thread) c.Int

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated placeholder parameter names (_llcppg_param1, _llcppg_param2) leak into the exported API throughout this darwin file (and into JitWriteCallbackT). The linux bindings use meaningful names (__threadid, __signo, …). Regenerating with real parameter names would improve godoc and keep the two targets consistent.

Comment thread c/pthread/types_other.go
import "github.com/goplus/lib/c"

// Attr represents POSIX thread attributes.
type Attr struct {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On non-validated POSIX targets (e.g. darwin/amd64, linux/arm64 glibc) this placeholder Attr is 24 bytes and Key (line 14) is 4 bytes, but the real pthread_attr_t is 56–64 bytes and darwin's pthread_key_t is 8 bytes. The Attr/Key methods declared in pthread.go would then let libc write past the Go allocation. This is pre-existing and is fixed for the two validated targets by this PR — noting it so the fallback path is tracked. (The sync fallback avoids this by using cgo C.pthread_* types.)

@MeteorsLiu MeteorsLiu changed the title feat(c/pthread): add native pthread bindings feat(c/pthread): generate native pthread layouts and bindings Oct 19, 2026
@MeteorsLiu MeteorsLiu changed the title feat(c/pthread): generate native pthread layouts and bindings feat(c/pthread): add native attributes and classified pthread APIs Oct 19, 2026
@MeteorsLiu MeteorsLiu changed the title feat(c/pthread): add native attributes and classified pthread APIs feat(c/pthread): add native thread layouts and APIs Oct 19, 2026
@MeteorsLiu MeteorsLiu changed the title feat(c/pthread): add native thread layouts and APIs feat(c/pthread): restore native thread APIs and layouts Oct 20, 2026
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

Successfully merging this pull request may close these issues.

1 participant