xref: /haiku/src/system/kernel/device_manager/IOScheduler.h (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
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