1 /* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef IO_SCHEDULER_H 7 #define IO_SCHEDULER_H 8 9 #include <KernelExport.h> 10 11 #include <condition_variable.h> 12 #include <lock.h> 13 #include <util/DoublyLinkedList.h> 14 #include <util/OpenHashTable.h> 15 16 #include "dma_resources.h" 17 #include "IORequest.h" 18 19 20 class IOCallback { 21 public: 22 virtual ~IOCallback(); 23 24 virtual status_t DoIO(IOOperation* operation) = 0; 25 }; 26 27 typedef status_t (*io_callback)(void* data, io_operation* operation); 28 29 30 struct IORequestOwner : DoublyLinkedListLinkImpl<IORequestOwner> { 31 team_id team; 32 thread_id thread; 33 int32 priority; 34 IORequestList requests; 35 IORequestList completed_requests; 36 IOOperationList operations; 37 IORequestOwner* hash_link; 38 39 bool IsActive() const 40 { return !requests.IsEmpty() 41 || !completed_requests.IsEmpty() 42 || !operations.IsEmpty(); } 43 44 void Dump() const; 45 }; 46 47 48 class IOScheduler { 49 public: 50 IOScheduler(DMAResource* resource); 51 ~IOScheduler(); 52 53 status_t Init(const char* name); 54 55 void SetCallback(IOCallback& callback); 56 void SetCallback(io_callback callback, void* data); 57 58 status_t ScheduleRequest(IORequest* request); 59 60 void AbortRequest(IORequest* request, 61 status_t status = B_CANCELED); 62 void OperationCompleted(IOOperation* operation, 63 status_t status, size_t transferredBytes); 64 // called by the driver when the operation 65 // has been completed successfully or failed 66 // for some reason 67 68 void Dump() const; 69 70 private: 71 typedef DoublyLinkedList<IORequestOwner> RequestOwnerList; 72 73 struct RequestOwnerHashDefinition; 74 struct RequestOwnerHashTable; 75 76 void _Finisher(); 77 bool _FinisherWorkPending(); 78 off_t _ComputeRequestOwnerBandwidth( 79 int32 priority) const; 80 void _NextActiveRequestOwner(IORequestOwner*& owner, 81 off_t& quantum); 82 bool _PrepareRequestOperations(IORequest* request, 83 IOOperationList& operations, 84 int32& operationsPrepared); 85 bool _PrepareRequestOperations(IORequest* request, 86 IOOperationList& operations, 87 int32& operationsPrepared, off_t quantum, 88 off_t& usedBandwidth); 89 void _SortOperations(IOOperationList& operations, 90 off_t& lastOffset); 91 status_t _Scheduler(); 92 static status_t _SchedulerThread(void* self); 93 status_t _RequestNotifier(); 94 static status_t _RequestNotifierThread(void* self); 95 96 void _AddRequestOwner(IORequestOwner* owner); 97 IORequestOwner* _GetRequestOwner(team_id team, thread_id thread, 98 bool allocate); 99 100 static status_t _IOCallbackWrapper(void* data, 101 io_operation* operation); 102 103 private: 104 DMAResource* fDMAResource; 105 spinlock fFinisherLock; 106 mutex fLock; 107 thread_id fSchedulerThread; 108 thread_id fRequestNotifierThread; 109 io_callback fIOCallback; 110 void* fIOCallbackData; 111 IORequestList fUnscheduledRequests; 112 IORequestList fFinishedRequests; 113 ConditionVariable fNewRequestCondition; 114 ConditionVariable fFinishedOperationCondition; 115 ConditionVariable fFinishedRequestCondition; 116 IOOperation** fOperationArray; 117 IOOperationList fUnusedOperations; 118 IOOperationList fCompletedOperations; 119 IORequestOwner* fAllocatedRequestOwners; 120 int32 fAllocatedRequestOwnerCount; 121 RequestOwnerList fActiveRequestOwners; 122 RequestOwnerList fUnusedRequestOwners; 123 RequestOwnerHashTable* fRequestOwners; 124 size_t fBlockSize; 125 int32 fPendingOperations; 126 off_t fIterationBandwidth; 127 off_t fMinOwnerBandwidth; 128 off_t fMaxOwnerBandwidth; 129 }; 130 131 #endif // IO_SCHEDULER_H 132