gnu: add sched_getcpu()

on x86_64 implemented with rdtscp or rdpid, generically with a syscall.

Change-Id: I8f776848bf35575abec8a8c612c4a25d8550daea
Reviewed-on: https://review.haiku-os.org/c/haiku/+/6866
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
This commit is contained in:
Jérôme Duval 2023-08-21 11:26:11 +02:00 committed by waddlesplash
parent 449929ad0e
commit efbeada748
8 changed files with 161 additions and 0 deletions

View File

@ -0,0 +1,29 @@
/*
* Copyright 2023 Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _GNU_SCHED_H_
#define _GNU_SCHED_H_
#include_next <sched.h>
#ifdef _GNU_SOURCE
#ifdef __cplusplus
extern "C" {
#endif
extern int sched_getcpu(void);
#ifdef __cplusplus
}
#endif
#endif
#endif /* _GNU_SCHED_H_ */

View File

@ -159,6 +159,7 @@ status_t _user_receive_data(thread_id *_sender, void *buffer, size_t buffer_size
thread_id _user_find_thread(const char *name);
status_t _user_get_thread_info(thread_id id, thread_info *info);
status_t _user_get_next_thread_info(team_id team, int32 *cookie, thread_info *info);
int _user_get_cpu();
status_t _user_block_thread(uint32 flags, bigtime_t timeout);
status_t _user_unblock_thread(thread_id thread, status_t status);

View File

@ -196,6 +196,7 @@ extern status_t _kern_get_team_usage_info(team_id team, int32 who,
team_usage_info *info, size_t size);
extern status_t _kern_get_extended_team_info(team_id teamID, uint32 flags,
void* buffer, size_t size, size_t* _sizeNeeded);
extern int _kern_get_cpu();
extern status_t _kern_start_watching_system(int32 object, uint32 flags,
port_id port, int32 token);

View File

@ -10,10 +10,16 @@ SubDirC++Flags [ FDefines _GNU_SOURCE=1 ] ;
local architectureObject ;
for architectureObject in [ MultiArchSubDirSetup ] {
on $(architectureObject) {
UsePrivateSystemHeaders ;
if $(TARGET_ARCH) = x86_64 {
SubDirC++Flags -mrdpid ;
}
SharedLibrary [ MultiArchDefaultGristFiles libgnu.so ] :
crypt.cpp
memmem.c
qsort.c
sched_getcpu.cpp
xattr.cpp
;
}

View File

@ -0,0 +1,90 @@
/*
* Copyright 2023, Jérôme Duval, jerome.duval@gmail.com. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <sched.h>
#include <syscalls.h>
#ifdef __x86_64__
#include <pthread.h>
#include <x86intrin.h>
#define IA32_FEATURE_RDPID (1 << 22) // RDPID Instruction
#define IA32_FEATURE_AMD_EXT_RDTSCP (1 << 27) // rdtscp instruction
typedef int (*sched_cpu_func)();
static pthread_once_t sSchedCpuInitOnce = PTHREAD_ONCE_INIT;
static sched_cpu_func sSchedCpuFunc = NULL;
static int
__sched_cpu_syscall()
{
return _kern_get_cpu();
}
static int
__sched_cpu_rdtscp()
{
uint32_t aux;
__rdtscp(&aux);
return aux;
}
static int
__sched_cpu_rdpid()
{
return _rdpid_u32();
}
static void
initSchedCpuFunc()
{
cpuid_info cpuInfo;
get_cpuid(&cpuInfo, 0, 0);
if (cpuInfo.eax_0.max_eax >= 0x7) {
get_cpuid(&cpuInfo, 0x7, 0);
if ((cpuInfo.regs.ecx & IA32_FEATURE_RDPID) != 0) {
sSchedCpuFunc = __sched_cpu_rdpid;
return;
}
}
get_cpuid(&cpuInfo, 0x80000000, 0);
if (cpuInfo.eax_0.max_eax >= 0x80000001) {
get_cpuid(&cpuInfo, 0x80000001, 0);
if ((cpuInfo.regs.edx & IA32_FEATURE_AMD_EXT_RDTSCP)!= 0) {
sSchedCpuFunc = __sched_cpu_rdtscp;
return;
}
}
sSchedCpuFunc = __sched_cpu_syscall;
}
int
sched_getcpu()
{
if (sSchedCpuFunc == NULL) {
pthread_once(&sSchedCpuInitOnce, &initSchedCpuFunc);
}
return sSchedCpuFunc();
}
#else
int
sched_getcpu()
{
return _kern_get_cpu();
}
#endif

View File

@ -3915,3 +3915,11 @@ _user_setrlimit(int resource, const struct rlimit *userResourceLimit)
return common_setrlimit(resource, &resourceLimit);
}
int
_user_get_cpu()
{
Thread* thread = thread_get_current_thread();
return thread->cpu->cpu_num;
}

View File

@ -0,0 +1,8 @@
SubDir HAIKU_TOP src tests libs gnu ;
UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility gnu ] : true ;
SubDirC++Flags [ FDefines _GNU_SOURCE=1 ] ;
SimpleTest sched_getcpu_test : sched_getcpu_test.cpp : libgnu.so ;

View File

@ -0,0 +1,18 @@
/*
* Copyright 2023, Jérôme Duval, jerome.duval@gmail.com. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <sched.h>
#include <stdio.h>
int
main(int argc, char** argv)
{
int cpu = sched_getcpu();
printf("cpu: %d\n", cpu);
return 0;
}