* Scheduler/wait object listener:
- Moved scheduler listening interface to <listeners.h> and added more
convenient to use templatized notification functions.
- Added a listener mechanism for the wait objects (semaphores, condition
variables, mutex, rw_lock).
* system profiler:
- Hopefully fixed locking issues related to notifying the profiler thread
for good. We still had an inconsistent locking order, since the scheduler
notification callbacks are invoked with the thread lock held and have to
acquire the object lock then, while the other callbacks acquired the object
lock first and as a side effect of ConditionVariable::NotifyOne() acquired
the thread lock. Now we make sure the object lock is the innermost lock.
- Track the number of dropped events due to a full buffer.
_user_system_profiler_next_buffer() returns this count now.
- When scheduling profiling events are requested also listen to wait objects
and generate the respective profiling events. We send those events lazily
and cache the infos to avoid resending an event for the same wait object.
- When starting profiling we do now generate "thread scheduled" events for
the already running threads.
- _user_system_profiler_start(): Check whether the parameters pointer is a
userland address at all.
- The system_profiler_team_added event does now also contain the team's name.
* Added a sem_get_name_unsafe() returning a semaphore's name. It is "unsafe",
since the caller has to ensure that the semaphore exists and continues to
exist as long as the returned name is used.
* Adjusted the "profile" and "scheduling_recorder" according to the system
profiling changes. The latter prints the number of dropped events, now.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30345 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -15,27 +15,6 @@ struct thread;
|
||||
struct SchedulerListener;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
struct SchedulerListener : DoublyLinkedListLinkImpl<SchedulerListener> {
|
||||
virtual ~SchedulerListener();
|
||||
|
||||
virtual void ThreadEnqueuedInRunQueue(
|
||||
struct thread* thread) = 0;
|
||||
virtual void ThreadRemovedFromRunQueue(
|
||||
struct thread* thread) = 0;
|
||||
virtual void ThreadScheduled(struct thread* oldThread,
|
||||
struct thread* newThread) = 0;
|
||||
};
|
||||
|
||||
typedef DoublyLinkedList<SchedulerListener> SchedulerListenerList;
|
||||
extern SchedulerListenerList gSchedulerListeners;
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
|
||||
struct scheduler_ops {
|
||||
void (*enqueue_in_run_queue)(struct thread* thread);
|
||||
void (*reschedule)(void);
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef KERNEL_LISTENERS_H
|
||||
#define KERNEL_LISTENERS_H
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <util/AutoLock.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
|
||||
class ConditionVariable;
|
||||
struct mutex;
|
||||
struct rw_lock;
|
||||
struct thread;
|
||||
|
||||
|
||||
// scheduler listeners
|
||||
|
||||
|
||||
struct SchedulerListener : DoublyLinkedListLinkImpl<SchedulerListener> {
|
||||
virtual ~SchedulerListener();
|
||||
|
||||
virtual void ThreadEnqueuedInRunQueue(
|
||||
struct thread* thread) = 0;
|
||||
virtual void ThreadRemovedFromRunQueue(
|
||||
struct thread* thread) = 0;
|
||||
virtual void ThreadScheduled(struct thread* oldThread,
|
||||
struct thread* newThread) = 0;
|
||||
};
|
||||
|
||||
|
||||
typedef DoublyLinkedList<SchedulerListener> SchedulerListenerList;
|
||||
extern SchedulerListenerList gSchedulerListeners;
|
||||
// guarded by the thread spinlock
|
||||
|
||||
|
||||
template<typename Parameter1>
|
||||
inline void
|
||||
NotifySchedulerListeners(void (SchedulerListener::*hook)(Parameter1),
|
||||
Parameter1 parameter1)
|
||||
{
|
||||
if (!gSchedulerListeners.IsEmpty()) {
|
||||
SchedulerListenerList::Iterator it = gSchedulerListeners.GetIterator();
|
||||
while (SchedulerListener* listener = it.Next())
|
||||
(listener->*hook)(parameter1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Parameter1, typename Parameter2>
|
||||
inline void
|
||||
NotifySchedulerListeners(
|
||||
void (SchedulerListener::*hook)(Parameter1, Parameter2),
|
||||
Parameter1 parameter1, Parameter2 parameter2)
|
||||
{
|
||||
if (!gSchedulerListeners.IsEmpty()) {
|
||||
SchedulerListenerList::Iterator it = gSchedulerListeners.GetIterator();
|
||||
while (SchedulerListener* listener = it.Next())
|
||||
(listener->*hook)(parameter1, parameter2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// wait object listeners
|
||||
|
||||
|
||||
struct WaitObjectListener : DoublyLinkedListLinkImpl<WaitObjectListener> {
|
||||
virtual void SemaphoreCreated(sem_id id,
|
||||
const char* name) = 0;
|
||||
virtual void ConditionVariableInitialized(
|
||||
ConditionVariable* variable) = 0;
|
||||
virtual void MutexInitialized(mutex* lock) = 0;
|
||||
virtual void RWLockInitialized(rw_lock* lock) = 0;
|
||||
};
|
||||
|
||||
typedef DoublyLinkedList<WaitObjectListener> WaitObjectListenerList;
|
||||
extern WaitObjectListenerList gWaitObjectListeners;
|
||||
extern spinlock gWaitObjectListenerLock;
|
||||
|
||||
|
||||
template<typename Parameter1>
|
||||
inline void
|
||||
NotifyWaitObjectListeners(void (WaitObjectListener::*hook)(Parameter1),
|
||||
Parameter1 parameter1)
|
||||
{
|
||||
if (!gWaitObjectListeners.IsEmpty()) {
|
||||
InterruptsSpinLocker locker(gWaitObjectListenerLock);
|
||||
WaitObjectListenerList::Iterator it
|
||||
= gWaitObjectListeners.GetIterator();
|
||||
while (WaitObjectListener* listener = it.Next())
|
||||
(listener->*hook)(parameter1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Parameter1, typename Parameter2>
|
||||
inline void
|
||||
NotifyWaitObjectListeners(
|
||||
void (WaitObjectListener::*hook)(Parameter1, Parameter2),
|
||||
Parameter1 parameter1, Parameter2 parameter2)
|
||||
{
|
||||
if (!gWaitObjectListeners.IsEmpty()) {
|
||||
InterruptsSpinLocker locker(gWaitObjectListenerLock);
|
||||
WaitObjectListenerList::Iterator it
|
||||
= gWaitObjectListeners.GetIterator();
|
||||
while (WaitObjectListener* listener = it.Next())
|
||||
(listener->*hook)(parameter1, parameter2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void add_wait_object_listener(struct WaitObjectListener* listener);
|
||||
void remove_wait_object_listener(struct WaitObjectListener* listener);
|
||||
|
||||
|
||||
#endif // KERNEL_LISTENERS_H
|
||||
@@ -31,6 +31,8 @@ extern status_t deselect_sem(int32 object, struct select_info *info,
|
||||
|
||||
extern sem_id create_sem_etc(int32 count, const char *name, team_id owner);
|
||||
|
||||
extern const char* sem_get_name_unsafe(sem_id id);
|
||||
|
||||
/* user calls */
|
||||
sem_id _user_create_sem(int32 count, const char *name);
|
||||
status_t _user_delete_sem(sem_id id);
|
||||
|
||||
@@ -17,7 +17,8 @@ __BEGIN_DECLS
|
||||
|
||||
status_t _user_system_profiler_start(
|
||||
struct system_profiler_parameters* parameters);
|
||||
status_t _user_system_profiler_next_buffer(size_t bytesRead);
|
||||
status_t _user_system_profiler_next_buffer(size_t bytesRead,
|
||||
uint64* _droppedEvents);
|
||||
status_t _user_system_profiler_stop();
|
||||
|
||||
__END_DECLS
|
||||
|
||||
@@ -393,7 +393,8 @@ extern status_t _kern_clear_debugger_breakpoint(void *address,
|
||||
|
||||
extern status_t _kern_system_profiler_start(
|
||||
struct system_profiler_parameters* parameters);
|
||||
extern status_t _kern_system_profiler_next_buffer(size_t bytesRead);
|
||||
extern status_t _kern_system_profiler_next_buffer(size_t bytesRead,
|
||||
uint64* _droppedEvents);
|
||||
extern status_t _kern_system_profiler_stop();
|
||||
|
||||
/* atomic_* ops (needed for CPUs that don't support them directly) */
|
||||
|
||||
@@ -81,7 +81,8 @@ struct system_profiler_event_header {
|
||||
// B_SYSTEM_PROFILER_TEAM_ADDED
|
||||
struct system_profiler_team_added {
|
||||
team_id team;
|
||||
char args[1];
|
||||
uint16 args_offset;
|
||||
char name[1];
|
||||
};
|
||||
|
||||
// B_SYSTEM_PROFILER_TEAM_REMOVED
|
||||
@@ -127,7 +128,7 @@ struct system_profiler_samples {
|
||||
addr_t samples[0];
|
||||
};
|
||||
|
||||
// B_SYSTEM_PROFILER_THREAD_SCHEDULED,
|
||||
// B_SYSTEM_PROFILER_THREAD_SCHEDULED
|
||||
struct system_profiler_thread_scheduled {
|
||||
bigtime_t time;
|
||||
thread_id thread;
|
||||
@@ -137,14 +138,14 @@ struct system_profiler_thread_scheduled {
|
||||
addr_t previous_thread_wait_object;
|
||||
};
|
||||
|
||||
// B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE,
|
||||
// B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE
|
||||
struct system_profiler_thread_enqueued_in_run_queue {
|
||||
bigtime_t time;
|
||||
thread_id thread;
|
||||
uint8 priority;
|
||||
};
|
||||
|
||||
// B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE,
|
||||
// B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE
|
||||
struct system_profiler_thread_removed_from_run_queue {
|
||||
bigtime_t time;
|
||||
thread_id thread;
|
||||
|
||||
Reference in New Issue
Block a user