From d4b5a9b14e186df1bd1d4ce2f6da2388a0f56198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 7 Nov 2008 12:22:05 +0000 Subject: [PATCH] * The kernel daemon now uses a recursive lock instead of a mutex. This fixes bug #3082. * Also, it now allows to remove daemons in their hook function. * Added a "daemons" KDL command that dumps all registered kernel daemons, and resource resizers. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28550 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/kernel_daemon.cpp | 94 +++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 13 deletions(-) diff --git a/src/system/kernel/kernel_daemon.cpp b/src/system/kernel/kernel_daemon.cpp index 44e2a35fe1..4aa3f53bed 100644 --- a/src/system/kernel/kernel_daemon.cpp +++ b/src/system/kernel/kernel_daemon.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -42,12 +43,15 @@ public: int frequency); status_t Unregister(daemon_hook function, void* arg); + void Dump(); + private: static status_t _DaemonThreadEntry(void* data); + struct daemon* _NextDaemon(struct daemon& marker); status_t _DaemonThread(); private: - mutex fLock; + recursive_lock fLock; DaemonList fDaemons; thread_id fThread; }; @@ -60,8 +64,7 @@ static KernelDaemon sResourceResizer; status_t KernelDaemon::Init(const char* name) { - new(&fDaemons) DaemonList; - mutex_init(&fLock, name); + recursive_lock_init(&fLock, name); fThread = spawn_kernel_thread(&_DaemonThreadEntry, name, B_LOW_PRIORITY, this); @@ -88,7 +91,7 @@ KernelDaemon::Register(daemon_hook function, void* arg, int frequency) daemon->arg = arg; daemon->frequency = frequency; - MutexLocker _(fLock); + RecursiveLocker _(fLock); if (frequency > 1) { // we try to balance the work-load for each daemon run @@ -114,7 +117,7 @@ KernelDaemon::Register(daemon_hook function, void* arg, int frequency) status_t KernelDaemon::Unregister(daemon_hook function, void* arg) { - MutexLocker _(fLock); + RecursiveLocker _(fLock); DaemonList::Iterator iterator = fDaemons.GetIterator(); @@ -134,6 +137,31 @@ KernelDaemon::Unregister(daemon_hook function, void* arg) } +void +KernelDaemon::Dump() +{ + DaemonList::Iterator iterator = fDaemons.GetIterator(); + + while (iterator.HasNext()) { + struct daemon* daemon = iterator.Next(); + const char *symbol, *imageName; + bool exactMatch; + + status_t status = elf_debug_lookup_symbol_address( + (addr_t)daemon->function, NULL, &symbol, &imageName, &exactMatch); + if (status == B_OK && exactMatch) { + if (strchr(imageName, '/') != NULL) + imageName = strrchr(imageName, '/') + 1; + + kprintf("\t%s:%s (%p), arg %p\n", imageName, symbol, + daemon->function, daemon->arg); + } else { + kprintf("\t%p, arg %p\n", daemon->function, daemon->arg); + } + } +} + + /*static*/ status_t KernelDaemon::_DaemonThreadEntry(void* data) { @@ -141,24 +169,44 @@ KernelDaemon::_DaemonThreadEntry(void* data) } +struct daemon* +KernelDaemon::_NextDaemon(struct daemon& marker) +{ + struct daemon* daemon; + + if (marker.GetDoublyLinkedListLink()->next == NULL + && marker.GetDoublyLinkedListLink()->previous == NULL + && fDaemons.Head() != &marker) { + // Marker is not part of the list yet, just return the first entry + daemon = fDaemons.Head(); + } else { + daemon = marker.GetDoublyLinkedListLink()->next; + fDaemons.Remove(&marker); + } + + if (daemon != NULL) + fDaemons.Insert(daemon->GetDoublyLinkedListLink()->next, &marker); + + return daemon; +} + + status_t KernelDaemon::_DaemonThread() { + struct daemon marker; int32 iteration = 0; while (true) { - mutex_lock(&fLock); - - DaemonList::Iterator iterator = fDaemons.GetIterator(); + RecursiveLocker locker(fLock); // iterate through the list and execute each daemon if needed - while (iterator.HasNext()) { - struct daemon* daemon = iterator.Next(); - + while (struct daemon* daemon = _NextDaemon(marker)) { if (((iteration + daemon->offset) % daemon->frequency) == 0) daemon->function(daemon->arg, iteration); } - mutex_unlock(&fLock); + + locker.Unlock(); iteration++; snooze(100000); // 0.1 seconds @@ -171,6 +219,22 @@ KernelDaemon::_DaemonThread() // #pragma mark - +static int +dump_daemons(int argc, char** argv) +{ + kprintf("kernel daemons:\n"); + sKernelDaemon.Dump(); + + kprintf("\nresource resizers:\n"); + sResourceResizer.Dump(); + + return 0; +} + + +// #pragma mark - + + extern "C" status_t register_kernel_daemon(daemon_hook function, void* arg, int frequency) { @@ -199,6 +263,9 @@ unregister_resource_resizer(daemon_hook function, void* arg) } +// #pragma mark - + + extern "C" status_t kernel_daemon_init(void) { @@ -210,5 +277,6 @@ kernel_daemon_init(void) if (sResourceResizer.Init("resource resizer") != B_OK) panic("kernel_daemon_init(): failed to init resource resizer"); + add_debugger_command("daemons", dump_daemons, "Shows registered kernel daemons."); return B_OK; }