* Fixed bug in the "scheduler" command: The check when a thread was

unscheduled was incorrect.
* Introduced _kern_analyze_scheduling() syscall. It requires scheduler
  kernel tracing to be enabled. It uses the tracing entries for a given
  period of time to do a similar analysis the "scheduler" debugger
  command does (i.e. number of runs, run time, latencies, preemption
  times) for each thread. Additionally the analysis includes for each
  thread how long the thread waited on each locking primitive in total.
* Added kernel tracing for the creation of semaphores and initialization
  of condition variables, mutexes, and rw locks. The enabling macro is
  SCHEDULING_ANALYSIS_TRACING. The only purpose is to provide
  _kern_analyze_scheduling() with more info on the locking primitives
  (the name in particular).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27304 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-09-03 15:10:44 +00:00
parent d5488b7703
commit 020ac56840
8 changed files with 1187 additions and 17 deletions
+7
View File
@@ -6,6 +6,10 @@
#define KERNEL_SCHEDULER_H
#include <SupportDefs.h>
struct scheduling_analysis;
struct thread;
@@ -20,6 +24,9 @@ void scheduler_reschedule(void);
void scheduler_init(void);
void scheduler_start(void);
status_t _user_analyze_scheduling(bigtime_t from, bigtime_t until, void* buffer,
size_t size, struct scheduling_analysis* analysis);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,193 @@
/*
* Copyright 2008, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_SCHEDULING_ANALYSIS_H
#define _KERNEL_SCHEDULING_ANALYSIS_H
#include <tracing.h>
#include <thread_defs.h>
class ConditionVariable;
struct mutex;
struct rw_lock;
#if SCHEDULING_ANALYSIS_TRACING
namespace SchedulingAnalysisTracing {
class WaitObjectTraceEntry : public AbstractTraceEntry {
public:
virtual uint32 Type() const = 0;
virtual void* Object() const = 0;
virtual const char* Name() const = 0;
virtual void* ReferencedObject() const
{
return NULL;
}
};
class CreateSemaphore : public WaitObjectTraceEntry {
public:
CreateSemaphore(sem_id id, const char* name)
:
fID(id),
fName(alloc_tracing_buffer_strcpy(name, 128, false))
{
Initialized();
}
virtual void AddDump(TraceOutput& out)
{
out.Print("sem create \"%s\" -> %ld", fName, fID);
}
virtual uint32 Type() const
{
return THREAD_BLOCK_TYPE_SEMAPHORE;
}
virtual void* Object() const
{
return (void*)(addr_t)fID;
}
virtual const char* Name() const
{
return fName;
}
private:
sem_id fID;
const char* fName;
};
class InitConditionVariable : public WaitObjectTraceEntry {
public:
InitConditionVariable(ConditionVariable* variable, const void* object,
const char* objectType)
:
fVariable(variable),
fObject(object),
fObjectType(alloc_tracing_buffer_strcpy(objectType, 128, false))
{
Initialized();
}
virtual void AddDump(TraceOutput& out)
{
out.Print("cvar init variable %p: object: %p \"%s\"", fVariable,
fObject, fObjectType);
}
virtual uint32 Type() const
{
return THREAD_BLOCK_TYPE_CONDITION_VARIABLE;
}
virtual void* Object() const
{
return fVariable;
}
virtual const char* Name() const
{
return fObjectType;
}
virtual void* ReferencedObject() const
{
return (void*)fObject;
}
private:
ConditionVariable* fVariable;
const void* fObject;
const char* fObjectType;
};
class InitMutex : public WaitObjectTraceEntry {
public:
InitMutex(mutex* lock, const char* name)
:
fMutex(lock),
fName(alloc_tracing_buffer_strcpy(name, 128, false))
{
Initialized();
}
virtual void AddDump(TraceOutput& out)
{
out.Print("mutex init %p: name: \"%s\"", fMutex, fName);
}
virtual uint32 Type() const
{
return THREAD_BLOCK_TYPE_MUTEX;
}
virtual void* Object() const
{
return fMutex;
}
virtual const char* Name() const
{
return fName;
}
private:
mutex* fMutex;
const char* fName;
};
class InitRWLock : public WaitObjectTraceEntry {
public:
InitRWLock(rw_lock* lock, const char* name)
:
fLock(lock),
fName(alloc_tracing_buffer_strcpy(name, 128, false))
{
Initialized();
}
virtual void AddDump(TraceOutput& out)
{
out.Print("rwlock init %p: name: \"%s\"", fLock, fName);
}
virtual uint32 Type() const
{
return THREAD_BLOCK_TYPE_RW_LOCK;
}
virtual void* Object() const
{
return fLock;
}
virtual const char* Name() const
{
return fName;
}
private:
rw_lock* fLock;
const char* fName;
};
} // namespace SchedulingAnalysisTracing
# define T_SCHEDULING_ANALYSIS(x) \
new(std::nothrow) SchedulingAnalysisTracing::x;
#else
# define T_SCHEDULING_ANALYSIS(x) ;
#endif // SCHEDULING_ANALYSIS_TRACING
#endif // _KERNEL_SCHEDULING_ANALYSIS_H
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright 2008, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _SYSTEM_SCHEDULER_DEFS_H
#define _SYSTEM_SCHEDULER_DEFS_H
#include <OS.h>
struct scheduling_analysis_thread_wait_object;
struct scheduling_analysis_thread {
thread_id id;
char name[B_OS_NAME_LENGTH];
int64 runs;
bigtime_t total_run_time;
bigtime_t min_run_time;
bigtime_t max_run_time;
int64 latencies;
bigtime_t total_latency;
bigtime_t min_latency;
bigtime_t max_latency;
int64 reruns;
bigtime_t total_rerun_time;
bigtime_t min_rerun_time;
bigtime_t max_rerun_time;
bigtime_t unspecified_wait_time;
int64 preemptions;
scheduling_analysis_thread_wait_object* wait_objects;
};
struct scheduling_analysis_wait_object {
uint32 type;
void* object;
char name[B_OS_NAME_LENGTH];
void* referenced_object;
};
struct scheduling_analysis_thread_wait_object {
thread_id thread;
scheduling_analysis_wait_object* wait_object;
bigtime_t wait_time;
scheduling_analysis_thread_wait_object* next_in_list;
};
struct scheduling_analysis {
uint32 thread_count;
scheduling_analysis_thread** threads;
uint64 wait_object_count;
uint64 thread_wait_object_count;
};
#endif /* _SYSTEM_SCHEDULER_DEFS_H */
+4
View File
@@ -27,6 +27,7 @@ struct iovec;
struct net_stat;
struct pollfd;
struct rlimit;
struct scheduling_analysis;
struct sigaction;
struct stat;
struct _sem_t;
@@ -394,6 +395,9 @@ extern int64 _kern_atomic_get64(vint64 *value);
/* System informations */
extern status_t _kern_get_system_info(system_info *info, size_t size);
extern status_t _kern_analyze_scheduling(bigtime_t from, bigtime_t until,
void* buffer, size_t size,
struct scheduling_analysis* analysis);
/* Debug output */
extern void _kern_debug_output(const char *message);