kernel & libbsd.so: add getloadavg() and _user_get_loadavg()
the algorithm and reference values are from FreeBSD. Change-Id: Ia74a796e13adce6a70434c7546c25ca3d553f11f Reviewed-on: https://review.haiku-os.org/c/haiku/+/9150 Reviewed-by: waddlesplash <[email protected]> Reviewed-by: Jérôme Duval <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
@@ -30,6 +30,8 @@ int mkstemps(char *templat, int slen);
|
|||||||
long long strtonum(const char *numstr, long long minval,
|
long long strtonum(const char *numstr, long long minval,
|
||||||
long long maxval, const char **errstrp);
|
long long maxval, const char **errstrp);
|
||||||
|
|
||||||
|
int getloadavg(double array[], int size);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ void scheduler_add_listener(struct SchedulerListener* listener);
|
|||||||
void scheduler_remove_listener(struct SchedulerListener* listener);
|
void scheduler_remove_listener(struct SchedulerListener* listener);
|
||||||
|
|
||||||
void scheduler_init(void);
|
void scheduler_init(void);
|
||||||
|
status_t scheduler_loadavg_init();
|
||||||
void scheduler_enable_scheduling(void);
|
void scheduler_enable_scheduling(void);
|
||||||
void scheduler_update_policy(void);
|
void scheduler_update_policy(void);
|
||||||
|
|
||||||
@@ -95,6 +96,9 @@ status_t _user_analyze_scheduling(bigtime_t from, bigtime_t until, void* buffer,
|
|||||||
status_t _user_set_scheduler_mode(int32 mode);
|
status_t _user_set_scheduler_mode(int32 mode);
|
||||||
int32 _user_get_scheduler_mode(void);
|
int32 _user_get_scheduler_mode(void);
|
||||||
|
|
||||||
|
status_t _user_get_loadavg(struct loadavg* info, size_t size);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -62,4 +62,10 @@ struct scheduling_analysis {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct loadavg {
|
||||||
|
uint32 ldavg[3];
|
||||||
|
long fscale;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* _SYSTEM_SCHEDULER_DEFS_H */
|
#endif /* _SYSTEM_SCHEDULER_DEFS_H */
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ struct fd_info;
|
|||||||
struct fd_set;
|
struct fd_set;
|
||||||
struct fs_info;
|
struct fs_info;
|
||||||
struct iovec;
|
struct iovec;
|
||||||
|
struct loadavg;
|
||||||
struct msqid_ds;
|
struct msqid_ds;
|
||||||
struct net_stat;
|
struct net_stat;
|
||||||
struct pollfd;
|
struct pollfd;
|
||||||
@@ -212,6 +213,7 @@ extern bigtime_t _kern_estimate_max_scheduling_latency(thread_id thread);
|
|||||||
|
|
||||||
extern status_t _kern_set_scheduler_mode(int32 mode);
|
extern status_t _kern_set_scheduler_mode(int32 mode);
|
||||||
extern int32 _kern_get_scheduler_mode(void);
|
extern int32 _kern_get_scheduler_mode(void);
|
||||||
|
extern status_t _kern_get_loadavg(struct loadavg* info, size_t size);
|
||||||
|
|
||||||
// user/group functions
|
// user/group functions
|
||||||
extern gid_t _kern_getgid(bool effective);
|
extern gid_t _kern_getgid(bool effective);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
|||||||
explicit_bzero.c
|
explicit_bzero.c
|
||||||
fgetln.c
|
fgetln.c
|
||||||
fts.c
|
fts.c
|
||||||
|
getloadavg.cpp
|
||||||
getpass.c
|
getpass.c
|
||||||
issetugid.c
|
issetugid.c
|
||||||
kqueue.cpp
|
kqueue.cpp
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025, Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <scheduler_defs.h>
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
getloadavg(double loadavg[], int count)
|
||||||
|
{
|
||||||
|
struct loadavg info;
|
||||||
|
|
||||||
|
if (_kern_get_loadavg(&info, sizeof(info)) != B_OK)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
size_t size = min_c((size_t)count, B_COUNT_OF(info.ldavg));
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
loadavg[i] = (double)info.ldavg[i] / info.fscale;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
@@ -70,6 +70,7 @@ KernelMergeObject kernel_core.o :
|
|||||||
power_saving.cpp
|
power_saving.cpp
|
||||||
scheduler.cpp
|
scheduler.cpp
|
||||||
scheduler_cpu.cpp
|
scheduler_cpu.cpp
|
||||||
|
scheduler_load.cpp
|
||||||
scheduler_profiler.cpp
|
scheduler_profiler.cpp
|
||||||
scheduler_thread.cpp
|
scheduler_thread.cpp
|
||||||
scheduler_tracing.cpp
|
scheduler_tracing.cpp
|
||||||
|
|||||||
@@ -313,6 +313,8 @@ main2(void* /*unused*/)
|
|||||||
TRACE("init system notifications\n");
|
TRACE("init system notifications\n");
|
||||||
system_notifications_init();
|
system_notifications_init();
|
||||||
|
|
||||||
|
scheduler_loadavg_init();
|
||||||
|
|
||||||
TRACE("Init modules\n");
|
TRACE("Init modules\n");
|
||||||
boot_splash_set_stage(BOOT_SPLASH_STAGE_1_INIT_MODULES);
|
boot_splash_set_stage(BOOT_SPLASH_STAGE_1_INIT_MODULES);
|
||||||
module_init_post_threads();
|
module_init_post_threads();
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025, Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "scheduler_cpu.h"
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <scheduler_defs.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace Scheduler;
|
||||||
|
|
||||||
|
// load average algorithm from FreeBSD, see kern_sync.c
|
||||||
|
const static int kFShift = 11;
|
||||||
|
const static long kFScale = 1 << kFShift;
|
||||||
|
static struct loadavg sAverageRunnable = {{0, 0, 0}, kFScale};
|
||||||
|
const static uint64 sCExp[3] = {(uint64)(0.9200444146293232 * kFScale),
|
||||||
|
(uint64)(0.9834714538216174 * kFScale), (uint64)(0.9944598480048967 * kFScale)};
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
_LoadavgUpdate(void *data, int iteration)
|
||||||
|
{
|
||||||
|
uint64 threadCount = 0;
|
||||||
|
for (int i = 0; i < gCoreCount; i++)
|
||||||
|
threadCount += gCoreEntries[i].ThreadCount();
|
||||||
|
threadCount--;
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
sAverageRunnable.ldavg[i]
|
||||||
|
= (sCExp[i] * sAverageRunnable.ldavg[i] + threadCount * kFScale * (kFScale - sCExp[i]))
|
||||||
|
>> kFShift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
scheduler_loadavg_init()
|
||||||
|
{
|
||||||
|
register_kernel_daemon(_LoadavgUpdate, NULL, 50);
|
||||||
|
// run the daemon once five second
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Syscalls
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
_user_get_loadavg(struct loadavg* userInfo, size_t size)
|
||||||
|
{
|
||||||
|
if (userInfo == NULL || !IS_USER_ADDRESS(userInfo))
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
if (size != sizeof(struct loadavg))
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (user_memcpy(userInfo, &sAverageRunnable, sizeof(struct loadavg)) < B_OK)
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ SubDir HAIKU_TOP src tests libs bsd ;
|
|||||||
UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility bsd ] : true ;
|
UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility bsd ] : true ;
|
||||||
|
|
||||||
SimpleTest forkpty_test : forkpty.c : libbsd.so ;
|
SimpleTest forkpty_test : forkpty.c : libbsd.so ;
|
||||||
|
SimpleTest getloadavg_test : getloadavg_test.cpp : libbsd.so ;
|
||||||
SimpleTest wait4_test : wait4_test.cpp : libbsd.so ;
|
SimpleTest wait4_test : wait4_test.cpp : libbsd.so ;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025, Jérôme Duval, jerome.duval@gmail.com. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
double loadavg[3];
|
||||||
|
int count = getloadavg(loadavg, 3);
|
||||||
|
if (count == -1)
|
||||||
|
return 1;
|
||||||
|
printf("getloadavg() returned %" PRId32 ", values %f %f %f\n", count, loadavg[0], loadavg[1],
|
||||||
|
loadavg[2]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user