020ac56840
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
194 lines
3.2 KiB
C++
194 lines
3.2 KiB
C++
/*
|
|
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
|
* 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
|