]>
Commit | Line | Data |
---|---|---|
d9a64523 A |
1 | /* |
2 | * Copyright (c) 2017 Apple Inc. All rights reserved. | |
3 | */ | |
4 | ||
5 | #pragma once | |
6 | ||
7 | #ifdef KERNEL_PRIVATE | |
8 | #ifdef __cplusplus | |
9 | ||
10 | #include <IOKit/IOService.h> | |
11 | ||
12 | struct thread_group; | |
13 | ||
0a7de745 A |
14 | enum{ |
15 | kIOPerfControlClientWorkUntracked = 0, | |
d9a64523 A |
16 | }; |
17 | ||
18 | /*! | |
19 | * @class IOPerfControlClient : public OSObject | |
20 | * @abstract Class which implements an interface allowing device drivers to participate in performance control. | |
21 | * @discussion TODO | |
22 | */ | |
23 | class IOPerfControlClient final : public OSObject | |
24 | { | |
0a7de745 | 25 | OSDeclareDefaultStructors(IOPerfControlClient); |
d9a64523 A |
26 | |
27 | protected: | |
0a7de745 | 28 | virtual bool init(IOService *driver, uint64_t maxWorkCapacity); |
d9a64523 A |
29 | |
30 | public: | |
0a7de745 A |
31 | /*! |
32 | * @function copyClient | |
33 | * @abstract Return a retained reference to a client object, to be released by the driver. It may be | |
34 | * shared with other drivers in the system. | |
35 | * @param driver The device driver that will be using this interface. | |
36 | * @param maxWorkCapacity The maximum number of concurrent work items supported by the device driver. | |
37 | * @returns An instance of IOPerfControlClient. | |
38 | */ | |
39 | static IOPerfControlClient *copyClient(IOService *driver, uint64_t maxWorkCapacity); | |
40 | ||
41 | /*! | |
42 | * @function registerDevice | |
43 | * @abstract Inform the system that work will be dispatched to a device in the future. | |
44 | * @discussion The system will do some one-time setup work associated with the device, and may block the | |
45 | * current thread during the setup. Devices should not be passed to work workSubmit, workSubmitAndBegin, | |
46 | * workBegin, or workEnd until they have been successfully registered. The unregistration process happens | |
47 | * automatically when the device object is deallocated. | |
48 | * @param device The device object. Some platforms require device to be a specific subclass of IOService. | |
49 | * @returns kIOReturnSuccess or an IOReturn error code | |
50 | */ | |
51 | virtual IOReturn registerDevice(IOService *driver, IOService *device); | |
52 | ||
53 | /*! | |
54 | * @function unregisterDevice | |
55 | * @abstract Inform the system that work will be no longer be dispatched to a device in the future. | |
56 | * @discussion This call is optional as the unregistration process happens automatically when the device | |
57 | * object is deallocated. This call may block the current thread and/or acquire locks. It should not be | |
58 | * called until after all submitted work has been ended using workEnd. | |
59 | * @param device The device object. Some platforms require device to be a specific subclass of IOService. | |
60 | */ | |
61 | virtual void unregisterDevice(IOService *driver, IOService *device); | |
62 | ||
63 | /*! | |
64 | * @struct WorkSubmitArgs | |
65 | * @discussion Drivers may submit additional device-specific arguments related to the submission of a work item | |
66 | * by passing a struct with WorkSubmitArgs as its first member. Note: Drivers are responsible for publishing | |
67 | * a header file describing these arguments. | |
68 | */ | |
69 | struct WorkSubmitArgs { | |
70 | uint32_t version; | |
71 | uint32_t size; | |
72 | uint64_t submit_time; | |
73 | uint64_t reserved[4]; | |
74 | void *driver_data; | |
75 | }; | |
76 | ||
77 | /*! | |
78 | * @function workSubmit | |
79 | * @abstract Tell the performance controller that work was submitted. | |
80 | * @param device The device that will execute the work. Some platforms require device to be a | |
81 | * specific subclass of IOService. | |
82 | * @param args Optional device-specific arguments related to the submission of this work item. | |
83 | * @returns A token representing this work item, which must be passed to workEnd when the work is finished | |
84 | * unless the token equals kIOPerfControlClientWorkUntracked. Failure to do this will result in memory leaks | |
85 | * and a degradation of system performance. | |
86 | */ | |
87 | virtual uint64_t workSubmit(IOService *device, WorkSubmitArgs *args = nullptr); | |
88 | ||
89 | /*! | |
90 | * @struct WorkBeginArgs | |
91 | * @discussion Drivers may submit additional device-specific arguments related to the start of a work item | |
92 | * by passing a struct with WorkBeginArgs as its first member. Note: Drivers are responsible for publishing | |
93 | * a header file describing these arguments. | |
94 | */ | |
95 | struct WorkBeginArgs { | |
96 | uint32_t version; | |
97 | uint32_t size; | |
98 | uint64_t begin_time; | |
99 | uint64_t reserved[4]; | |
100 | void *driver_data; | |
101 | }; | |
102 | ||
103 | /*! | |
104 | * @function workSubmitAndBegin | |
105 | * @abstract Tell the performance controller that work was submitted and immediately began executing. | |
106 | * @param device The device that is executing the work. Some platforms require device to be a | |
107 | * specific subclass of IOService. | |
108 | * @param submitArgs Optional device-specific arguments related to the submission of this work item. | |
109 | * @param beginArgs Optional device-specific arguments related to the start of this work item. | |
110 | * @returns A token representing this work item, which must be passed to workEnd when the work is finished | |
111 | * unless the token equals kIOPerfControlClientWorkUntracked. Failure to do this will result in memory leaks | |
112 | * and a degradation of system performance. | |
113 | */ | |
114 | virtual uint64_t workSubmitAndBegin(IOService *device, WorkSubmitArgs *submitArgs = nullptr, | |
115 | WorkBeginArgs *beginArgs = nullptr); | |
116 | ||
117 | /*! | |
118 | * @function workBegin | |
119 | * @abstract Tell the performance controller that previously submitted work began executing. | |
120 | * @param device The device that is executing the work. Some platforms require device to be a | |
121 | * specific subclass of IOService. | |
122 | * @param args Optional device-specific arguments related to the start of this work item. | |
123 | */ | |
124 | virtual void workBegin(IOService *device, uint64_t token, WorkBeginArgs *args = nullptr); | |
125 | ||
126 | /*! | |
127 | * @struct WorkEndArgs | |
128 | * @discussion Drivers may submit additional device-specific arguments related to the end of a work item | |
129 | * by passing a struct with WorkEndArgs as its first member. Note: Drivers are responsible for publishing | |
130 | * a header file describing these arguments. | |
131 | */ | |
132 | struct WorkEndArgs { | |
133 | uint32_t version; | |
134 | uint32_t size; | |
135 | uint64_t end_time; | |
136 | uint64_t reserved[4]; | |
137 | void *driver_data; | |
138 | }; | |
139 | ||
140 | /*! | |
141 | * @function workEnd | |
142 | * @abstract Tell the performance controller that previously started work finished executing. | |
143 | * @param device The device that executed the work. Some platforms require device to be a | |
144 | * specific subclass of IOService. | |
145 | * @param args Optional device-specific arguments related to the end of this work item. | |
146 | * @param done Optional Set to false if the work has not yet completed. Drivers are then responsible for | |
147 | * calling workBegin when the work resumes and workEnd with done set to True when it has completed. | |
148 | */ | |
149 | virtual void workEnd(IOService *device, uint64_t token, WorkEndArgs *args = nullptr, bool done = true); | |
150 | ||
151 | /*! | |
152 | * @struct PerfControllerInterface | |
153 | * @discussion Function pointers necessary to register a performance controller. Not for general driver use. | |
154 | */ | |
155 | struct PerfControllerInterface { | |
156 | struct WorkState { | |
157 | uint64_t thread_group_id; | |
158 | void *thread_group_data; | |
159 | void *work_data; | |
160 | uint32_t work_data_size; | |
161 | }; | |
162 | ||
163 | using RegisterDeviceFunction = IOReturn (*)(IOService *); | |
164 | using WorkCanSubmitFunction = bool (*)(IOService *, WorkState *, WorkSubmitArgs *); | |
165 | using WorkSubmitFunction = void (*)(IOService *, uint64_t, WorkState *, WorkSubmitArgs *); | |
166 | using WorkBeginFunction = void (*)(IOService *, uint64_t, WorkState *, WorkBeginArgs *); | |
167 | using WorkEndFunction = void (*)(IOService *, uint64_t, WorkState *, WorkEndArgs *, bool); | |
168 | ||
169 | uint64_t version; | |
170 | RegisterDeviceFunction registerDevice; | |
171 | RegisterDeviceFunction unregisterDevice; | |
172 | WorkCanSubmitFunction workCanSubmit; | |
173 | WorkSubmitFunction workSubmit; | |
174 | WorkBeginFunction workBegin; | |
175 | WorkEndFunction workEnd; | |
176 | }; | |
177 | ||
178 | /*! | |
179 | * @function registerPerformanceController | |
180 | * @abstract Register a performance controller to receive callbacks. Not for general driver use. | |
181 | * @param interface Struct containing callback functions implemented by the performance controller. | |
182 | * @returns kIOReturnSuccess or kIOReturnError if the interface was already registered. | |
183 | */ | |
184 | virtual IOReturn registerPerformanceController(PerfControllerInterface interface); | |
d9a64523 A |
185 | |
186 | private: | |
0a7de745 A |
187 | struct WorkTableEntry { |
188 | struct thread_group *thread_group; | |
189 | bool started; | |
190 | uint8_t perfcontrol_data[32]; | |
191 | }; | |
192 | ||
193 | // TODO: size of table should match sum(maxWorkCapacity) of all users | |
194 | static constexpr size_t kWorkTableNumEntries = 1024; | |
195 | ||
196 | uint64_t allocateToken(thread_group *thread_group); | |
197 | void deallocateToken(uint64_t token); | |
198 | bool getEntryForToken(uint64_t token, WorkTableEntry &entry); | |
199 | void markEntryStarted(uint64_t token, bool started); | |
200 | ||
201 | PerfControllerInterface interface; | |
202 | IOLock *interfaceLock; | |
203 | OSSet *deviceRegistrationList; | |
204 | ||
205 | // TODO: replace with ltable or pool of objects | |
206 | WorkTableEntry workTable[kWorkTableNumEntries]; | |
207 | size_t workTableNextIndex; | |
208 | IOSimpleLock *workTableLock; | |
d9a64523 A |
209 | }; |
210 | ||
211 | #endif /* __cplusplus */ | |
212 | #endif /* KERNEL_PRIVATE */ |