2 * Copyright (c) 2017 Apple Inc. All rights reserved.
10 #include <IOKit/IOService.h>
16 kIOPerfControlClientWorkUntracked
= 0,
20 * @class IOPerfControlClient : public OSObject
21 * @abstract Class which implements an interface allowing device drivers to participate in performance control.
24 class IOPerfControlClient final
: public OSObject
26 OSDeclareDefaultStructors(IOPerfControlClient
);
29 virtual bool init(IOService
*driver
, uint64_t maxWorkCapacity
);
33 * @function copyClient
34 * @abstract Return a retained reference to a client object, to be released by the driver. It may be
35 * shared with other drivers in the system.
36 * @param driver The device driver that will be using this interface.
37 * @param maxWorkCapacity The maximum number of concurrent work items supported by the device driver.
38 * @returns An instance of IOPerfControlClient.
40 static IOPerfControlClient
*copyClient(IOService
*driver
, uint64_t maxWorkCapacity
);
43 * @function registerDevice
44 * @abstract Inform the system that work will be dispatched to a device in the future.
45 * @discussion The system will do some one-time setup work associated with the device, and may block the
46 * current thread during the setup. Devices should not be passed to work workSubmit, workSubmitAndBegin,
47 * workBegin, or workEnd until they have been successfully registered. The unregistration process happens
48 * automatically when the device object is deallocated.
49 * @param device The device object. Some platforms require device to be a specific subclass of IOService.
50 * @returns kIOReturnSuccess or an IOReturn error code
52 virtual IOReturn
registerDevice(IOService
*driver
, IOService
*device
);
55 * @function unregisterDevice
56 * @abstract Inform the system that work will be no longer be dispatched to a device in the future.
57 * @discussion This call is optional as the unregistration process happens automatically when the device
58 * object is deallocated. This call may block the current thread and/or acquire locks. It should not be
59 * called until after all submitted work has been ended using workEnd.
60 * @param device The device object. Some platforms require device to be a specific subclass of IOService.
62 virtual void unregisterDevice(IOService
*driver
, IOService
*device
);
65 * @struct WorkSubmitArgs
66 * @discussion Drivers may submit additional device-specific arguments related to the submission of a work item
67 * by passing a struct with WorkSubmitArgs as its first member. Note: Drivers are responsible for publishing
68 * a header file describing these arguments.
80 * @function workSubmit
81 * @abstract Tell the performance controller that work was submitted.
82 * @param device The device that will execute the work. Some platforms require device to be a
83 * specific subclass of IOService.
84 * @param args Optional device-specific arguments related to the submission of this work item.
85 * @returns A token representing this work item, which must be passed to workEnd when the work is finished
86 * unless the token equals kIOPerfControlClientWorkUntracked. Failure to do this will result in memory leaks
87 * and a degradation of system performance.
89 virtual uint64_t workSubmit(IOService
*device
, WorkSubmitArgs
*args
= nullptr);
92 * @struct WorkBeginArgs
93 * @discussion Drivers may submit additional device-specific arguments related to the start of a work item
94 * by passing a struct with WorkBeginArgs as its first member. Note: Drivers are responsible for publishing
95 * a header file describing these arguments.
102 uint64_t reserved
[4];
107 * @function workSubmitAndBegin
108 * @abstract Tell the performance controller that work was submitted and immediately began executing.
109 * @param device The device that is executing the work. Some platforms require device to be a
110 * specific subclass of IOService.
111 * @param submitArgs Optional device-specific arguments related to the submission of this work item.
112 * @param beginArgs Optional device-specific arguments related to the start of this work item.
113 * @returns A token representing this work item, which must be passed to workEnd when the work is finished
114 * unless the token equals kIOPerfControlClientWorkUntracked. Failure to do this will result in memory leaks
115 * and a degradation of system performance.
117 virtual uint64_t workSubmitAndBegin(IOService
*device
, WorkSubmitArgs
*submitArgs
= nullptr,
118 WorkBeginArgs
*beginArgs
= nullptr);
121 * @function workBegin
122 * @abstract Tell the performance controller that previously submitted work began executing.
123 * @param device The device that is executing the work. Some platforms require device to be a
124 * specific subclass of IOService.
125 * @param args Optional device-specific arguments related to the start of this work item.
127 virtual void workBegin(IOService
*device
, uint64_t token
, WorkBeginArgs
*args
= nullptr);
130 * @struct WorkEndArgs
131 * @discussion Drivers may submit additional device-specific arguments related to the end of a work item
132 * by passing a struct with WorkEndArgs as its first member. Note: Drivers are responsible for publishing
133 * a header file describing these arguments.
140 uint64_t reserved
[4];
146 * @abstract Tell the performance controller that previously started work finished executing.
147 * @param device The device that executed the work. Some platforms require device to be a
148 * specific subclass of IOService.
149 * @param args Optional device-specific arguments related to the end of this work item.
150 * @param done Optional Set to false if the work has not yet completed. Drivers are then responsible for
151 * calling workBegin when the work resumes and workEnd with done set to True when it has completed.
153 virtual void workEnd(IOService
*device
, uint64_t token
, WorkEndArgs
*args
= nullptr, bool done
= true);
156 * @struct PerfControllerInterface
157 * @discussion Function pointers necessary to register a performance controller. Not for general driver use.
159 struct PerfControllerInterface
162 uint64_t thread_group_id
;
163 void *thread_group_data
;
165 uint32_t work_data_size
;
168 using RegisterDeviceFunction
= IOReturn (*)(IOService
*);
169 using WorkCanSubmitFunction
= bool (*)(IOService
*, WorkState
*, WorkSubmitArgs
*);
170 using WorkSubmitFunction
= void (*)(IOService
*, uint64_t, WorkState
*, WorkSubmitArgs
*);
171 using WorkBeginFunction
= void (*)(IOService
*, uint64_t, WorkState
*, WorkBeginArgs
*);
172 using WorkEndFunction
= void (*)(IOService
*, uint64_t, WorkState
*, WorkEndArgs
*, bool);
175 RegisterDeviceFunction registerDevice
;
176 RegisterDeviceFunction unregisterDevice
;
177 WorkCanSubmitFunction workCanSubmit
;
178 WorkSubmitFunction workSubmit
;
179 WorkBeginFunction workBegin
;
180 WorkEndFunction workEnd
;
184 * @function registerPerformanceController
185 * @abstract Register a performance controller to receive callbacks. Not for general driver use.
186 * @param interface Struct containing callback functions implemented by the performance controller.
187 * @returns kIOReturnSuccess or kIOReturnError if the interface was already registered.
189 virtual IOReturn
registerPerformanceController(PerfControllerInterface interface
);
192 struct WorkTableEntry
194 struct thread_group
*thread_group
;
196 uint8_t perfcontrol_data
[32];
199 // TODO: size of table should match sum(maxWorkCapacity) of all users
200 static constexpr size_t kWorkTableNumEntries
= 1024;
202 uint64_t allocateToken(thread_group
*thread_group
);
203 void deallocateToken(uint64_t token
);
204 bool getEntryForToken(uint64_t token
, WorkTableEntry
&entry
);
205 void markEntryStarted(uint64_t token
, bool started
);
207 PerfControllerInterface interface
;
208 IOLock
*interfaceLock
;
209 OSSet
*deviceRegistrationList
;
211 // TODO: replace with ltable or pool of objects
212 WorkTableEntry workTable
[kWorkTableNumEntries
];
213 size_t workTableNextIndex
;
214 IOSimpleLock
*workTableLock
;
217 #endif /* __cplusplus */
218 #endif /* KERNEL_PRIVATE */