[libc] Implement pthread_setschedparam and getschedparam (#205770)

Implemented the pthread_setschedparam and pthread_getschedparam
functions.

Added Linux syscall wrappers:
* sched_setscheduler
* sched_getscheduler
* sched_getparam

Updated the Thread class to support getting and setting scheduling
parameters.

Added integration tests to verify the implementation.

Assisted-by: Automated tooling, human reviewed.
This commit is contained in:
Jeff Bailey 2026-07-23 17:59:56 +01:00 committed by GitHub
parent 10e0a2ee03
commit 8d4f2368a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 509 additions and 0 deletions

View file

@ -1085,6 +1085,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_equal
libc.src.pthread.pthread_exit
libc.src.pthread.pthread_getname_np
libc.src.pthread.pthread_getschedparam
libc.src.pthread.pthread_getspecific
libc.src.pthread.pthread_getthreadid_np
libc.src.pthread.pthread_getunique_np
@ -1129,6 +1130,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_spin_unlock
libc.src.pthread.pthread_self
libc.src.pthread.pthread_setname_np
libc.src.pthread.pthread_setschedparam
libc.src.pthread.pthread_setspecific
# sched.h entrypoints

View file

@ -1279,6 +1279,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_equal
libc.src.pthread.pthread_exit
libc.src.pthread.pthread_getname_np
libc.src.pthread.pthread_getschedparam
libc.src.pthread.pthread_getspecific
libc.src.pthread.pthread_getthreadid_np
libc.src.pthread.pthread_getunique_np
@ -1326,6 +1327,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_spin_unlock
libc.src.pthread.pthread_self
libc.src.pthread.pthread_setname_np
libc.src.pthread.pthread_setschedparam
libc.src.pthread.pthread_setspecific
# sched.h entrypoints

View file

@ -1284,6 +1284,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_equal
libc.src.pthread.pthread_exit
libc.src.pthread.pthread_getname_np
libc.src.pthread.pthread_getschedparam
libc.src.pthread.pthread_getspecific
libc.src.pthread.pthread_getthreadid_np
libc.src.pthread.pthread_getunique_np
@ -1331,6 +1332,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_spin_unlock
libc.src.pthread.pthread_self
libc.src.pthread.pthread_setname_np
libc.src.pthread.pthread_setschedparam
libc.src.pthread.pthread_setspecific
# sched.h entrypoints

View file

@ -333,6 +333,15 @@ add_proxy_header_library(
libc.include.llvm-libc-types.pthread_barrierattr_t
)
add_proxy_header_library(
pthread_t
HDRS
pthread_t.h
FULL_BUILD_DEPENDS
libc.include.llvm-libc-types.pthread_t
libc.include.pthread
)
add_proxy_header_library(
atexithandler_t
HDRS

View file

@ -0,0 +1,22 @@
//===-- Proxy for pthread_t -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_HDR_TYPES_PTHREAD_T_H
#define LLVM_LIBC_HDR_TYPES_PTHREAD_T_H
#ifdef LIBC_FULL_BUILD
#include "include/llvm-libc-types/pthread_t.h"
#else // Overlay mode
#include <pthread.h>
#endif // LIBC_FULL_BUILD
#endif // LLVM_LIBC_HDR_TYPES_PTHREAD_T_H

View file

@ -232,6 +232,12 @@ functions:
- type: pthread_t
- type: char *
- type: size_t
- name: pthread_getschedparam
return_type: int
arguments:
- type: pthread_t
- type: int *__restrict
- type: struct sched_param *__restrict
- name: pthread_getspecific
return_type: void *
arguments:
@ -422,6 +428,12 @@ functions:
arguments:
- type: pthread_t
- type: const char *
- name: pthread_setschedparam
return_type: int
arguments:
- type: pthread_t
- type: int
- type: const struct sched_param *
- name: pthread_setspecific
return_type: int
arguments:

View file

@ -40,6 +40,47 @@ add_header_library(
libc.include.sys_syscall
)
add_header_library(
sched_setscheduler
HDRS
sched_setscheduler.h
DEPENDS
libc.hdr.types.pid_t
libc.hdr.types.struct_sched_param
libc.src.__support.OSUtil.osutil
libc.src.__support.common
libc.src.__support.error_or
libc.src.__support.macros.config
libc.include.sys_syscall
)
add_header_library(
sched_getscheduler
HDRS
sched_getscheduler.h
DEPENDS
libc.hdr.types.pid_t
libc.src.__support.OSUtil.osutil
libc.src.__support.common
libc.src.__support.error_or
libc.src.__support.macros.config
libc.include.sys_syscall
)
add_header_library(
sched_getparam
HDRS
sched_getparam.h
DEPENDS
libc.hdr.types.pid_t
libc.hdr.types.struct_sched_param
libc.src.__support.OSUtil.osutil
libc.src.__support.common
libc.src.__support.error_or
libc.src.__support.macros.config
libc.include.sys_syscall
)
add_header_library(
close
HDRS

View file

@ -0,0 +1,36 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Implementation header for sched_getparam syscall wrapper.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SCHED_GETPARAM_H
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SCHED_GETPARAM_H
#include "hdr/types/pid_t.h"
#include "hdr/types/struct_sched_param.h"
#include "src/__support/OSUtil/linux/syscall.h" // syscall_checked
#include "src/__support/common.h"
#include "src/__support/error_or.h"
#include "src/__support/macros/config.h"
#include <sys/syscall.h> // For syscall numbers
namespace LIBC_NAMESPACE_DECL {
namespace linux_syscalls {
LIBC_INLINE ErrorOr<int> sched_getparam(pid_t tid, struct sched_param *param) {
return syscall_checked<int>(SYS_sched_getparam, tid, param);
}
} // namespace linux_syscalls
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SCHED_GETPARAM_H

View file

@ -0,0 +1,35 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Implementation header for sched_getscheduler syscall wrapper.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SCHED_GETSCHEDULER_H
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SCHED_GETSCHEDULER_H
#include "hdr/types/pid_t.h"
#include "src/__support/OSUtil/linux/syscall.h" // syscall_checked
#include "src/__support/common.h"
#include "src/__support/error_or.h"
#include "src/__support/macros/config.h"
#include <sys/syscall.h> // For syscall numbers
namespace LIBC_NAMESPACE_DECL {
namespace linux_syscalls {
LIBC_INLINE ErrorOr<int> sched_getscheduler(pid_t tid) {
return syscall_checked<int>(SYS_sched_getscheduler, tid);
}
} // namespace linux_syscalls
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SCHED_GETSCHEDULER_H

View file

@ -0,0 +1,37 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Implementation header for sched_setscheduler syscall wrapper.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SCHED_SETSCHEDULER_H
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SCHED_SETSCHEDULER_H
#include "hdr/types/pid_t.h"
#include "hdr/types/struct_sched_param.h"
#include "src/__support/OSUtil/linux/syscall.h" // syscall_checked
#include "src/__support/common.h"
#include "src/__support/error_or.h"
#include "src/__support/macros/config.h"
#include <sys/syscall.h> // For syscall numbers
namespace LIBC_NAMESPACE_DECL {
namespace linux_syscalls {
LIBC_INLINE ErrorOr<int> sched_setscheduler(pid_t tid, int policy,
const struct sched_param *param) {
return syscall_checked<int>(SYS_sched_setscheduler, tid, policy, param);
}
} // namespace linux_syscalls
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SCHED_SETSCHEDULER_H

View file

@ -112,7 +112,9 @@ add_header_library(
thread.h
DEPENDS
libc.hdr.stdint_proxy
libc.hdr.types.struct_sched_param
libc.src.__support.common
libc.src.__support.error_or
libc.src.__support.CPP.atomic
libc.src.__support.CPP.optional
libc.src.__support.CPP.string_view

View file

@ -47,6 +47,9 @@ add_object_library(
libc.src.__support.OSUtil.linux.syscall_wrappers.munmap
libc.src.__support.OSUtil.linux.syscall_wrappers.open
libc.src.__support.OSUtil.linux.syscall_wrappers.read
libc.src.__support.OSUtil.linux.syscall_wrappers.sched_getparam
libc.src.__support.OSUtil.linux.syscall_wrappers.sched_getscheduler
libc.src.__support.OSUtil.linux.syscall_wrappers.sched_setscheduler
libc.src.__support.OSUtil.linux.syscall_wrappers.write
libc.src.__support.threads.thread_common
COMPILE_OPTIONS

View file

@ -17,6 +17,9 @@
#include "src/__support/OSUtil/linux/syscall_wrappers/munmap.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/open.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/read.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/sched_getparam.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/sched_getscheduler.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/sched_setscheduler.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/write.h"
#include "src/__support/OSUtil/syscall.h" // For syscall functions.
#include "src/__support/common.h"
@ -490,6 +493,27 @@ int Thread::get_name(cpp::StringStream &name) const {
return 0;
}
int Thread::setschedparam(SchedParameters params) {
auto result = linux_syscalls::sched_setscheduler(attrib->tid, params.policy,
&params.param);
if (!result.has_value())
return result.error();
return 0;
}
ErrorOr<SchedParameters> Thread::getschedparam() const {
auto pol_result = linux_syscalls::sched_getscheduler(attrib->tid);
if (!pol_result.has_value())
return Error(pol_result.error());
struct sched_param param;
auto param_result = linux_syscalls::sched_getparam(attrib->tid, &param);
if (!param_result.has_value())
return Error(param_result.error());
return SchedParameters{pol_result.value(), param};
}
void thread_exit(ThreadReturnValue retval, ThreadStyle style) {
auto attrib = self.attrib;

View file

@ -10,10 +10,12 @@
#define LLVM_LIBC_SRC___SUPPORT_THREADS_THREAD_H
#include "hdr/stdint_proxy.h"
#include "hdr/types/struct_sched_param.h"
#include "src/__support/CPP/atomic.h"
#include "src/__support/CPP/optional.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/CPP/stringstream.h"
#include "src/__support/error_or.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"
@ -25,6 +27,11 @@
namespace LIBC_NAMESPACE_DECL {
struct SchedParameters {
int policy;
struct sched_param param;
};
using ThreadRunnerPosix = void *(void *);
using ThreadRunnerStdc = int(void *);
@ -230,6 +237,14 @@ struct Thread {
// Return the name of the thread in |name|. Return the error number of error.
int get_name(cpp::StringStream &name) const;
// Set the scheduling policy and parameters of the thread.
// Return 0 on success, or an error number on failure.
int setschedparam(SchedParameters params);
// Get the scheduling policy and parameters of the thread.
// Return SchedParameters on success, or an error number on failure.
ErrorOr<SchedParameters> getschedparam() const;
};
LIBC_INLINE_VAR LIBC_THREAD_LOCAL Thread self;

View file

@ -941,3 +941,29 @@ add_entrypoint_object(
libc.src.__support.threads.fork_callbacks
libc.src.errno.errno
)
add_entrypoint_object(
pthread_setschedparam
SRCS
pthread_setschedparam.cpp
HDRS
pthread_setschedparam.h
DEPENDS
libc.hdr.types.pthread_t
libc.hdr.types.struct_sched_param
libc.src.__support.macros.null_check
libc.src.__support.threads.thread
)
add_entrypoint_object(
pthread_getschedparam
SRCS
pthread_getschedparam.cpp
HDRS
pthread_getschedparam.h
DEPENDS
libc.hdr.types.pthread_t
libc.hdr.types.struct_sched_param
libc.src.__support.macros.null_check
libc.src.__support.threads.thread
)

View file

@ -0,0 +1,41 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Linux implementation of the pthread_getschedparam function.
///
//===----------------------------------------------------------------------===//
#include "pthread_getschedparam.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/null_check.h"
#include "src/__support/threads/thread.h"
namespace LIBC_NAMESPACE_DECL {
static_assert(sizeof(pthread_t) == sizeof(LIBC_NAMESPACE::Thread),
"Mismatch between pthread_t and internal Thread.");
LLVM_LIBC_FUNCTION(int, pthread_getschedparam,
(pthread_t th, int *__restrict policy,
struct sched_param *__restrict param)) {
LIBC_CRASH_ON_NULLPTR(policy);
LIBC_CRASH_ON_NULLPTR(param);
auto *thread = reinterpret_cast<Thread *>(&th);
auto result = thread->getschedparam();
if (!result.has_value())
return result.error();
*policy = result.value().policy;
*param = result.value().param;
return 0;
}
} // namespace LIBC_NAMESPACE_DECL

View file

@ -0,0 +1,28 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Implementation header for pthread_getschedparam.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_GETSCHEDPARAM_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_GETSCHEDPARAM_H
#include "hdr/types/pthread_t.h"
#include "hdr/types/struct_sched_param.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
int pthread_getschedparam(pthread_t thread, int *__restrict policy,
struct sched_param *__restrict param);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_GETSCHEDPARAM_H

View file

@ -0,0 +1,34 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Linux implementation of the pthread_setschedparam function.
///
//===----------------------------------------------------------------------===//
#include "pthread_setschedparam.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/null_check.h"
#include "src/__support/threads/thread.h"
namespace LIBC_NAMESPACE_DECL {
static_assert(sizeof(pthread_t) == sizeof(LIBC_NAMESPACE::Thread),
"Mismatch between pthread_t and internal Thread.");
LLVM_LIBC_FUNCTION(int, pthread_setschedparam,
(pthread_t th, int policy,
const struct sched_param *param)) {
LIBC_CRASH_ON_NULLPTR(param);
auto *thread = reinterpret_cast<Thread *>(&th);
return thread->setschedparam({policy, *param});
}
} // namespace LIBC_NAMESPACE_DECL

View file

@ -0,0 +1,28 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Implementation header for pthread_setschedparam.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_SETSCHEDPARAM_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_SETSCHEDPARAM_H
#include "hdr/types/pthread_t.h"
#include "hdr/types/struct_sched_param.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
int pthread_setschedparam(pthread_t thread, int policy,
const struct sched_param *param);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_SETSCHEDPARAM_H

View file

@ -291,3 +291,21 @@ add_integration_test(
libc.src.__support.CPP.array
libc.src.__support.CPP.new
)
add_integration_test(
pthread_setschedparam_test
SUITE
libc-pthread-integration-tests
SRCS
pthread_setschedparam_test.cpp
DEPENDS
libc.hdr.errno_macros
libc.hdr.sched_macros
libc.hdr.types.struct_sched_param
libc.hdr.types.pthread_t
libc.src.pthread.pthread_create
libc.src.pthread.pthread_getschedparam
libc.src.pthread.pthread_join
libc.src.pthread.pthread_self
libc.src.pthread.pthread_setschedparam
)

View file

@ -0,0 +1,92 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Integration tests for pthread_setschedparam and pthread_getschedparam.
///
//===----------------------------------------------------------------------===//
#include "hdr/errno_macros.h"
#include "hdr/sched_macros.h"
#include "hdr/types/pthread_t.h"
#include "hdr/types/struct_sched_param.h"
#include "src/pthread/pthread_create.h"
#include "src/pthread/pthread_getschedparam.h"
#include "src/pthread/pthread_join.h"
#include "src/pthread/pthread_self.h"
#include "src/pthread/pthread_setschedparam.h"
#include "test/IntegrationTest/test.h"
static void *child_func(void *) { return nullptr; }
TEST_MAIN() {
auto main_thread = LIBC_NAMESPACE::pthread_self();
struct sched_param param;
int policy;
// 1. Test getschedparam on self
ASSERT_EQ(LIBC_NAMESPACE::pthread_getschedparam(main_thread, &policy, &param),
0);
// 2. Test setschedparam on self (Success)
param.sched_priority = 0;
ASSERT_EQ(
LIBC_NAMESPACE::pthread_setschedparam(main_thread, SCHED_OTHER, &param),
0);
// Verify it was set
int new_policy;
struct sched_param new_param;
ASSERT_EQ(LIBC_NAMESPACE::pthread_getschedparam(main_thread, &new_policy,
&new_param),
0);
ASSERT_EQ(new_policy, SCHED_OTHER);
ASSERT_EQ(new_param.sched_priority, 0);
// 3. Test setschedparam on self (Failure - Invalid Policy)
ASSERT_EQ(LIBC_NAMESPACE::pthread_setschedparam(main_thread, -1, &param),
EINVAL);
// 4. Test setschedparam on self (Failure - Invalid Priority for SCHED_OTHER)
param.sched_priority = 1; // Invalid for SCHED_OTHER
ASSERT_EQ(
LIBC_NAMESPACE::pthread_setschedparam(main_thread, SCHED_OTHER, &param),
EINVAL);
param.sched_priority = 0; // Reset
// 5. Test on Child Thread
pthread_t th;
ASSERT_EQ(LIBC_NAMESPACE::pthread_create(&th, nullptr, child_func, nullptr),
0);
// Get child's default sched param
ASSERT_EQ(LIBC_NAMESPACE::pthread_getschedparam(th, &policy, &param), 0);
// Set child's sched param (Success)
param.sched_priority = 0;
ASSERT_EQ(LIBC_NAMESPACE::pthread_setschedparam(th, SCHED_OTHER, &param), 0);
// Verify child's sched param
ASSERT_EQ(LIBC_NAMESPACE::pthread_getschedparam(th, &new_policy, &new_param),
0);
ASSERT_EQ(new_policy, SCHED_OTHER);
ASSERT_EQ(new_param.sched_priority, 0);
// Set child's sched param (Failure - Invalid Policy)
ASSERT_EQ(LIBC_NAMESPACE::pthread_setschedparam(th, -1, &param), EINVAL);
// Set child's sched param (Failure - Invalid Priority)
param.sched_priority = 1;
ASSERT_EQ(LIBC_NAMESPACE::pthread_setschedparam(th, SCHED_OTHER, &param),
EINVAL);
void *retval;
ASSERT_EQ(LIBC_NAMESPACE::pthread_join(th, &retval), 0);
return 0;
}