* 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. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34702 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel drivers disk scsi scsi_cd ;
|
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 ;
|
SubDirHdrs $(HAIKU_TOP) src system kernel device_manager ;
|
||||||
|
|
||||||
KernelAddon scsi_cd :
|
KernelAddon scsi_cd :
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel drivers disk scsi scsi_disk ;
|
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 ;
|
SubDirHdrs $(HAIKU_TOP) src system kernel device_manager ;
|
||||||
|
|
||||||
KernelAddon scsi_disk :
|
KernelAddon scsi_disk :
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008, Ingo Weinhold, [email protected].
|
* Copyright 2008-2009, Ingo Weinhold, [email protected].
|
||||||
* Copyright 2004-2009, Axel Dörfler, [email protected].
|
* Copyright 2004-2009, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -30,6 +30,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - IOCallback
|
||||||
|
|
||||||
|
|
||||||
IOCallback::~IOCallback()
|
IOCallback::~IOCallback()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -99,21 +102,51 @@ struct IOScheduler::RequestOwnerHashTable
|
|||||||
IOScheduler::IOScheduler(DMAResource* resource)
|
IOScheduler::IOScheduler(DMAResource* resource)
|
||||||
:
|
:
|
||||||
fDMAResource(resource),
|
fDMAResource(resource),
|
||||||
|
fName(NULL),
|
||||||
|
fID(-1),
|
||||||
|
fSchedulerThread(-1),
|
||||||
|
fRequestNotifierThread(-1),
|
||||||
fOperationArray(NULL),
|
fOperationArray(NULL),
|
||||||
fAllocatedRequestOwners(NULL),
|
fAllocatedRequestOwners(NULL),
|
||||||
fRequestOwners(NULL),
|
fRequestOwners(NULL),
|
||||||
fBlockSize(0),
|
fBlockSize(0),
|
||||||
fPendingOperations(0)
|
fPendingOperations(0),
|
||||||
|
fTerminating(false)
|
||||||
{
|
{
|
||||||
mutex_init(&fLock, "I/O scheduler");
|
mutex_init(&fLock, "I/O scheduler");
|
||||||
B_INITIALIZE_SPINLOCK(&fFinisherLock);
|
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()
|
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_lock(&fLock);
|
||||||
mutex_destroy(&fLock);
|
mutex_destroy(&fLock);
|
||||||
|
|
||||||
@@ -124,15 +157,17 @@ IOScheduler::~IOScheduler()
|
|||||||
|
|
||||||
delete fRequestOwners;
|
delete fRequestOwners;
|
||||||
delete[] fAllocatedRequestOwners;
|
delete[] fAllocatedRequestOwners;
|
||||||
|
|
||||||
|
free(fName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
IOScheduler::Init(const char* name)
|
IOScheduler::Init(const char* name)
|
||||||
{
|
{
|
||||||
fNewRequestCondition.Init(this, "I/O new request");
|
fName = strdup(name);
|
||||||
fFinishedOperationCondition.Init(this, "I/O finished operation");
|
if (fName == NULL)
|
||||||
fFinishedRequestCondition.Init(this, "I/O finished request");
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
size_t count = fDMAResource != NULL ? fDMAResource->BufferCount() : 16;
|
size_t count = fDMAResource != NULL ? fDMAResource->BufferCount() : 16;
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
@@ -195,10 +230,20 @@ IOScheduler::Init(const char* name)
|
|||||||
|
|
||||||
resume_thread(fSchedulerThread);
|
resume_thread(fSchedulerThread);
|
||||||
resume_thread(fRequestNotifierThread);
|
resume_thread(fRequestNotifierThread);
|
||||||
|
|
||||||
|
IOSchedulerRoster::Default()->AddScheduler(this);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
IOScheduler::InitCheck() const
|
||||||
|
{
|
||||||
|
return fRequestNotifierThread >= 0 ? B_OK : B_NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
IOScheduler::SetCallback(IOCallback& callback)
|
IOScheduler::SetCallback(IOCallback& callback)
|
||||||
{
|
{
|
||||||
@@ -259,6 +304,9 @@ IOScheduler::ScheduleRequest(IORequest* request)
|
|||||||
if (!wasActive)
|
if (!wasActive)
|
||||||
fActiveRequestOwners.Add(owner);
|
fActiveRequestOwners.Add(owner);
|
||||||
|
|
||||||
|
IOSchedulerRoster::Default()->Notify(IO_SCHEDULER_REQUEST_SCHEDULED, this,
|
||||||
|
request);
|
||||||
|
|
||||||
fNewRequestCondition.NotifyAll();
|
fNewRequestCondition.NotifyAll();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -325,7 +373,14 @@ IOScheduler::_Finisher()
|
|||||||
|
|
||||||
TRACE("IOScheduler::_Finisher(): operation: %p\n", operation);
|
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);
|
TRACE(" operation: %p not finished yet\n", operation);
|
||||||
MutexLocker _(fLock);
|
MutexLocker _(fLock);
|
||||||
operation->SetTransferredBytes(0);
|
operation->SetTransferredBytes(0);
|
||||||
@@ -379,6 +434,8 @@ IOScheduler::_Finisher()
|
|||||||
fFinishedRequestCondition.NotifyAll();
|
fFinishedRequestCondition.NotifyAll();
|
||||||
} else {
|
} else {
|
||||||
// No callbacks -- finish the request right now.
|
// No callbacks -- finish the request right now.
|
||||||
|
IOSchedulerRoster::Default()->Notify(
|
||||||
|
IO_SCHEDULER_REQUEST_FINISHED, this, request);
|
||||||
request->NotifyFinished();
|
request->NotifyFinished();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -472,10 +529,13 @@ IOScheduler::_ComputeRequestOwnerBandwidth(int32 priority) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
bool
|
||||||
IOScheduler::_NextActiveRequestOwner(IORequestOwner*& owner, off_t& quantum)
|
IOScheduler::_NextActiveRequestOwner(IORequestOwner*& owner, off_t& quantum)
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
|
if (fTerminating)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (owner != NULL)
|
if (owner != NULL)
|
||||||
owner = fActiveRequestOwners.GetNext(owner);
|
owner = fActiveRequestOwners.GetNext(owner);
|
||||||
if (owner == NULL)
|
if (owner == NULL)
|
||||||
@@ -483,7 +543,7 @@ IOScheduler::_NextActiveRequestOwner(IORequestOwner*& owner, off_t& quantum)
|
|||||||
|
|
||||||
if (owner != NULL) {
|
if (owner != NULL) {
|
||||||
quantum = _ComputeRequestOwnerBandwidth(owner->priority);
|
quantum = _ComputeRequestOwnerBandwidth(owner->priority);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for new requests owners. First check whether any finisher work
|
// Wait for new requests owners. First check whether any finisher work
|
||||||
@@ -579,7 +639,7 @@ IOScheduler::_Scheduler()
|
|||||||
IORequestOwner* owner = NULL;
|
IORequestOwner* owner = NULL;
|
||||||
off_t quantum = 0;
|
off_t quantum = 0;
|
||||||
|
|
||||||
while (true) {
|
while (!fTerminating) {
|
||||||
//dprintf("IOScheduler::_Scheduler(): next iteration: request owner: %p, quantum: %lld\n", owner, quantum);
|
//dprintf("IOScheduler::_Scheduler(): next iteration: request owner: %p, quantum: %lld\n", owner, quantum);
|
||||||
MutexLocker locker(fLock);
|
MutexLocker locker(fLock);
|
||||||
|
|
||||||
@@ -594,8 +654,12 @@ IOScheduler::_Scheduler()
|
|||||||
fActiveRequestOwners.Remove(&marker);
|
fActiveRequestOwners.Remove(&marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (owner == NULL || quantum < fBlockSize)
|
if (owner == NULL || quantum < fBlockSize) {
|
||||||
_NextActiveRequestOwner(owner, quantum);
|
if (!_NextActiveRequestOwner(owner, quantum)) {
|
||||||
|
// we've been asked to terminate
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (resourcesAvailable && iterationBandwidth >= fBlockSize) {
|
while (resourcesAvailable && iterationBandwidth >= fBlockSize) {
|
||||||
//dprintf("IOScheduler::_Scheduler(): request owner: %p (thread %ld)\n",
|
//dprintf("IOScheduler::_Scheduler(): request owner: %p (thread %ld)\n",
|
||||||
@@ -673,13 +737,16 @@ panic("no more requests for owner %p (thread %ld)", owner, owner->thread);
|
|||||||
TRACE("IOScheduler::_Scheduler(): calling callback for "
|
TRACE("IOScheduler::_Scheduler(): calling callback for "
|
||||||
"operation %ld: %p\n", i++, operation);
|
"operation %ld: %p\n", i++, operation);
|
||||||
|
|
||||||
|
IOSchedulerRoster::Default()->Notify(IO_SCHEDULER_OPERATION_STARTED,
|
||||||
|
this, operation->Parent(), operation);
|
||||||
|
|
||||||
fIOCallback(fIOCallbackData, operation);
|
fIOCallback(fIOCallbackData, operation);
|
||||||
|
|
||||||
_Finisher();
|
_Finisher();
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for all operations to finish
|
// wait for all operations to finish
|
||||||
while (true) {
|
while (!fTerminating) {
|
||||||
locker.Lock();
|
locker.Lock();
|
||||||
|
|
||||||
if (fPendingOperations == 0)
|
if (fPendingOperations == 0)
|
||||||
@@ -729,6 +796,9 @@ IOScheduler::_RequestNotifier()
|
|||||||
IORequest* request = fFinishedRequests.RemoveHead();
|
IORequest* request = fFinishedRequests.RemoveHead();
|
||||||
|
|
||||||
if (request == NULL) {
|
if (request == NULL) {
|
||||||
|
if (fTerminating)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
ConditionVariableEntry entry;
|
ConditionVariableEntry entry;
|
||||||
fFinishedRequestCondition.Add(&entry);
|
fFinishedRequestCondition.Add(&entry);
|
||||||
|
|
||||||
@@ -740,6 +810,9 @@ IOScheduler::_RequestNotifier()
|
|||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
|
IOSchedulerRoster::Default()->Notify(IO_SCHEDULER_REQUEST_FINISHED,
|
||||||
|
this, request);
|
||||||
|
|
||||||
// notify the request
|
// notify the request
|
||||||
request->NotifyFinished();
|
request->NotifyFinished();
|
||||||
}
|
}
|
||||||
@@ -796,3 +869,72 @@ IOScheduler::_IOCallbackWrapper(void* data, io_operation* operation)
|
|||||||
return ((IOCallback*)data)->DoIO(operation);
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008, Ingo Weinhold, [email protected].
|
* Copyright 2008-2009, Ingo Weinhold, [email protected].
|
||||||
* Copyright 2004-2008, Axel Dörfler, [email protected].
|
* Copyright 2004-2008, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef IO_SCHEDULER_H
|
#ifndef IO_SCHEDULER_H
|
||||||
#define IO_SCHEDULER_H
|
#define IO_SCHEDULER_H
|
||||||
|
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
#include <condition_variable.h>
|
#include <condition_variable.h>
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
|
#include <Notifications.h>
|
||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
#include <util/OpenHashTable.h>
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
@@ -17,6 +19,16 @@
|
|||||||
#include "IORequest.h"
|
#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 {
|
class IOCallback {
|
||||||
public:
|
public:
|
||||||
virtual ~IOCallback();
|
virtual ~IOCallback();
|
||||||
@@ -45,12 +57,13 @@ struct IORequestOwner : DoublyLinkedListLinkImpl<IORequestOwner> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class IOScheduler {
|
class IOScheduler : public DoublyLinkedListLinkImpl<IOScheduler> {
|
||||||
public:
|
public:
|
||||||
IOScheduler(DMAResource* resource);
|
IOScheduler(DMAResource* resource);
|
||||||
~IOScheduler();
|
~IOScheduler();
|
||||||
|
|
||||||
status_t Init(const char* name);
|
status_t Init(const char* name);
|
||||||
|
status_t InitCheck() const;
|
||||||
|
|
||||||
void SetCallback(IOCallback& callback);
|
void SetCallback(IOCallback& callback);
|
||||||
void SetCallback(io_callback callback, void* data);
|
void SetCallback(io_callback callback, void* data);
|
||||||
@@ -65,6 +78,11 @@ public:
|
|||||||
// has been completed successfully or failed
|
// has been completed successfully or failed
|
||||||
// for some reason
|
// for some reason
|
||||||
|
|
||||||
|
const char* Name() const { return fName; }
|
||||||
|
|
||||||
|
int32 ID() const { return fID; }
|
||||||
|
void SetID(int32 id) { fID = id; }
|
||||||
|
|
||||||
void Dump() const;
|
void Dump() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -77,7 +95,7 @@ private:
|
|||||||
bool _FinisherWorkPending();
|
bool _FinisherWorkPending();
|
||||||
off_t _ComputeRequestOwnerBandwidth(
|
off_t _ComputeRequestOwnerBandwidth(
|
||||||
int32 priority) const;
|
int32 priority) const;
|
||||||
void _NextActiveRequestOwner(IORequestOwner*& owner,
|
bool _NextActiveRequestOwner(IORequestOwner*& owner,
|
||||||
off_t& quantum);
|
off_t& quantum);
|
||||||
bool _PrepareRequestOperations(IORequest* request,
|
bool _PrepareRequestOperations(IORequest* request,
|
||||||
IOOperationList& operations,
|
IOOperationList& operations,
|
||||||
@@ -102,6 +120,8 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
DMAResource* fDMAResource;
|
DMAResource* fDMAResource;
|
||||||
|
char* fName;
|
||||||
|
int32 fID;
|
||||||
spinlock fFinisherLock;
|
spinlock fFinisherLock;
|
||||||
mutex fLock;
|
mutex fLock;
|
||||||
thread_id fSchedulerThread;
|
thread_id fSchedulerThread;
|
||||||
@@ -126,6 +146,45 @@ private:
|
|||||||
off_t fIterationBandwidth;
|
off_t fIterationBandwidth;
|
||||||
off_t fMinOwnerBandwidth;
|
off_t fMinOwnerBandwidth;
|
||||||
off_t fMaxOwnerBandwidth;
|
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
|
#endif // IO_SCHEDULER_H
|
||||||
|
|||||||
Reference in New Issue
Block a user