Changed the way how CPU activity is monitored: instead of taking the active

time of the idle thread as a measure, we now compute the CPU activity on
each thread switch - the time the CPU worked is the total of user and kernel
time a thread spent during its quantum.
Unlike before, this mechanism works correctly on SMP machines. I hope this
works as expected :)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16193 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-02-01 20:03:55 +00:00
parent a5fa64b505
commit d14aab0dca
7 changed files with 63 additions and 41 deletions
+7
View File
@@ -23,6 +23,12 @@ typedef union cpu_ent {
// thread.c: used to force a reschedule at quantum expiration time
int preempted;
timer quantum_timer;
// keeping track of CPU activity
bigtime_t active_time;
bigtime_t last_kernel_time;
bigtime_t last_user_time;
bool disabled;
} info;
} cpu_ent __attribute__((aligned(64)));
@@ -39,6 +45,7 @@ status_t cpu_preboot_init(struct kernel_args *args);
status_t cpu_init(struct kernel_args *args);
status_t cpu_init_post_vm(struct kernel_args *args);
status_t cpu_init_post_modules(struct kernel_args *args);
bigtime_t cpu_get_active_time(int32 cpu);
cpu_ent *get_cpu_struct(void);
extern inline cpu_ent *get_cpu_struct(void) { return &gCPU[smp_get_current_cpu()]; }
+8 -3
View File
@@ -34,7 +34,6 @@ status_t thread_per_cpu_init(int32 cpuNum);
void thread_yield(void);
void thread_exit(void);
bigtime_t thread_get_active_cpu_time(int32 cpuNum);
int32 thread_max_threads(void);
int32 thread_used_threads(void);
@@ -47,8 +46,14 @@ static thread_id thread_get_current_thread_id(void);
static inline thread_id
thread_get_current_thread_id(void)
{
struct thread *t = thread_get_current_thread();
return t ? t->id : 0;
struct thread *thread = thread_get_current_thread();
return thread ? thread->id : 0;
}
static inline bool
thread_is_idle_thread(struct thread *thread)
{
return thread->entry == NULL;
}
thread_id allocate_thread_id(void);
+1 -1
View File
@@ -25,7 +25,7 @@ KernelMergeObject kernel_core.o :
module.c
port.c
real_time_clock.c
scheduler.c
scheduler.cpp
sem.c
shutdown.c
signal.c
+26 -2
View File
@@ -8,9 +8,9 @@
/* This file contains the cpu functions (init, etc). */
#include <kernel.h>
#include <cpu.h>
#include <vm.h>
#include <thread_types.h>
#include <arch/cpu.h>
#include <boot/kernel_args.h>
@@ -58,6 +58,30 @@ cpu_preboot_init(kernel_args *args)
}
bigtime_t
cpu_get_active_time(int32 cpu)
{
bigtime_t activeTime;
cpu_status state;
if (cpu < 0 || cpu > smp_get_num_cpus())
return 0;
// We need to grab the thread lock here, because the thread activity
// time is not maintained atomically (because there is no need to)
state = disable_interrupts();
GRAB_THREAD_LOCK();
activeTime = gCPU[cpu].info.active_time;
RELEASE_THREAD_LOCK();
restore_interrupts(state);
return activeTime;
}
void
clear_caches(void *address, size_t length, uint32 flags)
{
@@ -127,11 +127,6 @@ scheduler_remove_from_run_queue(struct thread *thread)
static void
context_switch(struct thread *fromThread, struct thread *toThread)
{
// track kernel time (user time is tracked in thread_at_kernel_entry())
bigtime_t now = system_time();
fromThread->kernel_time += now - fromThread->last_time;
toThread->last_time = now;
toThread->cpu = fromThread->cpu;
fromThread->cpu = NULL;
@@ -223,6 +218,23 @@ scheduler_reschedule(void)
nextThread->state = B_THREAD_RUNNING;
nextThread->next_state = B_THREAD_READY;
// track kernel time (user time is tracked in thread_at_kernel_entry())
bigtime_t now = system_time();
oldThread->kernel_time += now - oldThread->last_time;
nextThread->last_time = now;
// track CPU activity
if (!thread_is_idle_thread(oldThread)) {
oldThread->cpu->info.active_time +=
(oldThread->kernel_time - oldThread->cpu->info.last_kernel_time)
+ (oldThread->user_time - oldThread->cpu->info.last_user_time);
}
if (!thread_is_idle_thread(nextThread)) {
oldThread->cpu->info.last_kernel_time = nextThread->kernel_time;
oldThread->cpu->info.last_user_time = nextThread->user_time;
}
if (nextThread != oldThread || oldThread->cpu->info.preempted) {
bigtime_t quantum = 3000; // ToDo: calculate quantum!
timer *quantumTimer = &oldThread->cpu->info.quantum_timer;
+3 -2
View File
@@ -10,7 +10,7 @@
#include <system_info.h>
#include <arch/system_info.h>
#include <vm.h>
#include <cpu.h>
#include <debug.h>
#include <port.h>
#include <real_time_clock.h>
@@ -18,6 +18,7 @@
#include <smp.h>
#include <team.h>
#include <thread.h>
#include <vm.h>
#include <vm_page.h>
#include <string.h>
@@ -41,7 +42,7 @@ _get_system_info(system_info *info, size_t size)
info->cpu_count = smp_get_num_cpus();
for (i = 0; i < info->cpu_count; i++)
info->cpu_infos[i].active_time = thread_get_active_cpu_time(i);
info->cpu_infos[i].active_time = cpu_get_active_time(i);
// ToDo: Add page_faults
info->max_pages = vm_page_num_pages();
+1 -28
View File
@@ -1281,34 +1281,6 @@ spawn_kernel_thread_etc(thread_func function, const char *name, int32 priority,
}
bigtime_t
thread_get_active_cpu_time(int32 cpuNum)
{
bigtime_t activeTime;
cpu_status state;
if (cpuNum < 0 || cpuNum > B_MAX_CPU_COUNT || sIdleThreads[cpuNum] == NULL)
return 0;
activeTime = system_time();
// we need to grab the thread lock here, because the thread activity
// time is not maintained atomically (because there is no need to)
state = disable_interrupts();
GRAB_THREAD_LOCK();
// TODO: this is wrong - the idle threads are arbitrarly executed by the CPUs
// there is no CPU affinity!
activeTime -= sIdleThreads[cpuNum]->kernel_time;
RELEASE_THREAD_LOCK();
restore_interrupts(state);
return activeTime;
}
int32
thread_max_threads(void)
{
@@ -1371,6 +1343,7 @@ thread_init(kernel_args *args)
thread->next_state = B_THREAD_READY;
sprintf(name, "idle thread %lu kstack", i + 1);
thread->kernel_stack_area = find_area(name);
thread->entry = NULL;
if (get_area_info(thread->kernel_stack_area, &info) != B_OK)
panic("error finding idle kstack area\n");