Skip to content

Land pthread_attr_* libc#9

Merged
jserv merged 1 commit into
mainfrom
pse51
May 13, 2026
Merged

Land pthread_attr_* libc#9
jserv merged 1 commit into
mainfrom
pse51

Conversation

@jserv
Copy link
Copy Markdown
Contributor

@jserv jserv commented May 13, 2026

Close the last narrow gap in the PSE51-oriented userspace surface. A portable libc that promises pthread_attr_t needs both the attribute accessors and a way to honor PTHREAD_EXPLICIT_SCHED without the SYS_THREAD_SETSCHEDPARAM race window; ship both in one branch.

Library lives at include/mazu/pthread.h as a header-only set of static inline functions: pthread_attr_init / _destroy, _set/_get for detachstate, inheritsched, schedpolicy, schedparam, stacksize, stack. All entry points NULL-guard, validate inputs, and return positive errno (POSIX convention). pthread_attr_destroy stamps every field so use-after-destroy is debugger-visible.

Stack accessors are constrained by the shared address-space model: the kernel assigns each thread slot a fixed VA band, so a caller-supplied stack cannot be honored. pthread_attr_setstack always returns ENOTSUP, and pthread_attr_setstacksize succeeds only for USER_STACK_SIZE; both signal the constraint up front instead of letting a portable caller observe a stack contract the kernel will not satisfy. pthread_attr_getstack / _getstacksize still round-trip the init-time defaults so feature probes work.

Kernel ABI adds a dedicated syscall, SYS_THREAD_CREATE_EXPLICIT (slot 101), rather than repurposing SYS_THREAD_CREATE's a2 register. Reusing the original syscall risked misinterpreting garbage a2 from pre-existing callers who never cleared unused registers. The new syscall reads a (prio + 1) encoding from a2 (0 inherits; 1..CONFIG_SCHED_NPRIO sets explicit prio = a2 - 1; anything else returns EINVAL), enforces the same privilege bound as pthread_setschedparam (cannot raise above creator's base priority, EPERM otherwise), and shares its body with sys_thread_create_h via sys_thread_create_common(use_explicit_prio_abi). td_base_prio is snapshotted with __atomic_load_n(__ATOMIC_RELAXED) so a cross-hart setschedparam against the creator cannot make the EPERM gate disagree with the inherit-default fallback.

pthread_attr_resolve_create_syscall and _resolve_prio_arg let a future pthread_create wrapper hand the attr straight to the right syscall. The prio resolver bounds-checks before the (u64) cast: a negative i32 cast to u64 plus 1 wraps to 0, which would have mimicked the inherit encoding and silently demoted an EXPLICIT_SCHED request from a caller who bypassed the setters. The resolver returns a sentinel above CONFIG_SCHED_NPRIO for any out-of-range value so the kernel's own bound check surfaces EINVAL.

ENOTSUP joins the rest of the errno constants in
include/mazu/errordef.h (value 95, matching the Linux EOPNOTSUPP numeric) with a matching error_code_str branch.


Summary by cubic

Implements a header-only pthread_attr_* library and adds SYS_THREAD_CREATE_EXPLICIT to support PTHREAD_EXPLICIT_SCHED without the post-create race. This closes the last gap in the PSE51 userspace surface.

  • New Features

    • Header-only pthread_attr_* at include/mazu/pthread.h (init/destroy; get/set for detachstate, inheritsched, schedpolicy, schedparam, stacksize, stack). All calls NULL-guarded and return positive errno.
    • Stack semantics: pthread_attr_setstack returns ENOTSUP; pthread_attr_setstacksize accepts only USER_STACK_SIZE. Getters round-trip defaults.
    • New SYS_THREAD_CREATE_EXPLICIT (slot 101): a2=0 inherits, 1..CONFIG_SCHED_NPRIO sets prio (a2−1), else EINVAL; EPERM if above creator’s base. Legacy SYS_THREAD_CREATE unchanged.
    • Adds ENOTSUP (95) and error string; updates docs (PSE51 matrix) and selftests for attrs and the new syscall.
  • Migration

    • For a pthread_create wrapper, use pthread_attr_resolve_create_syscall and pthread_attr_resolve_prio_arg to pick the syscall and a2 encoding.
    • Do not rely on caller-supplied stacks; accept kernel-assigned stacks and handle pthread_attr_setstack as unsupported.

Written for commit 6b5ed23. Summary will update on new commits.

Close the last narrow gap in the PSE51-oriented userspace surface.
A portable libc that promises pthread_attr_t needs both the attribute
accessors and a way to honor PTHREAD_EXPLICIT_SCHED without the
SYS_THREAD_SETSCHEDPARAM race window; ship both in one branch.

Library lives at include/mazu/pthread.h as a header-only set of
static inline functions: pthread_attr_init / _destroy,
_set/_get for detachstate, inheritsched, schedpolicy, schedparam,
stacksize, stack. All entry points NULL-guard, validate inputs, and
return positive errno (POSIX convention). pthread_attr_destroy
stamps every field so use-after-destroy is debugger-visible.

Stack accessors are constrained by the shared address-space model:
the kernel assigns each thread slot a fixed VA band, so a
caller-supplied stack cannot be honored. pthread_attr_setstack
always returns ENOTSUP, and pthread_attr_setstacksize succeeds only
for USER_STACK_SIZE; both signal the constraint up front instead of
letting a portable caller observe a stack contract the kernel will
not satisfy. pthread_attr_getstack / _getstacksize still round-trip
the init-time defaults so feature probes work.

Kernel ABI adds a dedicated syscall, SYS_THREAD_CREATE_EXPLICIT
(slot 101), rather than repurposing SYS_THREAD_CREATE's a2 register.
Reusing the original syscall risked misinterpreting garbage a2 from
pre-existing callers who never cleared unused registers. The new
syscall reads a (prio + 1) encoding from a2 (0 inherits;
1..CONFIG_SCHED_NPRIO sets explicit prio = a2 - 1; anything else
returns EINVAL), enforces the same privilege bound as
pthread_setschedparam (cannot raise above creator's base priority,
EPERM otherwise), and shares its body with sys_thread_create_h via
sys_thread_create_common(use_explicit_prio_abi). td_base_prio is
snapshotted with __atomic_load_n(__ATOMIC_RELAXED) so a cross-hart
setschedparam against the creator cannot make the EPERM gate
disagree with the inherit-default fallback.

pthread_attr_resolve_create_syscall and _resolve_prio_arg let a
future pthread_create wrapper hand the attr straight to the right
syscall. The prio resolver bounds-checks before the (u64) cast: a
negative i32 cast to u64 plus 1 wraps to 0, which would have mimicked
the inherit encoding and silently demoted an EXPLICIT_SCHED request
from a caller who bypassed the setters. The resolver returns a
sentinel above CONFIG_SCHED_NPRIO for any out-of-range value so the
kernel's own bound check surfaces EINVAL.

ENOTSUP joins the rest of the errno constants in
include/mazu/errordef.h (value 95, matching the Linux EOPNOTSUPP
numeric) with a matching error_code_str branch.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 7 files

@jserv jserv merged commit 8c0527c into main May 13, 2026
7 checks passed
@jserv jserv deleted the pse51 branch May 13, 2026 01:55
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