[haiku-commits] r34702 - in haiku/trunk/src: add-ons/kernel/drivers/disk/scsi/scsi_cd add-ons/kernel/drivers/disk/scsi/scsi_disk system/kernel/device_manager

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 19 Dec 2009 15:32:14 +0100 (CET)

Author: bonefish
Date: 2009-12-19 15:32:14 +0100 (Sat, 19 Dec 2009)
New Revision: 34702
Changeset: http://dev.haiku-os.org/changeset/34702/haiku

Modified:
   haiku/trunk/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/Jamfile
   haiku/trunk/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/Jamfile
   haiku/trunk/src/system/kernel/device_manager/IOScheduler.cpp
   haiku/trunk/src/system/kernel/device_manager/IOScheduler.h
Log:
* Implemented missing cleanup when an IOScheduler is destroyed. The threads
  weren't terminated orderly.
* IOScheduler now stores its name and gets a unique ID.
* Added IOSchedulerRoster singleton which registers all IOSchedulers. It also
  provides a notification service. We generate interesting events for
  IOSchedulers, IORequests, and IOOperations.


Modified: haiku/trunk/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/Jamfile
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/Jamfile    
2009-12-19 14:23:44 UTC (rev 34701)
+++ haiku/trunk/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/Jamfile    
2009-12-19 14:32:14 UTC (rev 34702)
@@ -1,6 +1,7 @@
 SubDir HAIKU_TOP src add-ons kernel drivers disk scsi scsi_cd ;
 
-UsePrivateHeaders drivers kernel ;
+UsePrivateKernelHeaders ;
+UsePrivateHeaders drivers ;
 SubDirHdrs $(HAIKU_TOP) src system kernel device_manager ;
 
 KernelAddon scsi_cd :

Modified: haiku/trunk/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/Jamfile
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/Jamfile  
2009-12-19 14:23:44 UTC (rev 34701)
+++ haiku/trunk/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/Jamfile  
2009-12-19 14:32:14 UTC (rev 34702)
@@ -1,6 +1,7 @@
 SubDir HAIKU_TOP src add-ons kernel drivers disk scsi scsi_disk ;
 
-UsePrivateHeaders drivers kernel ;
+UsePrivateKernelHeaders ;
+UsePrivateHeaders drivers ;
 SubDirHdrs $(HAIKU_TOP) src system kernel device_manager ;
 
 KernelAddon scsi_disk :

Modified: haiku/trunk/src/system/kernel/device_manager/IOScheduler.cpp
===================================================================
--- haiku/trunk/src/system/kernel/device_manager/IOScheduler.cpp        
2009-12-19 14:23:44 UTC (rev 34701)
+++ haiku/trunk/src/system/kernel/device_manager/IOScheduler.cpp        
2009-12-19 14:32:14 UTC (rev 34702)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
  * Copyright 2004-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
  * Distributed under the terms of the MIT License.
  */
@@ -30,6 +30,9 @@
 #endif
 
 
+// #pragma mark - IOCallback
+
+
 IOCallback::~IOCallback()
 {
 }
@@ -99,21 +102,51 @@
 IOScheduler::IOScheduler(DMAResource* resource)
        :
        fDMAResource(resource),
+       fName(NULL),
+       fID(-1),
+       fSchedulerThread(-1),
+       fRequestNotifierThread(-1),
        fOperationArray(NULL),
        fAllocatedRequestOwners(NULL),
        fRequestOwners(NULL),
        fBlockSize(0),
-       fPendingOperations(0)
+       fPendingOperations(0),
+       fTerminating(false)
 {
        mutex_init(&fLock, "I/O scheduler");
        B_INITIALIZE_SPINLOCK(&fFinisherLock);
+
+       fNewRequestCondition.Init(this, "I/O new request");
+       fFinishedOperationCondition.Init(this, "I/O finished operation");
+       fFinishedRequestCondition.Init(this, "I/O finished request");
+
 }
 
 
 IOScheduler::~IOScheduler()
 {
-       // TODO: Shutdown threads.
+       if (InitCheck() == B_OK)
+               IOSchedulerRoster::Default()->RemoveScheduler(this);
 
+       // shutdown threads
+       MutexLocker locker(fLock);
+       InterruptsSpinLocker finisherLocker(fFinisherLock);
+       fTerminating = true;
+
+       fNewRequestCondition.NotifyAll();
+       fFinishedOperationCondition.NotifyAll();
+       fFinishedRequestCondition.NotifyAll();
+
+       finisherLocker.Unlock();
+       locker.Unlock();
+
+       if (fSchedulerThread >= 0)
+               wait_for_thread(fSchedulerThread, NULL);
+
+       if (fRequestNotifierThread >= 0)
+               wait_for_thread(fRequestNotifierThread, NULL);
+
+       // destroy our belongings
        mutex_lock(&fLock);
        mutex_destroy(&fLock);
 
@@ -124,15 +157,17 @@
 
        delete fRequestOwners;
        delete[] fAllocatedRequestOwners;
+
+       free(fName);
 }
 
 
 status_t
 IOScheduler::Init(const char* name)
 {
-       fNewRequestCondition.Init(this, "I/O new request");
-       fFinishedOperationCondition.Init(this, "I/O finished operation");
-       fFinishedRequestCondition.Init(this, "I/O finished request");
+       fName = strdup(name);
+       if (fName == NULL)
+               return B_NO_MEMORY;
 
        size_t count = fDMAResource != NULL ? fDMAResource->BufferCount() : 16;
        for (size_t i = 0; i < count; i++) {
@@ -195,10 +230,20 @@
 
        resume_thread(fSchedulerThread);
        resume_thread(fRequestNotifierThread);
+
+       IOSchedulerRoster::Default()->AddScheduler(this);
+
        return B_OK;
 }
 
 
+status_t
+IOScheduler::InitCheck() const
+{
+       return fRequestNotifierThread >= 0 ? B_OK : B_NO_INIT;
+}
+
+
 void
 IOScheduler::SetCallback(IOCallback& callback)
 {
@@ -259,6 +304,9 @@
        if (!wasActive)
                fActiveRequestOwners.Add(owner);
 
+       IOSchedulerRoster::Default()->Notify(IO_SCHEDULER_REQUEST_SCHEDULED, 
this,
+               request);
+
        fNewRequestCondition.NotifyAll();
 
        return B_OK;
@@ -325,7 +373,14 @@
 
                TRACE("IOScheduler::_Finisher(): operation: %p\n", operation);
 
-               if (!operation->Finish()) {
+               bool operationFinished = operation->Finish();
+
+               
IOSchedulerRoster::Default()->Notify(IO_SCHEDULER_OPERATION_FINISHED,
+                       this, operation->Parent(), operation);
+                       // Notify for every time the operation is passed to the 
I/O hook,
+                       // not only when it is fully finished.
+
+               if (!operationFinished) {
                        TRACE("  operation: %p not finished yet\n", operation);
                        MutexLocker _(fLock);
                        operation->SetTransferredBytes(0);
@@ -379,6 +434,8 @@
                                        fFinishedRequestCondition.NotifyAll();
                                } else {
                                        // No callbacks -- finish the request 
right now.
+                                       IOSchedulerRoster::Default()->Notify(
+                                               IO_SCHEDULER_REQUEST_FINISHED, 
this, request);
                                        request->NotifyFinished();
                                }
                        }
@@ -472,10 +529,13 @@
 }
 
 
-void
+bool
 IOScheduler::_NextActiveRequestOwner(IORequestOwner*& owner, off_t& quantum)
 {
        while (true) {
+               if (fTerminating)
+                       return false;
+
                if (owner != NULL)
                        owner = fActiveRequestOwners.GetNext(owner);
                if (owner == NULL)
@@ -483,7 +543,7 @@
 
                if (owner != NULL) {
                        quantum = 
_ComputeRequestOwnerBandwidth(owner->priority);
-                       return;
+                       return true;
                }
 
                // Wait for new requests owners. First check whether any 
finisher work
@@ -579,7 +639,7 @@
        IORequestOwner* owner = NULL;
        off_t quantum = 0;
 
-       while (true) {
+       while (!fTerminating) {
 //dprintf("IOScheduler::_Scheduler(): next iteration: request owner: %p, 
quantum: %lld\n", owner, quantum);
                MutexLocker locker(fLock);
 
@@ -594,8 +654,12 @@
                        fActiveRequestOwners.Remove(&marker);
                }
 
-               if (owner == NULL || quantum < fBlockSize)
-                       _NextActiveRequestOwner(owner, quantum);
+               if (owner == NULL || quantum < fBlockSize) {
+                       if (!_NextActiveRequestOwner(owner, quantum)) {
+                               // we've been asked to terminate
+                               return B_OK;
+                       }
+               }
 
                while (resourcesAvailable && iterationBandwidth >= fBlockSize) {
 //dprintf("IOScheduler::_Scheduler(): request owner: %p (thread %ld)\n",
@@ -673,13 +737,16 @@
                        TRACE("IOScheduler::_Scheduler(): calling callback for "
                                "operation %ld: %p\n", i++, operation);
 
+                       
IOSchedulerRoster::Default()->Notify(IO_SCHEDULER_OPERATION_STARTED,
+                               this, operation->Parent(), operation);
+
                        fIOCallback(fIOCallbackData, operation);
 
                        _Finisher();
                }
 
                // wait for all operations to finish
-               while (true) {
+               while (!fTerminating) {
                        locker.Lock();
 
                        if (fPendingOperations == 0)
@@ -729,6 +796,9 @@
                IORequest* request = fFinishedRequests.RemoveHead();
 
                if (request == NULL) {
+                       if (fTerminating)
+                               return B_OK;
+
                        ConditionVariableEntry entry;
                        fFinishedRequestCondition.Add(&entry);
 
@@ -740,6 +810,9 @@
 
                locker.Unlock();
 
+               
IOSchedulerRoster::Default()->Notify(IO_SCHEDULER_REQUEST_FINISHED,
+                       this, request);
+
                // notify the request
                request->NotifyFinished();
        }
@@ -796,3 +869,72 @@
        return ((IOCallback*)data)->DoIO(operation);
 }
 
+
+// #pragma mark - IOSchedulerNotificationService
+
+
+/*static*/ IOSchedulerRoster IOSchedulerRoster::sDefaultInstance;
+
+
+/*static*/ void
+IOSchedulerRoster::Init()
+{
+       new(&sDefaultInstance) IOSchedulerRoster;
+}
+
+
+void
+IOSchedulerRoster::AddScheduler(IOScheduler* scheduler)
+{
+       AutoLocker<IOSchedulerRoster> locker(this);
+       scheduler->SetID(fNextID++);
+       fSchedulers.Add(scheduler);
+       locker.Unlock();
+
+       Notify(IO_SCHEDULER_ADDED, scheduler);
+}
+
+
+void
+IOSchedulerRoster::RemoveScheduler(IOScheduler* scheduler)
+{
+       AutoLocker<IOSchedulerRoster> locker(this);
+       fSchedulers.Remove(scheduler);
+       locker.Unlock();
+
+       Notify(IO_SCHEDULER_REMOVED, scheduler);
+}
+
+
+void
+IOSchedulerRoster::Notify(uint32 eventCode, const IOScheduler* scheduler,
+       IORequest* request, IOOperation* operation)
+{
+       char eventBuffer[128];
+       KMessage event;
+       event.SetTo(eventBuffer, sizeof(eventBuffer), IO_SCHEDULER_MONITOR);
+       event.AddInt32("event", eventCode);
+       event.AddPointer("scheduler", scheduler);
+       if (request != NULL) {
+               event.AddPointer("request", request);
+               if (operation != NULL)
+                       event.AddPointer("operation", operation);
+       }
+
+       fNotificationService.Notify(event, eventCode);
+}
+
+
+IOSchedulerRoster::IOSchedulerRoster()
+       :
+       fNextID(1),
+       fNotificationService("I/O")
+{
+       mutex_init(&fLock, "IOSchedulerRoster");
+}
+
+
+IOSchedulerRoster::~IOSchedulerRoster()
+{
+       mutex_destroy(&fLock);
+}

Modified: haiku/trunk/src/system/kernel/device_manager/IOScheduler.h
===================================================================
--- haiku/trunk/src/system/kernel/device_manager/IOScheduler.h  2009-12-19 
14:23:44 UTC (rev 34701)
+++ haiku/trunk/src/system/kernel/device_manager/IOScheduler.h  2009-12-19 
14:32:14 UTC (rev 34702)
@@ -1,15 +1,17 @@
 /*
- * Copyright 2008, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
  * Copyright 2004-2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
  * Distributed under the terms of the MIT License.
  */
 #ifndef IO_SCHEDULER_H
 #define IO_SCHEDULER_H
 
+
 #include <KernelExport.h>
 
 #include <condition_variable.h>
 #include <lock.h>
+#include <Notifications.h>
 #include <util/DoublyLinkedList.h>
 #include <util/OpenHashTable.h>
 
@@ -17,6 +19,16 @@
 #include "IORequest.h"
 
 
+// I/O scheduler notifications
+#define IO_SCHEDULER_MONITOR                   '_io_'
+#define IO_SCHEDULER_ADDED                             0x01
+#define IO_SCHEDULER_REMOVED                   0x02
+#define IO_SCHEDULER_REQUEST_SCHEDULED 0x04
+#define IO_SCHEDULER_REQUEST_FINISHED  0x08
+#define IO_SCHEDULER_OPERATION_STARTED 0x10
+#define IO_SCHEDULER_OPERATION_FINISHED        0x20
+
+
 class IOCallback {
 public:
        virtual                                         ~IOCallback();
@@ -45,12 +57,13 @@
 };
 
 
-class IOScheduler {
+class IOScheduler : public DoublyLinkedListLinkImpl<IOScheduler> {
 public:
                                                                
IOScheduler(DMAResource* resource);
                                                                ~IOScheduler();
 
                        status_t                        Init(const char* name);
+                       status_t                        InitCheck() const;
 
                        void                            SetCallback(IOCallback& 
callback);
                        void                            SetCallback(io_callback 
callback, void* data);
@@ -65,6 +78,11 @@
                                                                        // has 
been completed successfully or failed
                                                                        // for 
some reason
 
+                       const char*                     Name() const    { 
return fName; }
+
+                       int32                           ID() const              
{ return fID; }
+                       void                            SetID(int32 id) { fID = 
id; }
+
                        void                            Dump() const;
 
 private:
@@ -77,7 +95,7 @@
                        bool                            _FinisherWorkPending();
                        off_t                           
_ComputeRequestOwnerBandwidth(
                                                                        int32 
priority) const;
-                       void                            
_NextActiveRequestOwner(IORequestOwner*& owner,
+                       bool                            
_NextActiveRequestOwner(IORequestOwner*& owner,
                                                                        off_t& 
quantum);
                        bool                            
_PrepareRequestOperations(IORequest* request,
                                                                        
IOOperationList& operations,
@@ -102,6 +120,8 @@
 
 private:
                        DMAResource*            fDMAResource;
+                       char*                           fName;
+                       int32                           fID;
                        spinlock                        fFinisherLock;
                        mutex                           fLock;
                        thread_id                       fSchedulerThread;
@@ -126,6 +146,45 @@
                        off_t                           fIterationBandwidth;
                        off_t                           fMinOwnerBandwidth;
                        off_t                           fMaxOwnerBandwidth;
+       volatile bool                           fTerminating;
 };
 
+typedef DoublyLinkedList<IOScheduler> IOSchedulerList;
+
+
+class IOSchedulerRoster {
+public:
+       static  void                            Init();
+       static  IOSchedulerRoster*      Default()       { return 
&sDefaultInstance; }
+
+                       bool                            Lock()  { return 
mutex_lock(&fLock) == B_OK; }
+                       void                            Unlock()        { 
mutex_unlock(&fLock); }
+
+                       const IOSchedulerList& SchedulerList() const
+                                                                       { 
return fSchedulers; }
+                                                                       // 
caller must keep the roster locked,
+                                                                       // 
while accessing the list
+
+                       void                            
AddScheduler(IOScheduler* scheduler);
+                       void                            
RemoveScheduler(IOScheduler* scheduler);
+
+                       void                            Notify(uint32 eventCode,
+                                                                       const 
IOScheduler* scheduler,
+                                                                       
IORequest* request = NULL,
+                                                                       
IOOperation* operation = NULL);
+
+private:
+                                                               
IOSchedulerRoster();
+                                                               
~IOSchedulerRoster();
+
+private:
+                       mutex                           fLock;
+                       int32                           fNextID;
+                       IOSchedulerList         fSchedulers;
+                       DefaultNotificationService fNotificationService;
+
+       static  IOSchedulerRoster       sDefaultInstance;
+};
+
+
 #endif // IO_SCHEDULER_H


Other related posts:

  • » [haiku-commits] r34702 - in haiku/trunk/src: add-ons/kernel/drivers/disk/scsi/scsi_cd add-ons/kernel/drivers/disk/scsi/scsi_disk system/kernel/device_manager - ingo_weinhold