From b9366836d5e6e5217e096ff6cc7413713d3d72fb Mon Sep 17 00:00:00 2001 From: no92 Date: Wed, 5 Apr 2023 22:25:26 +0200 Subject: [PATCH 1/8] options/internal: make cpu_set_t a bit --- meson.build | 1 + options/internal/include/bits/cpu_set.h | 13 +++++++++++++ options/posix/include/pthread.h | 1 + options/posix/include/sched.h | 6 +----- 4 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 options/internal/include/bits/cpu_set.h diff --git a/meson.build b/meson.build index 4761527c79..73897814fd 100644 --- a/meson.build +++ b/meson.build @@ -282,6 +282,7 @@ if not no_headers 'options/internal/include/bits/sigset_t.h', 'options/internal/include/bits/inline-definition.h', 'options/internal/include/bits/ether_addr.h', + 'options/internal/include/bits/cpu_set.h', subdir: 'bits' ) endif diff --git a/options/internal/include/bits/cpu_set.h b/options/internal/include/bits/cpu_set.h new file mode 100644 index 0000000000..69f69232fe --- /dev/null +++ b/options/internal/include/bits/cpu_set.h @@ -0,0 +1,13 @@ +#ifndef _MLIBC_INTERNAL_CPU_SET_H +#define _MLIBC_INTERNAL_CPU_SET_H + +typedef unsigned long __cpu_mask; + +#define CPU_SETSIZE 1024 +#define __NCPUBITS (8 * sizeof(__cpu_mask)) + +typedef struct { + __cpu_mask __bits[CPU_SETSIZE / __NCPUBITS]; +} cpu_set_t; + +#endif /* _MLIBC_INTERNAL_CPU_SET_H */ diff --git a/options/posix/include/pthread.h b/options/posix/include/pthread.h index 743b116304..eeb2544640 100644 --- a/options/posix/include/pthread.h +++ b/options/posix/include/pthread.h @@ -3,6 +3,7 @@ #define _PTHREAD_H #include +#include // TODO: pthread is not required to define size_t. #include #include diff --git a/options/posix/include/sched.h b/options/posix/include/sched.h index a8a141fa60..9dfff0b10c 100644 --- a/options/posix/include/sched.h +++ b/options/posix/include/sched.h @@ -3,6 +3,7 @@ #define _SCHED_H #include +#include #include #include @@ -56,11 +57,6 @@ struct sched_param { int sched_yield(void); -struct __mlibc_cpu_set { - unsigned long __bits[128/sizeof(long)]; -}; -typedef struct __mlibc_cpu_set cpu_set_t; - int sched_getscheduler(pid_t pid); int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); From bc8ff2ffe17a24f647f8f9806d2eaef79cb68f55 Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 3 Apr 2023 21:50:43 +0200 Subject: [PATCH 2/8] options/posix: disable pthreads linux extensions without the linux option --- options/posix/generic/pthread-stubs.cpp | 2 + options/posix/include/pthread.h | 2 + tests/linux/pthread_attr.c | 89 +++++++++++++++++++++++++ tests/meson.build | 1 + tests/posix/pthread_attr.c | 72 -------------------- 5 files changed, 94 insertions(+), 72 deletions(-) create mode 100644 tests/linux/pthread_attr.c diff --git a/options/posix/generic/pthread-stubs.cpp b/options/posix/generic/pthread-stubs.cpp index 599a3ed7d8..735b8e1923 100644 --- a/options/posix/generic/pthread-stubs.cpp +++ b/options/posix/generic/pthread-stubs.cpp @@ -183,6 +183,7 @@ int pthread_attr_setschedpolicy(pthread_attr_t *__restrict attr, int policy) { return 0; } +#if __MLIBC_LINUX_OPTION int pthread_attr_getaffinity_np(const pthread_attr_t *__restrict attr, size_t cpusetsize, cpu_set_t *__restrict cpusetp) { if (!attr) @@ -316,6 +317,7 @@ int pthread_setaffinity_np(pthread_t, size_t, const cpu_set_t *) { __ensure(!"Not implemented"); __builtin_unreachable(); } +#endif // __MLIBC_LINUX_OPTION extern "C" Tcb *__rtdl_allocateTcb(); diff --git a/options/posix/include/pthread.h b/options/posix/include/pthread.h index eeb2544640..d638467647 100644 --- a/options/posix/include/pthread.h +++ b/options/posix/include/pthread.h @@ -195,6 +195,7 @@ int pthread_attr_setinheritsched(pthread_attr_t *__restrict, int); int pthread_attr_getschedparam(const pthread_attr_t *__restrict, struct sched_param *__restrict); int pthread_attr_setschedparam(pthread_attr_t *__restrict, const struct sched_param *__restrict); +#if __MLIBC_LINUX_OPTION int pthread_attr_getaffinity_np(const pthread_attr_t *__restrict, size_t, cpu_set_t *__restrict); int pthread_attr_setaffinity_np(pthread_attr_t *__restrict, size_t, const cpu_set_t *__restrict); @@ -205,6 +206,7 @@ int pthread_getattr_np(pthread_t, pthread_attr_t *); int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset); int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset); +#endif /* __MLIBC_LINUX_OPTION */ // pthread functions. int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, diff --git a/tests/linux/pthread_attr.c b/tests/linux/pthread_attr.c new file mode 100644 index 0000000000..b1b13ba150 --- /dev/null +++ b/tests/linux/pthread_attr.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include + +static void test_affinity() { + pthread_attr_t attr; + cpu_set_t set = {0}; + assert(!pthread_attr_init(&attr)); + assert(!pthread_attr_setaffinity_np(&attr, 1, &set)); + + cpu_set_t other_set = {0}; + assert(!pthread_attr_getaffinity_np(&attr, 1, &set)); + + assert(!memcmp(&set, &other_set, sizeof(cpu_set_t))); + + pthread_attr_destroy(&attr); +} + +#if !defined(USE_HOST_LIBC) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32) +static void test_sigmask() { + pthread_attr_t attr; + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGUSR1); +#ifndef USE_HOST_LIBC + sigaddset(&set, SIGCANCEL); +#endif + + assert(!pthread_attr_init(&attr)); + assert(!pthread_attr_setsigmask_np(&attr, &set)); + + sigset_t other_set; + sigemptyset(&other_set); + + assert(!pthread_attr_getsigmask_np(&attr, &other_set)); + + assert(sigismember(&other_set, SIGUSR1)); +#ifndef USE_HOST_LIBC + // Test whether internal signals get filtered properly. + assert(!sigismember(&other_set, SIGCANCEL)); +#endif + + pthread_attr_destroy(&attr); +} + +static void *getattr_worker(void *arg) { + (void)arg; + return NULL; +} + +static void test_getattrnp() { + pthread_attr_t attr; + size_t stacksize = PTHREAD_STACK_MIN; + assert(!pthread_attr_init(&attr)); + assert(!pthread_attr_setstacksize(&attr, stacksize)); + + pthread_t thread; + assert(!pthread_create(&thread, &attr, getattr_worker, NULL)); + assert(!pthread_getattr_np(thread, &attr)); + size_t other_stacksize; + assert(!pthread_attr_getstacksize(&attr, &other_stacksize)); + assert(other_stacksize == stacksize); + assert(!pthread_join(thread, NULL)); + + pthread_t own_thread = pthread_self(); + void *stack; + assert(!pthread_getattr_np(own_thread, &attr)); + assert(!pthread_attr_getstack(&attr, &stack, &other_stacksize)); + assert(stack); + assert(other_stacksize); + // Check that we can read from the highest byte returned. + // pthread_getattr_np() should return the lowest byte + // of the stack. + assert(!*(char*)(stack + other_stacksize - 1)); + + pthread_attr_destroy(&attr); +} +#endif // !defined(USE_HOST_LIBC) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32) + +int main() { + test_affinity(); +#if !defined(USE_HOST_LIBC) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32) + test_sigmask(); + test_getattrnp(); +#endif + + return 0; +} diff --git a/tests/meson.build b/tests/meson.build index 857d2c9304..9cfd073bce 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -92,6 +92,7 @@ all_test_cases = [ 'glibc/error_at_line', 'linux/xattr', 'linux/pthread_setname_np', + 'linux/pthread_attr', ] if host_machine.system() == 'linux' diff --git a/tests/posix/pthread_attr.c b/tests/posix/pthread_attr.c index a08d7aba9d..44d52b6da4 100644 --- a/tests/posix/pthread_attr.c +++ b/tests/posix/pthread_attr.c @@ -138,75 +138,6 @@ static void test_stack() { } #endif -static void test_affinity() { - pthread_attr_t attr; - cpu_set_t set = {0}; - assert(!pthread_attr_init(&attr)); - assert(!pthread_attr_setaffinity_np(&attr, 1, &set)); - - cpu_set_t other_set = {0}; - assert(!pthread_attr_getaffinity_np(&attr, 1, &set)); - - assert(!memcmp(&set, &other_set, sizeof(cpu_set_t))); -} - -#if !defined(USE_HOST_LIBC) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32) -static void test_sigmask() { - pthread_attr_t attr; - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGUSR1); -#ifndef USE_HOST_LIBC - sigaddset(&set, SIGCANCEL); -#endif - - assert(!pthread_attr_init(&attr)); - assert(!pthread_attr_setsigmask_np(&attr, &set)); - - sigset_t other_set; - sigemptyset(&other_set); - - assert(!pthread_attr_getsigmask_np(&attr, &other_set)); - - assert(sigismember(&other_set, SIGUSR1)); -#ifndef USE_HOST_LIBC - // Test whether internal signals get filtered properly. - assert(!sigismember(&other_set, SIGCANCEL)); -#endif -} - -static void *getattr_worker(void *arg) { - (void)arg; - return NULL; -} - -static void test_getattrnp() { - pthread_attr_t attr; - size_t stacksize = PTHREAD_STACK_MIN; - assert(!pthread_attr_init(&attr)); - assert(!pthread_attr_setstacksize(&attr, stacksize)); - - pthread_t thread; - assert(!pthread_create(&thread, &attr, getattr_worker, NULL)); - assert(!pthread_getattr_np(thread, &attr)); - size_t other_stacksize; - assert(!pthread_attr_getstacksize(&attr, &other_stacksize)); - assert(other_stacksize == stacksize); - assert(!pthread_join(thread, NULL)); - - pthread_t own_thread = pthread_self(); - void *stack; - assert(!pthread_getattr_np(own_thread, &attr)); - assert(!pthread_attr_getstack(&attr, &stack, &other_stacksize)); - assert(stack); - assert(other_stacksize); - // Check that we can read from the highest byte returned. - // pthread_getattr_np() should return the lowest byte - // of the stack. - assert(!*(char*)(stack + other_stacksize - 1)); -} -#endif - int main() { test_detachstate(); test_stacksize(); @@ -216,10 +147,7 @@ int main() { test_schedparam(); test_schedpolicy(); test_stackaddr(); - test_affinity(); #if !defined(USE_HOST_LIBC) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32) test_stack(); - test_sigmask(); - test_getattrnp(); #endif } From a3b23e3b35d1892d950d264a210ebe3e94d6d77c Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 3 Apr 2023 20:51:55 +0200 Subject: [PATCH 3/8] options/linux: move over linux extensions of sched.h --- options/linux/generic/sched.cpp | 29 +++++++++++++ .../linux/include/bits/linux/linux_sched.h | 43 +++++++++++++++++++ options/linux/include/mlibc/linux-sysdeps.hpp | 3 ++ options/posix/generic/sched-stubs.cpp | 29 ------------- options/posix/include/mlibc/posix-sysdeps.hpp | 1 - options/posix/include/sched.h | 33 -------------- 6 files changed, 75 insertions(+), 63 deletions(-) diff --git a/options/linux/generic/sched.cpp b/options/linux/generic/sched.cpp index ff4974373f..8d60b72ab6 100644 --- a/options/linux/generic/sched.cpp +++ b/options/linux/generic/sched.cpp @@ -18,3 +18,32 @@ int setns(int, int) { __ensure(!"Not implemented"); __builtin_unreachable(); } + +int sched_getscheduler(pid_t) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask) { + MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getaffinity, -1); + if(int e = mlibc::sys_getaffinity(pid, cpusetsize, mask); e) { + errno = e; + return -1; + } + return 0; +} + +int unshare(int) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +int sched_setaffinity(pid_t, size_t, const cpu_set_t *) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +int clone(int (*)(void *), void *, int, void *, ...) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} diff --git a/options/linux/include/bits/linux/linux_sched.h b/options/linux/include/bits/linux/linux_sched.h index 82b5afeb50..e6cd6cdcf6 100644 --- a/options/linux/include/bits/linux/linux_sched.h +++ b/options/linux/include/bits/linux/linux_sched.h @@ -2,6 +2,45 @@ #ifndef _LINUX_SCHED_H #define _LINUX_SCHED_H +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define CLONE_VM 0x00000100 +#define CLONE_FS 0x00000200 +#define CLONE_FILES 0x00000400 +#define CLONE_SIGHAND 0x00000800 +#define CLONE_PTRACE 0x00002000 +#define CLONE_VFORK 0x00004000 +#define CLONE_PARENT 0x00008000 +#define CLONE_THREAD 0x00010000 +#define CLONE_NEWNS 0x00020000 +#define CLONE_SYSVSEM 0x00040000 +#define CLONE_SETTLS 0x00080000 +#define CLONE_PARENT_SETTID 0x00100000 +#define CLONE_CHILD_CLEARTID 0x00200000 +#define CLONE_DETACHED 0x00400000 +#define CLONE_UNTRACED 0x00800000 +#define CLONE_CHILD_SETTID 0x01000000 +#define CLONE_NEWCGROUP 0x02000000 +#define CLONE_NEWUTS 0x04000000 +#define CLONE_NEWIPC 0x08000000 +#define CLONE_NEWUSER 0x10000000 +#define CLONE_NEWPID 0x20000000 +#define CLONE_NEWNET 0x40000000 +#define CLONE_IO 0x80000000 + +int sched_getscheduler(pid_t pid); +int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask); +int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); + +int unshare(int flags); +int clone(int (*)(void *), void *, int, void *, ...); + /* Glibc extension */ int sched_getcpu(void); @@ -9,4 +48,8 @@ int sched_getcpu(void); int setns(int fd, int nstype); #endif /* _GNU_SOURCE */ +#ifdef __cplusplus +} +#endif + #endif /* _LINUX_SCHED_H */ diff --git a/options/linux/include/mlibc/linux-sysdeps.hpp b/options/linux/include/mlibc/linux-sysdeps.hpp index 05186759c8..d864312835 100644 --- a/options/linux/include/mlibc/linux-sysdeps.hpp +++ b/options/linux/include/mlibc/linux-sysdeps.hpp @@ -1,6 +1,7 @@ #ifndef MLIBC_LINUX_SYSDEPS #define MLIBC_LINUX_SYSDEPS +#include #include #include #include @@ -69,6 +70,8 @@ int sys_write(int fd, const void *buf, size_t count, ssize_t *bytes_written); [[gnu::weak]] int sys_lremovexattr(const char *path, const char *name); [[gnu::weak]] int sys_fremovexattr(int fd, const char *name); +[[gnu::weak]] int sys_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); + } // namespace mlibc #endif // MLIBX_LINUX_SYSDEPS diff --git a/options/posix/generic/sched-stubs.cpp b/options/posix/generic/sched-stubs.cpp index e27aed9f43..acda6c69d5 100644 --- a/options/posix/generic/sched-stubs.cpp +++ b/options/posix/generic/sched-stubs.cpp @@ -17,15 +17,6 @@ int sched_yield(void) { return 0; } -int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask) { - MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getaffinity, -1); - if(int e = mlibc::sys_getaffinity(pid, cpusetsize, mask); e) { - errno = e; - return -1; - } - return 0; -} - int sched_get_priority_max(int) { __ensure(!"Not implemented"); __builtin_unreachable(); @@ -61,31 +52,11 @@ int __mlibc_cpu_count(const cpu_set_t *set) { return count; } -int unshare(int) { - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - -int clone(int (*)(void *), void *, int, void *, ...) { - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - int sched_setscheduler(pid_t, int, const struct sched_param *) { __ensure(!"Not implemented"); __builtin_unreachable(); } -int sched_setaffinity(pid_t, size_t, const cpu_set_t *) { - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - -int sched_getscheduler(pid_t) { - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - int sched_getparam(pid_t, struct sched_param *) { __ensure(!"Not implemented"); __builtin_unreachable(); diff --git a/options/posix/include/mlibc/posix-sysdeps.hpp b/options/posix/include/mlibc/posix-sysdeps.hpp index 4c33a751ec..3617407151 100644 --- a/options/posix/include/mlibc/posix-sysdeps.hpp +++ b/options/posix/include/mlibc/posix-sysdeps.hpp @@ -95,7 +95,6 @@ int sys_close(int fd); [[gnu::weak]] int sys_setegid(gid_t egid); [[gnu::weak]] int sys_getgroups(size_t size, const gid_t *list, int *ret); [[gnu::weak]] void sys_yield(); -[[gnu::weak]] int sys_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); [[gnu::weak]] int sys_sleep(time_t *secs, long *nanos); [[gnu::weak]] int sys_fork(pid_t *child); [[gnu::weak]] int sys_clone(void *tcb, pid_t *pid_out, void *stack); diff --git a/options/posix/include/sched.h b/options/posix/include/sched.h index 9dfff0b10c..0e39fce7ca 100644 --- a/options/posix/include/sched.h +++ b/options/posix/include/sched.h @@ -11,30 +11,6 @@ // MISSING: POSIX [PS], [SS] and [TSP] options -#define CLONE_VM 0x00000100 -#define CLONE_FS 0x00000200 -#define CLONE_FILES 0x00000400 -#define CLONE_SIGHAND 0x00000800 -#define CLONE_PTRACE 0x00002000 -#define CLONE_VFORK 0x00004000 -#define CLONE_PARENT 0x00008000 -#define CLONE_THREAD 0x00010000 -#define CLONE_NEWNS 0x00020000 -#define CLONE_SYSVSEM 0x00040000 -#define CLONE_SETTLS 0x00080000 -#define CLONE_PARENT_SETTID 0x00100000 -#define CLONE_CHILD_CLEARTID 0x00200000 -#define CLONE_DETACHED 0x00400000 -#define CLONE_UNTRACED 0x00800000 -#define CLONE_CHILD_SETTID 0x01000000 -#define CLONE_NEWCGROUP 0x02000000 -#define CLONE_NEWUTS 0x04000000 -#define CLONE_NEWIPC 0x08000000 -#define CLONE_NEWUSER 0x10000000 -#define CLONE_NEWPID 0x20000000 -#define CLONE_NEWNET 0x40000000 -#define CLONE_IO 0x80000000 - #define CPU_SETSIZE 128 #define CPU_ISSET __mlibc_cpu_isset #define CPU_COUNT __mlibc_cpu_count @@ -57,25 +33,16 @@ struct sched_param { int sched_yield(void); -int sched_getscheduler(pid_t pid); -int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); - int sched_get_priority_max(int policy); int sched_get_priority_min(int policy); -int unshare(int flags); - int __mlibc_cpu_isset(int cpu, cpu_set_t *set); int __mlibc_cpu_count(const cpu_set_t *set); int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param); -int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask); int sched_getparam(pid_t pid, struct sched_param *param); -// Linux extension -int clone(int (*)(void *), void *, int, void *, ...); - #if __MLIBC_LINUX_OPTION #include #endif From 77958544f5c415f4a76a5a3d4ca21d09da9c351b Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 3 Apr 2023 20:21:48 +0200 Subject: [PATCH 4/8] options/linux: set up header for CPU_* macros Co-authored-by: Dennis Bonke --- options/linux/include/bits/linux/cpu_set.h | 15 +++++++++++++++ options/linux/meson.build | 1 + options/posix/include/sched.h | 11 +++++------ 3 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 options/linux/include/bits/linux/cpu_set.h diff --git a/options/linux/include/bits/linux/cpu_set.h b/options/linux/include/bits/linux/cpu_set.h new file mode 100644 index 0000000000..6b1f7f8932 --- /dev/null +++ b/options/linux/include/bits/linux/cpu_set.h @@ -0,0 +1,15 @@ +#ifndef _LINUX_CPU_SET_H +#define _LINUX_CPU_SET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#ifdef __cplusplus +} +#endif + +#endif /* _LINUX_CPU_SET_H */ diff --git a/options/linux/meson.build b/options/linux/meson.build index 1e491c8ebd..8c6473face 100644 --- a/options/linux/meson.build +++ b/options/linux/meson.build @@ -46,6 +46,7 @@ if not no_headers install_headers( 'include/bits/linux/linux_unistd.h', 'include/bits/linux/linux_sched.h', + 'include/bits/linux/cpu_set.h', subdir: 'bits/linux' ) install_headers( diff --git a/options/posix/include/sched.h b/options/posix/include/sched.h index 0e39fce7ca..08cab35352 100644 --- a/options/posix/include/sched.h +++ b/options/posix/include/sched.h @@ -3,7 +3,6 @@ #define _SCHED_H #include -#include #include #include @@ -11,7 +10,6 @@ // MISSING: POSIX [PS], [SS] and [TSP] options -#define CPU_SETSIZE 128 #define CPU_ISSET __mlibc_cpu_isset #define CPU_COUNT __mlibc_cpu_count @@ -19,6 +17,11 @@ extern "C" { #endif +#if __MLIBC_LINUX_OPTION +#include +#include +#endif + #define SCHED_OTHER 0 #define SCHED_FIFO 1 #define SCHED_RR 2 @@ -43,10 +46,6 @@ int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param); int sched_getparam(pid_t pid, struct sched_param *param); -#if __MLIBC_LINUX_OPTION -#include -#endif - #ifdef __cplusplus } #endif From 53c0ed063250e7003b0d73a308020f6cd6c8e902 Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 3 Apr 2023 20:38:35 +0200 Subject: [PATCH 5/8] options/linux: add CPU_* (de)allocation macros --- options/linux/generic/cpuset.cpp | 15 +++++++++++++++ options/linux/include/bits/linux/cpu_set.h | 9 +++++++++ options/linux/meson.build | 1 + 3 files changed, 25 insertions(+) create mode 100644 options/linux/generic/cpuset.cpp diff --git a/options/linux/generic/cpuset.cpp b/options/linux/generic/cpuset.cpp new file mode 100644 index 0000000000..a35548016d --- /dev/null +++ b/options/linux/generic/cpuset.cpp @@ -0,0 +1,15 @@ +#include +#include +#include + +cpu_set_t *__mlibc_cpu_alloc(int num_cpus) { + return reinterpret_cast(calloc(1, CPU_ALLOC_SIZE(num_cpus))); +} + +#define CPU_MASK_BITS (CHAR_BIT * sizeof(__cpu_mask)) + +size_t __mlibc_cpu_alloc_size(int num_cpus) { + /* calculate the (unaligned) remainder that doesn't neatly fit in one __cpu_mask; 0 or 1 */ + size_t remainder = ((num_cpus % CPU_MASK_BITS) + CPU_MASK_BITS - 1) / CPU_MASK_BITS; + return sizeof(__cpu_mask) * (num_cpus / CPU_MASK_BITS + remainder); +} diff --git a/options/linux/include/bits/linux/cpu_set.h b/options/linux/include/bits/linux/cpu_set.h index 6b1f7f8932..49a8f33164 100644 --- a/options/linux/include/bits/linux/cpu_set.h +++ b/options/linux/include/bits/linux/cpu_set.h @@ -6,7 +6,16 @@ extern "C" { #endif #include +#include #include +#include + +cpu_set_t *__mlibc_cpu_alloc(int num_cpus); +size_t __mlibc_cpu_alloc_size(int num_cpus); + +#define CPU_ALLOC_SIZE(n) __mlibc_cpu_alloc_size((n)) +#define CPU_ALLOC(n) __mlibc_cpu_alloc((n)) +#define CPU_FREE(set) free((set)) #ifdef __cplusplus } diff --git a/options/linux/meson.build b/options/linux/meson.build index 8c6473face..871dc2c07d 100644 --- a/options/linux/meson.build +++ b/options/linux/meson.build @@ -28,6 +28,7 @@ libc_sources += files( 'generic/sys-klog.cpp', 'generic/sched.cpp', 'generic/sys-quota.cpp', + 'generic/cpuset.cpp', ) if not no_headers From 944f63918824c7f706bf2718e8429c03ca386045 Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 3 Apr 2023 20:53:28 +0200 Subject: [PATCH 6/8] options/linux: add CPU_* manipulation macros --- options/linux/generic/cpuset.cpp | 56 ++++++++++++++++++++++ options/linux/include/bits/linux/cpu_set.h | 21 ++++++++ options/posix/generic/sched-stubs.cpp | 19 -------- options/posix/include/sched.h | 6 --- 4 files changed, 77 insertions(+), 25 deletions(-) diff --git a/options/linux/generic/cpuset.cpp b/options/linux/generic/cpuset.cpp index a35548016d..d0292b7633 100644 --- a/options/linux/generic/cpuset.cpp +++ b/options/linux/generic/cpuset.cpp @@ -1,6 +1,7 @@ #include #include #include +#include cpu_set_t *__mlibc_cpu_alloc(int num_cpus) { return reinterpret_cast(calloc(1, CPU_ALLOC_SIZE(num_cpus))); @@ -13,3 +14,58 @@ size_t __mlibc_cpu_alloc_size(int num_cpus) { size_t remainder = ((num_cpus % CPU_MASK_BITS) + CPU_MASK_BITS - 1) / CPU_MASK_BITS; return sizeof(__cpu_mask) * (num_cpus / CPU_MASK_BITS + remainder); } + +void __mlibc_cpu_zero(const size_t setsize, cpu_set_t *set) { + memset(set, 0, CPU_ALLOC_SIZE(setsize)); +} + +void __mlibc_cpu_set(const int cpu, const size_t setsize, cpu_set_t *set) { + if(cpu >= static_cast(setsize * CHAR_BIT)) { + return; + } + + unsigned char *ptr = reinterpret_cast(set); + size_t off = cpu / CHAR_BIT; + size_t mask = 1 << (cpu % CHAR_BIT); + + ptr[off] |= mask; +} + +void __mlibc_cpu_clear(const int cpu, const size_t setsize, cpu_set_t *set) { + if(cpu >= static_cast(setsize * CHAR_BIT)) { + return; + } + + unsigned char *ptr = reinterpret_cast(set); + size_t off = cpu / CHAR_BIT; + size_t mask = 1 << (cpu % CHAR_BIT); + + ptr[off] &= ~mask; +} + + +int __mlibc_cpu_isset(const int cpu, const size_t setsize, const cpu_set_t *set) { + if(cpu >= static_cast(setsize * CHAR_BIT)) { + return false; + } + + const unsigned char *ptr = reinterpret_cast(set); + size_t off = cpu / CHAR_BIT; + size_t mask = 1 << (cpu % CHAR_BIT); + + return (ptr[off] & mask); +} + +int __mlibc_cpu_count(const size_t setsize, const cpu_set_t *set) { + size_t count = 0; + const unsigned char *ptr = reinterpret_cast(set); + + for(size_t i = 0; i < setsize; i++) { + for(size_t bit = 0; bit < CHAR_BIT; bit++) { + if((1 << bit) & ptr[i]) + count++; + } + } + + return count; +} diff --git a/options/linux/include/bits/linux/cpu_set.h b/options/linux/include/bits/linux/cpu_set.h index 49a8f33164..53a12f9969 100644 --- a/options/linux/include/bits/linux/cpu_set.h +++ b/options/linux/include/bits/linux/cpu_set.h @@ -13,10 +13,31 @@ extern "C" { cpu_set_t *__mlibc_cpu_alloc(int num_cpus); size_t __mlibc_cpu_alloc_size(int num_cpus); +void __mlibc_cpu_zero(const size_t setsize, cpu_set_t *set); +void __mlibc_cpu_set(const int cpu, const size_t setsize, cpu_set_t *set); +void __mlibc_cpu_clear(const int cpu, const size_t setsize, cpu_set_t *set); +int __mlibc_cpu_isset(const int cpu, const size_t setsize, const cpu_set_t *set); +int __mlibc_cpu_count(const size_t setsize, const cpu_set_t *set); + #define CPU_ALLOC_SIZE(n) __mlibc_cpu_alloc_size((n)) #define CPU_ALLOC(n) __mlibc_cpu_alloc((n)) #define CPU_FREE(set) free((set)) +#define CPU_ZERO_S(setsize, set) __mlibc_cpu_zero((setsize), (set)) +#define CPU_ZERO(set) CPU_ZERO_S(sizeof(cpu_set_t), set) + +#define CPU_SET_S(cpu, setsize, set) __mlibc_cpu_set((cpu), (setsize), (set)) +#define CPU_SET(cpu, set) CPU_ZERO_S(cpu, sizeof(cpu_set_t), set) + +#define CPU_CLR_S(cpu, setsize, set) __mlibc_cpu_clear((cpu), (setsize), (set)) +#define CPU_CLR(cpu, set) CPU_CLR_S(cpu, sizeof(cpu_set_t), set) + +#define CPU_ISSET_S(cpu, setsize, set) __mlibc_cpu_isset((cpu), (setsize), (set)) +#define CPU_ISSET(cpu, set) CPU_ISSET_S(cpu, sizeof(cpu_set_t), set) + +#define CPU_COUNT_S(setsize, set) __mlibc_cpu_count((setsize), (set)) +#define CPU_COUNT(set) CPU_COUNT_S(sizeof(cpu_set_t), set) + #ifdef __cplusplus } #endif diff --git a/options/posix/generic/sched-stubs.cpp b/options/posix/generic/sched-stubs.cpp index acda6c69d5..64e7bdfcc5 100644 --- a/options/posix/generic/sched-stubs.cpp +++ b/options/posix/generic/sched-stubs.cpp @@ -33,25 +33,6 @@ int sched_get_priority_min(int policy) { return res; } -int __mlibc_cpu_isset(int, cpu_set_t *) { - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - -int __mlibc_cpu_count(const cpu_set_t *set) { - size_t count = 0; - const unsigned char *ptr = reinterpret_cast(set); - - for(size_t i = 0; i < sizeof(cpu_set_t); i++) { - for(size_t bit = 0; bit < CHAR_BIT; bit++) { - if((1 << bit) & ptr[i]) - count++; - } - } - - return count; -} - int sched_setscheduler(pid_t, int, const struct sched_param *) { __ensure(!"Not implemented"); __builtin_unreachable(); diff --git a/options/posix/include/sched.h b/options/posix/include/sched.h index 08cab35352..f2c53e3b18 100644 --- a/options/posix/include/sched.h +++ b/options/posix/include/sched.h @@ -10,9 +10,6 @@ // MISSING: POSIX [PS], [SS] and [TSP] options -#define CPU_ISSET __mlibc_cpu_isset -#define CPU_COUNT __mlibc_cpu_count - #ifdef __cplusplus extern "C" { #endif @@ -39,9 +36,6 @@ int sched_yield(void); int sched_get_priority_max(int policy); int sched_get_priority_min(int policy); -int __mlibc_cpu_isset(int cpu, cpu_set_t *set); -int __mlibc_cpu_count(const cpu_set_t *set); - int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param); int sched_getparam(pid_t pid, struct sched_param *param); From df429ee2b26fbeb77504b046b7a8dd893809c425 Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 3 Apr 2023 20:55:11 +0200 Subject: [PATCH 7/8] tests/linux: add CPU_* macros test --- tests/linux/cpuset.c | 27 +++++++++++++++++++++++++++ tests/meson.build | 1 + 2 files changed, 28 insertions(+) create mode 100644 tests/linux/cpuset.c diff --git a/tests/linux/cpuset.c b/tests/linux/cpuset.c new file mode 100644 index 0000000000..3f5573251a --- /dev/null +++ b/tests/linux/cpuset.c @@ -0,0 +1,27 @@ +#include +#include +#include + +#define SET_SIZE 15 + +int main() { + cpu_set_t *set = CPU_ALLOC(SET_SIZE); + size_t setsize = CPU_ALLOC_SIZE(SET_SIZE); + + CPU_ZERO_S(setsize, set); + + assert(!CPU_ISSET_S(11, setsize, set)); + + CPU_SET_S(11, setsize, set); + assert(CPU_ISSET_S(11, setsize, set)); + assert(CPU_COUNT_S(setsize, set) == 1); + + assert(!CPU_ISSET_S(CPU_SETSIZE - 1, setsize, set)); + + CPU_CLR_S(11, setsize, set); + assert(!CPU_ISSET_S(11, setsize, set)); + + CPU_FREE(set); + + return 0; +} diff --git a/tests/meson.build b/tests/meson.build index 9cfd073bce..516c2560ce 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -93,6 +93,7 @@ all_test_cases = [ 'linux/xattr', 'linux/pthread_setname_np', 'linux/pthread_attr', + 'linux/cpuset', ] if host_machine.system() == 'linux' From 38af3c88fb9658f09243ee5f7de88d72268b7721 Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 3 Apr 2023 22:09:32 +0200 Subject: [PATCH 8/8] tests: fix random pthread_attr test failures --- tests/linux/pthread_attr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/linux/pthread_attr.c b/tests/linux/pthread_attr.c index b1b13ba150..4c1907c054 100644 --- a/tests/linux/pthread_attr.c +++ b/tests/linux/pthread_attr.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -72,7 +73,7 @@ static void test_getattrnp() { // Check that we can read from the highest byte returned. // pthread_getattr_np() should return the lowest byte // of the stack. - assert(!*(char*)(stack + other_stacksize - 1)); + printf("highest byte: %hhu\n", *(char *)(stack + other_stacksize - 1)); pthread_attr_destroy(&attr); }