feat(rtl): single-threaded mutex stubs — static hello now links fully static

runtime.thread.static.linux: no-op pthread_mutex_init/lock/unlock/destroy
(correct for a single-threaded process; real clone/futex threads are deferred).
pthread_create is intentionally absent so a thread-spawning static program fails
to link rather than silently misbehaving.

With this the LAST libc leaf is resolved: a --static hello now links to a fully
static ELF (statically linked, no NEEDED libc.so.6, no PT_INTERP).  It does not
yet RUN — it faults on the first threadvar access because %fs (the thread
pointer) is unset and the linker emits no PT_TLS for static mode.  Static TLS
setup (PT_TLS + arch_prctl(ARCH_SET_FS) in _start + correct TPOFF) is the next
piece.

Full suite green (3829); dynamic native/QBE unaffected.
This commit is contained in:
Graeme Geldenhuys 2026-06-26 01:10:19 +01:00
parent 5c3e6c1527
commit 7b6e275053
2 changed files with 54 additions and 0 deletions

View file

@ -504,6 +504,7 @@ begin
Units.Add('runtime.cstub');
Units.Add('runtime.libc.linux');
Units.Add('runtime.libc2.linux');
Units.Add('runtime.thread.static.linux');
end;
for I := 0 to Units.Count - 1 do

View file

@ -0,0 +1,53 @@
{
Blaise - An Object Pascal Compiler
Copyright (c) 2026 Graeme Geldenhuys
SPDX-License-Identifier: Apache-2.0 WITH Swift-exception
Licensed under the Apache License v2.0 with Runtime Library Exception.
See LICENSE file in the project root for full license terms.
}
unit runtime.thread.static.linux;
// Single-threaded mutex stubs for the --static (libc-free) build. Real threads
// (pthread_create via clone + futex-based mutexes) are deferred to the threads
// step of the migration (docs/linux-syscall-migration.adoc); until then a
// static program is single-threaded, so the locks are uncontended and these
// no-op stubs are correct. pthread_create itself is intentionally NOT provided:
// a static program that spawns a thread will fail to link, which is the honest
// signal that the threads leaf is not done yet.
//
// DEFINES the bare pthread_mutex_* names that runtime.weak / runtime.thread
// import via `external name`.
interface
function pthread_mutex_init(Mutex, Attr: Pointer): Integer;
function pthread_mutex_lock(Mutex: Pointer): Integer;
function pthread_mutex_unlock(Mutex: Pointer): Integer;
function pthread_mutex_destroy(Mutex: Pointer): Integer;
implementation
{ All no-ops returning success: a single-threaded process never contends. }
function pthread_mutex_init(Mutex, Attr: Pointer): Integer;
begin
Result := 0;
end;
function pthread_mutex_lock(Mutex: Pointer): Integer;
begin
Result := 0;
end;
function pthread_mutex_unlock(Mutex: Pointer): Integer;
begin
Result := 0;
end;
function pthread_mutex_destroy(Mutex: Pointer): Integer;
begin
Result := 0;
end;
end.