[haiku-commits] r36209 - haiku/trunk/src/system/kernel

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 13 Apr 2010 14:09:56 +0200 (CEST)

Author: axeld
Date: 2010-04-13 14:09:56 +0200 (Tue, 13 Apr 2010)
New Revision: 36209
Changeset: http://dev.haiku-os.org/changeset/36209/haiku
Ticket: http://dev.haiku-os.org/ticket/5421

Modified:
   haiku/trunk/src/system/kernel/kernel_daemon.cpp
Log:
* The kernel daemon no longer hold its lock when calling the registered hooks.
* This fixes bug #5421.


Modified: haiku/trunk/src/system/kernel/kernel_daemon.cpp
===================================================================
--- haiku/trunk/src/system/kernel/kernel_daemon.cpp     2010-04-13 11:25:15 UTC 
(rev 36208)
+++ haiku/trunk/src/system/kernel/kernel_daemon.cpp     2010-04-13 12:09:56 UTC 
(rev 36209)
@@ -29,6 +29,7 @@
        void*           arg;
        int32           frequency;
        int32           offset;
+       bool            executing;
 };
 
 
@@ -49,11 +50,14 @@
        static  status_t                        _DaemonThreadEntry(void* data);
                        struct daemon*          _NextDaemon(struct daemon& 
marker);
                        status_t                        _DaemonThread();
+                       bool                            _IsDaemon() const;
 
 private:
                        recursive_lock          fLock;
                        DaemonList                      fDaemons;
                        thread_id                       fThread;
+                       ConditionVariable       fUnregisterCondition;
+                       int32                           fUnregisterWaiters;
 };
 
 
@@ -72,6 +76,7 @@
                return fThread;
 
        send_signal_etc(fThread, SIGCONT, B_DO_NOT_RESCHEDULE);
+       fUnregisterCondition.Init(this, name);
 
        return B_OK;
 }
@@ -90,6 +95,7 @@
        daemon->function = function;
        daemon->arg = arg;
        daemon->frequency = frequency;
+       daemon->executing = false;
 
        RecursiveLocker _(fLock);
 
@@ -117,7 +123,7 @@
 status_t
 KernelDaemon::Unregister(daemon_hook function, void* arg)
 {
-       RecursiveLocker _(fLock);
+       RecursiveLocker locker(fLock);
 
        DaemonList::Iterator iterator = fDaemons.GetIterator();
 
@@ -127,6 +133,22 @@
 
                if (daemon->function == function && daemon->arg == arg) {
                        // found it!
+                       if (!_IsDaemon()) {
+                               // wait if it's busy
+                               while (daemon->executing) {
+                                       fUnregisterWaiters++;
+
+                                       ConditionVariableEntry entry;
+                                       fUnregisterCondition.Add(&entry);
+
+                                       locker.Unlock();
+
+                                       entry.Wait();
+                                       
+                                       locker.Lock();
+                               }
+                       }
+
                        iterator.Remove();
                        delete daemon;
                        return B_OK;
@@ -154,11 +176,12 @@
                        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);
-               }
+                       kprintf("\t%s:%s (%p)", imageName, symbol, 
daemon->function);
+               } else
+                       kprintf("\t%p", daemon->function);
+
+               kprintf(", arg %p%s\n", daemon->arg,
+                       daemon->executing ? " (running) " : "");
        }
 }
 
@@ -205,10 +228,21 @@
 
                // iterate through the list and execute each daemon if needed
                while (struct daemon* daemon = _NextDaemon(marker)) {
+                       daemon->executing = true;
+                       locker.Unlock();
+
                        if (((iteration + daemon->offset) % daemon->frequency) 
== 0)
                                daemon->function(daemon->arg, iteration);
+
+                       locker.Lock();
+                       daemon->executing = false;
                }
 
+               if (fUnregisterWaiters != 0) {
+                       fUnregisterCondition.NotifyAll();
+                       fUnregisterWaiters = 0;
+               }
+
                locker.Unlock();
 
                iteration++;
@@ -219,9 +253,16 @@
 }
 
 
-//     #pragma mark -
+bool
+KernelDaemon::_IsDaemon() const
+{
+       return find_thread(NULL) == fThread;
+}
 
 
+// #pragma mark -
+
+
 static int
 dump_daemons(int argc, char** argv)
 {


Other related posts:

  • » [haiku-commits] r36209 - haiku/trunk/src/system/kernel - axeld